mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security Solution][Detection Engine] Simplify rule preview route (#216384)
## Summary Refactors `runExecutors` to take a `SecurityAlertType` instead of an alerting framework `RuleType` and moves the logic to convert the `SecurityAlertType` into a `RuleType` into `runExecutors`. This makes the signature of `runExecutors` much simpler and reduces a lot of the duplication in the `switch` below.
This commit is contained in:
parent
1fdf5d450f
commit
74722fd11b
1 changed files with 48 additions and 184 deletions
|
@ -17,8 +17,6 @@ import type {
|
|||
RuleTypeState,
|
||||
} from '@kbn/alerting-plugin/common';
|
||||
import { parseDuration, DISABLE_FLAPPING_SETTINGS } from '@kbn/alerting-plugin/common';
|
||||
import type { ExecutorType } from '@kbn/alerting-plugin/server/types';
|
||||
import type { Alert } from '@kbn/alerting-plugin/server';
|
||||
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
|
||||
import {
|
||||
DEFAULT_PREVIEW_INDEX,
|
||||
|
@ -51,7 +49,10 @@ import type { RuleExecutionContext, StatusChangeArgs } from '../../../rule_monit
|
|||
|
||||
import type { ConfigType } from '../../../../../config';
|
||||
import { alertInstanceFactoryStub } from './alert_instance_factory_stub';
|
||||
import type { CreateSecurityRuleTypeWrapperProps } from '../../../rule_types/types';
|
||||
import type {
|
||||
CreateSecurityRuleTypeWrapperProps,
|
||||
SecurityAlertType,
|
||||
} from '../../../rule_types/types';
|
||||
import {
|
||||
createEqlAlertType,
|
||||
createEsqlAlertType,
|
||||
|
@ -197,45 +198,11 @@ export const previewRulesRoute = (
|
|||
isPreview: true,
|
||||
});
|
||||
|
||||
const runExecutors = async <
|
||||
TParams extends RuleParams,
|
||||
TState extends RuleTypeState,
|
||||
TInstanceState extends AlertInstanceState,
|
||||
TInstanceContext extends AlertInstanceContext,
|
||||
TActionGroupIds extends string = ''
|
||||
>(
|
||||
executor: ExecutorType<
|
||||
TParams,
|
||||
TState,
|
||||
TInstanceState,
|
||||
TInstanceContext,
|
||||
TActionGroupIds
|
||||
>,
|
||||
ruleTypeId: string,
|
||||
ruleTypeName: string,
|
||||
params: TParams,
|
||||
shouldWriteAlerts: () => boolean,
|
||||
alertFactory: {
|
||||
create: (
|
||||
id: string
|
||||
) => Pick<
|
||||
Alert<TInstanceState, TInstanceContext, TActionGroupIds>,
|
||||
| 'getState'
|
||||
| 'replaceState'
|
||||
| 'scheduleActions'
|
||||
| 'setContext'
|
||||
| 'getContext'
|
||||
| 'hasContext'
|
||||
| 'getUuid'
|
||||
| 'getStart'
|
||||
>;
|
||||
alertLimit: {
|
||||
getValue: () => number;
|
||||
setLimitReached: () => void;
|
||||
};
|
||||
done: () => { getRecoveredAlerts: () => [] };
|
||||
}
|
||||
const runExecutors = async <TParams extends RuleParams, TState extends RuleTypeState>(
|
||||
securityRuleType: SecurityAlertType<TParams, TState>,
|
||||
params: TParams
|
||||
) => {
|
||||
const ruleType = previewRuleTypeWrapper(securityRuleType);
|
||||
let statePreview = runState as TState;
|
||||
let loggedRequests = [];
|
||||
|
||||
|
@ -260,8 +227,8 @@ export const previewRulesRoute = (
|
|||
consumer: SERVER_APP_ID,
|
||||
enabled: true,
|
||||
revision: 0,
|
||||
ruleTypeId,
|
||||
ruleTypeName,
|
||||
ruleTypeId: ruleType.id,
|
||||
ruleTypeName: ruleType.name,
|
||||
updatedAt: new Date(),
|
||||
updatedBy: username ?? 'preview-updated-by',
|
||||
muteAll: false,
|
||||
|
@ -282,16 +249,29 @@ export const previewRulesRoute = (
|
|||
while (invocationCount > 0 && !isAborted) {
|
||||
invocationStartTime = moment();
|
||||
|
||||
({ state: statePreview, loggedRequests } = (await executor({
|
||||
({ state: statePreview, loggedRequests } = (await ruleType.executor({
|
||||
executionId: uuidv4(),
|
||||
params,
|
||||
previousStartedAt,
|
||||
rule,
|
||||
services: {
|
||||
shouldWriteAlerts,
|
||||
shouldWriteAlerts: () => true,
|
||||
shouldStopExecution: () => false,
|
||||
alertsClient: null,
|
||||
alertFactory,
|
||||
alertFactory: {
|
||||
create: alertInstanceFactoryStub<
|
||||
TParams,
|
||||
TState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
'default'
|
||||
>,
|
||||
alertLimit: {
|
||||
getValue: () => 1000,
|
||||
setLimitReached: () => {},
|
||||
},
|
||||
done: () => ({ getRecoveredAlerts: () => [] }),
|
||||
},
|
||||
savedObjectsClient: coreContext.savedObjects.client,
|
||||
scopedClusterClient: wrapScopedClusterClient({
|
||||
abortController,
|
||||
|
@ -350,161 +330,45 @@ export const previewRulesRoute = (
|
|||
|
||||
switch (previewRuleParams.type) {
|
||||
case 'query':
|
||||
const queryAlertType = previewRuleTypeWrapper(
|
||||
createQueryAlertType({
|
||||
id: QUERY_RULE_TYPE_ID,
|
||||
name: 'Custom Query Rule',
|
||||
})
|
||||
);
|
||||
await runExecutors(
|
||||
queryAlertType.executor,
|
||||
queryAlertType.id,
|
||||
queryAlertType.name,
|
||||
previewRuleParams,
|
||||
() => true,
|
||||
{
|
||||
create: alertInstanceFactoryStub,
|
||||
alertLimit: {
|
||||
getValue: () => 1000,
|
||||
setLimitReached: () => {},
|
||||
},
|
||||
done: () => ({ getRecoveredAlerts: () => [] }),
|
||||
}
|
||||
);
|
||||
const queryAlertType = createQueryAlertType({
|
||||
id: QUERY_RULE_TYPE_ID,
|
||||
name: 'Custom Query Rule',
|
||||
});
|
||||
await runExecutors(queryAlertType, previewRuleParams);
|
||||
break;
|
||||
case 'saved_query':
|
||||
const savedQueryAlertType = previewRuleTypeWrapper(
|
||||
createQueryAlertType({
|
||||
id: SAVED_QUERY_RULE_TYPE_ID,
|
||||
name: 'Saved Query Rule',
|
||||
})
|
||||
);
|
||||
await runExecutors(
|
||||
savedQueryAlertType.executor,
|
||||
savedQueryAlertType.id,
|
||||
savedQueryAlertType.name,
|
||||
previewRuleParams,
|
||||
() => true,
|
||||
{
|
||||
create: alertInstanceFactoryStub,
|
||||
alertLimit: {
|
||||
getValue: () => 1000,
|
||||
setLimitReached: () => {},
|
||||
},
|
||||
done: () => ({ getRecoveredAlerts: () => [] }),
|
||||
}
|
||||
);
|
||||
const savedQueryAlertType = createQueryAlertType({
|
||||
id: SAVED_QUERY_RULE_TYPE_ID,
|
||||
name: 'Saved Query Rule',
|
||||
});
|
||||
await runExecutors(savedQueryAlertType, previewRuleParams);
|
||||
break;
|
||||
case 'threshold':
|
||||
const thresholdAlertType = previewRuleTypeWrapper(createThresholdAlertType());
|
||||
await runExecutors(
|
||||
thresholdAlertType.executor,
|
||||
thresholdAlertType.id,
|
||||
thresholdAlertType.name,
|
||||
previewRuleParams,
|
||||
() => true,
|
||||
{
|
||||
create: alertInstanceFactoryStub,
|
||||
alertLimit: {
|
||||
getValue: () => 1000,
|
||||
setLimitReached: () => {},
|
||||
},
|
||||
done: () => ({ getRecoveredAlerts: () => [] }),
|
||||
}
|
||||
);
|
||||
const thresholdAlertType = createThresholdAlertType();
|
||||
await runExecutors(thresholdAlertType, previewRuleParams);
|
||||
break;
|
||||
case 'threat_match':
|
||||
const threatMatchAlertType = previewRuleTypeWrapper(createIndicatorMatchAlertType());
|
||||
await runExecutors(
|
||||
threatMatchAlertType.executor,
|
||||
threatMatchAlertType.id,
|
||||
threatMatchAlertType.name,
|
||||
previewRuleParams,
|
||||
() => true,
|
||||
{
|
||||
create: alertInstanceFactoryStub,
|
||||
alertLimit: {
|
||||
getValue: () => 1000,
|
||||
setLimitReached: () => {},
|
||||
},
|
||||
done: () => ({ getRecoveredAlerts: () => [] }),
|
||||
}
|
||||
);
|
||||
const threatMatchAlertType = createIndicatorMatchAlertType();
|
||||
await runExecutors(threatMatchAlertType, previewRuleParams);
|
||||
break;
|
||||
case 'eql':
|
||||
const eqlAlertType = previewRuleTypeWrapper(createEqlAlertType());
|
||||
await runExecutors(
|
||||
eqlAlertType.executor,
|
||||
eqlAlertType.id,
|
||||
eqlAlertType.name,
|
||||
previewRuleParams,
|
||||
() => true,
|
||||
{
|
||||
create: alertInstanceFactoryStub,
|
||||
alertLimit: {
|
||||
getValue: () => 1000,
|
||||
setLimitReached: () => {},
|
||||
},
|
||||
done: () => ({ getRecoveredAlerts: () => [] }),
|
||||
}
|
||||
);
|
||||
const eqlAlertType = createEqlAlertType();
|
||||
await runExecutors(eqlAlertType, previewRuleParams);
|
||||
break;
|
||||
case 'esql':
|
||||
if (config.experimentalFeatures.esqlRulesDisabled) {
|
||||
throw Error('ES|QL rule type is not supported');
|
||||
}
|
||||
const esqlAlertType = previewRuleTypeWrapper(createEsqlAlertType());
|
||||
await runExecutors(
|
||||
esqlAlertType.executor,
|
||||
esqlAlertType.id,
|
||||
esqlAlertType.name,
|
||||
previewRuleParams,
|
||||
() => true,
|
||||
{
|
||||
create: alertInstanceFactoryStub,
|
||||
alertLimit: {
|
||||
getValue: () => 1000,
|
||||
setLimitReached: () => {},
|
||||
},
|
||||
done: () => ({ getRecoveredAlerts: () => [] }),
|
||||
}
|
||||
);
|
||||
const esqlAlertType = createEsqlAlertType();
|
||||
await runExecutors(esqlAlertType, previewRuleParams);
|
||||
break;
|
||||
case 'machine_learning':
|
||||
const mlAlertType = previewRuleTypeWrapper(createMlAlertType(ml));
|
||||
await runExecutors(
|
||||
mlAlertType.executor,
|
||||
mlAlertType.id,
|
||||
mlAlertType.name,
|
||||
previewRuleParams,
|
||||
() => true,
|
||||
{
|
||||
create: alertInstanceFactoryStub,
|
||||
alertLimit: {
|
||||
getValue: () => 1000,
|
||||
setLimitReached: () => {},
|
||||
},
|
||||
done: () => ({ getRecoveredAlerts: () => [] }),
|
||||
}
|
||||
);
|
||||
const mlAlertType = createMlAlertType(ml);
|
||||
await runExecutors(mlAlertType, previewRuleParams);
|
||||
break;
|
||||
case 'new_terms':
|
||||
const newTermsAlertType = previewRuleTypeWrapper(createNewTermsAlertType());
|
||||
await runExecutors(
|
||||
newTermsAlertType.executor,
|
||||
newTermsAlertType.id,
|
||||
newTermsAlertType.name,
|
||||
previewRuleParams,
|
||||
() => true,
|
||||
{
|
||||
create: alertInstanceFactoryStub,
|
||||
alertLimit: {
|
||||
getValue: () => 1000,
|
||||
setLimitReached: () => {},
|
||||
},
|
||||
done: () => ({ getRecoveredAlerts: () => [] }),
|
||||
}
|
||||
);
|
||||
const newTermsAlertType = createNewTermsAlertType();
|
||||
await runExecutors(newTermsAlertType, previewRuleParams);
|
||||
break;
|
||||
default:
|
||||
assertUnreachable(previewRuleParams);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue