-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[alerting] Adds Action Type configuration support and whitelisting #44483
[alerting] Adds Action Type configuration support and whitelisting #44483
Conversation
Pinging @elastic/kibana-stack-services |
I'll we adding documentation for:
Just waiting to confirm the team is comfortable with the changes.... |
💚 Build Succeeded |
💚 Build Succeeded |
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 looking great! I'll re-review when you feel like it's done.
x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts
Outdated
Show resolved
Hide resolved
x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts
Outdated
Show resolved
Hide resolved
… an empty array and Any is now an asterix
💚 Build Succeeded |
💚 Build Succeeded |
💔 Build Failed |
💚 Build Succeeded |
💚 Build Succeeded |
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.
The implementation of isWhitelistedHost seems convoluted to me. I expected it to either return a boolean (based on * || Array.includes) or to throw if those conditions are not met. Returning an error seems like an odd choice to me, definitely don't expect errors to get passed around, only thrown when they are created.
} | ||
|
||
export interface ActionsConfigurationUtilities { | ||
isWhitelistedHostname: (hostname: string) => string | NotWhitelistedError; |
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 find the name and semantics of this to be strange. I expect is...
methods to return booleans.
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.
Fair, I could rename it to ensureIsWhitelisted...
or something like that.
return tryCatch(() => new URL(uri)) | ||
.map(url => url.hostname) | ||
.map(hostname => { | ||
const result = isWhitelistedHostname(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.
why doesn't this just throw instead of returning an error and then throwing based on instanceof? Seems overcomplicated to me.
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.
You can't typecheck thrown errors in Typescript, so the general recommendation there seems to be to return errors.
I agree it's over complicated- that's why the Result type is a much more elegant solution, but there were concerns about Result type being used on external APIs.
It did originally return a boolean, but following feedback from Patrick we decided the function would return the messaging that made it . clear what the source of the problem was (value not being in the whitelist) so that you don't have top repeat that in each action that uses the utility. I also agree, returning Errors is weird in JS land, which is why the Result type is a nice abstraction for this, but as long as there's unease about using TS types on APIs like this, we're low on options here. We can either:
To me, the ideal is option #4, where we use TS on our APIs, but sounds like we're not quite ready for that yet. |
I'm OK with the approach here so long as we change the name of the method to |
Cool, thanks, I'll rename to make it clearer. |
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.
Made a bunch of comments; most concerned with the validator function shapes here - eg, isWhitelistedHostname: (hostname: string) => string | NotWhitelistedError
- it doesn't seem very idiomatic to me. I suppose I could be convinced, but ... it will be tough heh.
} | ||
|
||
const whitelistingErrorMessage = 'target url not in whitelist'; | ||
const doesValueWhitelistAnyHostname = (whitelistedHostname: string): boolean => |
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 starts to read as a valuable piece of function, but there's no verbs, or something. Would something like isHostnameWildcard()
work instead? Or is this some kind of functional pattern I'm not familiar with?
I also noticed you used const <functionName> = <lambda>
as is the style for a lot of code these days, but I think we've generally just used functions in this area of Kibana at least; ie, function doesValueWhitelistAnyHostname(...) {...}
instead.
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.
Regarding doesValueWhitelistAnyHostname
it's not about FP, it's about communicating intent.
Implementation is easier to communicate (they read the code) but intent is much harder (read the code, and the surrounding code, and how they fit together). I find it helpful to communicate intent in the name of functions rather than implementation.
Hope that helps
x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts
Outdated
Show resolved
Hide resolved
const log = (level: string, msg: string) => | ||
execOptions.services.log([level, 'actions', 'webhook'], msg); | ||
|
||
const id = execOptions.id; | ||
const { method, url, headers = {} } = execOptions.config as ActionTypeConfigType; | ||
const { user: username, password } = execOptions.secrets as ActionTypeSecretsType; | ||
const { body: data } = execOptions.params as ActionParamsType; | ||
const whitelistValidation = configurationUtilities.isWhitelistedUri(url); |
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 thought we re-ran the validators (all of them?) before invoking the executor? Yeah, I think so, so this explicit check shouldn't be needed, and I think you'd never get into this method, and have the subsequent code run.
kibana/x-pack/legacy/plugins/actions/server/lib/execute.ts
Lines 50 to 56 in 49fdd24
try { | |
validatedParams = validateParams(actionType, params); | |
validatedConfig = validateConfig(actionType, config); | |
validatedSecrets = validateSecrets(actionType, secrets); | |
} catch (err) { | |
return { status: 'error', message: err.message, retry: false }; | |
} |
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.
Yup, I've double checked and this is true, but somewhat implicit as it requires prior knowledge of the wiring.
I've removed the redundant validation, but feel this is something worth revisiting in the future... perhaps there's a better way to model this so it's clearer.
x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts
Outdated
Show resolved
Hide resolved
x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts
Show resolved
Hide resolved
💚 Build Succeeded |
…ts, either throw or boolean
…r as config is rechecked before the executor is called
💚 Build Succeeded |
💚 Build Succeeded |
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.
Code LGTM
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.
Fantastic!
I made a few comments for things I think need to be fixed, but can be in a subsequent PR; let's get this sucker merged!
@@ -27,6 +27,13 @@ export function actions(kibana: any) { | |||
return Joi.object() | |||
.keys({ | |||
enabled: Joi.boolean().default(false), | |||
whitelistedHosts: Joi.alternatives() |
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 think alternatives was here when the property was string | string[]
? So, I think we can remove the alternatives()
and try()
wrappers, just make it a Joi.array()
? Or maybe there's some joi sneakiness I don't yet understand :-)
It clearly works now, so fine with shipping this way, create an issue / project card if it should be fixed later.
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.
Yeah, that's not needed anymore, I'll fix in a small PR next
@@ -19,6 +20,12 @@ import { ActionParamsType, ActionTypeConfigType } from './es_index'; | |||
|
|||
const ACTION_TYPE_ID = '.index'; | |||
const NO_OP_FN = () => {}; | |||
const MOCK_KIBANA_CONFIG_UTILS: ActionsConfigurationUtilities = { |
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.
fyi: more bits to add to the theoretical "testing rig for actions" :-)
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.
Agreed
configurationUtilities.ensureWhitelistedUri(configObject.url); | ||
} catch (whitelistError) { | ||
return i18n.translate('xpack.actions.builtin.webhook.webhookConfigurationError', { | ||
defaultMessage: 'error configuring webhook action: {message}', |
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 think we still need the actionId in here - unless it's somehow included in some other way (not obvious to me that it is).
If we need to get it added, can be done in a subsequent PR; create an issue | project card for 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.
Yeah, we don't have access to the ID at this point (in create it happens before an ID is generated, and in update/execute it's not provided), so this will have to be a separate PR.
…lastic#44483) A wide refactor of Action Types and their configuration: - Action Types are now initialised with a their associated configuration based on `kibana.yml` - You may now whitelist certain hostnames to allow built-in actions, such as _Webhooks_, to communicate with the outside world - The _Webhooks_ Built-in action is now available, if you have `alerting` and `actions` enabled
…44483) (#44969) A wide refactor of Action Types and their configuration: - Action Types are now initialised with a their associated configuration based on `kibana.yml` - You may now whitelist certain hostnames to allow built-in actions, such as _Webhooks_, to communicate with the outside world - The _Webhooks_ Built-in action is now available, if you have `alerting` and `actions` enabled
…ete-for-distance_feature * 'master' of github.com:elastic/kibana: (89 commits) Replace TSVB timeseries charts with elastic-charts (elastic#33558) [TSVB][Top N aggregation] Unable to deal with negative values (elastic#43581) [alerting] Adds Action Type configuration support and whitelisting (elastic#44483) FTR: fix WebDriver Actions calls (elastic#44605) [Code] add NodeRepositoriesService to watch new repositories on local node (elastic#44677) [skip-ci][Maps] Improve Maps intro page (elastic#44721) [Maps] Update titles and descriptions for data sources (elastic#44833) Types + Extract Integration Util (elastic#44433) Downgrade log level from info to debug for cases when we cannot handle authentication attempt. (elastic#44933) [Reporting] Remove Chome stdout/stderr observables, Add Browser Logger observable (elastic#44359) Update Jest script to output coverage (elastic#44447) [ftr] support --kibana-install-dir flag (elastic#44552) [WATCHER] Allow user to set a threshold value of 0 (elastic#44810) Remove injectI18n in dashboard plugin. (elastic#44580) [Graph] Save modal (elastic#44261) Use external script for the OIDC Implicit flow handler page. (elastic#44866) disable router prefixing with pluginId (elastic#44855) [SIEM] Fix bug on url + inspect functionality on hosts/hostDetails page (elastic#44671) [ML] File data viz limiting uploaded doc chunk size (elastic#44768) [code] Append go env variable 'GOCACHE' to go lsp spawn command. (elastic#44864) ...
…plate * 'master' of github.com:elastic/kibana: (91 commits) [APM] Make number of x ticks responsive to the plot width (elastic#44870) [ML] Single metric viewer: Fix top nav refresh behaviour. (elastic#44860) Replace TSVB timeseries charts with elastic-charts (elastic#33558) [TSVB][Top N aggregation] Unable to deal with negative values (elastic#43581) [alerting] Adds Action Type configuration support and whitelisting (elastic#44483) FTR: fix WebDriver Actions calls (elastic#44605) [Code] add NodeRepositoriesService to watch new repositories on local node (elastic#44677) [skip-ci][Maps] Improve Maps intro page (elastic#44721) [Maps] Update titles and descriptions for data sources (elastic#44833) Types + Extract Integration Util (elastic#44433) Downgrade log level from info to debug for cases when we cannot handle authentication attempt. (elastic#44933) [Reporting] Remove Chome stdout/stderr observables, Add Browser Logger observable (elastic#44359) Update Jest script to output coverage (elastic#44447) [ftr] support --kibana-install-dir flag (elastic#44552) [WATCHER] Allow user to set a threshold value of 0 (elastic#44810) Remove injectI18n in dashboard plugin. (elastic#44580) [Graph] Save modal (elastic#44261) Use external script for the OIDC Implicit flow handler page. (elastic#44866) disable router prefixing with pluginId (elastic#44855) [SIEM] Fix bug on url + inspect functionality on hosts/hostDetails page (elastic#44671) ...
Summary
Refactor Action Types registration.
Adds whitelisting configuration for the builtin webhooks action.
Refers to: https://github.com/elastic/kibana-team/issues/136
Checklist
Use
strikethroughsto remove checklist items you don't feel are applicable to this PR.This was checked for cross-browser compatibility, including a check against IE11This was checked for keyboard-only and screenreader accessibilityFor maintainers