diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts index 751a1fa08175..54f935ec7402 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts @@ -21,7 +21,7 @@ import { searchAfterAndBulkCreate } from '../search_after_bulk_create'; import { AlertAttributes, RuleRangeTuple } from '../types'; import { TelemetryEventsSender } from '../../../telemetry/sender'; import { BuildRuleMessage } from '../rule_messages'; -import { QueryRuleParams } from '../../schemas/rule_schemas'; +import { QueryRuleParams, SavedQueryRuleParams } from '../../schemas/rule_schemas'; export const queryExecutor = async ({ rule, @@ -36,7 +36,7 @@ export const queryExecutor = async ({ eventsTelemetry, buildRuleMessage, }: { - rule: SavedObject>; + rule: SavedObject>; tuples: RuleRangeTuple[]; listClient: ListClient; exceptionItems: ExceptionListItemSchema[]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 637826a94348..6e24e96c6e36 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -64,6 +64,7 @@ import { thresholdRuleParams, ruleParams, RuleParams, + savedQueryRuleParams, } from '../schemas/rule_schemas'; export const signalRulesAlertType = ({ @@ -261,7 +262,7 @@ export const signalRulesAlertType = ({ buildRuleMessage, }); } else if (isQueryRule(type)) { - const queryRuleSO = asTypeSpecificSO(savedObject, queryRuleParams); + const queryRuleSO = validateQueryRuleTypes(savedObject); result = await queryExecutor({ rule: queryRuleSO, tuples, @@ -382,6 +383,14 @@ export const signalRulesAlertType = ({ }; }; +const validateQueryRuleTypes = (ruleSO: SavedObject) => { + if (ruleSO.attributes.params.type === 'query') { + return asTypeSpecificSO(ruleSO, queryRuleParams); + } else { + return asTypeSpecificSO(ruleSO, savedQueryRuleParams); + } +}; + /** * This function takes a generic rule SavedObject and a type-specific schema for the rule params * and validates the SavedObject params against the schema. If they validate, it returns a SavedObject diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts index 4ae949d0cba8..d6cc7837acda 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts @@ -11,6 +11,7 @@ import { orderBy, get } from 'lodash'; import { EqlCreateSchema, QueryCreateSchema, + SavedQueryCreateSchema, ThresholdCreateSchema, } from '../../../../plugins/security_solution/common/detection_engine/schemas/request'; import { DEFAULT_SIGNALS_INDEX } from '../../../../plugins/security_solution/common/constants'; @@ -147,6 +148,57 @@ export default ({ getService }: FtrProviderContext) => { }); }); + it('should query and get back expected signal structure using a saved query rule', async () => { + const rule: SavedQueryCreateSchema = { + ...getRuleForSignalTesting(['auditbeat-*']), + type: 'saved_query', + query: `_id:${ID}`, + saved_id: 'doesnt-exist', + }; + const { id } = await createRule(supertest, rule); + await waitForRuleSuccessOrStatus(supertest, id); + await waitForSignalsToBePresent(supertest, 1, [id]); + const signalsOpen = await getSignalsByIds(supertest, [id]); + // remove rule to cut down on touch points for test changes when the rule format changes + const { rule: removedRule, ...signalNoRule } = signalsOpen.hits.hits[0]._source.signal; + expect(signalNoRule).eql({ + parents: [ + { + id: 'BhbXBmkBR346wHgn4PeZ', + type: 'event', + index: 'auditbeat-8.0.0-2019.02.19-000001', + depth: 0, + }, + ], + ancestors: [ + { + id: 'BhbXBmkBR346wHgn4PeZ', + type: 'event', + index: 'auditbeat-8.0.0-2019.02.19-000001', + depth: 0, + }, + ], + status: 'open', + depth: 1, + parent: { + id: 'BhbXBmkBR346wHgn4PeZ', + type: 'event', + index: 'auditbeat-8.0.0-2019.02.19-000001', + depth: 0, + }, + original_time: '2019-02-19T17:40:03.790Z', + original_event: { + action: 'socket_closed', + dataset: 'socket', + kind: 'event', + module: 'system', + }, + _meta: { + version: SIGNALS_TEMPLATE_VERSION, + }, + }); + }); + it('should query and get back expected signal structure when it is a signal on a signal', async () => { const rule: QueryCreateSchema = { ...getRuleForSignalTesting(['auditbeat-*']),