Allow saved_query rules to validate properly for query executor (#98921)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Marshall Main 2021-04-30 16:22:08 -04:00 committed by GitHub
parent 5203859cf9
commit 2236633184
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 3 deletions

View file

@ -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<AlertAttributes<QueryRuleParams>>;
rule: SavedObject<AlertAttributes<QueryRuleParams | SavedQueryRuleParams>>;
tuples: RuleRangeTuple[];
listClient: ListClient;
exceptionItems: ExceptionListItemSchema[];

View file

@ -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<AlertAttributes>) => {
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

View file

@ -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-*']),