-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(manifest): Strip protocol before feeding just the outgoing domain to the manifest API #246
base: main
Are you sure you want to change the base?
fix(manifest): Strip protocol before feeding just the outgoing domain to the manifest API #246
Conversation
…t API Signed-off-by: Arun <[email protected]>
I just have one question about |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @arunsathiya 👋🏻 Thanks for the PR! 🎉
☑️ It looks good to me, so I'll enable the GitHub checks to run. However, I'll let some of the Deno maintainers take a look as well.
🧪 One suggestion would be to consider add some tests, if possible.
I just have one question about
import_map.json
usage. Does theslack run
command run--import-map
behind the scenes? That part is a bit unclear to me because the Slack CLI is not open source.
The slack run
command starts a SocketMode connections managed by the CLI. When a function event is received, the CLI will invoke the script defined by the "start"
hook in slack.json
(example). That script currently calls the deno-slack-runtime/src/local-run.ts. In the source, you can see that the SDK reads the outgoing domains from the manifest and adds it to the Deno processes --allow-net
.
We're in the process of preparing the CLI to be open sourced 😃 It's written in Golang and I see you're a Go developer who enjoys working on CLIs. Hopefully we'll see you in that repo in the future!
…sts to parse valid and invalid domains Signed-off-by: Arun <[email protected]>
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #246 +/- ##
==========================================
- Coverage 98.07% 97.95% -0.12%
==========================================
Files 58 58
Lines 2280 2301 +21
Branches 137 140 +3
==========================================
+ Hits 2236 2254 +18
- Misses 42 45 +3
Partials 2 2 ☔ View full report in Codecov by Sentry. |
Thanks for the review, @mwbrooks!
Definitely! I have added them in 2cff6ca.
Appreciate the explanation here, and exciting that Slack CLI will be open source in the future! I look forward to it. 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for tackling this issue! We really appreciate it ❤️
However, I think we need to add a test for the simple case of including just a domain in the manifest. I.e. outgoingDomains: ["poop.com"]
fails with "invalid URL".
For example, testing this PR against our deno-github-functions sample fails when I try to run slack manifest validate
:
09:57:05 in deno-github-functions on main via 🦕 v1.37.1
➜ slak manifest validate
? Select a team filboxworkspace TXXXXX
? Choose an app environment Local AXXXXX
error: Uncaught (in promise) Error: Invalid outgoing domain: api.github.com, error TypeError: Invalid URL: 'api.github.com'
throw new Error(`Invalid outgoing domain: ${domain}, error ${e}`);
Probably because the URL()
constructor assumes a fully qualified URL, including protocol? Ideally, the fix for #245 would allow users to include the protocol, or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome work @arunsathiya 💯
@filmaj beat me to it, I think the following suggestion should allow users to include the protocol, or not.
src/manifest/mod.ts
Outdated
try { | ||
return new URL(domain).hostname; | ||
} catch (e) { | ||
throw new Error(`Invalid outgoing domain: ${domain}, error ${e}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Throwing an error here may be a breaking change since existing users are providing string values that may not be valid urls, for example raw.githubusercontent.com
Returning the domain
when the URL constructor throws an error would allow this change to be none breaking for existing apps and rely on the existing behavior to handle "bad" domains, let me know what you think of this?
throw new Error(`Invalid outgoing domain: ${domain}, error ${e}`); | |
return domain; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point about breaking change, but I think it may be warranted here. The current behaviour is: any string is accepted, even non-hostnames. That's not great as it may lead the developer into a false sense of security if they e.g. typo'ed a domain.
We may also want to raise this with the backend team to see if the manifest API should raise an error if the strings provided to outgoingDomains
are not a hostname.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point about raising this with the backend team. It would be more reliable and consistent to have the backend validate the outgoingDomains
format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Glad these concerns are being discussed, thanks for raising them! I implemented @WilliamBergamin's suggestion above, but have implemented another check where the http protocol is assumed in the absence of the protocol, and then the hostname is returned.
If that constructor fails for some reason, there is another defensive check that validates if the domain is valid and returns it, or throws an error: b584112
deno-slack-sdk/src/manifest/mod.ts
Lines 35 to 57 in b584112
export const validateOutgoingDomains = ( | |
domains: string[], | |
) => { | |
return domains.map((domain) => { | |
try { | |
const url = domain.includes("://") ? domain : `http://${domain}`; | |
return new URL(url).hostname; | |
} catch (e) { | |
if (isValidDomain(domain)) { | |
return domain; | |
} else { | |
throw new Error( | |
`Invalid outgoing domain: ${domain}, error ${e}`, | |
); | |
} | |
} | |
}); | |
}; | |
const isValidDomain = (domain: string) => { | |
const domainPattern = /^[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z]{2,}$/; | |
return domainPattern.test(domain); | |
}; |
Is this the direction the team would like to take, or prefer having these checks in the backend side of things and not the SDK? I am leaning towards the latter. If agreed, I'll limit the changes to William's suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One concern that still remains is, local hostnames like localhost
are considered valid in the current implementation (without this PR's changes as well). Is that expected?
I'd imagine only fully qualified external domains are valid based on this documentation:
https://api.slack.com/automation/admin
Outgoing domains are a new concept, and apply only to apps deployed to Slack's managed infrastructure. These are domains the app may require access to — for example, if a developer writes a function that makes a request to an external API, they will need to include that API in their outgoing domains.
If they shouldn't be supported, this again is something to implement on backend side of things, I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great @arunsathiya ! We can pursue both in parallel; no reason why the SDK can't be improved while we're here, and separately we can work on improving the backend internally, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are some test cases for the isValidDomain
regex:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't worry about validating the domain. I think we'd just want to make sure we can support named servers and IP addresses - at least IPv4. The outgoing domains field gets passed through directly to deno run --allow-net
(see this code) - so whatever the --allow-net
deno flag supports, we'd want to make sure the Manifest's outgoingDomains
supports it.
Co-authored-by: William Bergamin <[email protected]>
…lement an additional defensive check that returns the input as is or throw an error Signed-off-by: Arun <[email protected]>
outgoingDomains: [ | ||
"https://slack.com", | ||
"http://salesforce.com", | ||
"https://api.slack.com", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd add some more test cases here:
- Bare IP addresses
- Fully qualified domain names, including subdomains, i.e. en.wikipedia.org
- Either of the above w/ port specifiers
- All of the above with and without protocol specifiers
Summary
Fixes #245
When one or more outgoing domains in the manifest contain the protocol, the protocol is stripped off before feeding just the domain to the manifest API.
Testing
http:/example.com
orht*tp://example.com
in themanifest.ts
fileimport_map.json
on your Slack project to use the local, patched Deno SDK. Example below.slack run
to notice that the request fails with the appropriate error.Special notes
N/A
Requirements
deno task test
after making the changes.