[SIEM][Detection Engine] Fixes TypeScript types and adds format to time range query
## Summary * Fixes the Type Script types so we don't have to use non-null-assertions * Adds null checks where needed * Changes the time range query to have a format of epoch to avoid mapping issues ### Checklist - [x] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios
This commit is contained in:
parent
7e3c68bb7a
commit
5218e30487
|
@ -70,7 +70,7 @@ const MetaRule = t.intersection([
|
|||
}),
|
||||
t.partial({
|
||||
throttle: t.string,
|
||||
kibanaSiemAppUrl: t.string,
|
||||
kibana_siem_app_url: t.string,
|
||||
}),
|
||||
]);
|
||||
|
||||
|
|
|
@ -515,7 +515,7 @@ describe('helpers', () => {
|
|||
actions: [],
|
||||
enabled: false,
|
||||
meta: {
|
||||
kibanaSiemAppUrl: 'http://localhost:5601/app/siem',
|
||||
kibana_siem_app_url: 'http://localhost:5601/app/siem',
|
||||
},
|
||||
throttle: 'no_actions',
|
||||
};
|
||||
|
@ -533,7 +533,7 @@ describe('helpers', () => {
|
|||
actions: [],
|
||||
enabled: false,
|
||||
meta: {
|
||||
kibanaSiemAppUrl: mockStepData.kibanaSiemAppUrl,
|
||||
kibana_siem_app_url: mockStepData.kibanaSiemAppUrl,
|
||||
},
|
||||
throttle: 'no_actions',
|
||||
};
|
||||
|
@ -566,7 +566,7 @@ describe('helpers', () => {
|
|||
],
|
||||
enabled: false,
|
||||
meta: {
|
||||
kibanaSiemAppUrl: mockStepData.kibanaSiemAppUrl,
|
||||
kibana_siem_app_url: mockStepData.kibanaSiemAppUrl,
|
||||
},
|
||||
throttle: 'rule',
|
||||
};
|
||||
|
@ -599,7 +599,7 @@ describe('helpers', () => {
|
|||
],
|
||||
enabled: false,
|
||||
meta: {
|
||||
kibanaSiemAppUrl: mockStepData.kibanaSiemAppUrl,
|
||||
kibana_siem_app_url: mockStepData.kibanaSiemAppUrl,
|
||||
},
|
||||
throttle: mockStepData.throttle,
|
||||
};
|
||||
|
@ -631,7 +631,7 @@ describe('helpers', () => {
|
|||
],
|
||||
enabled: false,
|
||||
meta: {
|
||||
kibanaSiemAppUrl: mockStepData.kibanaSiemAppUrl,
|
||||
kibana_siem_app_url: mockStepData.kibanaSiemAppUrl,
|
||||
},
|
||||
throttle: 'no_actions',
|
||||
};
|
||||
|
|
|
@ -155,7 +155,7 @@ export const formatActionsStepData = (actionsStepData: ActionsStepRule): Actions
|
|||
enabled,
|
||||
throttle: actions.length ? throttle : NOTIFICATION_THROTTLE_NO_ACTIONS,
|
||||
meta: {
|
||||
kibanaSiemAppUrl,
|
||||
kibana_siem_app_url: kibanaSiemAppUrl,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ export const getActionsStepsData = (
|
|||
actions: actions?.map(transformRuleToAlertAction),
|
||||
isNew: false,
|
||||
throttle,
|
||||
kibanaSiemAppUrl: meta?.kibanaSiemAppUrl,
|
||||
kibanaSiemAppUrl: meta?.kibana_siem_app_url,
|
||||
enabled,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -41,6 +41,7 @@ describe('buildSignalsSearchQuery', () => {
|
|||
'@timestamp': {
|
||||
gt: from,
|
||||
lte: to,
|
||||
format: 'epoch_millis',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -32,6 +32,7 @@ export const buildSignalsSearchQuery = ({ ruleId, index, from, to }: BuildSignal
|
|||
'@timestamp': {
|
||||
gt: from,
|
||||
lte: to,
|
||||
format: 'epoch_millis',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -53,7 +53,7 @@ export const rulesNotificationAlertType = ({
|
|||
from: fromInMs,
|
||||
to: toInMs,
|
||||
index: ruleParams.outputIndex,
|
||||
ruleId: ruleParams.ruleId!,
|
||||
ruleId: ruleParams.ruleId,
|
||||
callCluster: services.callCluster,
|
||||
});
|
||||
|
||||
|
@ -61,14 +61,14 @@ export const rulesNotificationAlertType = ({
|
|||
from: fromInMs,
|
||||
to: toInMs,
|
||||
id: ruleAlertSavedObject.id,
|
||||
kibanaSiemAppUrl: ruleAlertParams.meta?.kibanaSiemAppUrl as string,
|
||||
kibanaSiemAppUrl: ruleAlertParams.meta?.kibana_siem_app_url,
|
||||
});
|
||||
|
||||
logger.info(
|
||||
`Found ${signalsCount} signals using signal rule name: "${ruleParams.name}", id: "${params.ruleAlertId}", rule_id: "${ruleParams.ruleId}" in "${ruleParams.outputIndex}" index`
|
||||
);
|
||||
|
||||
if (signalsCount) {
|
||||
if (signalsCount !== 0) {
|
||||
const alertInstance = services.alertInstanceFactory(alertId);
|
||||
scheduleNotificationActions({ alertInstance, signalsCount, resultsLink, ruleParams });
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import { mapKeys, snakeCase } from 'lodash/fp';
|
|||
import { AlertInstance } from '../../../../../../../plugins/alerting/server';
|
||||
import { RuleTypeParams } from '../types';
|
||||
|
||||
type NotificationRuleTypeParams = RuleTypeParams & {
|
||||
export type NotificationRuleTypeParams = RuleTypeParams & {
|
||||
name: string;
|
||||
id: string;
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ export const getNotificationResultsLink = ({
|
|||
from,
|
||||
to,
|
||||
}: {
|
||||
kibanaSiemAppUrl: string;
|
||||
kibanaSiemAppUrl?: string;
|
||||
id: string;
|
||||
from?: string;
|
||||
to?: string;
|
||||
|
|
|
@ -121,15 +121,15 @@ export const patchRulesBulkRoute = (router: IRouter) => {
|
|||
anomalyThreshold,
|
||||
machineLearningJobId,
|
||||
});
|
||||
if (rule != null) {
|
||||
if (rule != null && rule.enabled != null && rule.name != null) {
|
||||
const ruleActions = await updateRulesNotifications({
|
||||
ruleAlertId: rule.id,
|
||||
alertsClient,
|
||||
savedObjectsClient,
|
||||
enabled: rule.enabled!,
|
||||
enabled: rule.enabled,
|
||||
actions,
|
||||
throttle,
|
||||
name: rule.name!,
|
||||
name: rule.name,
|
||||
});
|
||||
const ruleStatuses = await savedObjectsClient.find<
|
||||
IRuleSavedAttributesSavedObjectAttributes
|
||||
|
|
|
@ -117,15 +117,15 @@ export const patchRulesRoute = (router: IRouter) => {
|
|||
anomalyThreshold,
|
||||
machineLearningJobId,
|
||||
});
|
||||
if (rule != null) {
|
||||
if (rule != null && rule.enabled != null && rule.name != null) {
|
||||
const ruleActions = await updateRulesNotifications({
|
||||
ruleAlertId: rule.id,
|
||||
alertsClient,
|
||||
savedObjectsClient,
|
||||
enabled: rule.enabled!,
|
||||
enabled: rule.enabled,
|
||||
actions,
|
||||
throttle,
|
||||
name: rule.name!,
|
||||
name: rule.name,
|
||||
});
|
||||
const ruleStatuses = await savedObjectsClient.find<
|
||||
IRuleSavedAttributesSavedObjectAttributes
|
||||
|
|
|
@ -309,7 +309,7 @@ export const validateLicenseForRuleType = ({
|
|||
}: {
|
||||
license: ILicense;
|
||||
ruleType: RuleType;
|
||||
}) => {
|
||||
}): void => {
|
||||
if (isMlRule(ruleType) && !license.hasAtLeast(MINIMUM_ML_LICENSE)) {
|
||||
const message = i18n.translate('xpack.siem.licensing.unsupportedMachineLearningMessage', {
|
||||
defaultMessage:
|
||||
|
|
|
@ -14,7 +14,7 @@ interface CreateRuleActionsSavedObject {
|
|||
ruleAlertId: string;
|
||||
savedObjectsClient: AlertServices['savedObjectsClient'];
|
||||
actions: RuleAlertAction[] | undefined;
|
||||
throttle: string | undefined;
|
||||
throttle: string | null | undefined;
|
||||
}
|
||||
|
||||
export const createRuleActionsSavedObject = async ({
|
||||
|
@ -22,7 +22,12 @@ export const createRuleActionsSavedObject = async ({
|
|||
savedObjectsClient,
|
||||
actions = [],
|
||||
throttle,
|
||||
}: CreateRuleActionsSavedObject) => {
|
||||
}: CreateRuleActionsSavedObject): Promise<{
|
||||
id: string;
|
||||
actions: RuleAlertAction[];
|
||||
alertThrottle: string | null;
|
||||
ruleThrottle: string;
|
||||
}> => {
|
||||
const ruleActionsSavedObject = await savedObjectsClient.create<
|
||||
IRuleActionsAttributesSavedObjectAttributes
|
||||
>(ruleActionsSavedObjectType, {
|
||||
|
|
|
@ -16,7 +16,7 @@ interface DeleteRuleActionsSavedObject {
|
|||
export const deleteRuleActionsSavedObject = async ({
|
||||
ruleAlertId,
|
||||
savedObjectsClient,
|
||||
}: DeleteRuleActionsSavedObject) => {
|
||||
}: DeleteRuleActionsSavedObject): Promise<{} | null> => {
|
||||
const ruleActions = await getRuleActionsSavedObject({ ruleAlertId, savedObjectsClient });
|
||||
|
||||
if (!ruleActions) return null;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { RuleAlertAction } from '../../../../common/detection_engine/types';
|
||||
import { AlertServices } from '../../../../../../../plugins/alerting/server';
|
||||
import { ruleActionsSavedObjectType } from './saved_object_mappings';
|
||||
import { IRuleActionsAttributesSavedObjectAttributes } from './types';
|
||||
|
@ -17,7 +18,12 @@ interface GetRuleActionsSavedObject {
|
|||
export const getRuleActionsSavedObject = async ({
|
||||
ruleAlertId,
|
||||
savedObjectsClient,
|
||||
}: GetRuleActionsSavedObject) => {
|
||||
}: GetRuleActionsSavedObject): Promise<{
|
||||
id: string;
|
||||
actions: RuleAlertAction[];
|
||||
alertThrottle: string | null;
|
||||
ruleThrottle: string;
|
||||
} | null> => {
|
||||
const { saved_objects } = await savedObjectsClient.find<
|
||||
IRuleActionsAttributesSavedObjectAttributes
|
||||
>({
|
||||
|
|
|
@ -15,7 +15,7 @@ interface UpdateOrCreateRuleActionsSavedObject {
|
|||
ruleAlertId: string;
|
||||
savedObjectsClient: AlertServices['savedObjectsClient'];
|
||||
actions: RuleAlertAction[] | undefined;
|
||||
throttle: string | undefined;
|
||||
throttle: string | null | undefined;
|
||||
}
|
||||
|
||||
export const updateOrCreateRuleActionsSavedObject = async ({
|
||||
|
|
|
@ -15,7 +15,7 @@ interface DeleteRuleActionsSavedObject {
|
|||
ruleAlertId: string;
|
||||
savedObjectsClient: AlertServices['savedObjectsClient'];
|
||||
actions: RuleAlertAction[] | undefined;
|
||||
throttle: string | undefined;
|
||||
throttle: string | null | undefined;
|
||||
}
|
||||
|
||||
export const updateRuleActionsSavedObject = async ({
|
||||
|
@ -23,7 +23,12 @@ export const updateRuleActionsSavedObject = async ({
|
|||
savedObjectsClient,
|
||||
actions,
|
||||
throttle,
|
||||
}: DeleteRuleActionsSavedObject) => {
|
||||
}: DeleteRuleActionsSavedObject): Promise<{
|
||||
ruleThrottle: string;
|
||||
alertThrottle: string | null;
|
||||
actions: RuleAlertAction[];
|
||||
id: string;
|
||||
} | null> => {
|
||||
const ruleActions = await getRuleActionsSavedObject({ ruleAlertId, savedObjectsClient });
|
||||
|
||||
if (!ruleActions) return null;
|
||||
|
|
|
@ -5,16 +5,27 @@
|
|||
*/
|
||||
|
||||
import { SavedObjectsUpdateResponse } from 'kibana/server';
|
||||
import { RuleAlertAction } from '../../../../common/detection_engine/types';
|
||||
import { IRuleActionsAttributesSavedObjectAttributes } from './types';
|
||||
|
||||
export const getThrottleOptions = (throttle = 'no_actions') => ({
|
||||
ruleThrottle: throttle,
|
||||
alertThrottle: ['no_actions', 'rule'].includes(throttle) ? null : throttle,
|
||||
export const getThrottleOptions = (
|
||||
throttle: string | undefined | null = 'no_actions'
|
||||
): {
|
||||
ruleThrottle: string;
|
||||
alertThrottle: string | null;
|
||||
} => ({
|
||||
ruleThrottle: throttle ?? 'no_actions',
|
||||
alertThrottle: ['no_actions', 'rule'].includes(throttle ?? 'no_actions') ? null : throttle,
|
||||
});
|
||||
|
||||
export const getRuleActionsFromSavedObject = (
|
||||
savedObject: SavedObjectsUpdateResponse<IRuleActionsAttributesSavedObjectAttributes>
|
||||
) => ({
|
||||
): {
|
||||
id: string;
|
||||
actions: RuleAlertAction[];
|
||||
alertThrottle: string | null;
|
||||
ruleThrottle: string;
|
||||
} => ({
|
||||
id: savedObject.id,
|
||||
actions: savedObject.attributes.actions || [],
|
||||
alertThrottle: savedObject.attributes.alertThrottle || null,
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { AlertsClient, AlertServices } from '../../../../../../../plugins/alerting/server';
|
||||
import {
|
||||
AlertsClient,
|
||||
AlertServices,
|
||||
PartialAlert,
|
||||
} from '../../../../../../../plugins/alerting/server';
|
||||
import { getRuleActionsSavedObject } from '../rule_actions/get_rule_actions_saved_object';
|
||||
import { readRules } from './read_rules';
|
||||
import { transformRuleToAlertAction } from '../../../../common/detection_engine/transform_actions';
|
||||
|
@ -19,7 +23,7 @@ export const updateRuleActions = async ({
|
|||
alertsClient,
|
||||
savedObjectsClient,
|
||||
ruleAlertId,
|
||||
}: UpdateRuleActions) => {
|
||||
}: UpdateRuleActions): Promise<PartialAlert | null> => {
|
||||
const rule = await readRules({ alertsClient, id: ruleAlertId });
|
||||
if (rule == null) {
|
||||
return null;
|
||||
|
|
|
@ -9,13 +9,14 @@ import { AlertsClient, AlertServices } from '../../../../../../../plugins/alerti
|
|||
import { updateOrCreateRuleActionsSavedObject } from '../rule_actions/update_or_create_rule_actions_saved_object';
|
||||
import { updateNotifications } from '../notifications/update_notifications';
|
||||
import { updateRuleActions } from './update_rule_actions';
|
||||
import { RuleActions } from '../rule_actions/types';
|
||||
|
||||
interface UpdateRulesNotifications {
|
||||
alertsClient: AlertsClient;
|
||||
savedObjectsClient: AlertServices['savedObjectsClient'];
|
||||
ruleAlertId: string;
|
||||
actions: RuleAlertAction[] | undefined;
|
||||
throttle: string | undefined;
|
||||
throttle: string | null | undefined;
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
}
|
||||
|
@ -28,7 +29,7 @@ export const updateRulesNotifications = async ({
|
|||
enabled,
|
||||
name,
|
||||
throttle,
|
||||
}: UpdateRulesNotifications) => {
|
||||
}: UpdateRulesNotifications): Promise<RuleActions> => {
|
||||
const ruleActions = await updateOrCreateRuleActionsSavedObject({
|
||||
savedObjectsClient,
|
||||
ruleAlertId,
|
||||
|
|
|
@ -47,7 +47,7 @@ const getPayload = (
|
|||
interval: ruleAlert.schedule.interval,
|
||||
name: ruleAlert.name,
|
||||
tags: ruleAlert.tags,
|
||||
throttle: ruleAlert.throttle!,
|
||||
throttle: ruleAlert.throttle,
|
||||
scrollSize: 10,
|
||||
scrollLock: '0',
|
||||
},
|
||||
|
|
|
@ -24,7 +24,10 @@ import { signalParamsSchema } from './signal_params_schema';
|
|||
import { siemRuleActionGroups } from './siem_rule_action_groups';
|
||||
import { findMlSignals } from './find_ml_signals';
|
||||
import { bulkCreateMlSignals } from './bulk_create_ml_signals';
|
||||
import { scheduleNotificationActions } from '../notifications/schedule_notification_actions';
|
||||
import {
|
||||
scheduleNotificationActions,
|
||||
NotificationRuleTypeParams,
|
||||
} from '../notifications/schedule_notification_actions';
|
||||
import { ruleStatusServiceFactory } from './rule_status_service';
|
||||
import { buildRuleMessageFactory } from './rule_messages';
|
||||
import { ruleStatusSavedObjectsClientFactory } from './rule_status_saved_objects_client';
|
||||
|
@ -246,7 +249,7 @@ export const signalRulesAlertType = ({
|
|||
|
||||
if (result.success) {
|
||||
if (actions.length) {
|
||||
const notificationRuleParams = {
|
||||
const notificationRuleParams: NotificationRuleTypeParams = {
|
||||
...ruleParams,
|
||||
name,
|
||||
id: savedObject.id,
|
||||
|
@ -259,7 +262,7 @@ export const signalRulesAlertType = ({
|
|||
from: fromInMs,
|
||||
to: toInMs,
|
||||
id: savedObject.id,
|
||||
kibanaSiemAppUrl: meta?.kibanaSiemAppUrl as string,
|
||||
kibanaSiemAppUrl: meta?.kibana_siem_app_url,
|
||||
});
|
||||
|
||||
logger.info(
|
||||
|
|
|
@ -162,5 +162,5 @@ export interface AlertAttributes {
|
|||
}
|
||||
|
||||
export interface RuleAlertAttributes extends AlertAttributes {
|
||||
params: RuleAlertParams;
|
||||
params: Omit<RuleAlertParams, 'ruleId'> & { ruleId: string };
|
||||
}
|
||||
|
|
|
@ -29,6 +29,11 @@ export interface ThreatParams {
|
|||
// We don't have the input types defined through io-ts just yet but as we being introducing types from there we will more and more remove
|
||||
// types and share them between input and output schema but have an input Rule Schema and an output Rule Schema.
|
||||
|
||||
export interface Meta {
|
||||
[key: string]: {} | string | undefined | null;
|
||||
kibana_siem_app_url?: string | undefined;
|
||||
}
|
||||
|
||||
export interface RuleAlertParams {
|
||||
actions: RuleAlertAction[];
|
||||
anomalyThreshold: number | undefined;
|
||||
|
@ -51,7 +56,7 @@ export interface RuleAlertParams {
|
|||
query: string | undefined | null;
|
||||
references: string[];
|
||||
savedId?: string | undefined | null;
|
||||
meta: Record<string, {} | string> | undefined | null;
|
||||
meta: Meta | undefined | null;
|
||||
severity: string;
|
||||
tags: string[];
|
||||
to: string;
|
||||
|
@ -60,7 +65,7 @@ export interface RuleAlertParams {
|
|||
threat: ThreatParams[] | undefined | null;
|
||||
type: RuleType;
|
||||
version: number;
|
||||
throttle: string;
|
||||
throttle: string | undefined | null;
|
||||
lists: ListsDefaultArraySchema | null | undefined;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue