[actions] add rule saved object reference to action execution event log doc (#101526)
resolves https://github.com/elastic/kibana/issues/99225 Prior to this PR, when an alerting connection action was executed, the event log document generated did not contain a reference to the originating rule. This makes it difficult to diagnose problems with connector errors, since the error is often in the parameters specified in the actions in the alert. In this PR, a reference to the alerting rule is added to the saved_objects field in the event document for these events.
This commit is contained in:
parent
2b0f1256dd
commit
86fb2cc90e
|
@ -1676,6 +1676,70 @@ describe('execute()', () => {
|
|||
name: 'my name',
|
||||
},
|
||||
});
|
||||
|
||||
await expect(
|
||||
actionsClient.execute({
|
||||
actionId,
|
||||
params: {
|
||||
name: 'my name',
|
||||
},
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: 'some-id',
|
||||
typeId: 'some-type-id',
|
||||
type: 'some-type',
|
||||
},
|
||||
],
|
||||
})
|
||||
).resolves.toMatchObject({ status: 'ok', actionId });
|
||||
|
||||
expect(actionExecutor.execute).toHaveBeenCalledWith({
|
||||
actionId,
|
||||
request,
|
||||
params: {
|
||||
name: 'my name',
|
||||
},
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: 'some-id',
|
||||
typeId: 'some-type-id',
|
||||
type: 'some-type',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await expect(
|
||||
actionsClient.execute({
|
||||
actionId,
|
||||
params: {
|
||||
name: 'my name',
|
||||
},
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: 'some-id',
|
||||
typeId: 'some-type-id',
|
||||
type: 'some-type',
|
||||
namespace: 'some-namespace',
|
||||
},
|
||||
],
|
||||
})
|
||||
).resolves.toMatchObject({ status: 'ok', actionId });
|
||||
|
||||
expect(actionExecutor.execute).toHaveBeenCalledWith({
|
||||
actionId,
|
||||
request,
|
||||
params: {
|
||||
name: 'my name',
|
||||
},
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: 'some-id',
|
||||
typeId: 'some-type-id',
|
||||
type: 'some-type',
|
||||
namespace: 'some-namespace',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -469,6 +469,7 @@ export class ActionsClient {
|
|||
actionId,
|
||||
params,
|
||||
source,
|
||||
relatedSavedObjects,
|
||||
}: Omit<ExecuteOptions, 'request'>): Promise<ActionTypeExecutorResult<unknown>> {
|
||||
if (
|
||||
(await getAuthorizationModeBySource(this.unsecuredSavedObjectsClient, source)) ===
|
||||
|
@ -476,7 +477,13 @@ export class ActionsClient {
|
|||
) {
|
||||
await this.authorization.ensureAuthorized('execute');
|
||||
}
|
||||
return this.actionExecutor.execute({ actionId, params, source, request: this.request });
|
||||
return this.actionExecutor.execute({
|
||||
actionId,
|
||||
params,
|
||||
source,
|
||||
request: this.request,
|
||||
relatedSavedObjects,
|
||||
});
|
||||
}
|
||||
|
||||
public async enqueueExecution(options: EnqueueExecutionOptions): Promise<void> {
|
||||
|
|
|
@ -83,6 +83,62 @@ describe('execute()', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('schedules the action with all given parameters and relatedSavedObjects', async () => {
|
||||
const actionTypeRegistry = actionTypeRegistryMock.create();
|
||||
const executeFn = createExecutionEnqueuerFunction({
|
||||
taskManager: mockTaskManager,
|
||||
actionTypeRegistry,
|
||||
isESOCanEncrypt: true,
|
||||
preconfiguredActions: [],
|
||||
});
|
||||
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(savedObjectsClient, {
|
||||
id: '123',
|
||||
params: { baz: false },
|
||||
spaceId: 'default',
|
||||
apiKey: Buffer.from('123:abc').toString('base64'),
|
||||
source: asHttpRequestExecutionSource(request),
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: 'some-id',
|
||||
namespace: 'some-namespace',
|
||||
type: 'some-type',
|
||||
typeId: 'some-typeId',
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(savedObjectsClient.create).toHaveBeenCalledWith(
|
||||
'action_task_params',
|
||||
{
|
||||
actionId: '123',
|
||||
params: { baz: false },
|
||||
apiKey: Buffer.from('123:abc').toString('base64'),
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: 'some-id',
|
||||
namespace: 'some-namespace',
|
||||
type: 'some-type',
|
||||
typeId: 'some-typeId',
|
||||
},
|
||||
],
|
||||
},
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
test('schedules the action with all given parameters with a preconfigured action', async () => {
|
||||
const executeFn = createExecutionEnqueuerFunction({
|
||||
taskManager: mockTaskManager,
|
||||
|
|
|
@ -11,6 +11,7 @@ import { RawAction, ActionTypeRegistryContract, PreConfiguredAction } from './ty
|
|||
import { ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE } from './constants/saved_objects';
|
||||
import { ExecuteOptions as ActionExecutorOptions } from './lib/action_executor';
|
||||
import { isSavedObjectExecutionSource } from './lib';
|
||||
import { RelatedSavedObjects } from './lib/related_saved_objects';
|
||||
|
||||
interface CreateExecuteFunctionOptions {
|
||||
taskManager: TaskManagerStartContract;
|
||||
|
@ -23,6 +24,7 @@ export interface ExecuteOptions extends Pick<ActionExecutorOptions, 'params' | '
|
|||
id: string;
|
||||
spaceId: string;
|
||||
apiKey: string | null;
|
||||
relatedSavedObjects?: RelatedSavedObjects;
|
||||
}
|
||||
|
||||
export type ExecutionEnqueuer = (
|
||||
|
@ -38,7 +40,7 @@ export function createExecutionEnqueuerFunction({
|
|||
}: CreateExecuteFunctionOptions) {
|
||||
return async function execute(
|
||||
unsecuredSavedObjectsClient: SavedObjectsClientContract,
|
||||
{ id, params, spaceId, source, apiKey }: ExecuteOptions
|
||||
{ id, params, spaceId, source, apiKey, relatedSavedObjects }: ExecuteOptions
|
||||
) {
|
||||
if (!isESOCanEncrypt) {
|
||||
throw new Error(
|
||||
|
@ -68,6 +70,7 @@ export function createExecutionEnqueuerFunction({
|
|||
actionId: id,
|
||||
params,
|
||||
apiKey,
|
||||
relatedSavedObjects,
|
||||
},
|
||||
executionSourceAsSavedObjectReferences(source)
|
||||
);
|
||||
|
|
|
@ -22,6 +22,7 @@ import { EVENT_LOG_ACTIONS } from '../constants/event_log';
|
|||
import { IEvent, IEventLogger, SAVED_OBJECT_REL_PRIMARY } from '../../../event_log/server';
|
||||
import { ActionsClient } from '../actions_client';
|
||||
import { ActionExecutionSource } from './action_execution_source';
|
||||
import { RelatedSavedObjects } from './related_saved_objects';
|
||||
|
||||
export interface ActionExecutorContext {
|
||||
logger: Logger;
|
||||
|
@ -42,6 +43,7 @@ export interface ExecuteOptions<Source = unknown> {
|
|||
request: KibanaRequest;
|
||||
params: Record<string, unknown>;
|
||||
source?: ActionExecutionSource<Source>;
|
||||
relatedSavedObjects?: RelatedSavedObjects;
|
||||
}
|
||||
|
||||
export type ActionExecutorContract = PublicMethodsOf<ActionExecutor>;
|
||||
|
@ -68,6 +70,7 @@ export class ActionExecutor {
|
|||
params,
|
||||
request,
|
||||
source,
|
||||
relatedSavedObjects,
|
||||
}: ExecuteOptions): Promise<ActionTypeExecutorResult<unknown>> {
|
||||
if (!this.isInitialized) {
|
||||
throw new Error('ActionExecutor not initialized');
|
||||
|
@ -154,6 +157,16 @@ export class ActionExecutor {
|
|||
},
|
||||
};
|
||||
|
||||
for (const relatedSavedObject of relatedSavedObjects || []) {
|
||||
event.kibana?.saved_objects?.push({
|
||||
rel: SAVED_OBJECT_REL_PRIMARY,
|
||||
type: relatedSavedObject.type,
|
||||
id: relatedSavedObject.id,
|
||||
type_id: relatedSavedObject.typeId,
|
||||
namespace: relatedSavedObject.namespace,
|
||||
});
|
||||
}
|
||||
|
||||
eventLogger.startTiming(event);
|
||||
let rawResult: ActionTypeExecutorResult<unknown>;
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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 { validatedRelatedSavedObjects } from './related_saved_objects';
|
||||
import { loggingSystemMock } from '../../../../../src/core/server/mocks';
|
||||
import { Logger } from '../../../../../src/core/server';
|
||||
|
||||
const loggerMock = loggingSystemMock.createLogger();
|
||||
|
||||
describe('related_saved_objects', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('validates valid objects', () => {
|
||||
ensureValid(loggerMock, undefined);
|
||||
ensureValid(loggerMock, []);
|
||||
ensureValid(loggerMock, [
|
||||
{
|
||||
id: 'some-id',
|
||||
type: 'some-type',
|
||||
},
|
||||
]);
|
||||
ensureValid(loggerMock, [
|
||||
{
|
||||
id: 'some-id',
|
||||
type: 'some-type',
|
||||
typeId: 'some-type-id',
|
||||
},
|
||||
]);
|
||||
ensureValid(loggerMock, [
|
||||
{
|
||||
id: 'some-id',
|
||||
type: 'some-type',
|
||||
namespace: 'some-namespace',
|
||||
},
|
||||
]);
|
||||
ensureValid(loggerMock, [
|
||||
{
|
||||
id: 'some-id',
|
||||
type: 'some-type',
|
||||
typeId: 'some-type-id',
|
||||
namespace: 'some-namespace',
|
||||
},
|
||||
]);
|
||||
ensureValid(loggerMock, [
|
||||
{
|
||||
id: 'some-id',
|
||||
type: 'some-type',
|
||||
},
|
||||
{
|
||||
id: 'some-id-2',
|
||||
type: 'some-type-2',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
it('handles invalid objects', () => {
|
||||
ensureInvalid(loggerMock, 42);
|
||||
ensureInvalid(loggerMock, {});
|
||||
ensureInvalid(loggerMock, [{}]);
|
||||
ensureInvalid(loggerMock, [{ id: 'some-id' }]);
|
||||
ensureInvalid(loggerMock, [{ id: 42 }]);
|
||||
ensureInvalid(loggerMock, [{ id: 'some-id', type: 'some-type', x: 42 }]);
|
||||
});
|
||||
|
||||
function ensureValid(logger: Logger, savedObjects: unknown) {
|
||||
const result = validatedRelatedSavedObjects(logger, savedObjects);
|
||||
expect(result).toEqual(savedObjects === undefined ? [] : savedObjects);
|
||||
expect(loggerMock.warn).not.toHaveBeenCalled();
|
||||
}
|
||||
|
||||
function ensureInvalid(logger: Logger, savedObjects: unknown) {
|
||||
const result = validatedRelatedSavedObjects(logger, savedObjects);
|
||||
expect(result).toEqual([]);
|
||||
|
||||
const message = loggerMock.warn.mock.calls[0][0];
|
||||
expect(message).toMatch(
|
||||
/ignoring invalid related saved objects: expected value of type \[array\] but got/
|
||||
);
|
||||
}
|
31
x-pack/plugins/actions/server/lib/related_saved_objects.ts
Normal file
31
x-pack/plugins/actions/server/lib/related_saved_objects.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 { schema, TypeOf } from '@kbn/config-schema';
|
||||
import { Logger } from '../../../../../src/core/server';
|
||||
|
||||
export type RelatedSavedObjects = TypeOf<typeof RelatedSavedObjectsSchema>;
|
||||
|
||||
const RelatedSavedObjectsSchema = schema.arrayOf(
|
||||
schema.object({
|
||||
namespace: schema.maybe(schema.string({ minLength: 1 })),
|
||||
id: schema.string({ minLength: 1 }),
|
||||
type: schema.string({ minLength: 1 }),
|
||||
// optional; for SO types like action/alert that have type id's
|
||||
typeId: schema.maybe(schema.string({ minLength: 1 })),
|
||||
}),
|
||||
{ defaultValue: [] }
|
||||
);
|
||||
|
||||
export function validatedRelatedSavedObjects(logger: Logger, data: unknown): RelatedSavedObjects {
|
||||
try {
|
||||
return RelatedSavedObjectsSchema.validate(data);
|
||||
} catch (err) {
|
||||
logger.warn(`ignoring invalid related saved objects: ${err.message}`);
|
||||
return [];
|
||||
}
|
||||
}
|
|
@ -126,6 +126,7 @@ test('executes the task by calling the executor with proper parameters', async (
|
|||
expect(mockedActionExecutor.execute).toHaveBeenCalledWith({
|
||||
actionId: '2',
|
||||
params: { baz: true },
|
||||
relatedSavedObjects: [],
|
||||
request: expect.objectContaining({
|
||||
headers: {
|
||||
// base64 encoded "123:abc"
|
||||
|
@ -247,6 +248,7 @@ test('uses API key when provided', async () => {
|
|||
expect(mockedActionExecutor.execute).toHaveBeenCalledWith({
|
||||
actionId: '2',
|
||||
params: { baz: true },
|
||||
relatedSavedObjects: [],
|
||||
request: expect.objectContaining({
|
||||
headers: {
|
||||
// base64 encoded "123:abc"
|
||||
|
@ -262,6 +264,79 @@ test('uses API key when provided', async () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('uses relatedSavedObjects when provided', async () => {
|
||||
const taskRunner = taskRunnerFactory.create({
|
||||
taskInstance: mockedTaskInstance,
|
||||
});
|
||||
|
||||
mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok', actionId: '2' });
|
||||
spaceIdToNamespace.mockReturnValueOnce('namespace-test');
|
||||
mockedEncryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({
|
||||
id: '3',
|
||||
type: 'action_task_params',
|
||||
attributes: {
|
||||
actionId: '2',
|
||||
params: { baz: true },
|
||||
apiKey: Buffer.from('123:abc').toString('base64'),
|
||||
relatedSavedObjects: [{ id: 'some-id', type: 'some-type' }],
|
||||
},
|
||||
references: [],
|
||||
});
|
||||
|
||||
await taskRunner.run();
|
||||
|
||||
expect(mockedActionExecutor.execute).toHaveBeenCalledWith({
|
||||
actionId: '2',
|
||||
params: { baz: true },
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: 'some-id',
|
||||
type: 'some-type',
|
||||
},
|
||||
],
|
||||
request: expect.objectContaining({
|
||||
headers: {
|
||||
// base64 encoded "123:abc"
|
||||
authorization: 'ApiKey MTIzOmFiYw==',
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
test('sanitizes invalid relatedSavedObjects when provided', async () => {
|
||||
const taskRunner = taskRunnerFactory.create({
|
||||
taskInstance: mockedTaskInstance,
|
||||
});
|
||||
|
||||
mockedActionExecutor.execute.mockResolvedValueOnce({ status: 'ok', actionId: '2' });
|
||||
spaceIdToNamespace.mockReturnValueOnce('namespace-test');
|
||||
mockedEncryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({
|
||||
id: '3',
|
||||
type: 'action_task_params',
|
||||
attributes: {
|
||||
actionId: '2',
|
||||
params: { baz: true },
|
||||
apiKey: Buffer.from('123:abc').toString('base64'),
|
||||
relatedSavedObjects: [{ Xid: 'some-id', type: 'some-type' }],
|
||||
},
|
||||
references: [],
|
||||
});
|
||||
|
||||
await taskRunner.run();
|
||||
|
||||
expect(mockedActionExecutor.execute).toHaveBeenCalledWith({
|
||||
actionId: '2',
|
||||
params: { baz: true },
|
||||
relatedSavedObjects: [],
|
||||
request: expect.objectContaining({
|
||||
headers: {
|
||||
// base64 encoded "123:abc"
|
||||
authorization: 'ApiKey MTIzOmFiYw==',
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
test(`doesn't use API key when not provided`, async () => {
|
||||
const factory = new TaskRunnerFactory(mockedActionExecutor);
|
||||
factory.initialize(taskRunnerFactoryInitializerParams);
|
||||
|
@ -284,6 +359,7 @@ test(`doesn't use API key when not provided`, async () => {
|
|||
expect(mockedActionExecutor.execute).toHaveBeenCalledWith({
|
||||
actionId: '2',
|
||||
params: { baz: true },
|
||||
relatedSavedObjects: [],
|
||||
request: expect.objectContaining({
|
||||
headers: {},
|
||||
}),
|
||||
|
|
|
@ -30,6 +30,7 @@ import {
|
|||
} from '../types';
|
||||
import { ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE } from '../constants/saved_objects';
|
||||
import { asSavedObjectExecutionSource } from './action_execution_source';
|
||||
import { validatedRelatedSavedObjects } from './related_saved_objects';
|
||||
|
||||
export interface TaskRunnerContext {
|
||||
logger: Logger;
|
||||
|
@ -77,7 +78,7 @@ export class TaskRunnerFactory {
|
|||
const namespace = spaceIdToNamespace(spaceId);
|
||||
|
||||
const {
|
||||
attributes: { actionId, params, apiKey },
|
||||
attributes: { actionId, params, apiKey, relatedSavedObjects },
|
||||
references,
|
||||
} = await encryptedSavedObjectsClient.getDecryptedAsInternalUser<ActionTaskParams>(
|
||||
ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE,
|
||||
|
@ -117,6 +118,7 @@ export class TaskRunnerFactory {
|
|||
actionId,
|
||||
request: fakeRequest,
|
||||
...getSourceFromReferences(references),
|
||||
relatedSavedObjects: validatedRelatedSavedObjects(logger, relatedSavedObjects),
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof ActionTypeDisabledError) {
|
||||
|
|
|
@ -65,6 +65,7 @@ describe('executeActionRoute', () => {
|
|||
someData: 'data',
|
||||
},
|
||||
source: asHttpRequestExecutionSource(req),
|
||||
relatedSavedObjects: [],
|
||||
});
|
||||
|
||||
expect(res.ok).toHaveBeenCalled();
|
||||
|
@ -101,6 +102,7 @@ describe('executeActionRoute', () => {
|
|||
expect(actionsClient.execute).toHaveBeenCalledWith({
|
||||
actionId: '1',
|
||||
params: {},
|
||||
relatedSavedObjects: [],
|
||||
source: asHttpRequestExecutionSource(req),
|
||||
});
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ export const executeActionRoute = (
|
|||
params,
|
||||
actionId: id,
|
||||
source: asHttpRequestExecutionSource(req),
|
||||
relatedSavedObjects: [],
|
||||
});
|
||||
return body
|
||||
? res.ok({
|
||||
|
|
|
@ -63,6 +63,7 @@ describe('executeActionRoute', () => {
|
|||
someData: 'data',
|
||||
},
|
||||
source: asHttpRequestExecutionSource(req),
|
||||
relatedSavedObjects: [],
|
||||
});
|
||||
|
||||
expect(res.ok).toHaveBeenCalled();
|
||||
|
@ -100,6 +101,7 @@ describe('executeActionRoute', () => {
|
|||
actionId: '1',
|
||||
params: {},
|
||||
source: asHttpRequestExecutionSource(req),
|
||||
relatedSavedObjects: [],
|
||||
});
|
||||
|
||||
expect(res.ok).not.toHaveBeenCalled();
|
||||
|
|
|
@ -48,6 +48,7 @@ export const executeActionRoute = (
|
|||
params,
|
||||
actionId: id,
|
||||
source: asHttpRequestExecutionSource(req),
|
||||
relatedSavedObjects: [],
|
||||
});
|
||||
return body
|
||||
? res.ok({
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
},
|
||||
"apiKey": {
|
||||
"type": "binary"
|
||||
},
|
||||
"relatedSavedObjects": {
|
||||
"enabled": false,
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,6 +135,14 @@ test('enqueues execution per selected action', async () => {
|
|||
"foo": true,
|
||||
"stateVal": "My goes here",
|
||||
},
|
||||
"relatedSavedObjects": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"namespace": "test1",
|
||||
"type": "alert",
|
||||
"typeId": "test",
|
||||
},
|
||||
],
|
||||
"source": Object {
|
||||
"source": Object {
|
||||
"id": "1",
|
||||
|
@ -247,6 +255,14 @@ test(`doesn't call actionsPlugin.execute for disabled actionTypes`, async () =>
|
|||
id: '1',
|
||||
type: 'alert',
|
||||
}),
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: '1',
|
||||
namespace: 'test1',
|
||||
type: 'alert',
|
||||
typeId: 'test',
|
||||
},
|
||||
],
|
||||
spaceId: 'test1',
|
||||
apiKey: createExecutionHandlerParams.apiKey,
|
||||
});
|
||||
|
@ -327,6 +343,14 @@ test('context attribute gets parameterized', async () => {
|
|||
"foo": true,
|
||||
"stateVal": "My goes here",
|
||||
},
|
||||
"relatedSavedObjects": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"namespace": "test1",
|
||||
"type": "alert",
|
||||
"typeId": "test",
|
||||
},
|
||||
],
|
||||
"source": Object {
|
||||
"source": Object {
|
||||
"id": "1",
|
||||
|
@ -360,6 +384,14 @@ test('state attribute gets parameterized', async () => {
|
|||
"foo": true,
|
||||
"stateVal": "My state-val goes here",
|
||||
},
|
||||
"relatedSavedObjects": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"namespace": "test1",
|
||||
"type": "alert",
|
||||
"typeId": "test",
|
||||
},
|
||||
],
|
||||
"source": Object {
|
||||
"source": Object {
|
||||
"id": "1",
|
||||
|
|
|
@ -157,6 +157,8 @@ export function createExecutionHandler<
|
|||
continue;
|
||||
}
|
||||
|
||||
const namespace = spaceId === 'default' ? {} : { namespace: spaceId };
|
||||
|
||||
// TODO would be nice to add the action name here, but it's not available
|
||||
const actionLabel = `${action.actionTypeId}:${action.id}`;
|
||||
const actionsClient = await actionsPlugin.getActionsClientWithRequest(request);
|
||||
|
@ -169,10 +171,16 @@ export function createExecutionHandler<
|
|||
id: alertId,
|
||||
type: 'alert',
|
||||
}),
|
||||
relatedSavedObjects: [
|
||||
{
|
||||
id: alertId,
|
||||
type: 'alert',
|
||||
namespace: namespace.namespace,
|
||||
typeId: alertType.id,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const namespace = spaceId === 'default' ? {} : { namespace: spaceId };
|
||||
|
||||
const event: IEvent = {
|
||||
event: {
|
||||
action: EVENT_LOG_ACTIONS.executeAction,
|
||||
|
|
|
@ -352,6 +352,14 @@ describe('Task Runner', () => {
|
|||
"params": Object {
|
||||
"foo": true,
|
||||
},
|
||||
"relatedSavedObjects": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"namespace": undefined,
|
||||
"type": "alert",
|
||||
"typeId": "test",
|
||||
},
|
||||
],
|
||||
"source": Object {
|
||||
"source": Object {
|
||||
"id": "1",
|
||||
|
@ -1098,6 +1106,14 @@ describe('Task Runner', () => {
|
|||
"params": Object {
|
||||
"foo": true,
|
||||
},
|
||||
"relatedSavedObjects": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"namespace": undefined,
|
||||
"type": "alert",
|
||||
"typeId": "test",
|
||||
},
|
||||
],
|
||||
"source": Object {
|
||||
"source": Object {
|
||||
"id": "1",
|
||||
|
@ -1634,6 +1650,14 @@ describe('Task Runner', () => {
|
|||
"params": Object {
|
||||
"isResolved": true,
|
||||
},
|
||||
"relatedSavedObjects": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"namespace": undefined,
|
||||
"type": "alert",
|
||||
"typeId": "test",
|
||||
},
|
||||
],
|
||||
"source": Object {
|
||||
"source": Object {
|
||||
"id": "1",
|
||||
|
@ -1826,6 +1850,14 @@ describe('Task Runner', () => {
|
|||
"params": Object {
|
||||
"isResolved": true,
|
||||
},
|
||||
"relatedSavedObjects": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"namespace": undefined,
|
||||
"type": "alert",
|
||||
"typeId": "test",
|
||||
},
|
||||
],
|
||||
"source": Object {
|
||||
"source": Object {
|
||||
"id": "1",
|
||||
|
|
|
@ -131,7 +131,7 @@ Below is a document in the expected structure, with descriptions of the fields:
|
|||
instance_id: "alert instance id, for relevant documents",
|
||||
action_group_id: "alert action group, for relevant documents",
|
||||
action_subgroup: "alert action subgroup, for relevant documents",
|
||||
status: "overall alert status, after alert execution",
|
||||
status: "overall alert status, after rule execution",
|
||||
},
|
||||
saved_objects: [
|
||||
{
|
||||
|
@ -160,21 +160,26 @@ plugins:
|
|||
- `action: execute-via-http` - generated when an action is executed via HTTP request
|
||||
|
||||
- `provider: alerting`
|
||||
- `action: execute` - generated when an alert executor runs
|
||||
- `action: execute-action` - generated when an alert schedules an action to run
|
||||
- `action: new-instance` - generated when an alert has a new instance id that is active
|
||||
- `action: recovered-instance` - generated when an alert has a previously active instance id that is no longer active
|
||||
- `action: active-instance` - generated when an alert determines an instance id is active
|
||||
- `action: execute` - generated when a rule executor runs
|
||||
- `action: execute-action` - generated when a rule schedules an action to run
|
||||
- `action: new-instance` - generated when a rule has a new instance id that is active
|
||||
- `action: recovered-instance` - generated when a rule has a previously active instance id that is no longer active
|
||||
- `action: active-instance` - generated when a rule determines an instance id is active
|
||||
|
||||
For the `saved_objects` array elements, these are references to saved objects
|
||||
associated with the event. For the `alerting` provider, those are alert saved
|
||||
ojects and for the `actions` provider those are action saved objects. The
|
||||
`alerts:execute-action` event includes both the alert and action saved object
|
||||
references. For that event, only the alert reference has the optional `rel`
|
||||
associated with the event. For the `alerting` provider, those are rule saved
|
||||
ojects and for the `actions` provider those are connector saved objects. The
|
||||
`alerts:execute-action` event includes both the rule and connector saved object
|
||||
references. For that event, only the rule reference has the optional `rel`
|
||||
property with a `primary` value. This property is used when searching the
|
||||
event log to indicate which saved objects should be directly searchable via
|
||||
saved object references. For the `alerts:execute-action` event, searching
|
||||
only via the alert saved object reference will return the event.
|
||||
saved object references. For the `alerts:execute-action` event, only searching
|
||||
via the rule saved object reference will return the event; searching via the
|
||||
connector save object reference will **NOT** return the event. The
|
||||
`actions:execute` event also includes both the rule and connector saved object
|
||||
references, and both of them have the `rel` property with a `primary` value,
|
||||
allowing those events to be returned in searches of either the rule or
|
||||
connector.
|
||||
|
||||
|
||||
## Event Log index - associated resources
|
||||
|
|
Loading…
Reference in a new issue