Skip to content
1 change: 1 addition & 0 deletions x-pack/plugins/alerting/common/alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export enum AlertExecutionStatusErrorReasons {
Unknown = 'unknown',
License = 'license',
Timeout = 'timeout',
Disabled = 'disabled',
}

export interface AlertExecutionStatus {
Expand Down
115 changes: 114 additions & 1 deletion x-pack/plugins/alerting/server/task_runner/task_runner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -399,6 +400,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -642,6 +644,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -842,6 +845,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -913,6 +917,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -1090,6 +1095,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -1158,6 +1164,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -1204,6 +1211,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -1514,6 +1522,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -1872,6 +1881,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -1994,6 +2004,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -2097,6 +2108,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -2300,6 +2312,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -2328,6 +2341,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -2359,7 +2373,9 @@ describe('Task Runner', () => {
encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({
id: '1',
type: 'alert',
attributes: {},
attributes: {
enabled: true,
},
references: [],
});

Expand Down Expand Up @@ -2396,6 +2412,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -2441,6 +2458,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -2667,6 +2685,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -2784,6 +2803,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -2900,6 +2920,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -3020,6 +3041,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -3070,6 +3092,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -3103,6 +3126,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -3144,6 +3168,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -3200,6 +3225,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -3486,6 +3512,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -3692,6 +3719,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -3889,6 +3917,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -4092,6 +4121,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -4266,6 +4296,7 @@ describe('Task Runner', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down Expand Up @@ -4401,4 +4432,86 @@ describe('Task Runner', () => {
{ refresh: false, namespace: undefined }
);
});

test('successfully bails on execution if the rule is disabled', async () => {
const state = {
...mockedTaskInstance.state,
previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(),
};
const taskRunner = new TaskRunner(
alertType,
{
...mockedTaskInstance,
state,
},
taskRunnerFactoryInitializerParams
);
rulesClient.get.mockResolvedValue(mockedAlertTypeSavedObject);
encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({
id: '1',
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: false,
},
references: [],
});
const runnerResult = await taskRunner.run();
expect(runnerResult.state.previousStartedAt?.toISOString()).toBe(state.previousStartedAt);
expect(runnerResult.schedule).toStrictEqual(mockedTaskInstance.schedule);

const eventLogger = taskRunnerFactoryInitializerParams.eventLogger;
expect(eventLogger.logEvent).toHaveBeenCalledTimes(2);
expect(eventLogger.logEvent.mock.calls[0][0]).toStrictEqual({
'@timestamp': '1970-01-01T00:00:00.000Z',
event: {
action: 'execute-start',
kind: 'alert',
category: ['alerts'],
},
kibana: {
saved_objects: [
{ rel: 'primary', type: 'alert', id: '1', namespace: undefined, type_id: 'test' },
],
task: { scheduled: '1970-01-01T00:00:00.000Z', schedule_delay: 0 },
},
rule: {
id: '1',
license: 'basic',
category: 'test',
ruleset: 'alerts',
},
message: 'alert execution start: "1"',
});
expect(eventLogger.logEvent.mock.calls[1][0]).toStrictEqual({
'@timestamp': '1970-01-01T00:00:00.000Z',
event: {
action: 'execute',
kind: 'alert',
category: ['alerts'],
reason: 'disabled',
outcome: 'failure',
},
kibana: {
saved_objects: [
{ rel: 'primary', type: 'alert', id: '1', namespace: undefined, type_id: 'test' },
],
task: {
scheduled: '1970-01-01T00:00:00.000Z',
schedule_delay: 0,
},
alerting: { status: 'error' },
},
rule: {
id: '1',
license: 'basic',
category: 'test',
ruleset: 'alerts',
},
error: {
message: 'Rule failed to execute because rule ran after it was disabled.',
},
message: 'test:1: execution failed',
});
});
});
24 changes: 19 additions & 5 deletions x-pack/plugins/alerting/server/task_runner/task_runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,22 @@ export class TaskRunner<
this.cancelled = false;
}

async getApiKeyForAlertPermissions(alertId: string, spaceId: string) {
async getDecryptedAttributes(
ruleId: string,
spaceId: string
): Promise<{ apiKey: string | null; enabled: boolean }> {
const namespace = this.context.spaceIdToNamespace(spaceId);
// Only fetch encrypted attributes here, we'll create a saved objects client
// scoped with the API key to fetch the remaining data.
const {
attributes: { apiKey },
attributes: { apiKey, enabled },
} = await this.context.encryptedSavedObjectsClient.getDecryptedAsInternalUser<RawAlert>(
'alert',
alertId,
ruleId,
{ namespace }
);

return apiKey;
return { apiKey, enabled };
}

private getFakeKibanaRequest(spaceId: string, apiKey: RawAlert['apiKey']) {
Expand Down Expand Up @@ -516,12 +519,23 @@ export class TaskRunner<
const {
params: { alertId, spaceId },
} = this.taskInstance;
let enabled: boolean;
let apiKey: string | null;
try {
apiKey = await this.getApiKeyForAlertPermissions(alertId, spaceId);
const decryptedAttributes = await this.getDecryptedAttributes(alertId, spaceId);
apiKey = decryptedAttributes.apiKey;
enabled = decryptedAttributes.enabled;
} catch (err) {
throw new ErrorWithReason(AlertExecutionStatusErrorReasons.Decrypt, err);
}

if (!enabled) {
throw new ErrorWithReason(
AlertExecutionStatusErrorReasons.Disabled,
new Error(`Rule failed to execute because rule ran after it was disabled.`)
);
}

const [services, rulesClient] = this.getServicesWithSpaceLevelPermissions(spaceId, apiKey);

let alert: SanitizedAlert<Params>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ describe('Task Runner Cancel', () => {
type: 'alert',
attributes: {
apiKey: Buffer.from('123:abc').toString('base64'),
enabled: true,
},
references: [],
});
Expand Down
Loading