Skip to content

Commit 14db2ce

Browse files
committed
Changed alerting wrong param name for help xpack.encrypted_saved_objects.encryptionKey to xpack.encryptedSavedObjects.encryptionKey (#63307)
# Conflicts: # rfcs/text/0002_encrypted_attributes.md
1 parent fdb501d commit 14db2ce

5 files changed

Lines changed: 257 additions & 5 deletions

File tree

docs/settings/alert-action-settings.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Alerts and actions are enabled by default in {kib}, but require you configure th
99

1010
. <<using-kibana-with-security,Set up {kib} to work with {stack} {security-features}>>.
1111
. <<configuring-tls-kib-es,Set up TLS encryption between {kib} and {es}>>.
12-
. <<general-alert-action-settings,Specify a value for `xpack.encrypted_saved_objects.encryptionKey`>>.
12+
. <<general-alert-action-settings,Specify a value for `xpack.encryptedSavedObjects.encryptionKey`>>.
1313

1414
You can configure the following settings in the `kibana.yml` file.
1515

@@ -18,7 +18,7 @@ You can configure the following settings in the `kibana.yml` file.
1818
[[general-alert-action-settings]]
1919
==== General settings
2020

21-
`xpack.encrypted_saved_objects.encryptionKey`::
21+
`xpack.encryptedSavedObjects.encryptionKey`::
2222

2323
A string of 32 or more characters used to encrypt sensitive properties on alerts and actions before they're stored in {es}. Third party credentials &mdash; such as the username and password used to connect to an SMTP service &mdash; are an example of encrypted properties.
2424
+

docs/user/alerting/index.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ Pre-packaged *alert types* simplify setup, hide the details complex domain-speci
157157
If you are using an *on-premises* Elastic Stack deployment with <<using-kibana-with-security, *security*>>:
158158

159159
* TLS must be configured for communication <<configuring-tls-kib-es, between {es} and {kib}>>. {kib} alerting uses <<api-keys, API keys>> to secure background alert checks and actions, and API keys require {ref}/configuring-tls.html#tls-http[TLS on the HTTP interface].
160-
* In the kibana.yml configuration file, add the <<alert-action-settings-kb,`xpack.encrypted_saved_objects.encryptionKey` setting>>
160+
* In the kibana.yml configuration file, add the <<alert-action-settings-kb,`xpack.encryptedSavedObjects.encryptionKey` setting>>
161161

162162
[float]
163163
[[alerting-security]]
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
- Start Date: 2019-03-22
2+
- RFC PR: [#33740](https://github.com/elastic/kibana/pull/33740)
3+
- Kibana Issue: (leave this empty)
4+
5+
# Summary
6+
7+
In order to support the action service we need a way to encrypt/decrypt
8+
attributes on saved objects that works with security and spaces filtering as
9+
well as performing audit logging. Sufficiently hides the private key used and
10+
removes encrypted attributes from being exposed through regular means.
11+
12+
# Basic example
13+
14+
Register saved object type with the `encrypted_saved_objects` plugin:
15+
16+
```typescript
17+
server.plugins.encrypted_saved_objects.registerType({
18+
type: 'server-action',
19+
attributesToEncrypt: new Set(['credentials', 'apiKey']),
20+
});
21+
```
22+
23+
Use the same API to create saved objects with encrypted attributes as for any other saved object type:
24+
25+
```typescript
26+
const savedObject = await server.savedObjects
27+
.getScopedSavedObjectsClient(request)
28+
.create('server-action', {
29+
name: 'my-server-action',
30+
data: { location: 'BBOX (100.0, ..., 0.0)', email: '<html>...</html>' },
31+
credentials: { username: 'some-user', password: 'some-password' },
32+
apiKey: 'dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvb'
33+
});
34+
35+
// savedObject = {
36+
// id: 'dd9750b9-ef0a-444c-8405-4dfcc2e9d670',
37+
// type: 'server-action',
38+
// name: 'my-server-action',
39+
// data: { location: 'BBOX (100.0, ..., 0.0)', email: '<html>...</html>' },
40+
// };
41+
42+
```
43+
44+
Use dedicated method to retrieve saved object with decrypted attributes on behalf of Kibana internal user:
45+
46+
```typescript
47+
const savedObject = await server.plugins.encrypted_saved_objects.getDecryptedAsInternalUser(
48+
'server-action',
49+
'dd9750b9-ef0a-444c-8405-4dfcc2e9d670'
50+
);
51+
52+
// savedObject = {
53+
// id: 'dd9750b9-ef0a-444c-8405-4dfcc2e9d670',
54+
// type: 'server-action',
55+
// name: 'my-server-action',
56+
// data: { location: 'BBOX (100.0, ..., 0.0)', email: '<html>...</html>' },
57+
// credentials: { username: 'some-user', password: 'some-password' },
58+
// apiKey: 'dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvb',
59+
// };
60+
```
61+
62+
# Motivation
63+
64+
Main motivation is the storage and usage of third-party credentials for use with
65+
the action service to do notifications. Also perform other types integrations,
66+
call webhooks using tokens.
67+
68+
# Detailed design
69+
70+
In order for this to be in basic it needs to be done as a wrapper around the
71+
saved object client. This can be added from the `x-pack` plugin.
72+
73+
## General
74+
75+
To be able to manage saved objects with encrypted attributes from any plugin one should
76+
do the following:
77+
78+
1. Define `encrypted_saved_objects` plugin as a dependency.
79+
2. Add attributes to be encrypted in `mappings.json` file for the respective saved object type. These attributes should
80+
always have a `binary` type since they'll contain encrypted content as a `Base64` encoded string and should never be
81+
searchable or analyzed. This makes defining of attributes that require encryption explicit and auditable, and significantly
82+
simplifies implementation:
83+
```json
84+
{
85+
"server-action": {
86+
"properties": {
87+
"name": { "type": "keyword" },
88+
"data": {
89+
"properties": {
90+
"location": { "type": "geo_shape" },
91+
"email": { "type": "text" }
92+
}
93+
},
94+
"credentials": { "type": "binary" },
95+
"apiKey": { "type": "binary" }
96+
}
97+
}
98+
}
99+
```
100+
3. Register saved object type and attributes that should be encrypted with `encrypted_saved_objects` plugin:
101+
```typescript
102+
server.plugins.encrypted_saved_objects.registerType({
103+
type: 'server-action',
104+
attributesToEncrypt: new Set(['credentials', 'apiKey']),
105+
attributesToExcludeFromAAD: new Set(['data']),
106+
});
107+
```
108+
109+
Notice the optional `attributesToExcludeFromAAD` property, it allows one to exclude some of the saved object attributes
110+
from Additional authenticated data (AAD), read more about that below in `Encryption and decryption` section.
111+
112+
Since `encrypted_saved_objects` adds its own wrapper (`EncryptedSavedObjectsClientWrapper`) into `SavedObjectsClient`
113+
wrapper chain consumers will be able to create, update, delete and retrieve saved objects using standard Saved Objects API.
114+
Two main responsibilities of the wrapper are:
115+
116+
* It encrypts attributes that are supposed to be encrypted during `create`, `bulkCreate` and `update` operations
117+
* It strips encrypted attributes from **any** saved object returned from the Saved Objects API
118+
119+
As noted above the wrapper is stripping encrypted attributes from saved objects returned from the API methods, that means
120+
that there is no way at all to retrieve encrypted attributes using standard Saved Objects API unless `encrypted_saved_objects`
121+
plugin is disabled. This potentially can lead to the situation when consumer retrieves saved object, updates its non-encrypted
122+
properties and passes that same object to the `update` Saved Objects API method without re-defining encrypted attributes. In
123+
this case only specified attributes will be updated and encrypted attributes will stay untouched. And if these updated
124+
attributes are included into AAD, that is true by default for all attributes unless they are specifically excluded via
125+
`attributesToExcludeFromAAD`, then it will be no longer possible to decrypt encrypted attributes. At this stage we consider
126+
this as a developer mistake and don't prevent it from happening in any way apart from logging this type of event. Partial
127+
update of only attributes that are not the part of AAD will not cause this issue.
128+
129+
Saved object ID is an essential part of AAD used during encryption process and hence should be as hard to guess as possible.
130+
To fulfil this requirement wrapper generates highly random IDs (UUIDv4) for the saved objects that contain encrypted
131+
attributes and hence consumers are not allowed to specify ID when calling `create` or `bulkCreate` method and if they try
132+
to do so the error will be thrown.
133+
134+
To reduce the risk of unintentional decryption and consequent leaking of the sensitive information there is only one way
135+
to retrieve saved object and decrypt its encrypted attributes and it's exposed only through `encrypted_saved_objects` plugin:
136+
137+
```typescript
138+
const savedObject = await server.plugins.encrypted_saved_objects.getDecryptedAsInternalUser(
139+
'server-action',
140+
'dd9750b9-ef0a-444c-8405-4dfcc2e9d670'
141+
);
142+
143+
// savedObject = {
144+
// id: 'dd9750b9-ef0a-444c-8405-4dfcc2e9d670',
145+
// type: 'server-action',
146+
// name: 'my-server-action',
147+
// data: { location: 'BBOX (100.0, ..., 0.0)', email: '<html>...</html>' },
148+
// credentials: { username: 'some-user', password: 'some-password' },
149+
// apiKey: 'dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvb',
150+
// };
151+
```
152+
153+
As can be seen from the method name, the request to retrieve saved object and decrypt its attributes is performed on
154+
behalf of the internal Kibana user and hence isn't supposed to be called within user request context.
155+
156+
**Note:** the fact that saved object with encrypted attributes is created using standard Saved Objects API within a
157+
particular user and space context, but retrieved out of any context makes it unclear how consumers are supposed to
158+
provide that context and retrieve saved object from a particular space. Current plan for `getDecryptedAsInternalUser`
159+
method is to accept a third `BaseOptions` argument that allows consumers to specify `namespace` that they can retrieve
160+
from the request using public `spaces` plugin API.
161+
162+
## Encryption and decryption
163+
164+
Saved object attributes are encrypted using [@elastic/node-crypto](https://github.com/elastic/node-crypto) library. Please
165+
take a look at the source code of this library to know how encryption is performed exactly, what algorithm and encryption
166+
parameters are used, but in short it's AES Encryption with AES-256-GCM that uses random initialization vector and salt.
167+
168+
As with encryption key for Kibana's session cookie, master encryption key used by `encrypted_saved_objects` plugin can be
169+
defined as a configuration value (`xpack.encryptedSavedObjects.encryptionKey`) via `kibana.yml`, but it's **highly
170+
recommended** to define this key in the [Kibana Keystore](https://www.elastic.co/guide/en/kibana/current/secure-settings.html)
171+
instead. The master key should be cryptographically safe and be equal or greater than 32 bytes.
172+
173+
To prevent certain vectors of attacks where raw content of encrypted attributes of one saved object is copied to another
174+
saved object which would unintentionally allow it to decrypt content that was not supposed to be decrypted we rely on Additional
175+
authenticated data (AAD) during encryption and decryption. AAD consists of the following components:
176+
177+
* Saved object ID
178+
* Saved object type
179+
* Saved object attributes
180+
181+
AAD does not include encrypted attributes themselves and attributes defined in optional `attributesToExcludeFromAAD`
182+
parameter provided during saved object type registration with `encrypted_saved_objects` plugin. There are a number of
183+
reasons why one would want to exclude certain attributes from AAD:
184+
185+
* if attribute contains large amount of data that can significantly slow down encryption and decryption, especially during
186+
bulk operations (e.g. large geo shape or arbitrary HTML document)
187+
* if attribute contains data that is supposed to be updated separately from encrypted attributes or attributes included
188+
into AAD (e.g some user defined content associated with the email action or alert)
189+
190+
## Audit
191+
192+
Encrypted attributes will most likely contain sensitive information and any attempt to access these should be properly
193+
logged to allow any further audit procedures. The following events will be logged with Kibana audit log functionality:
194+
195+
* Successful attempt to encrypt attributes (incl. saved object ID, type and attributes names)
196+
* Failed attempt to encrypt attribute (incl. saved object ID, type and attribute name)
197+
* Successful attempt to decrypt attributes (incl. saved object ID, type and attributes names)
198+
* Failed attempt to decrypt attribute (incl. saved object ID, type and attribute name)
199+
200+
In addition to audit log events we'll issue ordinary log events for any attempts to save, update or decrypt saved objects
201+
with missing attributes that were supposed to be encrypted/decrypted based on the registration parameters.
202+
203+
# Benefits
204+
205+
* None of the registered types will expose their encrypted details. The saved
206+
objects with their unencrypted attributes could still be obtained and searched
207+
on. The wrapper will follow all the security and spaces filtering of saved
208+
objects so that only users with appropriate permissions will be able to obtain
209+
the scrubbed objects or _save_ objects with encrypted attributes.
210+
211+
* No explicit access to a method that takes in an encrypted string exists. If the
212+
type was not registered no decryption is possible. No need to handle the saved object
213+
with the encrypted attributes reducing the risk of accidentally returning it in a
214+
handler.
215+
216+
# Drawbacks
217+
218+
* It isn't possible to decrypt existing encrypted attributes once encryption key changes
219+
* Possibly have a performance impact on Saved Objects API operations that require encryption/decryption
220+
* Will require non trivial tests to test functionality along with spaces and security
221+
* The attributes that are encrypted have to be defined and if they change they need to be migrated
222+
223+
# Out of scope
224+
225+
* Encryption key rotation mechanism, either regular or emergency
226+
* Mechanism that would detect and warn when Kibana does not use keystore to store encryption key
227+
228+
# Alternatives
229+
230+
Only allow this to be used within the Actions service itself where the details
231+
of the saved object are handled there directly. And the saved objects are
232+
`hidden` but still use the security and spaces wrappers.
233+
234+
# Adoption strategy
235+
236+
Integration should be pretty easy which would include depending on the plugin, registering the desired saved object type
237+
with it and defining encrypted attributes in the `mappings.json`.
238+
239+
# How we teach this
240+
241+
The `encrypted_saved_objects` as the name of the `thing` where it's seen as a separate
242+
extension on top of the saved object service.
243+
244+
Provide a README.md in the plugin directory with the usage examples.
245+
246+
# Unresolved questions
247+
248+
* Is it acceptable to have this plugin in Basic?
249+
* Are there any other use-cases that are not served with that interface?
250+
* How would this work with Saved Objects Export\Import API?
251+
* How would this work with migrations, if the attribute names wanted to be
252+
changed, a decrypt context would need to be created for migration?

x-pack/plugins/triggers_actions_ui/public/application/components/health_check.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ describe('health check', () => {
9292

9393
const description = queryByRole(/banner/i);
9494
expect(description!.textContent).toMatchInlineSnapshot(
95-
`"To create an alert, set a value for xpack.encrypted_saved_objects.encryptionKey in your kibana.yml file. Learn how."`
95+
`"To create an alert, set a value for xpack.encryptedSavedObjects.encryptionKey in your kibana.yml file. Learn how."`
9696
);
9797

9898
const action = queryByText(/Learn/i);

x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ const EncryptionError = ({
132132
defaultMessage: 'To create an alert, set a value for ',
133133
}
134134
)}
135-
<EuiCode>{'xpack.encrypted_saved_objects.encryptionKey'}</EuiCode>
135+
<EuiCode>{'xpack.encryptedSavedObjects.encryptionKey'}</EuiCode>
136136
{i18n.translate(
137137
'xpack.triggersActionsUI.components.healthCheck.encryptionErrorAfterKey',
138138
{

0 commit comments

Comments
 (0)