Skip to content

Commit

Permalink
[7.12][SECURITY SOLUTIONS][Alerts Actions] Fix migration from 7.11.0/…
Browse files Browse the repository at this point in the history
…7.11.1 to 7.12 (#94881)

* do not modify connector with the right structure

* review trying to bring back incident to live when we can

* manage custom action
  • Loading branch information
XavierM authored Mar 18, 2021
1 parent a576e2a commit b7f9a41
Show file tree
Hide file tree
Showing 3 changed files with 378 additions and 182 deletions.
126 changes: 126 additions & 0 deletions x-pack/plugins/alerts/server/saved_objects/migrations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,132 @@ describe('7.11.2', () => {
} as SavedObjectUnsanitizedDoc<RawAlert>;
expect(isAnyActionSupportIncidents(doc)).toBe(false);
});

test('it does not transforms alerts when the right structure connectors is already applied', () => {
const migration7112 = getMigrations(encryptedSavedObjectsSetup)['7.11.2'];
const alert = getMockData({
actions: [
{
actionTypeId: '.server-log',
group: 'threshold met',
params: {
level: 'info',
message: 'log message',
},
id: '99257478-e591-4560-b264-441bdd4fe1d9',
},
{
actionTypeId: '.servicenow',
group: 'threshold met',
params: {
subAction: 'pushToService',
subActionParams: {
incident: {
short_description: 'SN short desc',
description: 'SN desc',
severity: '2',
impact: '2',
urgency: '2',
},
comments: [{ commentId: '1', comment: 'sn comment' }],
},
},
id: '1266562a-4e1f-4305-99ca-1b44c469b26e',
},
],
});

expect(migration7112(alert, migrationContext)).toEqual(alert);
});

test('if incident attribute is an empty object, copy back the related attributes from subActionParams back to incident', () => {
const migration7112 = getMigrations(encryptedSavedObjectsSetup)['7.11.2'];
const alert = getMockData({
actions: [
{
actionTypeId: '.server-log',
group: 'threshold met',
params: {
level: 'info',
message: 'log message',
},
id: '99257478-e591-4560-b264-441bdd4fe1d9',
},
{
actionTypeId: '.servicenow',
group: 'threshold met',
params: {
subAction: 'pushToService',
subActionParams: {
short_description: 'SN short desc',
description: 'SN desc',
severity: '2',
impact: '2',
urgency: '2',
incident: {},
comments: [{ commentId: '1', comment: 'sn comment' }],
},
},
id: '1266562a-4e1f-4305-99ca-1b44c469b26e',
},
],
});

expect(migration7112(alert, migrationContext)).toEqual({
...alert,
attributes: {
...alert.attributes,
actions: [
alert.attributes.actions![0],
{
actionTypeId: '.servicenow',
group: 'threshold met',
params: {
subAction: 'pushToService',
subActionParams: {
incident: {
short_description: 'SN short desc',
description: 'SN desc',
severity: '2',
impact: '2',
urgency: '2',
},
comments: [{ commentId: '1', comment: 'sn comment' }],
},
},
id: '1266562a-4e1f-4305-99ca-1b44c469b26e',
},
],
},
});
});

test('custom action does not get migrated/loss', () => {
const migration7112 = getMigrations(encryptedSavedObjectsSetup)['7.11.2'];
const alert = getMockData({
actions: [
{
actionTypeId: '.mike',
group: 'threshold met',
params: {
subAction: 'pushToService',
subActionParams: {
short_description: 'SN short desc',
description: 'SN desc',
severity: '2',
impact: '2',
urgency: '2',
incident: {},
comments: [{ commentId: '1', comment: 'sn comment' }],
},
},
id: '1266562a-4e1f-4305-99ca-1b44c469b26e',
},
],
});

expect(migration7112(alert, migrationContext)).toEqual(alert);
});
});

function getUpdatedAt(): string {
Expand Down
217 changes: 126 additions & 91 deletions x-pack/plugins/alerts/server/saved_objects/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
SavedObjectUnsanitizedDoc,
SavedObjectMigrationFn,
SavedObjectMigrationContext,
SavedObjectAttributes,
} from '../../../../../src/core/server';
import { RawAlert, RawAlertAction } from '../types';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
Expand Down Expand Up @@ -180,113 +181,147 @@ function initializeExecutionStatus(
};
}

function isEmptyObject(obj: {}) {
for (const attr in obj) {
if (Object.prototype.hasOwnProperty.call(obj, attr)) {
return false;
}
}
return true;
}

function restructureConnectorsThatSupportIncident(
doc: SavedObjectUnsanitizedDoc<RawAlert>
): SavedObjectUnsanitizedDoc<RawAlert> {
const { actions } = doc.attributes;
const newActions = actions.reduce((acc, action) => {
if (action.params.subAction !== 'pushToService') {
return [...acc, action];
}

if (action.actionTypeId === '.servicenow') {
const { title, comments, comment, description, severity, urgency, impact } = action.params
.subActionParams as {
title: string;
description?: string;
severity?: string;
urgency?: string;
impact?: string;
comment?: string;
comments?: Array<{ commentId: string; comment: string }>;
};
return [
...acc,
{
...action,
params: {
subAction: 'pushToService',
subActionParams: {
incident: {
short_description: title,
description,
severity,
urgency,
impact,
if (
['.servicenow', '.jira', '.resilient'].includes(action.actionTypeId) &&
action.params.subAction === 'pushToService'
) {
// Future developer, we needed to do that because when we created this migration
// we forget to think about user already using 7.11.0 and having an incident attribute build the right way
// IMPORTANT -> if you change this code please do the same inside of this file
// x-pack/plugins/alerting/server/saved_objects/migrations.ts
const subActionParamsIncident =
(action.params?.subActionParams as SavedObjectAttributes)?.incident ?? null;
if (subActionParamsIncident != null && !isEmptyObject(subActionParamsIncident)) {
return [...acc, action];
}
if (action.actionTypeId === '.servicenow') {
const {
title,
comments,
comment,
description,
severity,
urgency,
impact,
short_description: shortDescription,
} = action.params.subActionParams as {
title: string;
description?: string;
severity?: string;
urgency?: string;
impact?: string;
comment?: string;
comments?: Array<{ commentId: string; comment: string }>;
short_description?: string;
};
return [
...acc,
{
...action,
params: {
subAction: 'pushToService',
subActionParams: {
incident: {
short_description: shortDescription ?? title,
description,
severity,
urgency,
impact,
},
comments: [
...(comments ?? []),
...(comment != null ? [{ commentId: '1', comment }] : []),
],
},
comments: [
...(comments ?? []),
...(comment != null ? [{ commentId: '1', comment }] : []),
],
},
},
},
] as RawAlertAction[];
}

if (action.actionTypeId === '.jira') {
const { title, comments, description, issueType, priority, labels, parent } = action.params
.subActionParams as {
title: string;
description: string;
issueType: string;
priority?: string;
labels?: string[];
parent?: string;
comments?: unknown[];
};
return [
...acc,
{
...action,
params: {
subAction: 'pushToService',
subActionParams: {
incident: {
summary: title,
description,
issueType,
priority,
labels,
parent,
] as RawAlertAction[];
} else if (action.actionTypeId === '.jira') {
const {
title,
comments,
description,
issueType,
priority,
labels,
parent,
summary,
} = action.params.subActionParams as {
title: string;
description: string;
issueType: string;
priority?: string;
labels?: string[];
parent?: string;
comments?: unknown[];
summary?: string;
};
return [
...acc,
{
...action,
params: {
subAction: 'pushToService',
subActionParams: {
incident: {
summary: summary ?? title,
description,
issueType,
priority,
labels,
parent,
},
comments,
},
comments,
},
},
},
] as RawAlertAction[];
}

if (action.actionTypeId === '.resilient') {
const { title, comments, description, incidentTypes, severityCode } = action.params
.subActionParams as {
title: string;
description: string;
incidentTypes?: number[];
severityCode?: number;
comments?: unknown[];
};
return [
...acc,
{
...action,
params: {
subAction: 'pushToService',
subActionParams: {
incident: {
name: title,
description,
incidentTypes,
severityCode,
] as RawAlertAction[];
} else if (action.actionTypeId === '.resilient') {
const { title, comments, description, incidentTypes, severityCode, name } = action.params
.subActionParams as {
title: string;
description: string;
incidentTypes?: number[];
severityCode?: number;
comments?: unknown[];
name?: string;
};
return [
...acc,
{
...action,
params: {
subAction: 'pushToService',
subActionParams: {
incident: {
name: name ?? title,
description,
incidentTypes,
severityCode,
},
comments,
},
comments,
},
},
},
] as RawAlertAction[];
] as RawAlertAction[];
}
}

return acc;
return [...acc, action];
}, [] as RawAlertAction[]);

return {
Expand Down
Loading

0 comments on commit b7f9a41

Please sign in to comment.