mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Replace Encrypted Saved Object AAD exclude list with include list (#167705)
Closes #156023 ## Summary ESO = Encrypted Saved Object(s) This PR modifies the `EncryptedSavedObjectTypeRegistration` definition, replacing the `attributesToExcludeFromAAD` property with a `attributesToIncludeInAAD` property. The purpose is to alter the default inclusion of new SO attributes, which will help to resolve potential decryption issues with serverless zero downtime upgrades (see https://github.com/elastic/kibana/issues/156023). NOTE: nested fields are included when the parent field is added to the include list. In this way the include list behaves just as the exclude list did. #### Attention Code Owners: I attempted to create the include list for existing ESOs by comparing the exclude list to the full list of attributes, ~~however, I am sure this is either incomplete or partially incorrect~~ UPDATE: new tests have been created to validate the include list (see the **Testing** section). These changes will need to be carefully audited by the owning teams during the review process. This PR will not merge until all code owners have reviewed and approved the changes. If your team is a consumer of ESOs, please see the **Testing** section below. ## Testing Automated test suites have been updated to account for the changes to ESO registration. The riskier part of this PR are the changes to existing ESOs, and validating that they are effectively identical to their previous implementations. I have used main branch Kibana to generate several ESOs - one of each type, then saved those raw encrypted objects to an esArchiver JSON file. New functional tests, in the `encrypted_saved_objects_api_integration` suite, have been created to verify that those objects can be successfully decrypted using the new ESO definitions containing the AAD include list. ### ESO Types to Validate See `x-pack/test/encrypted_saved_objects_api_integration/tests/encrypted_saved_objects_aad_include_list.ts` - [x] ACTION_SAVED_OBJECT_TYPE/'action' - [x] ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE/'action_task_params' - [x] CONNECTOR_TOKEN_SAVED_OBJECT_TYPE/'connector_token' - [x] RULE_SAVED_OBJECT_TYPE/'alert' - [x] 'api_key_pending_invalidation' - [x] OUTPUT_SAVED_OBJECT_TYPE/'ingest-outputs - [x] MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE/'fleet-message-signing-keys - [x] UNINSTALL_TOKENS_SAVED_OBJECT_TYPE/'fleet-uninstall-tokens' - [x] syntheticsApiKeyObjectType/'uptime-synthetics-api-key' - [x] syntheticsMonitorType/'synthetics-monitor' - [x] syntheticsParamType/'synthetics-param' ### Flaky Test Runner https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/5419 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com>
This commit is contained in:
parent
8a594a4f96
commit
f214e207e5
23 changed files with 1095 additions and 177 deletions
12
.github/CODEOWNERS
vendored
12
.github/CODEOWNERS
vendored
|
@ -1584,6 +1584,18 @@ packages/react @elastic/appex-sharedux
|
|||
/src/plugins/**/kibana.jsonc @elastic/kibana-core
|
||||
/x-pack/plugins/**/kibana.jsonc @elastic/kibana-core
|
||||
|
||||
# Temporary Encrypted Saved Objects (ESO) guarding
|
||||
# This additional code-ownership is meant to be a temporary precaution to notify the Kibana platform security team
|
||||
# when an encrypted saved object is changed. Very careful review is necessary to ensure any changes are compatible
|
||||
# with serverless zero downtime upgrades (ZDT). This section should be removed only when proper guidance for
|
||||
# maintaining ESOs has been documented and consuming teams have acclimated to ZDT changes.
|
||||
x-pack/plugins/actions/server/saved_objects/index.ts @elastic/response-ops @elastic/kibana-security
|
||||
x-pack/plugins/alerting/server/saved_objects/index.ts @elastic/response-ops @elastic/kibana-security
|
||||
x-pack/plugins/fleet/server/saved_objects/index.ts @elastic/fleet @elastic/kibana-security
|
||||
x-pack/plugins/observability_solution/synthetics/server/saved_objects/saved_objects.ts @elastic/obs-ux-infra_services-team @elastic/kibana-security
|
||||
x-pack/plugins/observability_solution/synthetics/server/saved_objects/synthetics_monitor.ts @elastic/obs-ux-infra_services-team @elastic/kibana-security
|
||||
x-pack/plugins/observability_solution/synthetics/server/saved_objects/synthetics_param.ts @elastic/obs-ux-infra_services-team @elastic/kibana-security
|
||||
|
||||
####
|
||||
## These rules are always last so they take ultimate priority over everything else
|
||||
####
|
||||
|
|
|
@ -113,9 +113,10 @@ export class EsoModelVersionExample implements Plugin<void, void> {
|
|||
aadField1: schema.maybe(schema.object({ flag1: schema.maybe(schema.boolean()) })),
|
||||
secrets: schema.any(),
|
||||
},
|
||||
// 'ignore' will strip any new unknown fields coming from new versions (a zero-downtime upgrade consideration)
|
||||
// We want to do this unless we have a compelling reason not to, like if we know we want to add a new AAD field
|
||||
// in the next version (see model version 2)
|
||||
// 'ignore' will strip any new unknown fields coming from new versions
|
||||
// We want to do this unless we have a compelling reason not to, e.g. in a zero-downtime upgrade scenario
|
||||
// and we know that in the next version we will add a new nested field to an attribute that is already
|
||||
// included in AAD (see model version 2)
|
||||
{ unknowns: 'ignore' }
|
||||
),
|
||||
create: schema.object({
|
||||
|
@ -126,28 +127,36 @@ export class EsoModelVersionExample implements Plugin<void, void> {
|
|||
}),
|
||||
},
|
||||
},
|
||||
inputType: esoModelVersionExampleV1.EsoModelVersionExampleTypeRegistration, // Pass in the type registration for the specific version
|
||||
outputType: esoModelVersionExampleV1.EsoModelVersionExampleTypeRegistration, // In this case both input an output are V1
|
||||
// Pass in the type registration for the specific version. In this case both input and output are V1.
|
||||
inputType: esoModelVersionExampleV1.EsoModelVersionExampleTypeRegistration,
|
||||
outputType: esoModelVersionExampleV1.EsoModelVersionExampleTypeRegistration,
|
||||
shouldTransformIfDecryptionFails: true,
|
||||
}),
|
||||
2: plugins.encryptedSavedObjects.createModelVersion({
|
||||
modelVersion: {
|
||||
changes: [
|
||||
// Version 2 adds additional optional properties (or "sub-fields") to aadField1 and secrets, we're going to back fill them.
|
||||
// Version 2 also adds an optional field aadExcludedField, which is excluded from AAD. This will be stripped out for
|
||||
// older versions during zero-downtime upgrades due to the forwardCompatibility schema in model version 1.
|
||||
// Version 2 adds a new attribute aadField2 which is included in AAD, we're not going to backfill it. During a
|
||||
// zero-downtime upgrade, the previous version of Kibana will not know to include it in AAD based on the wrapped
|
||||
// model version 1 definition. We need to keep it empty in this version, but can backfill it in the next version
|
||||
// safely.
|
||||
|
||||
// Version 2 also adds an additional optional property (or "sub-field") to secrets, an encrypted field, we're
|
||||
// going to backfill it. Note that during a zero-downtime upgrade, the previous version of Kibana needs to be
|
||||
// able to handle additional properties to encrypted attributes gracefully if they are backfilled.
|
||||
|
||||
// Version 2 also adds an optional field aadExcludedField, which is excluded from AAD. This will be stripped out
|
||||
// in older versions during zero-downtime upgrades due to the forwardCompatibility schema in model version 1.
|
||||
{
|
||||
type: 'data_backfill',
|
||||
backfillFn: (doc) => {
|
||||
const aadField1 = doc.attributes.aadField1;
|
||||
const secrets = doc.attributes.secrets;
|
||||
return {
|
||||
attributes: {
|
||||
aadField1: { ...aadField1, flag2: false },
|
||||
secrets: {
|
||||
...secrets,
|
||||
b: "model version 2 adds property 'b' to the secrets attribute",
|
||||
},
|
||||
aadExcludedField: 'model version 2 adds this non-AAD attribute',
|
||||
},
|
||||
};
|
||||
},
|
||||
|
@ -161,17 +170,22 @@ export class EsoModelVersionExample implements Plugin<void, void> {
|
|||
aadField1: schema.maybe(
|
||||
schema.object({
|
||||
flag1: schema.maybe(schema.boolean()),
|
||||
flag2: schema.maybe(schema.boolean()),
|
||||
})
|
||||
),
|
||||
aadField2: schema.maybe(
|
||||
schema.object({
|
||||
foo: schema.maybe(schema.string()),
|
||||
bar: schema.maybe(schema.string()),
|
||||
})
|
||||
),
|
||||
aadExcludedField: schema.maybe(schema.string()),
|
||||
secrets: schema.any(),
|
||||
},
|
||||
// If we know that we will be adding a new AAD field in the next version, we will NOT strip new fields
|
||||
// in the forward compatibility schema. This is a Zero-downtime upgrade consideration and ensures that
|
||||
// old versions will use those fields when constructing AAD. The caveat is that we need to know ahead
|
||||
// of time, and make sure the consuming code can handle having the additional attribute, even if it
|
||||
// is not used yet.
|
||||
// If we know that we will be adding a new property/sub-field to an AAD-included attribute in the next
|
||||
// version, we will choose NOT to strip new fields in the forward compatibility schema. This is a zero-
|
||||
// downtime upgrade consideration and ensures that old versions will use the additionally included
|
||||
// fields when constructing AAD. The caveat is that we need to know ahead of time, and this version of
|
||||
// Kibana (prior to version 3) needs to be able to handle the additional properties gracefully.
|
||||
{ unknowns: 'allow' }
|
||||
),
|
||||
create: schema.object({
|
||||
|
@ -180,7 +194,12 @@ export class EsoModelVersionExample implements Plugin<void, void> {
|
|||
aadField1: schema.maybe(
|
||||
schema.object({
|
||||
flag1: schema.maybe(schema.boolean()),
|
||||
flag2: schema.maybe(schema.boolean()),
|
||||
})
|
||||
),
|
||||
aadField2: schema.maybe(
|
||||
schema.object({
|
||||
foo: schema.maybe(schema.string()),
|
||||
bar: schema.maybe(schema.string()),
|
||||
})
|
||||
),
|
||||
aadExcludedField: schema.maybe(schema.string()),
|
||||
|
@ -188,20 +207,40 @@ export class EsoModelVersionExample implements Plugin<void, void> {
|
|||
}),
|
||||
},
|
||||
},
|
||||
inputType: esoModelVersionExampleV1.EsoModelVersionExampleTypeRegistration, // In this case we are expecting to transform from a V1 object
|
||||
outputType: esoModelVersionExampleV2.EsoModelVersionExampleTypeRegistration, // to a V2 object
|
||||
// In this case we are expecting to transform from a V1 object to a V2 object
|
||||
inputType: esoModelVersionExampleV1.EsoModelVersionExampleTypeRegistration,
|
||||
outputType: esoModelVersionExampleV2.EsoModelVersionExampleTypeRegistration,
|
||||
shouldTransformIfDecryptionFails: true,
|
||||
}),
|
||||
3: plugins.encryptedSavedObjects.createModelVersion({
|
||||
modelVersion: {
|
||||
// Version 3 adds a new attribute aadField2 which is included in AAD, we're not going to back fill it.
|
||||
// For zero-downtime this new attribute is ok, because the previous model version allows unknown fields and will not strip it.
|
||||
// The previous version will include it by default when constructing AAD.
|
||||
// Version 3 removes the toBeRemoved attribute.
|
||||
|
||||
// Version 3 adds an optional field flag2 to the aadField1 attribute, which is included in AAD. As the previous model
|
||||
// version allows unknown fields, we can backill it here.
|
||||
|
||||
// Version 3 also backfills the previously added addField2, which is safe to do now, as the previous model version
|
||||
// has already defined it as an AAD-included field.
|
||||
changes: [
|
||||
{
|
||||
type: 'data_removal',
|
||||
removedAttributePaths: ['toBeRemoved'],
|
||||
},
|
||||
{
|
||||
type: 'data_backfill',
|
||||
backfillFn: (doc) => {
|
||||
const aadField1 = doc.attributes.aadField1;
|
||||
return {
|
||||
attributes: {
|
||||
aadField1: { ...aadField1, flag2: false },
|
||||
aadField2: {
|
||||
foo: 'model version 3 backfills aadField2.foo',
|
||||
bar: 'model version 3 backfills aadField2.bar',
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
schemas: {
|
||||
forwardCompatibility: schema.object(
|
||||
|
@ -244,8 +283,10 @@ export class EsoModelVersionExample implements Plugin<void, void> {
|
|||
}),
|
||||
},
|
||||
},
|
||||
inputType: esoModelVersionExampleV2.EsoModelVersionExampleTypeRegistration, // In this case we are expecting to transform from V2 to V3. This happens to be the latest
|
||||
outputType: esoModelVersionExampleV3.EsoModelVersionExampleTypeRegistration, // version, but being explicit means we don't need to change this when we implement V4
|
||||
// In this case we are expecting to transform from V2 to V3. This happens to be the latest
|
||||
// version, but being explicit means we don't need to change this when we implement V4
|
||||
inputType: esoModelVersionExampleV2.EsoModelVersionExampleTypeRegistration,
|
||||
outputType: esoModelVersionExampleV3.EsoModelVersionExampleTypeRegistration,
|
||||
shouldTransformIfDecryptionFails: true,
|
||||
}),
|
||||
},
|
||||
|
@ -400,10 +441,10 @@ export class EsoModelVersionExample implements Plugin<void, void> {
|
|||
const decrypted = await Promise.all(
|
||||
documentVersionConstants.map(async (obj) => {
|
||||
const parts = obj.id.split(':', 2);
|
||||
const dooder = await esoClient.getDecryptedAsInternalUser(parts[0], parts[1], {
|
||||
const result = await esoClient.getDecryptedAsInternalUser(parts[0], parts[1], {
|
||||
namespace,
|
||||
});
|
||||
return dooder;
|
||||
return result;
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ export interface EsoModelVersionExample {
|
|||
export const EsoModelVersionExampleTypeRegistration: EncryptedSavedObjectTypeRegistration = {
|
||||
type: EXAMPLE_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: new Set(['secrets']),
|
||||
attributesToExcludeFromAAD: new Set(['name', 'toBeRemoved']), // aadField1 is included in AAD, but not name or toBeRemoved
|
||||
attributesToIncludeInAAD: new Set(['aadField1']), // aadField1 is included in AAD, but not name or toBeRemoved
|
||||
};
|
||||
|
||||
// This is just some static information used to generate a document
|
||||
|
|
|
@ -10,10 +10,14 @@ import { EncryptedSavedObjectTypeRegistration } from '@kbn/encrypted-saved-objec
|
|||
|
||||
export const EXAMPLE_SAVED_OBJECT_TYPE = 'eso_model_version_example';
|
||||
|
||||
// V2 adds a new sub-field "flag2"
|
||||
export interface EsoModelVersionExampleOptions1 {
|
||||
flag1?: boolean;
|
||||
flag2?: boolean;
|
||||
}
|
||||
|
||||
// This is a new attribute added in V2
|
||||
export interface EsoModelVersionExampleOptions2 {
|
||||
foo?: string;
|
||||
bar?: string;
|
||||
}
|
||||
|
||||
// V2 adds a new encrypted sub-field "b"
|
||||
|
@ -27,6 +31,7 @@ export interface EsoModelVersionExample {
|
|||
name: string; // Display name attribute. Not part of AAD
|
||||
toBeRemoved: string; // An attribute that will be removed in a later model version.
|
||||
aadField1?: EsoModelVersionExampleOptions1; // Optional attribute that is part of AAD.
|
||||
aadField2?: EsoModelVersionExampleOptions2; // Optional attribute that is part of AAD.
|
||||
aadExcludedField?: string; // Optional attribute that is NOT part of AAD.
|
||||
secrets: EsoModelVersionExampleSecretData; // An encrypted attribute.
|
||||
}
|
||||
|
@ -37,26 +42,29 @@ export interface EsoModelVersionExample {
|
|||
export const EsoModelVersionExampleTypeRegistration: EncryptedSavedObjectTypeRegistration = {
|
||||
type: EXAMPLE_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: new Set(['secrets']),
|
||||
attributesToExcludeFromAAD: new Set(['name', 'toBeRemoved', 'aadExcludedField']), // aadField1 is included in AAD, but not name, toBeRemoved, or aadExcludedField
|
||||
attributesToIncludeInAAD: new Set(['aadField1']), // aadField1 is included in AAD, but not name, toBeRemoved, or aadExcludedField
|
||||
};
|
||||
|
||||
// This is just some static information used to generate a document
|
||||
// for this specific model version. Otherwise, creating a saved object
|
||||
// will always create the latest model version.
|
||||
// secrets: {
|
||||
// a: 'this is a model version 2 object',
|
||||
// b: 'this is a new nested encrypted field',
|
||||
// }
|
||||
export const ESO_MV_RAW_DOC = {
|
||||
index: '.kibana',
|
||||
id: 'eso_model_version_example:52868e00-7dd5-11ee-bc21-35484912189c',
|
||||
id: 'eso_model_version_example:9495eb6f-e356-47f7-a5b9-dce395375cbe',
|
||||
document: {
|
||||
eso_model_version_example: {
|
||||
name: 'MV2 Test',
|
||||
toBeRemoved: 'nothing to see here',
|
||||
aadField1: {
|
||||
flag1: true,
|
||||
flag2: true,
|
||||
},
|
||||
aadExcludedField: 'this will not be used in AAD',
|
||||
aadExcludedField: 'this is a new field excluded from AAD',
|
||||
secrets:
|
||||
'uXBOQpvkI9+lAcfJ52yQAroKIIj+YBT9Ym3IpH1nmPBj2u51tZ07tnPQ3EtO379zHzGOMu+9Da3+bVmDbtsL0z/YrDad3f0o0XSnuEDvmPIVWqC0EwKguik+t63s5LrFvp4r+X3OmsG+jIISx/PXXgLl/8NiWa/urjp649lTGo/k4QvSHyQ4egeM1LjRihFSBFEZkQljF6SJLFocuDlQb8GHkVtgp0pKKfrZu0mI8Q==',
|
||||
'yf9UJyLPfq5iN6oH1mhDQuGX9WRNUnbsN+YDsNDcbCHQAg4N9CC458s+3xwZG/Sm+0GO2o5v+JPUCbkBhuFCNybIdrrzWm00CwHscOYPA4yoLU3blyIMdMzRjClbkKyQNPANOVD7ST1xv5ZAqhujsFI3ascDEVCk+mfBIJbnwOPaohWvsLaMhc0igjpwAeadc8F0cGWg34Nkue0JoaUHxx8CdkComFnwQPK8BER+Wg==',
|
||||
},
|
||||
type: 'eso_model_version_example',
|
||||
references: [],
|
||||
|
@ -64,7 +72,7 @@ export const ESO_MV_RAW_DOC = {
|
|||
namespaces: ['default'],
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: '10.2.0',
|
||||
updated_at: '2023-11-08T01:22:46.112Z',
|
||||
created_at: '2023-11-08T01:22:46.112Z',
|
||||
updated_at: '2023-12-18T18:13:06.568Z',
|
||||
created_at: '2023-12-18T18:13:06.568Z',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -10,12 +10,12 @@ import { EncryptedSavedObjectTypeRegistration } from '@kbn/encrypted-saved-objec
|
|||
|
||||
export const EXAMPLE_SAVED_OBJECT_TYPE = 'eso_model_version_example';
|
||||
|
||||
// V3 adds an additional field 'flag2' to an AAD-included attribute
|
||||
export interface EsoModelVersionExampleOptions1 {
|
||||
flag1?: boolean;
|
||||
flag2?: boolean;
|
||||
}
|
||||
|
||||
// This is a new attribute added in V3
|
||||
export interface EsoModelVersionExampleOptions2 {
|
||||
foo?: string;
|
||||
bar?: string;
|
||||
|
@ -42,15 +42,19 @@ export interface EsoModelVersionExample {
|
|||
export const EsoModelVersionExampleTypeRegistration: EncryptedSavedObjectTypeRegistration = {
|
||||
type: EXAMPLE_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: new Set(['secrets']),
|
||||
attributesToExcludeFromAAD: new Set(['name', 'aadExcludedField']), // aadField1 and aadField2 are included in AAD, but not name, or aadExcludedField
|
||||
attributesToIncludeInAAD: new Set(['aadField1', 'aadField2']), // aadField1 and aadField2 are included in AAD, but not name, or aadExcludedField
|
||||
};
|
||||
|
||||
// This is just some static information used to generate a document
|
||||
// for this specific model version. Otherwise, creating a saved object
|
||||
// will always create the latest model version.
|
||||
// secrets: {
|
||||
// a: 'this is a model version 3 object',
|
||||
// b: 'this property was added in model version 2',
|
||||
// }
|
||||
export const ESO_MV_RAW_DOC = {
|
||||
index: '.kibana',
|
||||
id: 'eso_model_version_example:4b43a8b0-7dd7-11ee-8355-7d13444c2fd7',
|
||||
id: 'eso_model_version_example:bb379c40-8618-4747-9ace-9bb27209e57f',
|
||||
document: {
|
||||
eso_model_version_example: {
|
||||
name: 'MV3 Test',
|
||||
|
@ -59,12 +63,12 @@ export const ESO_MV_RAW_DOC = {
|
|||
flag2: true,
|
||||
},
|
||||
aadField2: {
|
||||
foo: 'bar',
|
||||
bar: 'foo',
|
||||
foo: 'theses were added in model version 2 and',
|
||||
bar: 'are now safe to use in model version 3',
|
||||
},
|
||||
aadExcludedField: 'this is a field excluded from AAD',
|
||||
secrets:
|
||||
'YYtHdisdq44Mvd9VdUui62hM8OowEgkuWSfidWq11lG4aXYR61tf+G+BlbwO6rqKPbFWK238Vn1tP+zceeiCofDqEZkViinT1nGDGjArEEsmIUlDtj5IdaY6boMGRzUJ+37viUrISFXMVV9n2qVMp7IYb2BGkAb3hyh4+ZO9SPTbrKhkcpKgpLs3CEvmfsgeW/Tkxh+F65uK2RShkgLoPy62JI35XUz1paop+zSQ90yPL9ysoQ==',
|
||||
'YQFEVfXtSDBWYjzzvFGC+LkReyAdDOFCyD9UoDdtL83HIFqH3VXb2TnankD4zaP0gralADCyuHOPohVmcBP5fYZ4mVW47aA1uDEP2ORHSGBXjUYNshiZ3+5JxDJRSmgIl0RD4mqAVNa7iQ7j2R+xvCyNG/OzFPw1hythAwv48JLUTXmOsvjJycqKqEkfhWbgvl4R2eZVHGAqsBZaB+J74E8KXGQXL7US+b+Xld/RUxTuhQqGlw==',
|
||||
},
|
||||
type: 'eso_model_version_example',
|
||||
references: [],
|
||||
|
@ -72,7 +76,7 @@ export const ESO_MV_RAW_DOC = {
|
|||
namespaces: ['default'],
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: '10.3.0',
|
||||
updated_at: '2023-11-08T01:36:52.923Z',
|
||||
created_at: '2023-11-08T01:36:52.923Z',
|
||||
updated_at: '2023-12-18T18:34:08.476Z',
|
||||
created_at: '2023-12-18T18:34:08.476Z',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -69,7 +69,7 @@ export function setupSavedObjects(
|
|||
encryptedSavedObjects.registerType({
|
||||
type: ACTION_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: new Set(['secrets']),
|
||||
attributesToExcludeFromAAD: new Set(['name']),
|
||||
attributesToIncludeInAAD: new Set(['actionTypeId', 'isMissingSecrets', 'config']),
|
||||
});
|
||||
|
||||
savedObjects.registerType({
|
||||
|
@ -98,6 +98,14 @@ export function setupSavedObjects(
|
|||
encryptedSavedObjects.registerType({
|
||||
type: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: new Set(['apiKey']),
|
||||
attributesToIncludeInAAD: new Set([
|
||||
'actionId',
|
||||
'consumer',
|
||||
'params',
|
||||
'executionId',
|
||||
'relatedSavedObjects',
|
||||
'source',
|
||||
]),
|
||||
});
|
||||
|
||||
savedObjects.registerType({
|
||||
|
@ -114,5 +122,12 @@ export function setupSavedObjects(
|
|||
encryptedSavedObjects.registerType({
|
||||
type: CONNECTOR_TOKEN_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: new Set(['token']),
|
||||
attributesToIncludeInAAD: new Set([
|
||||
'connectorId',
|
||||
'tokenType',
|
||||
'expiresAt',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
]),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -33,45 +33,57 @@ import { ruleModelVersions } from './rule_model_versions';
|
|||
|
||||
export const RULE_SAVED_OBJECT_TYPE = 'alert';
|
||||
|
||||
// Use caution when removing items from this array! Any field which has
|
||||
// ever existed in the rule SO must be included in this array to prevent
|
||||
// decryption failures during migration.
|
||||
export const RuleAttributesExcludedFromAAD = [
|
||||
'scheduledTaskId',
|
||||
'muteAll',
|
||||
'mutedInstanceIds',
|
||||
'updatedBy',
|
||||
'updatedAt',
|
||||
'executionStatus',
|
||||
'monitoring',
|
||||
'snoozeEndTime', // field removed in 8.2, but must be retained in case an rule created/updated in 8.2 is being migrated
|
||||
'snoozeSchedule',
|
||||
'isSnoozedUntil',
|
||||
'lastRun',
|
||||
'nextRun',
|
||||
'revision',
|
||||
'running',
|
||||
export const RuleAttributesToEncrypt = ['apiKey'];
|
||||
|
||||
// Use caution when removing items from this array! These fields
|
||||
// are used to construct decryption AAD and must be remain in
|
||||
// this array to prevent decryption failures during migration.
|
||||
// NOTE: Always update the RuleAttributesNotPartiallyUpdatable
|
||||
// type if this const changes!
|
||||
export const RuleAttributesIncludedInAAD = [
|
||||
'enabled',
|
||||
'name',
|
||||
'tags',
|
||||
'alertTypeId',
|
||||
'consumer',
|
||||
'legacyId',
|
||||
'schedule',
|
||||
'actions',
|
||||
'params',
|
||||
'mapped_params',
|
||||
'createdBy',
|
||||
'createdAt',
|
||||
'apiKeyOwner',
|
||||
'apiKeyCreatedByUser',
|
||||
'throttle',
|
||||
'notifyWhen',
|
||||
'meta',
|
||||
'alertDelay',
|
||||
];
|
||||
|
||||
// useful for Pick<RawAlert, RuleAttributesExcludedFromAAD> which is a
|
||||
// type which is a subset of RawAlert with just attributes excluded from AAD
|
||||
|
||||
// useful for Pick<RawAlert, RuleAttributesExcludedFromAAD>
|
||||
export type RuleAttributesExcludedFromAADType =
|
||||
| 'scheduledTaskId'
|
||||
| 'muteAll'
|
||||
| 'mutedInstanceIds'
|
||||
| 'updatedBy'
|
||||
| 'updatedAt'
|
||||
| 'executionStatus'
|
||||
| 'monitoring'
|
||||
| 'snoozeEndTime'
|
||||
| 'snoozeSchedule'
|
||||
| 'isSnoozedUntil'
|
||||
| 'lastRun'
|
||||
| 'nextRun'
|
||||
| 'revision'
|
||||
| 'running';
|
||||
// useful type for Omit<RuleAttributes, [...RuleAttributesToEncrypt, ...RuleAttributesIncludedInAAD]>
|
||||
// which will produce a subset of RuleAttributes with just attributes that are safe to partually
|
||||
// update from AAD
|
||||
export type RuleAttributesNotPartiallyUpdatable =
|
||||
| 'apiKey'
|
||||
| 'enabled'
|
||||
| 'name'
|
||||
| 'tags'
|
||||
| 'alertTypeId'
|
||||
| 'consumer'
|
||||
| 'legacyId'
|
||||
| 'schedule'
|
||||
| 'actions'
|
||||
| 'params'
|
||||
| 'mapped_params'
|
||||
| 'createdBy'
|
||||
| 'createdAt'
|
||||
| 'apiKeyOwner'
|
||||
| 'apiKeyCreatedByUser'
|
||||
| 'throttle'
|
||||
| 'notifyWhen'
|
||||
| 'meta'
|
||||
| 'alertDelay';
|
||||
|
||||
export function setupSavedObjects(
|
||||
savedObjects: SavedObjectsServiceSetup,
|
||||
|
@ -149,13 +161,14 @@ export function setupSavedObjects(
|
|||
// Encrypted attributes
|
||||
encryptedSavedObjects.registerType({
|
||||
type: RULE_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: new Set(['apiKey']),
|
||||
attributesToExcludeFromAAD: new Set(RuleAttributesExcludedFromAAD),
|
||||
attributesToEncrypt: new Set(RuleAttributesToEncrypt),
|
||||
attributesToIncludeInAAD: new Set(RuleAttributesIncludedInAAD),
|
||||
});
|
||||
|
||||
// Encrypted attributes
|
||||
encryptedSavedObjects.registerType({
|
||||
type: 'api_key_pending_invalidation',
|
||||
attributesToEncrypt: new Set(['apiKeyId']),
|
||||
attributesToIncludeInAAD: new Set(['createdAt']),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
SavedObjectsErrorHelpers,
|
||||
} from '@kbn/core/server';
|
||||
|
||||
import { partiallyUpdateRule, PartiallyUpdateableRuleAttributes } from './partially_update_rule';
|
||||
import { PartiallyUpdateableRuleAttributes, partiallyUpdateRule } from './partially_update_rule';
|
||||
import { savedObjectsClientMock } from '@kbn/core/server/mocks';
|
||||
import { RULE_SAVED_OBJECT_TYPE } from '.';
|
||||
|
||||
|
@ -39,14 +39,14 @@ describe('partially_update_rule', () => {
|
|||
});
|
||||
|
||||
test('should work with extraneous attributes ', async () => {
|
||||
const attributes = InvalidAttributes as unknown as PartiallyUpdateableRuleAttributes;
|
||||
const attributes = ExtraneousAttributes as unknown as PartiallyUpdateableRuleAttributes;
|
||||
soClient.update.mockResolvedValueOnce(MockUpdateValue);
|
||||
|
||||
await partiallyUpdateRule(soClient, MockRuleId, attributes);
|
||||
expect(soClient.update).toHaveBeenCalledWith(
|
||||
RULE_SAVED_OBJECT_TYPE,
|
||||
MockRuleId,
|
||||
DefaultAttributes,
|
||||
ExtraneousAttributes,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
@ -124,7 +124,7 @@ const DefaultAttributes = {
|
|||
updatedAt: '2019-02-12T21:01:22.479Z',
|
||||
};
|
||||
|
||||
const InvalidAttributes = { ...DefaultAttributes, foo: 'bar' };
|
||||
const ExtraneousAttributes = { ...DefaultAttributes, foo: 'bar' };
|
||||
|
||||
const MockRuleId = 'rule-id';
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { pick } from 'lodash';
|
||||
import { omit, pick } from 'lodash';
|
||||
import {
|
||||
SavedObjectsClient,
|
||||
SavedObjectsErrorHelpers,
|
||||
|
@ -14,13 +14,18 @@ import {
|
|||
import { RawRule } from '../types';
|
||||
|
||||
import {
|
||||
RuleAttributesExcludedFromAAD,
|
||||
RuleAttributesExcludedFromAADType,
|
||||
RuleAttributesToEncrypt,
|
||||
RuleAttributesIncludedInAAD,
|
||||
RuleAttributesNotPartiallyUpdatable,
|
||||
RULE_SAVED_OBJECT_TYPE,
|
||||
} from '.';
|
||||
import { RuleAttributes } from '../data/rule/types';
|
||||
|
||||
// We have calling code that references both RawRule and RuleAttributes,
|
||||
// so we need to support both of these types (they are effectively the same)
|
||||
export type PartiallyUpdateableRuleAttributes = Partial<
|
||||
Pick<RawRule, RuleAttributesExcludedFromAADType>
|
||||
| Omit<RawRule, RuleAttributesNotPartiallyUpdatable>
|
||||
| Omit<RuleAttributes, RuleAttributesNotPartiallyUpdatable>
|
||||
>;
|
||||
|
||||
interface PartiallyUpdateRuleSavedObjectOptions {
|
||||
|
@ -41,9 +46,12 @@ export async function partiallyUpdateRule(
|
|||
attributes: PartiallyUpdateableRuleAttributes,
|
||||
options: PartiallyUpdateRuleSavedObjectOptions = {}
|
||||
): Promise<void> {
|
||||
// ensure we only have the valid attributes excluded from AAD
|
||||
const attributeUpdates = pick(attributes, RuleAttributesExcludedFromAAD);
|
||||
const updateOptions: SavedObjectsUpdateOptions<RawRule> = pick(
|
||||
// ensure we only have the valid attributes that are not encrypted and are excluded from AAD
|
||||
const attributeUpdates = omit(attributes, [
|
||||
...RuleAttributesToEncrypt,
|
||||
...RuleAttributesIncludedInAAD,
|
||||
]);
|
||||
const updateOptions: SavedObjectsUpdateOptions<RuleAttributes> = pick(
|
||||
options,
|
||||
'namespace',
|
||||
'version',
|
||||
|
@ -51,7 +59,7 @@ export async function partiallyUpdateRule(
|
|||
);
|
||||
|
||||
try {
|
||||
await savedObjectsClient.update<RawRule>(
|
||||
await savedObjectsClient.update<RuleAttributes>(
|
||||
RULE_SAVED_OBJECT_TYPE,
|
||||
id,
|
||||
attributeUpdates,
|
||||
|
|
|
@ -180,7 +180,7 @@ savedObjects.registerType({
|
|||
});
|
||||
```
|
||||
|
||||
### Example: Migating a Type
|
||||
### Example: Migrating a Type
|
||||
If your migration needs to change the type by, for example, removing an encrypted field, you will have to specify the legacy type for the input.
|
||||
|
||||
```typescript
|
||||
|
|
|
@ -15,7 +15,7 @@ it('correctly determines attribute properties', () => {
|
|||
EncryptedSavedObjectTypeRegistration,
|
||||
{
|
||||
shouldBeEncrypted: boolean[];
|
||||
shouldBeExcludedFromAAD: boolean[];
|
||||
shouldBeIncludedInAAD: boolean[];
|
||||
shouldBeStripped: boolean[];
|
||||
}
|
||||
]
|
||||
|
@ -27,7 +27,7 @@ it('correctly determines attribute properties', () => {
|
|||
},
|
||||
{
|
||||
shouldBeEncrypted: [true, true, true, true],
|
||||
shouldBeExcludedFromAAD: [true, true, true, true],
|
||||
shouldBeIncludedInAAD: [false, false, false, false],
|
||||
shouldBeStripped: [true, true, true, true],
|
||||
},
|
||||
],
|
||||
|
@ -38,7 +38,7 @@ it('correctly determines attribute properties', () => {
|
|||
},
|
||||
{
|
||||
shouldBeEncrypted: [true, true, false, false],
|
||||
shouldBeExcludedFromAAD: [true, true, false, false],
|
||||
shouldBeIncludedInAAD: [false, false, false, false],
|
||||
shouldBeStripped: [true, true, false, false],
|
||||
},
|
||||
],
|
||||
|
@ -49,7 +49,7 @@ it('correctly determines attribute properties', () => {
|
|||
},
|
||||
{
|
||||
shouldBeEncrypted: [true, true, false, false],
|
||||
shouldBeExcludedFromAAD: [true, true, false, false],
|
||||
shouldBeIncludedInAAD: [false, false, false, false],
|
||||
shouldBeStripped: [true, true, false, false],
|
||||
},
|
||||
],
|
||||
|
@ -57,11 +57,11 @@ it('correctly determines attribute properties', () => {
|
|||
{
|
||||
type: 'so-type',
|
||||
attributesToEncrypt: new Set(['attr#1', 'attr#2']),
|
||||
attributesToExcludeFromAAD: new Set(['attr#3']),
|
||||
attributesToIncludeInAAD: new Set(['attr#4']),
|
||||
},
|
||||
{
|
||||
shouldBeEncrypted: [true, true, false, false],
|
||||
shouldBeExcludedFromAAD: [true, true, true, false],
|
||||
shouldBeIncludedInAAD: [false, false, false, true],
|
||||
shouldBeStripped: [true, true, false, false],
|
||||
},
|
||||
],
|
||||
|
@ -73,11 +73,11 @@ it('correctly determines attribute properties', () => {
|
|||
'attr#2',
|
||||
{ key: 'attr#4', dangerouslyExposeValue: true },
|
||||
]),
|
||||
attributesToExcludeFromAAD: new Set(['attr#3']),
|
||||
attributesToIncludeInAAD: new Set(['attr#3']),
|
||||
},
|
||||
{
|
||||
shouldBeEncrypted: [true, true, false, true],
|
||||
shouldBeExcludedFromAAD: [true, true, true, true],
|
||||
shouldBeIncludedInAAD: [false, false, true, false], // will not include attr#4 because it is to be encrypted
|
||||
shouldBeStripped: [true, true, false, false],
|
||||
},
|
||||
],
|
||||
|
@ -89,11 +89,11 @@ it('correctly determines attribute properties', () => {
|
|||
'attr#2',
|
||||
{ key: 'attr#4', dangerouslyExposeValue: true },
|
||||
]),
|
||||
attributesToExcludeFromAAD: new Set(['some-other-attribute']),
|
||||
attributesToIncludeInAAD: new Set(['attr#3', 'some-other-attribute']),
|
||||
},
|
||||
{
|
||||
shouldBeEncrypted: [true, true, false, true],
|
||||
shouldBeExcludedFromAAD: [true, true, false, true],
|
||||
shouldBeIncludedInAAD: [false, false, true, false],
|
||||
shouldBeStripped: [false, true, false, false],
|
||||
},
|
||||
],
|
||||
|
@ -108,9 +108,25 @@ it('correctly determines attribute properties', () => {
|
|||
expect(typeDefinition.shouldBeStripped(attributeName)).toBe(
|
||||
asserts.shouldBeStripped[attributeIndex]
|
||||
);
|
||||
expect(typeDefinition.shouldBeExcludedFromAAD(attributeName)).toBe(
|
||||
asserts.shouldBeExcludedFromAAD[attributeIndex]
|
||||
expect(typeDefinition.shouldBeIncludedInAAD(attributeName)).toBe(
|
||||
asserts.shouldBeIncludedInAAD[attributeIndex]
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('throws when the same attributes are included in AAD and encrypted', () => {
|
||||
const registration = {
|
||||
type: 'some-type',
|
||||
attributesToEncrypt: new Set(['attr#1', 'attr#3', 'attr#5', 'attr#7']),
|
||||
attributesToIncludeInAAD: new Set(['attr#1', 'attr#2', 'attr#4', 'attr#7']),
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
new EncryptedSavedObjectAttributesDefinition(registration);
|
||||
}).toThrow(
|
||||
new Error(
|
||||
`Invalid EncryptedSavedObjectTypeRegistration for type 'some-type'. attributesToIncludeInAAD must not contain any values in attributesToEncrypt: attr#1,attr#7`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
|
|
@ -9,15 +9,32 @@ import type { EncryptedSavedObjectTypeRegistration } from './encrypted_saved_obj
|
|||
|
||||
/**
|
||||
* Represents the definition of the attributes of the specific saved object that are supposed to be
|
||||
* encrypted. The definition also dictates which attributes should be excluded from AAD and/or
|
||||
* encrypted. The definition also dictates which attributes should be included in AAD and/or
|
||||
* stripped from response.
|
||||
*/
|
||||
export class EncryptedSavedObjectAttributesDefinition {
|
||||
public readonly attributesToEncrypt: ReadonlySet<string>;
|
||||
private readonly attributesToExcludeFromAAD: ReadonlySet<string> | undefined;
|
||||
private readonly attributesToIncludeInAAD: ReadonlySet<string> | undefined;
|
||||
private readonly attributesToStrip: ReadonlySet<string>;
|
||||
|
||||
constructor(typeRegistration: EncryptedSavedObjectTypeRegistration) {
|
||||
if (typeRegistration.attributesToIncludeInAAD) {
|
||||
const invalidAttributeKeys = new Array<string>();
|
||||
typeRegistration.attributesToEncrypt.forEach((attribute) => {
|
||||
const attributeKey = typeof attribute !== 'string' ? attribute.key : attribute;
|
||||
if (typeRegistration.attributesToIncludeInAAD?.has(attributeKey)) {
|
||||
invalidAttributeKeys.push(attributeKey);
|
||||
}
|
||||
});
|
||||
|
||||
if (invalidAttributeKeys.length > 0) {
|
||||
throw new Error(
|
||||
`Invalid EncryptedSavedObjectTypeRegistration for type '${typeRegistration.type}'. ` +
|
||||
`attributesToIncludeInAAD must not contain any values in attributesToEncrypt: ${invalidAttributeKeys}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const attributesToEncrypt = new Set<string>();
|
||||
const attributesToStrip = new Set<string>();
|
||||
for (const attribute of typeRegistration.attributesToEncrypt) {
|
||||
|
@ -34,7 +51,7 @@ export class EncryptedSavedObjectAttributesDefinition {
|
|||
|
||||
this.attributesToEncrypt = attributesToEncrypt;
|
||||
this.attributesToStrip = attributesToStrip;
|
||||
this.attributesToExcludeFromAAD = typeRegistration.attributesToExcludeFromAAD;
|
||||
this.attributesToIncludeInAAD = typeRegistration.attributesToIncludeInAAD;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,14 +64,14 @@ export class EncryptedSavedObjectAttributesDefinition {
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines whether particular attribute should be excluded from AAD.
|
||||
* Determines whether particular attribute should be included in AAD.
|
||||
* @param attributeName Name of the attribute.
|
||||
*/
|
||||
public shouldBeExcludedFromAAD(attributeName: string) {
|
||||
public shouldBeIncludedInAAD(attributeName: string) {
|
||||
return (
|
||||
this.shouldBeEncrypted(attributeName) ||
|
||||
(this.attributesToExcludeFromAAD != null &&
|
||||
this.attributesToExcludeFromAAD.has(attributeName))
|
||||
!this.shouldBeEncrypted(attributeName) &&
|
||||
this.attributesToIncludeInAAD != null &&
|
||||
this.attributesToIncludeInAAD.has(attributeName)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -65,4 +82,20 @@ export class EncryptedSavedObjectAttributesDefinition {
|
|||
public shouldBeStripped(attributeName: string) {
|
||||
return this.attributesToStrip.has(attributeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all attributes (both keys and values) that should contribute to AAD.
|
||||
* @param attributes Attributes of the saved object
|
||||
*/
|
||||
public collectAttributesForAAD(attributes: Record<string, unknown>) {
|
||||
const aadAttributes: Record<string, unknown> = {};
|
||||
if (this.attributesToIncludeInAAD) {
|
||||
for (const attributeKey of this.attributesToIncludeInAAD) {
|
||||
if (!this.shouldBeEncrypted(attributeKey) && Object.hasOwn(attributes, attributeKey)) {
|
||||
aadAttributes[attributeKey] = attributes[attributeKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
return aadAttributes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -508,6 +508,7 @@ describe('#encryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree', 'attrFour']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
const mockUser = mockAuthenticatedUser();
|
||||
|
@ -535,6 +536,7 @@ describe('#encryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree', 'attrFour']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
await expect(
|
||||
|
@ -556,6 +558,7 @@ describe('#encryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
const mockUser = mockAuthenticatedUser();
|
||||
|
@ -575,6 +578,7 @@ describe('#encryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
const mockUser = mockAuthenticatedUser();
|
||||
|
@ -590,18 +594,19 @@ describe('#encryptAttributes', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('does not include specified attributes to AAD', async () => {
|
||||
it('only includes specified attributes in AAD', async () => {
|
||||
const knownType1attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' };
|
||||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
const knownType2attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' };
|
||||
service.registerType({
|
||||
type: 'known-type-2',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToExcludeFromAAD: new Set(['attrTwo']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne']),
|
||||
});
|
||||
|
||||
await expect(
|
||||
|
@ -809,7 +814,7 @@ describe('#decryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToExcludeFromAAD: new Set(['attrOne']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
const encryptedAttributes = await service.encryptAttributes(
|
||||
|
@ -912,6 +917,7 @@ describe('#decryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
const encryptedAttributes = service.encryptAttributesSync(
|
||||
|
@ -955,6 +961,7 @@ describe('#decryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
const encryptedAttributes = service.encryptAttributesSync(
|
||||
|
@ -998,6 +1005,7 @@ describe('#decryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
const encryptedAttributes = service.encryptAttributesSync(
|
||||
|
@ -1124,11 +1132,13 @@ describe('#decryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
service.registerType({
|
||||
type: 'known-type-2',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
encryptedAttributes = await service.encryptAttributes(
|
||||
|
@ -1416,6 +1426,7 @@ describe('#decryptAttributes', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree', 'attrFour']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three', attrFour: null };
|
||||
|
@ -1476,6 +1487,7 @@ describe('#encryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree', 'attrFour']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
expect(
|
||||
|
@ -1500,6 +1512,7 @@ describe('#encryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree', 'attrFour']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
expect(
|
||||
|
@ -1521,6 +1534,7 @@ describe('#encryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
expect(
|
||||
|
@ -1537,6 +1551,7 @@ describe('#encryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
expect(
|
||||
|
@ -1555,13 +1570,14 @@ describe('#encryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
const knownType2attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three' };
|
||||
service.registerType({
|
||||
type: 'known-type-2',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToExcludeFromAAD: new Set(['attrTwo']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne']),
|
||||
});
|
||||
|
||||
expect(
|
||||
|
@ -1747,7 +1763,7 @@ describe('#decryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToExcludeFromAAD: new Set(['attrOne']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
const encryptedAttributes = service.encryptAttributesSync(
|
||||
|
@ -1846,6 +1862,7 @@ describe('#decryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
const encryptedAttributes = service.encryptAttributesSync(
|
||||
|
@ -1889,6 +1906,7 @@ describe('#decryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
const encryptedAttributes = service.encryptAttributesSync(
|
||||
|
@ -1932,6 +1950,7 @@ describe('#decryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
});
|
||||
|
||||
const encryptedAttributes = service.encryptAttributesSync(
|
||||
|
@ -2050,11 +2069,13 @@ describe('#decryptAttributesSync', () => {
|
|||
const type1 = {
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
};
|
||||
|
||||
const type2 = {
|
||||
type: 'known-type-2',
|
||||
attributesToEncrypt: new Set(['attrThree']),
|
||||
attributesToIncludeInAAD: new Set(['attrOne', 'attrTwo']),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -2356,6 +2377,7 @@ describe('#decryptAttributesSync', () => {
|
|||
service.registerType({
|
||||
type: 'known-type-1',
|
||||
attributesToEncrypt: new Set(['attrOne', 'attrThree', 'attrFour']),
|
||||
attributesToIncludeInAAD: new Set(['attrTwo']),
|
||||
});
|
||||
|
||||
const attributes = { attrOne: 'one', attrTwo: 'two', attrThree: 'three', attrFour: null };
|
||||
|
|
|
@ -32,7 +32,7 @@ export interface AttributeToEncrypt {
|
|||
export interface EncryptedSavedObjectTypeRegistration {
|
||||
readonly type: string;
|
||||
readonly attributesToEncrypt: ReadonlySet<string | AttributeToEncrypt>;
|
||||
readonly attributesToExcludeFromAAD?: ReadonlySet<string>;
|
||||
readonly attributesToIncludeInAAD?: ReadonlySet<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -600,12 +600,8 @@ export class EncryptedSavedObjectsService {
|
|||
attributes: Record<string, unknown>
|
||||
) {
|
||||
// Collect all attributes (both keys and values) that should contribute to AAD.
|
||||
const attributesAAD: Record<string, unknown> = {};
|
||||
for (const [attributeKey, attributeValue] of Object.entries(attributes)) {
|
||||
if (!typeDefinition.shouldBeExcludedFromAAD(attributeKey)) {
|
||||
attributesAAD[attributeKey] = attributeValue;
|
||||
}
|
||||
}
|
||||
const attributesAAD: Record<string, unknown> =
|
||||
typeDefinition.collectAttributesForAAD(attributes);
|
||||
|
||||
if (Object.keys(attributesAAD).length === 0) {
|
||||
this.options.logger.debug(
|
||||
|
@ -615,6 +611,7 @@ export class EncryptedSavedObjectsService {
|
|||
);
|
||||
}
|
||||
|
||||
// Always add the descriptor to the AAD.
|
||||
return stringify([...descriptorToArray(descriptor), attributesAAD]);
|
||||
}
|
||||
|
||||
|
|
|
@ -714,41 +714,13 @@ export function registerSavedObjects(savedObjects: SavedObjectsServiceSetup) {
|
|||
});
|
||||
}
|
||||
|
||||
export const OUTPUT_EXLCUDE_AAD_FIELDS = new Set([
|
||||
'output_id',
|
||||
'name',
|
||||
'type',
|
||||
'is_default',
|
||||
'is_default_monitoring',
|
||||
'hosts',
|
||||
'ca_sha256',
|
||||
'ca_trusted_fingerprint',
|
||||
'config',
|
||||
'config_yaml',
|
||||
'is_internal',
|
||||
'is_preconfigured',
|
||||
'proxy_id',
|
||||
'version',
|
||||
'key',
|
||||
'compression',
|
||||
'compression_level',
|
||||
'client_id',
|
||||
'auth_type',
|
||||
'connection_type',
|
||||
'username',
|
||||
'sasl',
|
||||
'partition',
|
||||
'random',
|
||||
'round_robin',
|
||||
'hash',
|
||||
'topic',
|
||||
'topics',
|
||||
'headers',
|
||||
'timeout',
|
||||
'broker_timeout',
|
||||
'required_acks',
|
||||
'preset',
|
||||
'secrets',
|
||||
export const OUTPUT_INCLUDE_AAD_FIELDS = new Set([
|
||||
'service_token',
|
||||
'shipper',
|
||||
'allow_edit',
|
||||
'broker_ack_reliability',
|
||||
'broker_buffer_size',
|
||||
'channel_buffer_size',
|
||||
]);
|
||||
|
||||
export const OUTPUT_ENCRYPTED_FIELDS = new Set([
|
||||
|
@ -762,15 +734,17 @@ export function registerEncryptedSavedObjects(
|
|||
encryptedSavedObjects.registerType({
|
||||
type: OUTPUT_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: OUTPUT_ENCRYPTED_FIELDS,
|
||||
attributesToExcludeFromAAD: OUTPUT_EXLCUDE_AAD_FIELDS,
|
||||
attributesToIncludeInAAD: OUTPUT_INCLUDE_AAD_FIELDS,
|
||||
});
|
||||
// Encrypted saved objects
|
||||
encryptedSavedObjects.registerType({
|
||||
type: MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: new Set(['passphrase']),
|
||||
attributesToIncludeInAAD: new Set(['private_key', 'public_key', 'passphrase_plain']),
|
||||
});
|
||||
encryptedSavedObjects.registerType({
|
||||
type: UNINSTALL_TOKENS_SAVED_OBJECT_TYPE,
|
||||
attributesToEncrypt: new Set(['token']),
|
||||
attributesToIncludeInAAD: new Set(['policy_id', 'token_plain']),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import type { Output } from '../../../common/types';
|
|||
import {
|
||||
getSavedObjectTypes,
|
||||
OUTPUT_ENCRYPTED_FIELDS,
|
||||
OUTPUT_EXLCUDE_AAD_FIELDS,
|
||||
OUTPUT_INCLUDE_AAD_FIELDS,
|
||||
} from '../../saved_objects';
|
||||
import type { OutputSOAttributes } from '../../types';
|
||||
|
||||
|
@ -24,7 +24,7 @@ export const _getFieldsToIncludeEncryptedSO = once(() => {
|
|||
for (const field of Object.keys(
|
||||
getSavedObjectTypes()[OUTPUT_SAVED_OBJECT_TYPE].mappings.properties
|
||||
)) {
|
||||
if (!OUTPUT_EXLCUDE_AAD_FIELDS.has(field)) {
|
||||
if (OUTPUT_INCLUDE_AAD_FIELDS.has(field)) {
|
||||
res.add(field);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import {
|
|||
import { PRIVATE_LOCATIONS_SAVED_OBJECT_TYPE } from './private_locations';
|
||||
import { DYNAMIC_SETTINGS_DEFAULT_ATTRIBUTES } from '../constants/settings';
|
||||
import { DynamicSettingsAttributes } from '../runtime_types/settings';
|
||||
import { ConfigKey } from '../../common/runtime_types';
|
||||
import { UptimeConfig } from '../../common/config';
|
||||
import { settingsObjectId, settingsObjectType } from './uptime_settings';
|
||||
import {
|
||||
|
@ -46,7 +45,7 @@ export const registerUptimeSavedObjects = (
|
|||
encryptedSavedObjects.registerType({
|
||||
type: syntheticsServiceApiKey.name,
|
||||
attributesToEncrypt: new Set(['apiKey']),
|
||||
attributesToExcludeFromAAD: new Set([ConfigKey.ALERT_CONFIG]),
|
||||
attributesToIncludeInAAD: new Set(['id', 'name']),
|
||||
});
|
||||
|
||||
encryptedSavedObjects.registerType(SYNTHETICS_MONITOR_ENCRYPTED_TYPE);
|
||||
|
|
|
@ -13,7 +13,53 @@ import { syntheticsMonitorType } from '../../common/types/saved_objects';
|
|||
import { ConfigKey, LegacyConfigKey, secretKeys } from '../../common/constants/monitor_management';
|
||||
import { monitorMigrations } from './migrations/monitors';
|
||||
|
||||
const legacyConfigKeys = Object.values(LegacyConfigKey);
|
||||
const attributesToIncludeInAAD = new Set([
|
||||
ConfigKey.APM_SERVICE_NAME,
|
||||
ConfigKey.CUSTOM_HEARTBEAT_ID,
|
||||
ConfigKey.CONFIG_ID,
|
||||
ConfigKey.CONFIG_HASH,
|
||||
ConfigKey.ENABLED,
|
||||
ConfigKey.FORM_MONITOR_TYPE,
|
||||
ConfigKey.HOSTS,
|
||||
ConfigKey.IGNORE_HTTPS_ERRORS,
|
||||
ConfigKey.MONITOR_SOURCE_TYPE,
|
||||
ConfigKey.JOURNEY_FILTERS_MATCH,
|
||||
ConfigKey.JOURNEY_FILTERS_TAGS,
|
||||
ConfigKey.JOURNEY_ID,
|
||||
ConfigKey.MAX_REDIRECTS,
|
||||
ConfigKey.MODE,
|
||||
ConfigKey.MONITOR_TYPE,
|
||||
ConfigKey.NAME,
|
||||
ConfigKey.NAMESPACE,
|
||||
ConfigKey.LOCATIONS,
|
||||
ConfigKey.PLAYWRIGHT_OPTIONS,
|
||||
ConfigKey.ORIGINAL_SPACE,
|
||||
ConfigKey.PORT,
|
||||
ConfigKey.PROXY_URL,
|
||||
ConfigKey.PROXY_USE_LOCAL_RESOLVER,
|
||||
ConfigKey.RESPONSE_BODY_INDEX,
|
||||
ConfigKey.RESPONSE_HEADERS_INDEX,
|
||||
ConfigKey.RESPONSE_BODY_MAX_BYTES,
|
||||
ConfigKey.RESPONSE_STATUS_CHECK,
|
||||
ConfigKey.REQUEST_METHOD_CHECK,
|
||||
ConfigKey.REVISION,
|
||||
ConfigKey.SCHEDULE,
|
||||
ConfigKey.SCREENSHOTS,
|
||||
ConfigKey.IPV4,
|
||||
ConfigKey.IPV6,
|
||||
ConfigKey.PROJECT_ID,
|
||||
ConfigKey.TEXT_ASSERTION,
|
||||
ConfigKey.TLS_CERTIFICATE_AUTHORITIES,
|
||||
ConfigKey.TLS_CERTIFICATE,
|
||||
ConfigKey.TLS_VERIFICATION_MODE,
|
||||
ConfigKey.TLS_VERSION,
|
||||
ConfigKey.TAGS,
|
||||
ConfigKey.TIMEOUT,
|
||||
ConfigKey.THROTTLING_CONFIG,
|
||||
ConfigKey.URLS,
|
||||
ConfigKey.WAIT,
|
||||
ConfigKey.MONITOR_QUERY_ID,
|
||||
]);
|
||||
|
||||
export const LEGACY_SYNTHETICS_MONITOR_ENCRYPTED_TYPE = {
|
||||
type: syntheticsMonitorType,
|
||||
|
@ -27,6 +73,25 @@ export const LEGACY_SYNTHETICS_MONITOR_ENCRYPTED_TYPE = {
|
|||
* payload on the `secrets` key. This ensures performant decryption. */
|
||||
...secretKeys,
|
||||
]),
|
||||
attributesToIncludeInAAD: new Set([
|
||||
LegacyConfigKey.SOURCE_ZIP_URL,
|
||||
LegacyConfigKey.SOURCE_ZIP_USERNAME,
|
||||
LegacyConfigKey.SOURCE_ZIP_PASSWORD,
|
||||
LegacyConfigKey.SOURCE_ZIP_FOLDER,
|
||||
LegacyConfigKey.SOURCE_ZIP_PROXY_URL,
|
||||
LegacyConfigKey.ZIP_URL_TLS_CERTIFICATE_AUTHORITIES,
|
||||
LegacyConfigKey.ZIP_URL_TLS_CERTIFICATE,
|
||||
LegacyConfigKey.ZIP_URL_TLS_KEY,
|
||||
LegacyConfigKey.ZIP_URL_TLS_KEY_PASSPHRASE,
|
||||
LegacyConfigKey.ZIP_URL_TLS_VERIFICATION_MODE,
|
||||
LegacyConfigKey.ZIP_URL_TLS_VERSION,
|
||||
LegacyConfigKey.THROTTLING_CONFIG,
|
||||
LegacyConfigKey.IS_THROTTLING_ENABLED,
|
||||
LegacyConfigKey.DOWNLOAD_SPEED,
|
||||
LegacyConfigKey.UPLOAD_SPEED,
|
||||
LegacyConfigKey.LATENCY,
|
||||
...attributesToIncludeInAAD,
|
||||
]),
|
||||
};
|
||||
|
||||
export const SYNTHETICS_MONITOR_ENCRYPTED_TYPE = {
|
||||
|
@ -41,12 +106,7 @@ export const SYNTHETICS_MONITOR_ENCRYPTED_TYPE = {
|
|||
* payload on the `secrets` key. This ensures performant decryption. */
|
||||
...secretKeys,
|
||||
]),
|
||||
attributesToExcludeFromAAD: new Set([
|
||||
ConfigKey.ALERT_CONFIG,
|
||||
ConfigKey.METADATA,
|
||||
ConfigKey.MAX_ATTEMPTS,
|
||||
...legacyConfigKeys,
|
||||
]),
|
||||
attributesToIncludeInAAD,
|
||||
};
|
||||
|
||||
export const getSyntheticsMonitorSavedObjectType = (
|
||||
|
|
|
@ -10,6 +10,7 @@ import { syntheticsParamType } from '../../common/types/saved_objects';
|
|||
export const SYNTHETICS_SECRET_ENCRYPTED_TYPE = {
|
||||
type: syntheticsParamType,
|
||||
attributesToEncrypt: new Set(['value']),
|
||||
attributesToIncludeInAAD: new Set(['key', 'description', 'tags']),
|
||||
};
|
||||
|
||||
export const syntheticsParamSavedObjectType: SavedObjectsType = {
|
||||
|
|
|
@ -0,0 +1,523 @@
|
|||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "fleet-message-signing-keys:15d50edc-e8aa-4856-a5a3-df0188c4f550",
|
||||
"index": ".kibana_ingest",
|
||||
"source": {
|
||||
"fleet-message-signing-keys": {
|
||||
"private_key": "private_key",
|
||||
"public_key": "public_key",
|
||||
"passphrase": "+gMsqYHYbY62vUhjQbz6zVzTwfDC8n5dTkmFHoq7a6OwOvA8XIFfMYgThcnB/vewKbJWl/OCDrckZwuZCfpWjGGkgxUbUafO0FrkYz7vfxJs4tzHKWVpDhR+xio8YGKwoVofZzlGBMe9duAu6nj3BX7B92Q=",
|
||||
"passphrase_plain": "This is the passphrase"
|
||||
},
|
||||
"type": "fleet-message-signing-keys",
|
||||
"references": [],
|
||||
"updated_at": "2023-12-21T22:10:37.254Z",
|
||||
"namespaces": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana_alerting_cases",
|
||||
"id": "alert:5c892f54-c428-496b-b760-075c01b5fcdd",
|
||||
"source": {
|
||||
"alert": {
|
||||
"name": "test_rule",
|
||||
"tags": [],
|
||||
"enabled": true,
|
||||
"alertTypeId": "apm.transaction_error_rate",
|
||||
"consumer": "alerts",
|
||||
"legacyId": "some-legacy-id",
|
||||
"schedule": {
|
||||
"interval": "1m"
|
||||
},
|
||||
"alertDelay": {
|
||||
"active": 1234
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"group": "threshold_met",
|
||||
"params": {
|
||||
"documents": [
|
||||
{
|
||||
"it-worked": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"actionTypeId": ".index",
|
||||
"frequency": {
|
||||
"summary": false,
|
||||
"throttle": null,
|
||||
"notifyWhen": "onActionGroupChange"
|
||||
},
|
||||
"uuid": "974b1bed-4eac-41af-b34a-d751b916d811",
|
||||
"actionRef": "action_0"
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
"threshold": 30,
|
||||
"windowSize": 5,
|
||||
"windowUnit": "m",
|
||||
"environment": "ENVIRONMENT_ALL"
|
||||
},
|
||||
"mapped_params": {
|
||||
"risk_score": 1.23,
|
||||
"severity": "some-severity"
|
||||
},
|
||||
"createdBy": "elastic",
|
||||
"updatedBy": "elastic",
|
||||
"createdAt": "2024-01-16T22:09:07.964Z",
|
||||
"updatedAt": "2024-01-16T22:09:07.964Z",
|
||||
"apiKey": "RfC7Uqq/0mZ7iZou3FCKEtS697YRLrgx3RE/MH87s5RMYJf4KZXjDSsreTJfMIxq2LrStpx9DnYaNSQ4HTWholYqwwheYdnC9+lXWI42aKJat3AibhlpCIeMt1YHZrO+9pqjoAKJE9xtIPA1CPN+5oGTFsgcbe+lb3qCBjx1/jbeBhq7x6vRw0FnALBk58QUdWemYeBH1LRURk/yydk=",
|
||||
"apiKeyOwner": "elastic",
|
||||
"apiKeyCreatedByUser": false,
|
||||
"throttle": "some-throttle-value",
|
||||
"notifyWhen": "onThrottleInterval",
|
||||
"muteAll": false,
|
||||
"mutedInstanceIds": [],
|
||||
"executionStatus": {
|
||||
"status": "ok",
|
||||
"lastExecutionDate": "2024-01-16T22:09:09.482Z",
|
||||
"lastDuration": 1651,
|
||||
"error": null,
|
||||
"warning": null
|
||||
},
|
||||
"monitoring": {
|
||||
"run": {
|
||||
"history": [
|
||||
{
|
||||
"success": true,
|
||||
"timestamp": 1705442949482,
|
||||
"duration": 1651
|
||||
}
|
||||
],
|
||||
"calculated_metrics": {
|
||||
"success_ratio": 1,
|
||||
"p50": 1651,
|
||||
"p95": 1651,
|
||||
"p99": 1651
|
||||
},
|
||||
"last_run": {
|
||||
"timestamp": "2024-01-16T22:09:09.482Z",
|
||||
"metrics": {
|
||||
"duration": 1651,
|
||||
"total_search_duration_ms": null,
|
||||
"total_indexing_duration_ms": null,
|
||||
"total_alerts_detected": null,
|
||||
"total_alerts_created": null,
|
||||
"gap_duration_s": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"snoozeSchedule": [],
|
||||
"revision": 0,
|
||||
"running": false,
|
||||
"meta": {
|
||||
"versionApiKeyLastmodified": "8.13.0"
|
||||
},
|
||||
"scheduledTaskId": "903b890f-4e98-4ea5-bc10-71433f01de18",
|
||||
"lastRun": {
|
||||
"outcome": "succeeded",
|
||||
"outcomeOrder": 0,
|
||||
"outcomeMsg": null,
|
||||
"warning": null,
|
||||
"alertsCount": {
|
||||
"active": 0,
|
||||
"new": 0,
|
||||
"recovered": 0,
|
||||
"ignored": 0
|
||||
}
|
||||
},
|
||||
"nextRun": "2024-01-16T22:10:09.409Z"
|
||||
},
|
||||
"type": "alert",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"namespaces": [
|
||||
"default"
|
||||
],
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"typeMigrationVersion": "10.1.0",
|
||||
"updated_at": "2024-02-22T19:34:13.564Z",
|
||||
"created_at": "2024-02-22T19:34:13.564Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana_alerting_cases",
|
||||
"id": "action:1e78caea-c2d9-47ec-bba5-5b69c211c274",
|
||||
"source": {
|
||||
"action": {
|
||||
"actionTypeId": ".torq",
|
||||
"name": "test-torq-connector",
|
||||
"isMissingSecrets": false,
|
||||
"config": {
|
||||
"webhookIntegrationUrl": "https://hooks.torq.io/v1/hookid"
|
||||
},
|
||||
"secrets": "3BUB4WqB0+RM/ty2XwJLppQWl9o0rzbmdpGGzzMBhWYSM+4uzVesnULPQjHz7mP8EQDrveFip/J+1kdcbQ5OqgdbEpnZt6luK43HJfT3c0A3t9n6V3mkS6o7lLMag41Gs9AJEYLKD140zRdECHkzsXkGIwFBdY6QR0rFt8r95Q=="
|
||||
},
|
||||
"type": "action",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"namespaces": [
|
||||
"default"
|
||||
],
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"typeMigrationVersion": "8.3.0",
|
||||
"updated_at": "2024-01-17T00:04:47.371Z",
|
||||
"created_at": "2024-01-17T00:04:47.371Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana",
|
||||
"id": "synthetics-param:a304e397-723a-495c-a934-126504d53d10",
|
||||
"source": {
|
||||
"synthetics-param": {
|
||||
"key": "test_synthetics_param",
|
||||
"value": "VxVUb6Ic61EO/VYkgTrnhK7YO2aOeJdEjPowQ0SJd0W2S43VdNL+gx1Um5sqi2YaAk1ArP/tJ2Bfdxq4I6u64O5l6p2LHio6RgCb0QwzK7fmY0pS4iRYiPyhWmrZn0Y0qkVonQXsux+nAZWJQv5JZZVm/loAc0jA0kmVTNFUE/K0sjrFnASqH9OAr5Z+kzgGCPkMK4HmP79N8H23",
|
||||
"description": "some description here",
|
||||
"tags": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
]
|
||||
},
|
||||
"type": "synthetics-param",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"namespaces": [
|
||||
"default"
|
||||
],
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"updated_at": "2024-01-18T22:32:44.274Z",
|
||||
"created_at": "2024-01-18T22:32:44.274Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana",
|
||||
"id": "synthetics-monitor:305ea066-0f33-47f2-8d15-2bf82c5ea430",
|
||||
"source": {
|
||||
"synthetics-monitor": {
|
||||
"type": "browser",
|
||||
"form_monitor_type": "multistep",
|
||||
"enabled": true,
|
||||
"alert": {
|
||||
"status": {
|
||||
"enabled": true
|
||||
},
|
||||
"tls": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"schedule": {
|
||||
"unit": "m",
|
||||
"number": "10"
|
||||
},
|
||||
"service.name": "some-service-name",
|
||||
"custom_heartbeat_id": "some-heartbeat-id",
|
||||
"config_id": "85e2583e-d02e-4cff-8b23-a91ae75e8dc2",
|
||||
"tags": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"timeout": 9999,
|
||||
"wait": 200,
|
||||
"name": "localhost",
|
||||
"locations": [
|
||||
{
|
||||
"id": "b9ba5cfb-a676-4e3e-ab74-316ae2d697de",
|
||||
"label": "test_location",
|
||||
"geo": {
|
||||
"lat": 0,
|
||||
"lon": 0
|
||||
},
|
||||
"isServiceManaged": false
|
||||
}
|
||||
],
|
||||
"namespace": "default",
|
||||
"original_space": "some-space",
|
||||
"origin": "ui",
|
||||
"journey_id": "some-journey-id",
|
||||
"hash": "some-hash",
|
||||
"max_redirects": 2,
|
||||
"mode": "some-mode",
|
||||
"id": "85e2583e-d02e-4cff-8b23-a91ae75e8dc2",
|
||||
"max_attempts": 2,
|
||||
"project_id": "some-project-id",
|
||||
"playwright_options": "some-playwright-options",
|
||||
"__ui": {
|
||||
"script_source": {
|
||||
"is_generated_script": false,
|
||||
"file_name": ""
|
||||
}
|
||||
},
|
||||
"url.port": 9555,
|
||||
"proxy_url": "some-proxy-url",
|
||||
"proxy_use_local_resolver": false,
|
||||
"response.include_body": false,
|
||||
"response.include_headers": false,
|
||||
"response.include_body_max_bytes": true,
|
||||
"check.response.status": 200,
|
||||
"check.request.method": "get",
|
||||
"ipv4": "10.10.10.10",
|
||||
"ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
|
||||
"playwright_text_assertion": "some-assertion",
|
||||
"urls": "localhost",
|
||||
"screenshots": "on",
|
||||
"filter_journeys.match": "some-filter-journeys-match",
|
||||
"filter_journeys.tags": [
|
||||
"a",
|
||||
"b",
|
||||
"c"
|
||||
],
|
||||
"ignore_https_errors": false,
|
||||
"throttling": {
|
||||
"value": {
|
||||
"download": "5",
|
||||
"upload": "3",
|
||||
"latency": "20"
|
||||
},
|
||||
"id": "default",
|
||||
"label": "Default"
|
||||
},
|
||||
"ssl.certificate_authorities": "some-ca",
|
||||
"ssl.certificate": "some-certificate",
|
||||
"ssl.verification_mode": "full",
|
||||
"ssl.supported_protocols": [
|
||||
"TLSv1.1",
|
||||
"TLSv1.2",
|
||||
"TLSv1.3"
|
||||
],
|
||||
"revision": 2,
|
||||
"secrets": "hK+lf2dby84QJJm2W9Sml+XdqtzXUZGAcMlRNBP8ta+WjkCRqBc8e2IZaHCVwQsp4YhjPuP2DANk5fbge0fcjR/1BPpenpcRPvglSxTyfcrIYH8LtZ6Jt4Z6D1126101CdDMwtFHVVZhx5g26b4FSd2lr8mtjCda+K6tFbKTk8qhnEx0f+L6PhlFBAYruehfQd6NJFd/Ts4CKk4tHONhpCsGFHL32HUipGgxiDJi3oLMA4+QGAAd/BcsONC6Fh6niRUi7IbCkTxqJgOCHrYtOfuDW8K+0UF2ysgGuhT+fKi7ldL26KI3s2qc60GbQ6+KhUunnTwpE7PpZjqmELxHBusq4p+Q/zjK4IUBNFEvFJihA9AraCRqtSI6ckho1qpy0ny/TX7H2hyYibgiFyxW0OeHd13Y195vs0DArHik+BafZGnXfx+S2m/GYVGnTSY8X1VevhWeEuMzOE7OC703uGwzUns3/fmGwqQwk/7xnnU6slIcYIP38yqDBbnuFdTyREumNA=="
|
||||
},
|
||||
"type": "synthetics-monitor",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"typeMigrationVersion": "8.9.0",
|
||||
"updated_at": "2024-01-19T00:13:32.522Z",
|
||||
"created_at": "2024-01-19T00:13:32.522Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana_alerting_cases",
|
||||
"id": "connector_token:601750d9-a82a-4344-ac5c-badfbe12a4ca",
|
||||
"source": {
|
||||
"connector_token": {
|
||||
"connectorId": "connector-id",
|
||||
"token": "ToodRP10TblHckqc9mIGKv4hWUN/rjhzP2OW4j41/z4V4HLSMGJGd6LknngRK7il+8nvMh2pvWJCA/6iIdM62+GAqJZlaHy4gOJnxb62J8ucolZxmmSX2AL1Fsn+6BaIVtegxDt82fdm4S94ANlpwzt9JvshB20vm32vkZrDl74/E9pwtHSsyz+b6s2iyLfELoo2feo=",
|
||||
"expiresAt": "9999",
|
||||
"tokenType": "access_token",
|
||||
"createdAt": "2024-01-17T16:27:21.181Z",
|
||||
"updatedAt": "2024-01-17T16:27:21.181Z"
|
||||
},
|
||||
"type": "connector_token",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"updated_at": "2024-01-17T16:27:21.181Z",
|
||||
"created_at": "2024-01-17T16:27:21.181Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana_ingest",
|
||||
"id": "ingest-outputs:e7e5ea1b-8342-45f3-8051-1bc1448fd923",
|
||||
"source": {
|
||||
"ingest-outputs": {
|
||||
"service_token": "some-service-token",
|
||||
"shipper": {
|
||||
"prop1": "a",
|
||||
"prop2": "b"
|
||||
},
|
||||
"allow_edit": false,
|
||||
"broker_ack_reliability": "some-value",
|
||||
"broker_buffer_size": 100,
|
||||
"channel_buffer_size": 100,
|
||||
"name": "test_kafka_output",
|
||||
"type": "kafka",
|
||||
"hosts": [
|
||||
"localhost:9092"
|
||||
],
|
||||
"is_default": false,
|
||||
"is_default_monitoring": false,
|
||||
"config_yaml": "",
|
||||
"proxy_id": null,
|
||||
"client_id": "Elastic",
|
||||
"version": "1.0.0",
|
||||
"key": "some-key",
|
||||
"compression": "none",
|
||||
"auth_type": "user_pass",
|
||||
"username": "some-username",
|
||||
"sasl": {
|
||||
"mechanism": "PLAIN"
|
||||
},
|
||||
"partition": "random",
|
||||
"random": {
|
||||
"group_events": 1
|
||||
},
|
||||
"topics": [
|
||||
{
|
||||
"topic": "some topic"
|
||||
}
|
||||
],
|
||||
"headers": [
|
||||
{
|
||||
"key": "",
|
||||
"value": ""
|
||||
}
|
||||
],
|
||||
"timeout": 30,
|
||||
"broker_timeout": 30,
|
||||
"required_acks": 1,
|
||||
"ssl": "QxjwNqSXWYqkJmZkgn9o4jBvzu6JIvqatP2F+CH3zPSF9fLSLBp7Q6PRWjztmuKv0Uq6Q+BrZRM4rE7OTt2wQoYrhtRETzQsxWWXXDD9B2Ph7ivUqlRiZmXLSERNYDPYlWspRDlv8e5gcncV8WUyinJAnRucNZuFQBvH1H+L7CkwpuVOG8avoiaJ00ZEn93AruSMxvPdTDfd+YIOjrcrE/ReU4fxith794adlLDDubN5vblbvBM0O4fsGjAoYxjNpWdOm9GvoxTDDw9v1QM9FLwV2i1FAYSVXLc69OWnd5s=",
|
||||
"password": "xtsCxu6mdPQxLusMO6pkfM3yriLyt+8/9pn3BHcc5qce4wYjrdWhRsyyMcMSR/DUwfZzmWXDNT3uYUxeegbMzDwypqCcgYyGl85jB6ekUOJeGkokfW0vl130Xk7TccY6wjlyzMVC61PWavNLfaaEOEdGktKcx+6Tn+syxAc734puI0wMGxgyenMX+lkXqXEW4TYZ27hOthWwKSW35V/m"
|
||||
},
|
||||
"type": "ingest-outputs",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"typeMigrationVersion": "10.4.0",
|
||||
"updated_at": "2024-01-23T03:10:45.098Z",
|
||||
"created_at": "2024-01-23T03:10:45.098Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana_ingest",
|
||||
"id": "fleet-uninstall-tokens:1db22a8f-4cbb-415d-90d1-7608a6923ba1",
|
||||
"source": {
|
||||
"fleet-uninstall-tokens": {
|
||||
"policy_id": "some-policy-id",
|
||||
"token": "eIGQf+EuprdGJlLunhXdvPoDO1NCLG3RtsbhVjWLbRuG+/YmNa8GFyD6924nwNJOND8900YQjT1sGInpQI3rLTC6KX0fthjlBk2RWElyndlnE6jga140dGNf++cbrY1d2c1k6JYPb+SjGs9VEfHQlrM9RpAFx8ZRUGHEbzgGCsaGVcNUZdB0G4A0UFrLSkcme2ICNgxp/qS0xU+0",
|
||||
"token_plain": "This token was encrypted prior to the AAD include list change."
|
||||
},
|
||||
"type": "fleet-uninstall-tokens",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"updated_at": "2024-01-17T18:19:50.628Z",
|
||||
"created_at": "2024-01-17T18:19:50.628Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana",
|
||||
"id": "uptime-synthetics-api-key:b448dffe-6e9c-4032-aa9a-5d9446531b83",
|
||||
"source": {
|
||||
"uptime-synthetics-api-key": {
|
||||
"id": "some-id",
|
||||
"name": "some-name",
|
||||
"apiKey": "iqDazOl7MJ5ZAMFGm5p8palEp72ZYIEdNVfmd+WPVfpak61HiOZZx3HmeNaFZa6yviAWm+ES6e2PNKAOPRKmvPWbnQfSXI2Eww2zC+st7RrzNEEGiU7j2w4h+tgCfvGco8CiQZIGZ9dhViOW32p6nsKiuo8P9dRIEdYJA7zPU3oilA4oAz87DTAO3rmdn2dCQqqyOUuEDPL+ytpCyMY="
|
||||
},
|
||||
"type": "uptime-synthetics-api-key",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"updated_at": "2024-01-17T22:27:14.580Z",
|
||||
"created_at": "2024-01-17T22:27:14.580Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana_alerting_cases",
|
||||
"id": "api_key_pending_invalidation:e67824d0-b428-47c7-be46-fd4e2021519f",
|
||||
"source": {
|
||||
"api_key_pending_invalidation": {
|
||||
"createdAt": "2024-02-08T19:10:37.114Z",
|
||||
"apiKeyId": "QXdPIxu0RSFEr2g0n0F/adxDeiu5hR4+CAnX/OvW59oJwTs3knvVxnPttXfcNR8V2fE3btEN5wwXh+fgZ+ADZ3E/fbFxz1Op8tToYWlSheZX3RennPgfnfi5f99edg0FWtAf0TU2FlBnAqzmDrxzhA+q6m3mj4/hzZKuJI2ghuECWJFj0wMLQ6ZDdCLOdRrX5MU7Enxtqvue7uZGboJxEoA="
|
||||
},
|
||||
"type": "api_key_pending_invalidation",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"updated_at": "2024-02-08T19:10:37.114Z",
|
||||
"created_at": "2024-02-08T19:10:37.114Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": ".kibana_alerting_cases",
|
||||
"id": "action_task_params:248408b1-b3b0-46a0-80fa-e2b6fbc9085d",
|
||||
"source": {
|
||||
"action_task_params": {
|
||||
"apiKey": "UI4MwCfF2yw1h+JQMEEFu18HI0ebFrGxbgKFA76YHKLOdpG9PY4oG5h+ctJjVlyUtcv8+DGnnvpjmxWErJxSe9ni8aQn9cBEZAqScOt1V7eZ5JB2fUVQxFIkrTmOG20vih1OSjaZl4tm55vziSXnvnQapksFWaQGQuIp1c2EasBESHrx9FTgpnUR7UvULYx3eNeQHIvenB030c8gDwg=",
|
||||
"actionId": "some-action-id",
|
||||
"consumer": "some-consumer",
|
||||
"params": {
|
||||
"param1": "a",
|
||||
"param2": "b",
|
||||
"param3": "c"
|
||||
},
|
||||
"executionId": "some-exe-id",
|
||||
"relatedSavedObjects": [
|
||||
{
|
||||
"namespace": "default",
|
||||
"id": "obj1-id",
|
||||
"type": "obj1-type"
|
||||
},
|
||||
{
|
||||
"namespace": "default",
|
||||
"id": "obj2-id",
|
||||
"type": "obj2-type",
|
||||
"typeId": "some-type-id"
|
||||
},
|
||||
{
|
||||
"namespace": "default",
|
||||
"id": "obj3-id",
|
||||
"type": "obj3-type"
|
||||
}
|
||||
],
|
||||
"source": "SAVED_OBJECT"
|
||||
},
|
||||
"type": "action_task_params",
|
||||
"references": [],
|
||||
"managed": false,
|
||||
"namespaces": [
|
||||
"default"
|
||||
],
|
||||
"coreMigrationVersion": "8.8.0",
|
||||
"typeMigrationVersion": "8.0.0",
|
||||
"updated_at": "2024-02-08T15:31:13.593Z",
|
||||
"created_at": "2024-02-08T15:31:13.593Z"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -78,7 +78,7 @@ export const plugin: PluginInitializer<void, void, PluginsSetup, PluginsStart> =
|
|||
'privateProperty',
|
||||
{ key: 'publicPropertyStoredEncrypted', dangerouslyExposeValue: true },
|
||||
]),
|
||||
attributesToExcludeFromAAD: new Set(['publicPropertyExcludedFromAAD']),
|
||||
attributesToIncludeInAAD: new Set(['publicProperty']),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -164,12 +164,14 @@ function defineTypeWithMigration(core: CoreSetup<PluginsStart>, deps: PluginsSet
|
|||
const typePriorTo790 = {
|
||||
type: SAVED_OBJECT_WITH_MIGRATION_TYPE,
|
||||
attributesToEncrypt: new Set(['encryptedAttribute']),
|
||||
attributesToIncludeInAAD: new Set(['nonEncryptedAttribute']), // No attributes were excluded previously, so we have to add this
|
||||
};
|
||||
|
||||
// current type is registered
|
||||
deps.encryptedSavedObjects.registerType({
|
||||
type: SAVED_OBJECT_WITH_MIGRATION_TYPE,
|
||||
attributesToEncrypt: new Set(['encryptedAttribute', 'additionalEncryptedAttribute']),
|
||||
attributesToIncludeInAAD: new Set(['nonEncryptedAttribute']), // No attributes were excluded previously, so we have to add this
|
||||
});
|
||||
|
||||
core.savedObjects.registerType({
|
||||
|
@ -261,11 +263,13 @@ function defineModelVersionWithMigration(core: CoreSetup<PluginsStart>, deps: Pl
|
|||
const typePriorTo810 = {
|
||||
type: SAVED_OBJECT_MV_TYPE,
|
||||
attributesToEncrypt: new Set(['encryptedAttribute']),
|
||||
attributesToIncludeInAAD: new Set(['nonEncryptedAttribute']),
|
||||
};
|
||||
|
||||
const latestType = {
|
||||
type: SAVED_OBJECT_MV_TYPE,
|
||||
attributesToEncrypt: new Set(['encryptedAttribute', 'additionalEncryptedAttribute']),
|
||||
attributesToIncludeInAAD: new Set(['nonEncryptedAttribute']),
|
||||
};
|
||||
deps.encryptedSavedObjects.registerType(latestType);
|
||||
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { MAIN_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server';
|
||||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const es = getService('es');
|
||||
|
||||
describe('encrypted saved objects decryption', () => {
|
||||
// This test uses esArchiver to load snapshots of encrypted objects which were captured from the main branch prior to
|
||||
// the AAD include list change. It then uses get-decrypted-as-internal-user to attempt to decrypt each encrypted object.
|
||||
describe('aad exclude list to include list', () => {
|
||||
before(async () => {
|
||||
await es.indices.putMapping({ index: MAIN_SAVED_OBJECT_INDEX, dynamic: true });
|
||||
await esArchiver.load(
|
||||
'x-pack/test/encrypted_saved_objects_api_integration/fixtures/es_archiver/encrypted_saved_objects_pre_aad_change'
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload(
|
||||
'x-pack/test/encrypted_saved_objects_api_integration/fixtures/es_archiver/encrypted_saved_objects_pre_aad_change'
|
||||
);
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'action' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/action/1e78caea-c2d9-47ec-bba5-5b69c211c274`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
expect(decryptedObject.attributes.secrets).to.eql({ token: 'some-random-token-value' });
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'action_task_params' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/action_task_params/248408b1-b3b0-46a0-80fa-e2b6fbc9085d`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
expect(decryptedObject.attributes.apiKey).to.eql(
|
||||
'This api key was encrypted prior to the AAD include list change.'
|
||||
);
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'connector_token' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/connector_token/601750d9-a82a-4344-ac5c-badfbe12a4ca`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
expect(decryptedObject.attributes.token).to.eql(
|
||||
'Token value encrypted prior to AAD include list change.'
|
||||
);
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'alert' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/alert/5c892f54-c428-496b-b760-075c01b5fcdd`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
expect(decryptedObject.attributes.apiKey).to.eql(
|
||||
'This api key was encrypted prior to the AAD include list change.'
|
||||
);
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'api_key_pending_invalidation' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/api_key_pending_invalidation/e67824d0-b428-47c7-be46-fd4e2021519f`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
expect(decryptedObject.attributes.apiKeyId).to.eql(
|
||||
'This api key id was encrypted prior to the AAD include list change.'
|
||||
);
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'ingest-outputs' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/ingest-outputs/e7e5ea1b-8342-45f3-8051-1bc1448fd923`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
const ssl = JSON.parse(decryptedObject.attributes.ssl);
|
||||
expect(ssl).to.eql({
|
||||
certificate_authorities: [
|
||||
'This SSL CA was encrypted prior to the AAD include list change.',
|
||||
],
|
||||
verification_mode: 'full',
|
||||
});
|
||||
expect(decryptedObject.attributes.password).to.eql(
|
||||
'This password was encrypted prior to the AAD include list change.'
|
||||
);
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'fleet-message-signing-keys' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/fleet-message-signing-keys/15d50edc-e8aa-4856-a5a3-df0188c4f550`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
expect(decryptedObject.attributes.passphrase).to.eql('This is the passphrase');
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'fleet-uninstall-tokens' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/fleet-uninstall-tokens/1db22a8f-4cbb-415d-90d1-7608a6923ba1`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
expect(decryptedObject.attributes.token).to.eql(
|
||||
'This token was encrypted prior to the AAD include list change.'
|
||||
);
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'uptime-synthetics-api-key' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/uptime-synthetics-api-key/b448dffe-6e9c-4032-aa9a-5d9446531b83`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
expect(decryptedObject.attributes.apiKey).to.eql(
|
||||
'This api key was encrypted prior to the AAD include list change.'
|
||||
);
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'synthetics-monitor' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/synthetics-monitor/305ea066-0f33-47f2-8d15-2bf82c5ea430`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
const secrets = JSON.parse(decryptedObject.attributes.secrets);
|
||||
expect(secrets).to.eql({
|
||||
params: 'some-params',
|
||||
'source.inline.script': `step('Go to localhost', async () => {\n await page.goto('localhost');\n});`,
|
||||
'source.project.content': '',
|
||||
synthetics_args: ['param1', 'param2', 'param3'],
|
||||
'ssl.key': 'some-ssl-key',
|
||||
'ssl.key_passphrase': 'some-passphrase',
|
||||
});
|
||||
});
|
||||
|
||||
it(`successfully decrypts 'synthetics-param' objects`, async () => {
|
||||
const decryptResponse = await supertest
|
||||
.get(
|
||||
`/api/hidden_saved_objects/get-decrypted-as-internal-user/synthetics-param/a304e397-723a-495c-a934-126504d53d10`
|
||||
)
|
||||
.expect(200);
|
||||
|
||||
const decryptedObject = JSON.parse(decryptResponse.text);
|
||||
expect(decryptedObject.attributes.value).to.eql(
|
||||
'This value was encrypted prior to the AAD include list change.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -11,5 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
|
|||
describe('encryptedSavedObjects', function encryptedSavedObjectsSuite() {
|
||||
loadTestFile(require.resolve('./encrypted_saved_objects_api'));
|
||||
loadTestFile(require.resolve('./encrypted_saved_objects_decryption'));
|
||||
loadTestFile(require.resolve('./encrypted_saved_objects_aad_include_list'));
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue