Skip to content

Commit

Permalink
Moving security context variables to server. Adding summaryBuilder fu…
Browse files Browse the repository at this point in the history
…nction to action variable definition
  • Loading branch information
ymao1 committed Dec 14, 2022
1 parent 526f376 commit b289217
Show file tree
Hide file tree
Showing 12 changed files with 207 additions and 89 deletions.
25 changes: 25 additions & 0 deletions x-pack/plugins/alerting/common/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,36 @@ export interface AlertsHealth {
};
}

export interface SummarizedAlertsWithAll {
new: {
count: number;
data: unknown[];
};
ongoing: {
count: number;
data: unknown[];
};
recovered: {
count: number;
data: unknown[];
};
all: {
count: number;
data: unknown[];
};
}

export interface ActionVariable {
name: string;
description: string;
deprecated?: boolean;
useWithTripleBracesInTemplates?: boolean;

// If this callback function is defined, this
// action variable will be available for summary
// alerts and will be generated from the list of summary
// alerts
summaryBuilder?: (alerts: SummarizedAlertsWithAll) => unknown;
}

export interface RuleMonitoringHistory extends SavedObjectAttributes {
Expand Down
10 changes: 9 additions & 1 deletion x-pack/plugins/alerting/server/task_runner/execution_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ import { RuleRunMetricsStore } from '../lib/rule_run_metrics_store';
import { injectActionParams } from './inject_action_params';
import { ExecutionHandlerOptions, RuleTaskInstance } from './types';
import { TaskRunnerContext } from './task_runner_factory';
import { transformActionParams, transformSummaryActionParams } from './transform_action_params';
import {
transformActionParams,
transformSummaryActionParams,
transformSummaryContext,
} from './transform_action_params';
import { Alert } from '../alert';
import { NormalizedRuleType } from '../rule_type_registry';
import {
Expand Down Expand Up @@ -217,6 +221,10 @@ export class ExecutionHandler<
actionsPlugin,
actionTypeId,
kibanaBaseUrl: this.taskRunnerContext.kibanaBaseUrl,
summaryContext: transformSummaryContext(
this.ruleType.actionVariables?.context,
summarizedAlerts
),
ruleUrl: this.buildRuleUrl(spaceId),
}),
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
AlertInstanceContext,
RuleTypeParams,
SanitizedRule,
ActionVariable,
SummarizedAlertsWithAll,
} from '../types';

interface TransformActionParamsOptions {
Expand All @@ -34,25 +36,6 @@ interface TransformActionParamsOptions {
ruleUrl?: string;
}

interface SummarizedAlertsWithAll {
new: {
count: number;
data: unknown[];
};
ongoing: {
count: number;
data: unknown[];
};
recovered: {
count: number;
data: unknown[];
};
all: {
count: number;
data: unknown[];
};
}

export function transformActionParams({
actionsPlugin,
alertId,
Expand Down Expand Up @@ -122,11 +105,13 @@ export function transformSummaryActionParams({
actionParams,
ruleUrl,
kibanaBaseUrl,
summaryContext,
}: {
alerts: SummarizedAlertsWithAll;
rule: SanitizedRule<RuleTypeParams>;
ruleTypeId: string;
actionsPlugin: ActionsPluginStartContract;
summaryContext: AlertInstanceContext;
actionId: string;
actionTypeId: string;
spaceId: string;
Expand All @@ -137,6 +122,7 @@ export function transformSummaryActionParams({
const variables = {
kibanaBaseUrl,
date: new Date().toISOString(),
context: summaryContext,
rule: {
params: rule.params,
id: rule.id,
Expand All @@ -155,3 +141,18 @@ export function transformSummaryActionParams({
variables
);
}

export function transformSummaryContext(
context: ActionVariable[] | undefined,
alerts: SummarizedAlertsWithAll
): AlertInstanceContext {
return (context ?? []).reduce((acc, currContext: ActionVariable) => {
if (currContext.summaryBuilder) {
return {
...acc,
[currContext.name]: currContext.summaryBuilder(alerts),
};
}
return acc;
}, {});
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ export const createPersistenceRuleTypeWrapper: CreatePersistenceRuleTypeWrapper
};
})
.filter((_, idx) => response.body.items[idx].create?.status === 201);
console.log(`persistence alerts ${createdAlerts.length}`);

createdAlerts.forEach((alert) =>
options.services.alertFactory.create(alert._id).scheduleActions('default', {})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import agent from 'elastic-apm-node';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { TIMESTAMP } from '@kbn/rule-data-utils';
import { createPersistenceRuleTypeWrapper } from '@kbn/rule-registry-plugin/server';
import { parseScheduleDates } from '@kbn/securitysolution-io-ts-utils';

import { buildExceptionFilter } from '@kbn/lists-plugin/server/services/exception_lists';
import {
Expand All @@ -25,10 +24,6 @@ import {
import { DEFAULT_MAX_SIGNALS, DEFAULT_SEARCH_AFTER_PAGE_SIZE } from '../../../../common/constants';
import type { CreateSecurityRuleTypeWrapper } from './types';
import { getListClient } from './utils/get_list_client';
// eslint-disable-next-line no-restricted-imports
import type { NotificationRuleTypeParams } from '../rule_actions_legacy';
// eslint-disable-next-line no-restricted-imports
import { getNotificationResultsLink } from '../rule_actions_legacy';
import { createResultObject } from './utils';
import { bulkCreateFactory, wrapHitsFactory, wrapSequencesFactory } from './factories';
import { RuleExecutionStatus } from '../../../../common/detection_engine/rule_monitoring';
Expand Down Expand Up @@ -71,15 +66,8 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper =
let runState = state;
let inputIndex: string[] = [];
let runtimeMappings: estypes.MappingRuntimeFields | undefined;
const {
from,
maxSignals,
meta,
ruleId,
timestampOverride,
timestampOverrideFallbackDisabled,
to,
} = params;
const { from, maxSignals, timestampOverride, timestampOverrideFallbackDisabled, to } =
params;
const {
alertWithPersistence,
savedObjectsClient,
Expand Down Expand Up @@ -110,7 +98,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper =

const {
actions,
name,
schedule: { interval },
} = completeRule.ruleConfig;

Expand All @@ -127,12 +114,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper =
let wroteWarningStatus = false;
let hasError = false;

const notificationRuleParams: NotificationRuleTypeParams = {
...params,
name,
id: rule.id,
};

const primaryTimestamp = timestampOverride ?? TIMESTAMP;
const secondaryTimestamp =
primaryTimestamp !== TIMESTAMP && !timestampOverrideFallbackDisabled
Expand Down Expand Up @@ -383,47 +364,6 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper =

const createdSignalsCount = result.createdSignals.length;

if (actions.length) {
const fromInMs = parseScheduleDates(`now-${interval}`)?.format('x');
const toInMs = parseScheduleDates('now')?.format('x');
const resultsLink = getNotificationResultsLink({
from: fromInMs,
to: toInMs,
id: rule.id,
kibanaSiemAppUrl: (meta as { kibana_siem_app_url?: string } | undefined)
?.kibana_siem_app_url,
});

ruleExecutionLogger.debug(`Found ${createdSignalsCount} signals for notification.`);

// if (completeRule.ruleConfig.throttle != null) {
// // NOTE: Since this is throttled we have to call it even on an error condition, otherwise it will "reset" the throttle and fire early
// await scheduleThrottledNotificationActions({
// alertInstance: services.alertFactory.create(rule.id),
// throttle: completeRule.ruleConfig.throttle ?? '',
// startedAt,
// id: rule.id,
// kibanaSiemAppUrl: (meta as { kibana_siem_app_url?: string } | undefined)
// ?.kibana_siem_app_url,
// outputIndex: ruleDataClient.indexNameWithNamespace(spaceId),
// ruleId,
// esClient: services.scopedClusterClient.asCurrentUser,
// notificationRuleParams,
// signals: result.createdSignals,
// logger,
// });
// } else if (createdSignalsCount) {
// const alertInstance = services.alertFactory.create(rule.id);
// scheduleNotificationActions({
// alertInstance,
// signalsCount: createdSignalsCount,
// signals: result.createdSignals,
// resultsLink,
// ruleParams: notificationRuleParams,
// });
// }
}

if (result.success) {
ruleExecutionLogger.debug('[+] Signal Rule execution completed.');
ruleExecutionLogger.debug(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { eqlRuleParams } from '../../rule_schema';
import { eqlExecutor } from '../../signals/executors/eql';
import type { CreateRuleOptions, SecurityAlertType } from '../types';
import { validateIndexPatterns } from '../utils';
import { getActionContext } from '../utils/helpers';

export const createEqlAlertType = (
createOptions: CreateRuleOptions
Expand Down Expand Up @@ -55,7 +56,7 @@ export const createEqlAlertType = (
],
defaultActionGroupId: 'default',
actionVariables: {
context: [{ name: 'server', description: 'the server' }],
context: getActionContext('eql'),
},
minimumLicenseRequired: 'basic',
isExportable: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { threatRuleParams } from '../../rule_schema';
import { threatMatchExecutor } from '../../signals/executors/threat_match';
import type { CreateRuleOptions, SecurityAlertType } from '../types';
import { validateIndexPatterns } from '../utils';
import { getActionContext } from '../utils/helpers';

export const createIndicatorMatchAlertType = (
createOptions: CreateRuleOptions
Expand Down Expand Up @@ -56,7 +57,7 @@ export const createIndicatorMatchAlertType = (
],
defaultActionGroupId: 'default',
actionVariables: {
context: [{ name: 'server', description: 'the server' }],
context: getActionContext('threat_match'),
},
minimumLicenseRequired: 'basic',
isExportable: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { MachineLearningRuleParams } from '../../rule_schema';
import { machineLearningRuleParams } from '../../rule_schema';
import { mlExecutor } from '../../signals/executors/ml';
import type { CreateRuleOptions, SecurityAlertType } from '../types';
import { getActionContext } from '../utils/helpers';

export const createMlAlertType = (
createOptions: CreateRuleOptions
Expand Down Expand Up @@ -43,7 +44,7 @@ export const createMlAlertType = (
],
defaultActionGroupId: 'default',
actionVariables: {
context: [{ name: 'server', description: 'the server' }],
context: getActionContext('machine_learning'),
},
minimumLicenseRequired: 'basic',
isExportable: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
getUnprocessedExceptionsWarnings,
} from '../../signals/utils';
import { createEnrichEventsFunction } from '../../signals/enrichments';
import { getActionContext } from '../utils/helpers';

export const createNewTermsAlertType = (
createOptions: CreateRuleOptions
Expand Down Expand Up @@ -86,7 +87,7 @@ export const createNewTermsAlertType = (
],
defaultActionGroupId: 'default',
actionVariables: {
context: [{ name: 'server', description: 'the server' }],
context: getActionContext('new_terms'),
},
minimumLicenseRequired: 'basic',
isExportable: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { unifiedQueryRuleParams } from '../../rule_schema';
import { queryExecutor } from '../../signals/executors/query';
import type { CreateQueryRuleOptions, SecurityAlertType } from '../types';
import { validateIndexPatterns } from '../utils';
import { getActionContext } from '../utils/helpers';

export interface QueryRuleState {
suppressionGroupHistory?: BucketHistory[];
Expand Down Expand Up @@ -68,7 +69,7 @@ export const createQueryAlertType = (
],
defaultActionGroupId: 'default',
actionVariables: {
context: [{ name: 'server', description: 'the server' }],
context: getActionContext('query'),
},
minimumLicenseRequired: 'basic',
isExportable: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { thresholdExecutor } from '../../signals/executors/threshold';
import type { ThresholdAlertState } from '../../signals/types';
import type { CreateRuleOptions, SecurityAlertType } from '../types';
import { validateIndexPatterns } from '../utils';
import { getActionContext } from '../utils/helpers';

export const createThresholdAlertType = (
createOptions: CreateRuleOptions
Expand Down Expand Up @@ -56,7 +57,7 @@ export const createThresholdAlertType = (
],
defaultActionGroupId: 'default',
actionVariables: {
context: [{ name: 'server', description: 'the server' }],
context: getActionContext('threshold'),
},
minimumLicenseRequired: 'basic',
isExportable: false,
Expand Down
Loading

0 comments on commit b289217

Please sign in to comment.