Skip to content
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

[ResponseOps][actions] add config for allow-listing email address domains #129001

Merged
merged 3 commits into from
Apr 26, 2022

Conversation

pmuellr
Copy link
Member

@pmuellr pmuellr commented Mar 31, 2022

Summary

resolves #126944

docs preview:

Adds a new configuration setting for the actions plugin, xpack.actions.email.domain_allowlist, which is an array of domain name strings which are allowed to be sent emails by the email connector. If this setting isn't used, there is no change to the way the email connector works before this PR - email addresses are generally only validated when the connector is executed, by node-mailer. If this setting is used, for each email connector, each email address specified in the from property in config, and to, cc, and bcc properties in params, will be validated, and their domains checked against the allow list. If any email is invalid (so we can't determine the domain), or it's domain is not in the allow list, that's considered an error condition, when the validation is run:

  • a connector create will fail if an invalid/not allowed email is used in the config from property
  • a rule create/update will fail if an invalid/not allowed email is used in the email connector params to, cc, or bcc of any of it's actions
  • and a connector run will fail if any of from, to, cc, or bcc are invalid/not allowed.

This adds a new dependency on an npm package email-addresses, which we use to extract the domain from an email address. This also validates the email address, first. This seems like a well-maintained package and has no dependencies.

We expose the config setting down into the UX via exposeToBrowser. A chat with Kibana Security indicated they didn't feel like this was a security concern. Basically, if we WANT to be able to validate email addresses in the UX, we will have to expose SOME way of validating email addresses via HTTP, so even the most obscure way of doing this (for example, exposing a new server endpoint to validate email addresses) will end up "leaking" which domains are actually allowed. If this is still felt to be a security concern, we can rip out everything on the UX side, and let the validation only happen on the server. The same error conditions will work, but the UX is not quite as nice - "Error saving connector: blah blah" instead of nice error indicators in appropriate fields in the UX.

This required adding a new public plugin for actions - it didn't have one before. The common folder for actions is also where the new validation logic is implemented, where it calls into the email-addresses package, so it's shared between client and server.

Creating this new plugin caused some other issues, with some ServiceNow public code that was referencing the server plugin types, but using a // eslint-disable-next-line @kbn/eslint/no-restricted-paths comment to disable the compile time warning. With the new public plugin, this changed to a runtime warning message. So, the relevant types were extracted into common, and then the references to them changed. Seems like a good cleanup, and eliminated some //eslint-disable usages.

For function tests, security_and_spaces was left alone, so is the tester for NOT using the new config. spaces_only now uses the new setting, and has added tests to ensure the code works as expected.

To Verify

Add the new config, for example:

xpack.actions.email.domain_allowlist: ['elastic.co']

Then try creating a connector with a from with a different email address, and with an elastic.co address. Should only work for elastic.co. After creating a connector, try using the test page and using different values for to, cc, and bcc. Should only work with elastic.co addresses. Then add the email connector to an existing rule, and try setting the to, cc, and bcc to different values to see they work or generate errors.

Note, the email doesn't have to be a "live" one, you can use Gmail but give it bogus userid / password. In which case if you see a failure from Gmail, then the email would have validated and sent :-).

You can also test using previously created email connectors without the setting, then turn the setting on, and edit the connector to see the "new" errors.

Checklist

Delete any items that are not applicable to this PR.

Release Note

Adds a new configuration setting for the actions plugin, xpack.actions.email.domain_allowlist, which is an array of domain name strings which are allowed to be sent emails by the email connector.

@pmuellr pmuellr force-pushed the actions/126944-email-allowlist branch 2 times, most recently from 854f486 to b80b9c2 Compare April 1, 2022 20:44
@pmuellr pmuellr force-pushed the actions/126944-email-allowlist branch 3 times, most recently from 6ff5116 to 3c4b94c Compare April 18, 2022 17:59
@pmuellr pmuellr force-pushed the actions/126944-email-allowlist branch 2 times, most recently from 74e277f to 56da55d Compare April 20, 2022 22:53
…ains

resolves elastic#126944

Adds a new configuration setting for the actions plugin,
xpack.actions.email.domain_allowlist, which is an array of domain name
strings which are allowed to be sent emails by the email connector.
@pmuellr pmuellr force-pushed the actions/126944-email-allowlist branch from 45f4962 to 7e8cd7f Compare April 21, 2022 14:09
@pmuellr pmuellr added Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) release_note:enhancement Feature:Actions/Framework Issues related to the Actions Framework v8.3.0 v7.17.4 labels Apr 21, 2022
@@ -1,5 +1,6 @@
pageLoadAssetSize:
advancedSettings: 27596
actions: 20000
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual value was ~16K, figured I'd add some slop, but not quite sure if that's ok

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's fine

@@ -0,0 +1,56 @@
/*
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These definitions were originally in a server directory, and accessed from a public directory, with an eslint directive to not generate a warning about that. However, when the actions plugin grew a public plugin, things got worse - we started getting a runtime message when Kibana started. So I extracted all the stuff from the server directory that the public code needed, and moved it in here.

@@ -454,21 +482,9 @@ describe('execute()', () => {
"status": "ok",
}
`);
delete sendEmailMock.mock.calls[0][1].configurationUtilities;
Copy link
Member Author

@pmuellr pmuellr Apr 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where I delete the configuration utilities from the calls structure, so we no longer compare it, so we don't have to change this code when we add new methods to the configuration utilities. I do this in some other tests that had the same pattern.

"configPath": ["xpack", "trigger_actions_ui"],
"extraPublicDirs": ["public/common", "public/common/constants"],
"requiredBundles": ["alerting", "esUiShared", "kibanaReact", "kibanaUtils"]
"requiredBundles": ["alerting", "esUiShared", "kibanaReact", "kibanaUtils", "actions"]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured we need to add the actions bundle here, since it's now referencing code there. Though I think it worked at dev time without it - or maybe I was imagining that.


const ACTION_TYPE_ID = '.index';
let actionTypeModel: ActionTypeModel;

beforeAll(() => {
const actionTypeRegistry = new TypeRegistry<ActionTypeModel>();
registerBuiltInActionTypes({ actionTypeRegistry });
registerBuiltInActionTypes({ actionTypeRegistry, services: registrationServicesMock });
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

registerBuiltInActionTypes() takes an additional parameter now - services - so all the connector type tests need this change; more below ...

@pmuellr pmuellr marked this pull request as ready for review April 21, 2022 15:50
@pmuellr pmuellr requested review from a team as code owners April 21, 2022 15:50
@elasticmachine
Copy link
Contributor

Pinging @elastic/response-ops (Team:ResponseOps)

@@ -1,5 +1,6 @@
pageLoadAssetSize:
advancedSettings: 27596
actions: 20000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's fine

@mikecote mikecote self-requested a review April 21, 2022 16:53
Copy link
Contributor

@mikecote mikecote left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM! Tested locally the UI form validation in rule actions & connector flyouts. Also, tested implementing the allow_list after creating a rule and connector and saw the runtime validation prevent emails from sending out. Great work 👍

@@ -125,6 +125,11 @@ The contents of a PEM-encoded certificate file, or multiple files appended
into a single string. This configuration can be used for environments where
the files cannot be made available.

`xpack.actions.email.domain_allowlist`::
A list of allowed email domains which can be used with the email connector. When this setting is not used, all email domains are allowed. When this setting is used, if any email is attempted to be sent that includes an addressee with an email domain that is not in the allowlist, the run of the connector will fail with a message indicating the emails not allowed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to add a mention about the from email domain as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, we do. I realized I hadn't dealt with from this week, so added it in as well, but forgot to update this.

@pmuellr
Copy link
Member Author

pmuellr commented Apr 25, 2022

For some reason the issue for this PR mentioned in the summary wasn't auto-linked in the issue itself; let's try it manually -here's the originating issue: #126944

Copy link
Contributor

@ymao1 ymao1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Verified adding the domain allowlist works as expected for existing and new connectors. Left some comments about docs and more specificity in the error message.

@@ -125,6 +125,11 @@ The contents of a PEM-encoded certificate file, or multiple files appended
into a single string. This configuration can be used for environments where
the files cannot be made available.

`xpack.actions.email.domain_allowlist`::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UI when creating a connector shows Email address <email> is not allowed. if the from is not allowed with a link to the email action type: https://www.elastic.co/guide/en/kibana/master/email-action-type.html but there is no mention of the domain allowlist on that page. Should we add a mention or a link to this allowlist entry?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, good idea, will add a link to that.

@jportner jportner self-requested a review April 25, 2022 15:12
@jportner
Copy link
Contributor

Reviewing now!

Copy link
Contributor

@jportner jportner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the integration test change for the newly-exposed config setting -- LGTM.

I also took the liberty of reviewing the validation itself. I have some suggestions below!

@pmuellr pmuellr requested a review from a team as a code owner April 26, 2022 06:19
@pmuellr
Copy link
Member Author

pmuellr commented Apr 26, 2022

@elasticmachine merge upstream

Copy link
Contributor

@jportner jportner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the changes!

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
actions - 12 +12
triggersActionsUi 365 360 -5
total +7

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
actions 128 191 +63

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
triggersActionsUi 712.4KB 711.9KB -580.0B

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
actions 10 11 +1

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
actions - 15.0KB +15.0KB
triggersActionsUi 100.0KB 99.4KB -700.0B
total +14.3KB
Unknown metric groups

API count

id before after diff
actions 128 195 +67

ESLint disabled line counts

id before after diff
triggersActionsUi 170 167 -3

Total ESLint disabled count

id before after diff
triggersActionsUi 176 173 -3

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@pmuellr pmuellr merged commit 6ad418b into elastic:main Apr 26, 2022
pmuellr added a commit to pmuellr/kibana that referenced this pull request Apr 26, 2022
…ains (elastic#129001)

resolves elastic#126944

Adds a new configuration setting for the actions plugin,
xpack.actions.email.domain_allowlist, which is an array of domain name
strings which are allowed to be sent emails by the email connector.

backport of elastic#129001
pmuellr added a commit that referenced this pull request Apr 26, 2022
…ess domains (#129001)  (#131014)

resolves #126944

Adds a new configuration setting for the actions plugin,
xpack.actions.email.domain_allowlist, which is an array of domain name
strings which are allowed to be sent emails by the email connector.

backport of #129001

* additional changes after merge conflicts during cherry pick for backport
kertal pushed a commit to kertal/kibana that referenced this pull request May 24, 2022
…ains (elastic#129001)

resolves elastic#126944

Adds a new configuration setting for the actions plugin,
xpack.actions.email.domain_allowlist, which is an array of domain name
strings which are allowed to be sent emails by the email connector.
@gmmorris gmmorris added the Feature:Actions/ConnectorTypes Issues related to specific Connector Types on the Actions Framework label Jun 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backported Feature:Actions/ConnectorTypes Issues related to specific Connector Types on the Actions Framework Feature:Actions/Framework Issues related to the Actions Framework release_note:enhancement Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) v7.17.4 v8.3.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add allowed host support for email connector recipients (to, cc, bcc)
9 participants