From 86fac6d01c89eecbac604c758e21fd235762c789 Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Tue, 14 Apr 2020 18:20:50 -0400 Subject: [PATCH] [Alerting] fixes to allow pre-configured actions to be executed (#63432) resolves https://github.com/elastic/kibana/issues/63162 Most of the support for pre-configured actions has already been added to Kibana, except for one small piece. The ability for them to be executed. This PR adds that support. --- .../server/create_execute_function.test.ts | 67 +++++++++++++ .../actions/server/create_execute_function.ts | 25 ++++- .../server/lib/action_executor.test.ts | 2 + .../actions/server/lib/action_executor.ts | 72 +++++++++++--- .../server/lib/task_runner_factory.test.ts | 1 + x-pack/plugins/actions/server/plugin.ts | 2 + .../alerting_api_integration/common/config.ts | 21 +++++ .../es_index_preconfigured.ts | 68 ++++++++++++++ .../tests/actions/get_all.ts | 66 +++++++++++++ .../tests/actions/index.ts | 1 + .../tests/alerting/alerts.ts | 94 +++++++++++++++++++ .../spaces_only/tests/actions/get_all.ts | 44 +++++++++ 12 files changed, 445 insertions(+), 18 deletions(-) create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts diff --git a/x-pack/plugins/actions/server/create_execute_function.test.ts b/x-pack/plugins/actions/server/create_execute_function.test.ts index 68c3967359ff4..6bdd30848e4b7 100644 --- a/x-pack/plugins/actions/server/create_execute_function.test.ts +++ b/x-pack/plugins/actions/server/create_execute_function.test.ts @@ -23,6 +23,7 @@ describe('execute()', () => { actionTypeRegistry: actionTypeRegistryMock.create(), getScopedSavedObjectsClient: jest.fn().mockReturnValueOnce(savedObjectsClient), isESOUsingEphemeralEncryptionKey: false, + preconfiguredActions: [], }); savedObjectsClient.get.mockResolvedValueOnce({ id: '123', @@ -68,6 +69,68 @@ describe('execute()', () => { }); }); + test('schedules the action with all given parameters with a preconfigured action', async () => { + const executeFn = createExecuteFunction({ + getBasePath, + taskManager: mockTaskManager, + actionTypeRegistry: actionTypeRegistryMock.create(), + getScopedSavedObjectsClient: jest.fn().mockReturnValueOnce(savedObjectsClient), + isESOUsingEphemeralEncryptionKey: false, + preconfiguredActions: [ + { + id: '123', + actionTypeId: 'mock-action-preconfigured', + config: {}, + isPreconfigured: true, + name: 'x', + secrets: {}, + }, + ], + }); + savedObjectsClient.get.mockResolvedValueOnce({ + id: '123', + type: 'action', + attributes: { + actionTypeId: 'mock-action', + }, + references: [], + }); + savedObjectsClient.create.mockResolvedValueOnce({ + id: '234', + type: 'action_task_params', + attributes: {}, + references: [], + }); + await executeFn({ + id: '123', + params: { baz: false }, + spaceId: 'default', + apiKey: Buffer.from('123:abc').toString('base64'), + }); + expect(mockTaskManager.schedule).toHaveBeenCalledTimes(1); + expect(mockTaskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "params": Object { + "actionTaskParamsId": "234", + "spaceId": "default", + }, + "scope": Array [ + "actions", + ], + "state": Object {}, + "taskType": "actions:mock-action-preconfigured", + }, + ] + `); + expect(savedObjectsClient.get).not.toHaveBeenCalled(); + expect(savedObjectsClient.create).toHaveBeenCalledWith('action_task_params', { + actionId: '123', + params: { baz: false }, + apiKey: Buffer.from('123:abc').toString('base64'), + }); + }); + test('uses API key when provided', async () => { const getScopedSavedObjectsClient = jest.fn().mockReturnValueOnce(savedObjectsClient); const executeFn = createExecuteFunction({ @@ -76,6 +139,7 @@ describe('execute()', () => { getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey: false, actionTypeRegistry: actionTypeRegistryMock.create(), + preconfiguredActions: [], }); savedObjectsClient.get.mockResolvedValueOnce({ id: '123', @@ -125,6 +189,7 @@ describe('execute()', () => { getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey: false, actionTypeRegistry: actionTypeRegistryMock.create(), + preconfiguredActions: [], }); savedObjectsClient.get.mockResolvedValueOnce({ id: '123', @@ -171,6 +236,7 @@ describe('execute()', () => { getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey: true, actionTypeRegistry: actionTypeRegistryMock.create(), + preconfiguredActions: [], }); await expect( executeFn({ @@ -193,6 +259,7 @@ describe('execute()', () => { getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey: false, actionTypeRegistry: mockedActionTypeRegistry, + preconfiguredActions: [], }); mockedActionTypeRegistry.ensureActionTypeEnabled.mockImplementation(() => { throw new Error('Fail'); diff --git a/x-pack/plugins/actions/server/create_execute_function.ts b/x-pack/plugins/actions/server/create_execute_function.ts index 4bbcda4cba7fc..4a9ddf412b7cc 100644 --- a/x-pack/plugins/actions/server/create_execute_function.ts +++ b/x-pack/plugins/actions/server/create_execute_function.ts @@ -6,7 +6,12 @@ import { SavedObjectsClientContract } from '../../../../src/core/server'; import { TaskManagerStartContract } from '../../task_manager/server'; -import { GetBasePathFunction, RawAction, ActionTypeRegistryContract } from './types'; +import { + GetBasePathFunction, + RawAction, + ActionTypeRegistryContract, + PreConfiguredAction, +} from './types'; interface CreateExecuteFunctionOptions { taskManager: TaskManagerStartContract; @@ -14,6 +19,7 @@ interface CreateExecuteFunctionOptions { getBasePath: GetBasePathFunction; isESOUsingEphemeralEncryptionKey: boolean; actionTypeRegistry: ActionTypeRegistryContract; + preconfiguredActions: PreConfiguredAction[]; } export interface ExecuteOptions { @@ -29,6 +35,7 @@ export function createExecuteFunction({ actionTypeRegistry, getScopedSavedObjectsClient, isESOUsingEphemeralEncryptionKey, + preconfiguredActions, }: CreateExecuteFunctionOptions) { return async function execute({ id, params, spaceId, apiKey }: ExecuteOptions) { if (isESOUsingEphemeralEncryptionKey === true) { @@ -61,9 +68,9 @@ export function createExecuteFunction({ }; const savedObjectsClient = getScopedSavedObjectsClient(fakeRequest); - const actionSavedObject = await savedObjectsClient.get('action', id); + const actionTypeId = await getActionTypeId(id); - actionTypeRegistry.ensureActionTypeEnabled(actionSavedObject.attributes.actionTypeId); + actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); const actionTaskParamsRecord = await savedObjectsClient.create('action_task_params', { actionId: id, @@ -72,7 +79,7 @@ export function createExecuteFunction({ }); await taskManager.schedule({ - taskType: `actions:${actionSavedObject.attributes.actionTypeId}`, + taskType: `actions:${actionTypeId}`, params: { spaceId, actionTaskParamsId: actionTaskParamsRecord.id, @@ -80,5 +87,15 @@ export function createExecuteFunction({ state: {}, scope: ['actions'], }); + + async function getActionTypeId(actionId: string): Promise { + const pcAction = preconfiguredActions.find(action => action.id === actionId); + if (pcAction) { + return pcAction.actionTypeId; + } + + const actionSO = await savedObjectsClient.get('action', actionId); + return actionSO.attributes.actionTypeId; + } }; } diff --git a/x-pack/plugins/actions/server/lib/action_executor.test.ts b/x-pack/plugins/actions/server/lib/action_executor.test.ts index bbcb0457fc1d1..124e5951c714b 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -43,6 +43,7 @@ actionExecutor.initialize({ actionTypeRegistry, encryptedSavedObjectsPlugin, eventLogger: eventLoggerMock.create(), + preconfiguredActions: [], }); beforeEach(() => { @@ -232,6 +233,7 @@ test('throws an error when passing isESOUsingEphemeralEncryptionKey with value o actionTypeRegistry, encryptedSavedObjectsPlugin, eventLogger: eventLoggerMock.create(), + preconfiguredActions: [], }); await expect( customActionExecutor.execute(executeParams) diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index ba8bb79170c63..a33fb8830a930 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -11,6 +11,8 @@ import { ActionTypeRegistryContract, GetServicesFunction, RawAction, + PreConfiguredAction, + Services, } from '../types'; import { EncryptedSavedObjectsPluginStart } from '../../../encrypted_saved_objects/server'; import { SpacesServiceSetup } from '../../../spaces/server'; @@ -24,6 +26,7 @@ export interface ActionExecutorContext { encryptedSavedObjectsPlugin: EncryptedSavedObjectsPluginStart; actionTypeRegistry: ActionTypeRegistryContract; eventLogger: IEventLogger; + preconfiguredActions: PreConfiguredAction[]; } export interface ExecuteOptions { @@ -72,28 +75,22 @@ export class ActionExecutor { encryptedSavedObjectsPlugin, actionTypeRegistry, eventLogger, + preconfiguredActions, } = this.actionExecutorContext!; const services = getServices(request); const spaceId = spaces && spaces.getSpaceId(request); const namespace = spaceId && spaceId !== 'default' ? { namespace: spaceId } : {}; - // Ensure user can read the action before processing - const { - attributes: { actionTypeId, config, name }, - } = await services.savedObjectsClient.get('action', actionId); - - actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); - - // Only get encrypted attributes here, the remaining attributes can be fetched in - // the savedObjectsClient call - const { - attributes: { secrets }, - } = await encryptedSavedObjectsPlugin.getDecryptedAsInternalUser( - 'action', + const { actionTypeId, name, config, secrets } = await getActionInfo( + services, + encryptedSavedObjectsPlugin, + preconfiguredActions, actionId, - namespace + namespace.namespace ); + + actionTypeRegistry.ensureActionTypeEnabled(actionTypeId); const actionType = actionTypeRegistry.get(actionTypeId); let validatedParams: Record; @@ -173,3 +170,50 @@ function actionErrorToMessage(result: ActionTypeExecutorResult): string { return message; } + +interface ActionInfo { + actionTypeId: string; + name: string; + config: any; + secrets: any; +} + +async function getActionInfo( + services: Services, + encryptedSavedObjectsPlugin: EncryptedSavedObjectsPluginStart, + preconfiguredActions: PreConfiguredAction[], + actionId: string, + namespace: string | undefined +): Promise { + // check to see if it's a pre-configured action first + const pcAction = preconfiguredActions.find( + preconfiguredAction => preconfiguredAction.id === actionId + ); + if (pcAction) { + return { + actionTypeId: pcAction.actionTypeId, + name: pcAction.name, + config: pcAction.config, + secrets: pcAction.secrets, + }; + } + + // if not pre-configured action, should be a saved object + // ensure user can read the action before processing + const { + attributes: { actionTypeId, config, name }, + } = await services.savedObjectsClient.get('action', actionId); + + const { + attributes: { secrets }, + } = await encryptedSavedObjectsPlugin.getDecryptedAsInternalUser('action', actionId, { + namespace: namespace === 'default' ? undefined : namespace, + }); + + return { + actionTypeId, + name, + config, + secrets, + }; +} diff --git a/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts index 43882cef21170..f070f714ee508 100644 --- a/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts +++ b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts @@ -61,6 +61,7 @@ const actionExecutorInitializerParams = { actionTypeRegistry, encryptedSavedObjectsPlugin: mockedEncryptedSavedObjectsPlugin, eventLogger: eventLoggerMock.create(), + preconfiguredActions: [], }; const taskRunnerFactoryInitializerParams = { spaceIdToNamespace, diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 34c9e7aa9e8b8..ef3716070ab04 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -245,6 +245,7 @@ export class ActionsPlugin implements Plugin, Plugi getServices: this.getServicesFactory(core.savedObjects), encryptedSavedObjectsPlugin: plugins.encryptedSavedObjects, actionTypeRegistry: actionTypeRegistry!, + preconfiguredActions, }); taskRunnerFactory!.initialize({ @@ -265,6 +266,7 @@ export class ActionsPlugin implements Plugin, Plugi getScopedSavedObjectsClient: core.savedObjects.getScopedClient, getBasePath: this.getBasePath, isESOUsingEphemeralEncryptionKey: isESOUsingEphemeralEncryptionKey!, + preconfiguredActions, }), isActionTypeEnabled: id => { return this.actionTypeRegistry!.isActionTypeEnabled(id); diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index 4d32a5ae9f53c..457b7621e84bd 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -100,6 +100,27 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) xyzSecret2: 'credential2', }, }, + { + id: 'preconfigured-es-index-action', + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + }, + { + id: 'preconfigured.test.index-record', + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + secrets: { + encrypted: 'this-is-also-ignored-and-also-required', + }, + }, ])}`, ...disabledPlugins.map(key => `--xpack.${key}.enabled=false`), `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'alerts')}`, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts new file mode 100644 index 0000000000000..b04bc13ffc5e4 --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +// from: x-pack/test/alerting_api_integration/common/config.ts +const ACTION_ID = 'preconfigured-es-index-action'; +const ES_TEST_INDEX_NAME = 'functional-test-actions-index-preconfigured'; + +// eslint-disable-next-line import/no-default-export +export default function indexTest({ getService }: FtrProviderContext) { + const es = getService('legacyEs'); + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('preconfigured index action', () => { + after(() => esArchiver.unload('empty_kibana')); + beforeEach(() => clearTestIndex(es)); + + it('should execute successfully when expected for a single body', async () => { + const { body: result } = await supertest + .post(`/api/action/${ACTION_ID}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + documents: [{ testing: [4, 5, 6] }], + }, + }) + .expect(200); + expect(result.status).to.eql('ok'); + + const items = await getTestIndexItems(es); + expect(items.length).to.eql(1); + + // check document sans timestamp + const document = items[0]._source; + const timestamp = document.timestamp; + delete document.timestamp; + expect(document).to.eql({ testing: [4, 5, 6] }); + + // check timestamp + const timestampTime = new Date(timestamp).getTime(); + const timeNow = Date.now(); + const timeMinuteAgo = timeNow - 1000 * 60; + expect(timestampTime).to.be.within(timeMinuteAgo, timeNow); + }); + }); +} + +async function clearTestIndex(es: any) { + return await es.indices.delete({ + index: ES_TEST_INDEX_NAME, + ignoreUnavailable: true, + }); +} + +async function getTestIndexItems(es: any) { + const result = await es.search({ + index: ES_TEST_INDEX_NAME, + }); + + return result.hits.hits; +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts index 80b512f3fb5e3..0b637326d4667 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts @@ -68,6 +68,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -90,6 +102,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); break; default: @@ -167,6 +189,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 1, }, + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -189,6 +223,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); break; default: @@ -232,6 +276,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { case 'superuser at space1': expect(response.statusCode).to.eql(200); expect(response.body).to.eql([ + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -254,6 +310,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); break; default: diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts index d7ec2e78ccb30..8e002bcc8d3da 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts @@ -11,6 +11,7 @@ export default function actionsTests({ loadTestFile }: FtrProviderContext) { describe('Actions', () => { loadTestFile(require.resolve('./builtin_action_types/email')); loadTestFile(require.resolve('./builtin_action_types/es_index')); + loadTestFile(require.resolve('./builtin_action_types/es_index_preconfigured')); loadTestFile(require.resolve('./builtin_action_types/pagerduty')); loadTestFile(require.resolve('./builtin_action_types/server_log')); loadTestFile(require.resolve('./builtin_action_types/servicenow')); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts index 6eed28cc381dd..d8e4f808f5cd2 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts @@ -165,6 +165,100 @@ instanceStateValue: true } }); + it('should schedule task, run alert and schedule preconfigured actions when appropriate', async () => { + const testStart = new Date(); + const reference = alertUtils.generateReference(); + const response = await alertUtils.createAlwaysFiringAction({ + reference, + indexRecordActionId: 'preconfigured.test.index-record', + }); + + switch (scenario.id) { + case 'no_kibana_privileges at space1': + case 'global_read at space1': + case 'space_1_all at space2': + expect(response.statusCode).to.eql(404); + expect(response.body).to.eql({ + statusCode: 404, + error: 'Not Found', + message: 'Not Found', + }); + break; + case 'superuser at space1': + case 'space_1_all at space1': + expect(response.statusCode).to.eql(200); + + // Wait for the action to index a document before disabling the alert and waiting for tasks to finish + await esTestIndexTool.waitForDocs('action:test.index-record', reference); + + await taskManagerUtils.waitForAllTasksIdle(testStart); + + const alertId = response.body.id; + await alertUtils.disable(alertId); + await taskManagerUtils.waitForEmpty(testStart); + + // Ensure only 1 alert executed with proper params + const alertSearchResult = await esTestIndexTool.search( + 'alert:test.always-firing', + reference + ); + expect(alertSearchResult.hits.total.value).to.eql(1); + expect(alertSearchResult.hits.hits[0]._source).to.eql({ + source: 'alert:test.always-firing', + reference, + state: {}, + params: { + index: ES_TEST_INDEX_NAME, + reference, + }, + alertInfo: { + alertId, + spaceId: space.id, + namespace: space.id, + name: 'abc', + tags: ['tag-A', 'tag-B'], + createdBy: user.fullName, + updatedBy: user.fullName, + }, + }); + + // Ensure only 1 action executed with proper params + const actionSearchResult = await esTestIndexTool.search( + 'action:test.index-record', + reference + ); + expect(actionSearchResult.hits.total.value).to.eql(1); + expect(actionSearchResult.hits.hits[0]._source).to.eql({ + config: { + unencrypted: 'ignored-but-required', + }, + secrets: { + encrypted: 'this-is-also-ignored-and-also-required', + }, + params: { + index: ES_TEST_INDEX_NAME, + reference, + message: ` +alertId: ${alertId}, +alertName: abc, +spaceId: ${space.id}, +tags: tag-A,tag-B, +alertInstanceId: 1, +instanceContextValue: true, +instanceStateValue: true +`.trim(), + }, + reference, + source: 'action:test.index-record', + }); + + await taskManagerUtils.waitForActionTaskParamsToBeCleanedUp(testStart); + break; + default: + throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); + } + }); + it('should pass updated alert params to executor', async () => { const testStart = new Date(); // create an alert diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get_all.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get_all.ts index 517c64f178af5..ec59e56b08308 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get_all.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/get_all.ts @@ -45,6 +45,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -67,6 +79,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); }); @@ -88,6 +110,18 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { objectRemover.add(Spaces.space1.id, createdAction.id, 'action'); await supertest.get(`${getUrlPrefix(Spaces.other.id)}/api/action/_getAll`).expect(200, [ + { + id: 'preconfigured-es-index-action', + isPreconfigured: true, + actionTypeId: '.index', + name: 'preconfigured_es_index_action', + config: { + index: 'functional-test-actions-index-preconfigured', + refresh: true, + executionTimeField: 'timestamp', + }, + referencedByCount: 0, + }, { id: 'my-slack1', isPreconfigured: true, @@ -110,6 +144,16 @@ export default function getAllActionTests({ getService }: FtrProviderContext) { }, referencedByCount: 0, }, + { + id: 'preconfigured.test.index-record', + isPreconfigured: true, + actionTypeId: 'test.index-record', + name: 'Test:_Preconfigured_Index_Record', + config: { + unencrypted: 'ignored-but-required', + }, + referencedByCount: 0, + }, ]); }); });