diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts index 9403c0c28c153..512f4618792fb 100644 --- a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts +++ b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts @@ -970,6 +970,48 @@ describe('successful migrations', () => { }); }); }); + + describe('7.14.1', () => { + test('security solution author field is migrated to array if it is undefined', () => { + const migration7141 = getMigrations(encryptedSavedObjectsSetup)['7.14.1']; + const alert = getMockData({ + alertTypeId: 'siem.signals', + params: {}, + }); + + expect(migration7141(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + params: { + author: [], + }, + }, + }); + }); + + test('security solution author field does not override existing values if they exist', () => { + const migration7141 = getMigrations(encryptedSavedObjectsSetup)['7.14.1']; + const alert = getMockData({ + alertTypeId: 'siem.signals', + params: { + note: 'some note', + author: ['author 1'], + }, + }); + + expect(migration7141(alert, migrationContext)).toEqual({ + ...alert, + attributes: { + ...alert.attributes, + params: { + note: 'some note', + author: ['author 1'], + }, + }, + }); + }); + }); }); describe('handles errors during migrations', () => { diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.ts index 9f6adeb27083a..944acbdca0182 100644 --- a/x-pack/plugins/alerting/server/saved_objects/migrations.ts +++ b/x-pack/plugins/alerting/server/saved_objects/migrations.ts @@ -85,11 +85,18 @@ export function getMigrations( pipeMigrations(removeNullsFromSecurityRules) ); + const migrationSecurityRules714 = createEsoMigration( + encryptedSavedObjects, + (doc): doc is SavedObjectUnsanitizedDoc => isSecuritySolutionRule(doc), + pipeMigrations(removeNullAuthorFromSecurityRules) + ); + return { '7.10.0': executeMigrationWithErrorHandling(migrationWhenRBACWasIntroduced, '7.10.0'), '7.11.0': executeMigrationWithErrorHandling(migrationAlertUpdatedAtAndNotifyWhen, '7.11.0'), '7.11.2': executeMigrationWithErrorHandling(migrationActions7112, '7.11.2'), '7.13.0': executeMigrationWithErrorHandling(migrationSecurityRules713, '7.13.0'), + '7.14.1': executeMigrationWithErrorHandling(migrationSecurityRules714, '7.14.1'), }; } @@ -432,6 +439,34 @@ function removeNullsFromSecurityRules( }; } +/** + * The author field was introduced later and was not part of the original rules. We overlooked + * the filling in the author field as an empty array in an earlier upgrade routine from + * 'removeNullsFromSecurityRules' during the 7.13.0 upgrade. Since we don't change earlier migrations, + * but rather only move forward with the "arrow of time" we are going to upgrade and fix + * it if it is missing for anyone in 7.14.0 and above release. Earlier releases if we want to fix them, + * would have to be modified as a "7.13.1", etc... if we want to fix it there. + * @param doc The document that is not migrated and contains a "null" or "undefined" author field + * @returns The document with the author field fleshed in. + */ +function removeNullAuthorFromSecurityRules( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { params }, + } = doc; + return { + ...doc, + attributes: { + ...doc.attributes, + params: { + ...params, + author: params.author != null ? params.author : [], + }, + }, + }; +} + function pipeMigrations(...migrations: AlertMigration[]): AlertMigration { return (doc: SavedObjectUnsanitizedDoc) => migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc), doc);