Skip to content

Commit

Permalink
[RAM][SECURITYSOLUTION][ALERTS] - Throw an error when user tries to s…
Browse files Browse the repository at this point in the history
…et schedule interval shorter than any action frequency (elastic#156644)

## Summary

These changes insure that alerting framework throws an exception when
user tries to set rule's schedule interval shorter than one of the
action frequencies.

The message will look like:

`"message": "Error updating rule: the interval is longer than the action
frequencies: 1h"`

TheUI changes will be addressed in the 8.9 in this ticket
elastic#155502

---------

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
e40pud and kibanamachine authored May 5, 2023
1 parent b5fc7c4 commit e1ee019
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 2 deletions.
37 changes: 35 additions & 2 deletions x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
RuleWithLegacyId,
RuleTypeRegistry,
RawRuleAction,
RuleNotifyWhen,
} from '../../types';
import {
validateRuleTypeParams,
Expand Down Expand Up @@ -685,6 +686,9 @@ async function getUpdatedAttributesFromOperations(
break;
}
default: {
if (operation.field === 'schedule') {
validateScheduleOperation(operation.value, attributes.actions, rule.id);
}
const { modifiedAttributes, isAttributeModified } = applyBulkEditOperation(
operation,
rule.attributes
Expand Down Expand Up @@ -725,8 +729,7 @@ function validateScheduleInterval(
if (!scheduleInterval) {
return;
}
const isIntervalInvalid =
parseDuration(scheduleInterval as string) < context.minimumScheduleIntervalInMs;
const isIntervalInvalid = parseDuration(scheduleInterval) < context.minimumScheduleIntervalInMs;
if (isIntervalInvalid && context.minimumScheduleInterval.enforce) {
throw Error(
`Error updating rule: the interval is less than the allowed minimum interval of ${context.minimumScheduleInterval.value}`
Expand All @@ -738,6 +741,36 @@ function validateScheduleInterval(
}
}

/**
* Validate that updated schedule interval is not longer than any of the existing action frequencies
* @param schedule Schedule interval that user tries to set
* @param actions Rule actions
*/
function validateScheduleOperation(
schedule: RawRule['schedule'],
actions: RawRule['actions'],
ruleId: string
): void {
const scheduleInterval = parseDuration(schedule.interval);
const actionsWithInvalidThrottles = [];

for (const action of actions) {
// check for actions throttled shorter than the rule schedule
if (
action.frequency?.notifyWhen === RuleNotifyWhen.THROTTLE &&
parseDuration(action.frequency.throttle!) < scheduleInterval
) {
actionsWithInvalidThrottles.push(action);
}
}

if (actionsWithInvalidThrottles.length > 0) {
throw Error(
`Error updating rule with ID "${ruleId}": the interval ${schedule.interval} is longer than the action frequencies`
);
}
}

async function prepareApiKeys(
context: RulesClientContext,
rule: SavedObjectsFindResult<RawRule>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2359,6 +2359,67 @@ describe('bulkEdit()', () => {
'Error updating rule: the interval is less than the allowed minimum interval of 3m'
);
});

test('should not update saved object and return error if schedule interval is shorter than any action frequency in the rule', async () => {
mockCreatePointInTimeFinderAsInternalUser({
saved_objects: [
{
...existingDecryptedRule,
attributes: {
...existingDecryptedRule.attributes,
actions: [
{
actionRef: 'action_0',
actionTypeId: 'test',
frequency: { notifyWhen: 'onThrottleInterval', summary: false, throttle: '5m' },
group: 'default',
params: {},
uuid: '111',
},
{
actionRef: 'action_1',
actionTypeId: '',
frequency: { notifyWhen: 'onThrottleInterval', summary: true, throttle: '10s' },
group: 'default',
params: {},
uuid: '100',
},
],
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
references: [
{
name: 'action_0',
type: 'action',
id: '1',
},
{
name: 'action_1',
type: 'action',
id: '2',
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
] as any,
},
],
});

const result = await rulesClient.bulkEdit({
operations: [
{
field: 'schedule',
operation: 'set',
value: { interval: '10m' },
},
],
});

expect(result.errors).toHaveLength(1);
expect(result.rules).toHaveLength(0);
expect(result.errors[0].message).toBe(
`Error updating rule with ID "${existingDecryptedRule.id}": the interval 10m is longer than the action frequencies`
);
});
});

describe('paramsModifier', () => {
Expand Down

0 comments on commit e1ee019

Please sign in to comment.