mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Security Solution][Upgrade] Add tag for disabled rules on upgrade (#125448)
* Add tag for disabled rules on upgrade * Resiliency * Restore 8.0 AAD migration and add 8.0.1 migration for auto-disabled tags * Add integration test for migration Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
485ab50302
commit
8f03c791e0
5 changed files with 413 additions and 15 deletions
|
@ -2063,31 +2063,172 @@ describe('successful migrations', () => {
|
|||
{ params: { outputIndex: 'output-index', type: 'query' }, alertTypeId: 'not.siem.signals' },
|
||||
true
|
||||
);
|
||||
expect(migration800(alert, migrationContext).attributes.alertTypeId).toEqual(
|
||||
'not.siem.signals'
|
||||
);
|
||||
expect(migration800(alert, migrationContext).attributes.enabled).toEqual(true);
|
||||
expect(migration800(alert, migrationContext).attributes.params.outputIndex).toEqual(
|
||||
'output-index'
|
||||
);
|
||||
const migratedAlert = migration800(alert, migrationContext);
|
||||
expect(migratedAlert.attributes.alertTypeId).toEqual('not.siem.signals');
|
||||
expect(migratedAlert.attributes.enabled).toEqual(true);
|
||||
expect(migratedAlert.attributes.tags).toEqual(['foo']);
|
||||
expect(migratedAlert.attributes.params.outputIndex).toEqual('output-index');
|
||||
});
|
||||
|
||||
test.each(Object.keys(ruleTypeMappings) as RuleType[])(
|
||||
'Changes AAD rule params accordingly if rule is a siem.signals %p rule',
|
||||
'changes AAD rule params accordingly if rule is a siem.signals %p rule',
|
||||
(ruleType) => {
|
||||
const migration800 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['8.0.0'];
|
||||
const alert = getMockData(
|
||||
{ params: { outputIndex: 'output-index', type: ruleType }, alertTypeId: 'siem.signals' },
|
||||
true
|
||||
);
|
||||
expect(migration800(alert, migrationContext).attributes.alertTypeId).toEqual(
|
||||
ruleTypeMappings[ruleType]
|
||||
);
|
||||
expect(migration800(alert, migrationContext).attributes.enabled).toEqual(false);
|
||||
expect(migration800(alert, migrationContext).attributes.params.outputIndex).toEqual('');
|
||||
const migratedAlert = migration800(alert, migrationContext);
|
||||
expect(migratedAlert.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]);
|
||||
expect(migratedAlert.attributes.enabled).toEqual(false);
|
||||
expect(migratedAlert.attributes.tags).toEqual(['foo']);
|
||||
expect(migratedAlert.attributes.params.outputIndex).toEqual('');
|
||||
}
|
||||
);
|
||||
|
||||
describe('8.0.1', () => {
|
||||
describe.each(Object.keys(ruleTypeMappings) as RuleType[])(
|
||||
'auto_disabled %p rule tags',
|
||||
(ruleType) => {
|
||||
const alert717Enabled = getMockData(
|
||||
{
|
||||
params: { outputIndex: 'output-index', type: ruleType },
|
||||
alertTypeId: 'siem.signals',
|
||||
enabled: true,
|
||||
scheduledTaskId: 'abcd',
|
||||
},
|
||||
true
|
||||
);
|
||||
const alert717Disabled = getMockData(
|
||||
{
|
||||
params: { outputIndex: 'output-index', type: ruleType },
|
||||
alertTypeId: 'siem.signals',
|
||||
enabled: false,
|
||||
},
|
||||
true
|
||||
);
|
||||
const alert800 = getMockData(
|
||||
{
|
||||
params: { outputIndex: '', type: ruleType },
|
||||
alertTypeId: ruleTypeMappings[ruleType],
|
||||
enabled: false,
|
||||
scheduledTaskId: 'abcd',
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
test('Does not update rule tags if rule has already been enabled', () => {
|
||||
const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured);
|
||||
const migration800 = migrations['8.0.0'];
|
||||
const migration801 = migrations['8.0.1'];
|
||||
|
||||
// migrate to 8.0.0
|
||||
const migratedAlert800 = migration800(alert717Enabled, migrationContext);
|
||||
expect(migratedAlert800.attributes.enabled).toEqual(false);
|
||||
|
||||
// reenable rule
|
||||
migratedAlert800.attributes.enabled = true;
|
||||
|
||||
// migrate to 8.0.1
|
||||
const migratedAlert801 = migration801(migratedAlert800, migrationContext);
|
||||
|
||||
expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]);
|
||||
expect(migratedAlert801.attributes.enabled).toEqual(true);
|
||||
expect(migratedAlert801.attributes.params.outputIndex).toEqual('');
|
||||
|
||||
// tags not updated
|
||||
expect(migratedAlert801.attributes.tags).toEqual(['foo']);
|
||||
});
|
||||
|
||||
test('Does not update rule tags if rule was already disabled before upgrading to 8.0', () => {
|
||||
const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured);
|
||||
const migration800 = migrations['8.0.0'];
|
||||
const migration801 = migrations['8.0.1'];
|
||||
|
||||
// migrate to 8.0.0
|
||||
const migratedAlert800 = migration800(alert717Disabled, migrationContext);
|
||||
expect(migratedAlert800.attributes.enabled).toEqual(false);
|
||||
|
||||
// migrate to 8.0.1
|
||||
const migratedAlert801 = migration801(migratedAlert800, migrationContext);
|
||||
|
||||
expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]);
|
||||
expect(migratedAlert801.attributes.enabled).toEqual(false);
|
||||
expect(migratedAlert801.attributes.params.outputIndex).toEqual('');
|
||||
|
||||
// tags not updated
|
||||
expect(migratedAlert801.attributes.tags).toEqual(['foo']);
|
||||
});
|
||||
|
||||
test('Updates rule tags if rule was auto-disabled in 8.0 upgrade and not reenabled', () => {
|
||||
const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured);
|
||||
const migration800 = migrations['8.0.0'];
|
||||
const migration801 = migrations['8.0.1'];
|
||||
|
||||
// migrate to 8.0.0
|
||||
const migratedAlert800 = migration800(alert717Enabled, migrationContext);
|
||||
expect(migratedAlert800.attributes.enabled).toEqual(false);
|
||||
|
||||
// migrate to 8.0.1
|
||||
const migratedAlert801 = migration801(migratedAlert800, migrationContext);
|
||||
|
||||
expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]);
|
||||
expect(migratedAlert801.attributes.enabled).toEqual(false);
|
||||
expect(migratedAlert801.attributes.params.outputIndex).toEqual('');
|
||||
|
||||
// tags updated
|
||||
expect(migratedAlert801.attributes.tags).toEqual(['foo', 'auto_disabled_8.0']);
|
||||
});
|
||||
|
||||
test('Updates rule tags correctly if tags are undefined', () => {
|
||||
const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured);
|
||||
const migration801 = migrations['8.0.1'];
|
||||
|
||||
const alert = {
|
||||
...alert800,
|
||||
attributes: {
|
||||
...alert800.attributes,
|
||||
tags: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
// migrate to 8.0.1
|
||||
const migratedAlert801 = migration801(alert, migrationContext);
|
||||
|
||||
expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]);
|
||||
expect(migratedAlert801.attributes.enabled).toEqual(false);
|
||||
expect(migratedAlert801.attributes.params.outputIndex).toEqual('');
|
||||
|
||||
// tags updated
|
||||
expect(migratedAlert801.attributes.tags).toEqual(['auto_disabled_8.0']);
|
||||
});
|
||||
|
||||
test('Updates rule tags correctly if tags are null', () => {
|
||||
const migrations = getMigrations(encryptedSavedObjectsSetup, isPreconfigured);
|
||||
const migration801 = migrations['8.0.1'];
|
||||
|
||||
const alert = {
|
||||
...alert800,
|
||||
attributes: {
|
||||
...alert800.attributes,
|
||||
tags: null,
|
||||
},
|
||||
};
|
||||
|
||||
// migrate to 8.0.1
|
||||
const migratedAlert801 = migration801(alert, migrationContext);
|
||||
|
||||
expect(migratedAlert801.attributes.alertTypeId).toEqual(ruleTypeMappings[ruleType]);
|
||||
expect(migratedAlert801.attributes.enabled).toEqual(false);
|
||||
expect(migratedAlert801.attributes.params.outputIndex).toEqual('');
|
||||
|
||||
// tags updated
|
||||
expect(migratedAlert801.attributes.tags).toEqual(['auto_disabled_8.0']);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('Metrics Inventory Threshold rule', () => {
|
||||
test('Migrates incorrect action group spelling', () => {
|
||||
const migration800 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['8.0.0'];
|
||||
|
|
|
@ -58,6 +58,9 @@ export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc<RawRu
|
|||
export const isSiemSignalsRuleType = (doc: SavedObjectUnsanitizedDoc<RawRule>): boolean =>
|
||||
doc.attributes.alertTypeId === 'siem.signals';
|
||||
|
||||
export const isDetectionEngineAADRuleType = (doc: SavedObjectUnsanitizedDoc<RawRule>): boolean =>
|
||||
(Object.values(ruleTypeMappings) as string[]).includes(doc.attributes.alertTypeId);
|
||||
|
||||
/**
|
||||
* Returns true if the alert type is that of "siem.notifications" which is a legacy notification system that was deprecated in 7.16.0
|
||||
* in favor of using the newer alerting notifications system.
|
||||
|
@ -136,6 +139,12 @@ export function getMigrations(
|
|||
)
|
||||
);
|
||||
|
||||
const migrationRules801 = createEsoMigration(
|
||||
encryptedSavedObjects,
|
||||
(doc: SavedObjectUnsanitizedDoc<RawRule>): doc is SavedObjectUnsanitizedDoc<RawRule> => true,
|
||||
pipeMigrations(addSecuritySolutionAADRuleTypeTags)
|
||||
);
|
||||
|
||||
return {
|
||||
'7.10.0': executeMigrationWithErrorHandling(migrationWhenRBACWasIntroduced, '7.10.0'),
|
||||
'7.11.0': executeMigrationWithErrorHandling(migrationAlertUpdatedAtAndNotifyWhen, '7.11.0'),
|
||||
|
@ -145,6 +154,7 @@ export function getMigrations(
|
|||
'7.15.0': executeMigrationWithErrorHandling(migrationSecurityRules715, '7.15.0'),
|
||||
'7.16.0': executeMigrationWithErrorHandling(migrateRules716, '7.16.0'),
|
||||
'8.0.0': executeMigrationWithErrorHandling(migrationRules800, '8.0.0'),
|
||||
'8.0.1': executeMigrationWithErrorHandling(migrationRules801, '8.0.1'),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -672,6 +682,28 @@ function addSecuritySolutionAADRuleTypes(
|
|||
: doc;
|
||||
}
|
||||
|
||||
function addSecuritySolutionAADRuleTypeTags(
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
const ruleType = doc.attributes.params.type;
|
||||
return isDetectionEngineAADRuleType(doc) && isRuleType(ruleType)
|
||||
? {
|
||||
...doc,
|
||||
attributes: {
|
||||
...doc.attributes,
|
||||
// If the rule is disabled at this point, then the rule has not been re-enabled after
|
||||
// running the 8.0.0 migrations. If `doc.attributes.scheduledTaskId` exists, then the
|
||||
// rule was enabled prior to running the migration. Thus we know we should add the
|
||||
// tag to indicate it was auto-disabled.
|
||||
tags:
|
||||
!doc.attributes.enabled && doc.attributes.scheduledTaskId
|
||||
? [...(doc.attributes.tags ?? []), 'auto_disabled_8.0']
|
||||
: doc.attributes.tags ?? [],
|
||||
},
|
||||
}
|
||||
: doc;
|
||||
}
|
||||
|
||||
function addThreatIndicatorPathToThreatMatchRules(
|
||||
doc: SavedObjectUnsanitizedDoc<RawRule>
|
||||
): SavedObjectUnsanitizedDoc<RawRule> {
|
||||
|
|
|
@ -181,7 +181,7 @@ export default function createGetTests({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('7.15.0 migrates security_solution alerts with exceptionLists to be saved object references', async () => {
|
||||
// NOTE: We hae to use elastic search directly against the ".kibana" index because alerts do not expose the references which we want to test exists
|
||||
// NOTE: We have to use elasticsearch directly against the ".kibana" index because alerts do not expose the references which we want to test exists
|
||||
const response = await es.get<{ references: [{}] }>(
|
||||
{
|
||||
index: '.kibana',
|
||||
|
@ -373,5 +373,39 @@ export default function createGetTests({ getService }: FtrProviderContext) {
|
|||
expect(response.body._source?.alert?.alertTypeId).to.be('siem.queryRule');
|
||||
expect(response.body._source?.alert?.enabled).to.be(false);
|
||||
});
|
||||
|
||||
it('8.0.1 migrates and adds tags to disabled rules in 8.0', async () => {
|
||||
const responseEnabledBeforeMigration = await es.get<{ alert: RawRule }>(
|
||||
{
|
||||
index: '.kibana',
|
||||
id: 'alert:1efdfa40-8ec7-11ec-a700-5524407a7653',
|
||||
},
|
||||
{ meta: true }
|
||||
);
|
||||
expect(responseEnabledBeforeMigration.statusCode).to.eql(200);
|
||||
const responseDisabledBeforeMigration = await es.get<{ alert: RawRule }>(
|
||||
{
|
||||
index: '.kibana',
|
||||
id: 'alert:13fdfa40-8ec7-11ec-a700-5524407a7667',
|
||||
},
|
||||
{ meta: true }
|
||||
);
|
||||
expect(responseDisabledBeforeMigration.statusCode).to.eql(200);
|
||||
|
||||
// Both should be disabled
|
||||
expect(responseEnabledBeforeMigration.body._source?.alert?.enabled).to.be(false);
|
||||
expect(responseDisabledBeforeMigration.body._source?.alert?.enabled).to.be(false);
|
||||
|
||||
// Only the rule that was enabled should be tagged
|
||||
expect(responseEnabledBeforeMigration.body._source?.alert?.tags).to.eql([
|
||||
'__internal_rule_id:064e3fed-6328-416b-bb85-c08265088f41',
|
||||
'__internal_immutable:false',
|
||||
'auto_disabled_8.0',
|
||||
]);
|
||||
expect(responseDisabledBeforeMigration.body._source?.alert?.tags).to.eql([
|
||||
'__internal_rule_id:364e3fed-6328-416b-bb85-c08265088f41',
|
||||
'__internal_immutable:false',
|
||||
]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -663,3 +663,194 @@
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type":"doc",
|
||||
"value":{
|
||||
"id":"alert:1efdfa40-8ec7-11ec-a700-5524407a7653",
|
||||
"index":".kibana_1",
|
||||
"source":{
|
||||
"alert":{
|
||||
"name":"enabled 7.16.1 query rule",
|
||||
"tags":[
|
||||
"__internal_rule_id:064e3fed-6328-416b-bb85-c08265088f41",
|
||||
"__internal_immutable:false"
|
||||
],
|
||||
"alertTypeId":"siem.signals",
|
||||
"consumer":"siem",
|
||||
"params":{
|
||||
"author":[
|
||||
|
||||
],
|
||||
"description":"enabled 7.16.1 query rule",
|
||||
"ruleId":"064e3fed-6328-416b-bb85-c08265088f41",
|
||||
"falsePositives":[
|
||||
|
||||
],
|
||||
"from":"now-36000060s",
|
||||
"immutable":false,
|
||||
"license":"",
|
||||
"outputIndex":".siem-signals-default",
|
||||
"meta":{
|
||||
"from":"10000h"
|
||||
},
|
||||
"maxSignals":100,
|
||||
"riskScore":21,
|
||||
"riskScoreMapping":[
|
||||
|
||||
],
|
||||
"severity":"low",
|
||||
"severityMapping":[
|
||||
|
||||
],
|
||||
"threat":[
|
||||
|
||||
],
|
||||
"to":"now",
|
||||
"references":[
|
||||
|
||||
],
|
||||
"version":4,
|
||||
"exceptionsList":[
|
||||
],
|
||||
"type":"query",
|
||||
"language":"kuery",
|
||||
"index":[
|
||||
"apm-*-transaction*",
|
||||
"traces-apm*",
|
||||
"auditbeat-*",
|
||||
"endgame-*",
|
||||
"filebeat-*",
|
||||
"logs-*",
|
||||
"packetbeat-*",
|
||||
"winlogbeat-*",
|
||||
"test-index-3"
|
||||
],
|
||||
"query":"*:*",
|
||||
"filters":[
|
||||
|
||||
]
|
||||
},
|
||||
"schedule":{
|
||||
"interval":"1m"
|
||||
},
|
||||
"enabled":true,
|
||||
"actions":[
|
||||
|
||||
],
|
||||
"throttle":null,
|
||||
"apiKeyOwner":"3270256467",
|
||||
"apiKey":"UnFCyd4CthfIw6Mv5SRRbhYC7NPD2Jn8L+aCT/JfPQ5/poIsrwkh0plDAllpBYjFYhGXTQPtSPgu9yAwsuuaUhXxtFcnFHPleQeLvmu8VICueSxgMnK25Oqku8hfSQw9ETf9WZ3yXQOwvD9i8fkIUx84zt5q2LMuZv826fY9433/seVoCWspTj5qm2DchMDgTWzMKQaR2zbvRA==",
|
||||
"createdBy":"3270256467",
|
||||
"updatedBy":"3270256467",
|
||||
"createdAt":"2022-02-16T01:24:02.121Z",
|
||||
"muteAll":true,
|
||||
"mutedInstanceIds":[
|
||||
|
||||
],
|
||||
"scheduledTaskId":"2030ade0-8ec7-11ec-a700-5524407a7653"
|
||||
},
|
||||
"type":"alert",
|
||||
"references":[],
|
||||
"migrationVersion":{
|
||||
"alert":"7.16.0"
|
||||
},
|
||||
"updated_at":"2022-02-16T16:20:19.375Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type":"doc",
|
||||
"value":{
|
||||
"id":"alert:13fdfa40-8ec7-11ec-a700-5524407a7667",
|
||||
"index":".kibana_1",
|
||||
"source":{
|
||||
"alert":{
|
||||
"name":"disabled 7.16.1 query rule",
|
||||
"tags":[
|
||||
"__internal_rule_id:364e3fed-6328-416b-bb85-c08265088f41",
|
||||
"__internal_immutable:false"
|
||||
],
|
||||
"alertTypeId":"siem.signals",
|
||||
"consumer":"siem",
|
||||
"params":{
|
||||
"author":[
|
||||
|
||||
],
|
||||
"description":"disabled 7.16.1 query rule",
|
||||
"ruleId":"364e3fed-6328-416b-bb85-c08265088f41",
|
||||
"falsePositives":[
|
||||
|
||||
],
|
||||
"from":"now-36000060s",
|
||||
"immutable":false,
|
||||
"license":"",
|
||||
"outputIndex":".siem-signals-default",
|
||||
"meta":{
|
||||
"from":"10000h"
|
||||
},
|
||||
"maxSignals":100,
|
||||
"riskScore":21,
|
||||
"riskScoreMapping":[
|
||||
|
||||
],
|
||||
"severity":"low",
|
||||
"severityMapping":[
|
||||
|
||||
],
|
||||
"threat":[
|
||||
|
||||
],
|
||||
"to":"now",
|
||||
"references":[
|
||||
|
||||
],
|
||||
"version":4,
|
||||
"exceptionsList":[
|
||||
],
|
||||
"type":"query",
|
||||
"language":"kuery",
|
||||
"index":[
|
||||
"apm-*-transaction*",
|
||||
"traces-apm*",
|
||||
"auditbeat-*",
|
||||
"endgame-*",
|
||||
"filebeat-*",
|
||||
"logs-*",
|
||||
"packetbeat-*",
|
||||
"winlogbeat-*",
|
||||
"test-index-3"
|
||||
],
|
||||
"query":"*:*",
|
||||
"filters":[
|
||||
|
||||
]
|
||||
},
|
||||
"schedule":{
|
||||
"interval":"1m"
|
||||
},
|
||||
"enabled":true,
|
||||
"actions":[
|
||||
|
||||
],
|
||||
"throttle":null,
|
||||
"apiKeyOwner":"3270256467",
|
||||
"apiKey":"UnFCyd4CthfIw6Mv5SRRbhYC7NPD2Jn8L+aCT/JfPQ5/poIsrwkh0plDAllpBYjFYhGXTQPtSPgu9yAwsuuaUhXxtFcnFHPleQeLvmu8VICueSxgMnK25Oqku8hfSQw9ETf9WZ3yXQOwvD9i8fkIUx84zt5q2LMuZv826fY9433/seVoCWspTj5qm2DchMDgTWzMKQaR2zbvRA==",
|
||||
"createdBy":"3270256467",
|
||||
"updatedBy":"3270256467",
|
||||
"createdAt":"2022-02-16T01:25:02.121Z",
|
||||
"muteAll":true,
|
||||
"mutedInstanceIds":[
|
||||
|
||||
],
|
||||
"scheduledTaskId":null
|
||||
},
|
||||
"type":"alert",
|
||||
"references":[],
|
||||
"migrationVersion":{
|
||||
"alert":"7.16.0"
|
||||
},
|
||||
"updated_at":"2022-02-16T16:21:19.375Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,4 +341,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue