mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
# Backport This will backport the following commits from `main` to `8.18`: - [[Security Solution] Adds prebuilt rule customization integration tests (#207016)](https://github.com/elastic/kibana/pull/207016) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Davis Plumlee","email":"56367316+dplumlee@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-02-24T14:35:17Z","message":"[Security Solution] Adds prebuilt rule customization integration tests (#207016)\n\n## Summary\n\nAdds tests in accordance to\nhttps://github.com/elastic/kibana/pull/204888\n\nAdds integration tests for the prebuilt rule customization features\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [x] 🟢 ESS x100:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7919\n- [x] 🟡 Serverless x100:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7920\n- [x] 🟡 Serverless x100\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7927\n\n---------\n\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"a51e96eae2904aa3488af1037d87d83beec2cd0d","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["test","release_note:skip","v9.0.0","Team:Detections and Resp","Team: SecuritySolution","Team:Detection Rule Management","Feature:Prebuilt Detection Rules","backport:version","v8.18.0","v9.1.0","v8.19.0"],"title":"[Security Solution] Adds prebuilt rule customization integration tests","number":207016,"url":"https://github.com/elastic/kibana/pull/207016","mergeCommit":{"message":"[Security Solution] Adds prebuilt rule customization integration tests (#207016)\n\n## Summary\n\nAdds tests in accordance to\nhttps://github.com/elastic/kibana/pull/204888\n\nAdds integration tests for the prebuilt rule customization features\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [x] 🟢 ESS x100:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7919\n- [x] 🟡 Serverless x100:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7920\n- [x] 🟡 Serverless x100\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7927\n\n---------\n\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"a51e96eae2904aa3488af1037d87d83beec2cd0d"}},"sourceBranch":"main","suggestedTargetBranches":["8.18","8.x"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"url":"https://github.com/elastic/kibana/pull/212253","number":212253,"state":"MERGED","mergeCommit":{"sha":"c8beef4b9608465b14a097d8ab5fecb8fffbff5b","message":"[9.0] [Security Solution] Adds prebuilt rule customization integration tests (#207016) (#212253)\n\n# Backport\n\nThis will backport the following commits from `main` to `9.0`:\n- [[Security Solution] Adds prebuilt rule customization integration\ntests (#207016)](https://github.com/elastic/kibana/pull/207016)\n\n\n\n### Questions ?\nPlease refer to the [Backport tool\ndocumentation](https://github.com/sorenlouv/backport)\n\n\n\nCo-authored-by: Davis Plumlee <56367316+dplumlee@users.noreply.github.com>"}},{"branch":"8.18","label":"v8.18.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/207016","number":207016,"mergeCommit":{"message":"[Security Solution] Adds prebuilt rule customization integration tests (#207016)\n\n## Summary\n\nAdds tests in accordance to\nhttps://github.com/elastic/kibana/pull/204888\n\nAdds integration tests for the prebuilt rule customization features\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] [Flaky Test\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\nused on any tests changed\n- [x] 🟢 ESS x100:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7919\n- [x] 🟡 Serverless x100:\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7920\n- [x] 🟡 Serverless x100\nhttps://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/7927\n\n---------\n\nCo-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>","sha":"a51e96eae2904aa3488af1037d87d83beec2cd0d"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
This commit is contained in:
parent
2f193a9859
commit
b1da764d7d
2 changed files with 925 additions and 0 deletions
|
@ -12,6 +12,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => {
|
|||
loadTestFile(require.resolve('./is_customized_calculation'));
|
||||
loadTestFile(require.resolve('./import_rules'));
|
||||
loadTestFile(require.resolve('./rules_export'));
|
||||
loadTestFile(require.resolve('./rule_customization'));
|
||||
loadTestFile(require.resolve('./preview_prebuilt_rules_upgrade'));
|
||||
loadTestFile(require.resolve('./upgrade_prebuilt_rules'));
|
||||
});
|
||||
|
|
|
@ -0,0 +1,924 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import expect from 'expect';
|
||||
import {
|
||||
getPrebuiltRuleMock,
|
||||
getPrebuiltRuleMockOfType,
|
||||
} from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks';
|
||||
import { deleteAllRules } from '../../../../../../../common/utils/security_solution';
|
||||
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
|
||||
import {
|
||||
createPrebuiltRuleAssetSavedObjects,
|
||||
createRuleAssetSavedObject,
|
||||
deleteAllPrebuiltRuleAssets,
|
||||
getWebHookAction,
|
||||
installPrebuiltRules,
|
||||
} from '../../../../utils';
|
||||
|
||||
export default ({ getService }: FtrProviderContext): void => {
|
||||
const es = getService('es');
|
||||
const supertest = getService('supertest');
|
||||
const securitySolutionApi = getService('securitySolutionApi');
|
||||
const log = getService('log');
|
||||
|
||||
const ruleAsset = createRuleAssetSavedObject({
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
|
||||
describe('@ess @serverless @skipInServerlessMKI rule customization', () => {
|
||||
before(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
describe('detecting rule customizations', () => {
|
||||
describe('common rule fields', () => {
|
||||
beforeEach(async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [ruleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('name field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', name: 'some other name' } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('description field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', description: 'some other description' } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('interval field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', interval: '30m' } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('from field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', from: 'now-10m' } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('to field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', to: 'now-1m' } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('note field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', note: '# some note markdown' } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('severity field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', severity: 'medium' } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('tags field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', tags: ['red fish', 'blue fish'] } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('severity_mapping field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
severity_mapping: [
|
||||
{
|
||||
field: 'event.severity',
|
||||
operator: 'equals',
|
||||
severity: 'low',
|
||||
value: 'LOW',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('risk_score field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', risk_score: 72 } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('risk_score_mapping field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
risk_score_mapping: [{ field: 'event.risk_score', operator: 'equals', value: '' }],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('references field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', references: ['http://test.test'] } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('false_positives field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', false_positives: ['false positive example'] } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('threat field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
threat: [
|
||||
{
|
||||
framework: 'MITRE ATT&CK',
|
||||
tactic: {
|
||||
id: 'TA0000',
|
||||
name: 'test tactic',
|
||||
reference: 'https://attack.mitre.org/tactics/TA0000/',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('setup field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', setup: '# some setup markdown' } })
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('related_integrations field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
related_integrations: [{ package: 'package-a', version: '^1.2.3' }],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('required_fields field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
required_fields: [{ name: '@timestamp', type: 'date' }],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('max_signals field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
max_signals: 42,
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('investigation_fields field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: { rule_id: 'rule_1', investigation_fields: { field_names: ['blob', 'boop'] } },
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('rule_name_override field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: { rule_id: 'rule_1', rule_name_override: 'override string' },
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('timestamp_override field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: { rule_id: 'rule_1', timestamp_override: 'event.ingested' },
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('timeline_template fields', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: { rule_id: 'rule_1', timeline_id: '123', timeline_title: 'timeline title' },
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('building_block_type field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: { rule_id: 'rule_1', building_block_type: 'building block string' },
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
});
|
||||
|
||||
describe('query rule fields', () => {
|
||||
beforeEach(async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [ruleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('query field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: { rule_id: 'rule_1', query: 'event.action: *' },
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('language field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: { rule_id: 'rule_1', language: 'lucene' },
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('filters field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
filters: [
|
||||
{
|
||||
meta: {
|
||||
negate: false,
|
||||
disabled: false,
|
||||
type: 'phrase',
|
||||
key: 'test',
|
||||
params: {
|
||||
query: 'value',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
term: {
|
||||
field: 'value',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('index field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: { rule_id: 'rule_1', index: ['new-index-pattern-*'] },
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('data_view_id field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: { rule_id: 'rule_1', data_view_id: 'new-data-view', index: undefined },
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('alert_suppression field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
alert_suppression: {
|
||||
group_by: ['host.name'],
|
||||
duration: { value: 5, unit: 'm' },
|
||||
missing_fields_strategy: 'suppress',
|
||||
},
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
});
|
||||
|
||||
describe('eql rule type fields', () => {
|
||||
beforeEach(async () => {
|
||||
const eqlRuleAsset = createRuleAssetSavedObject({
|
||||
...getPrebuiltRuleMockOfType('eql'),
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [eqlRuleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('event_category_override field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
event_category_override: 'host.name',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('timestamp_field field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
timestamp_field: 'event.ingested',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('tiebreaker_field field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
tiebreaker_field: 'event.ingested',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
});
|
||||
|
||||
describe('threat match rule type fields', () => {
|
||||
beforeEach(async () => {
|
||||
const threatMatchRuleAsset = createRuleAssetSavedObject({
|
||||
...getPrebuiltRuleMockOfType('threat_match'),
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [threatMatchRuleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('threat_index field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'threat_match',
|
||||
threat_index: ['blue fish', 'red fish'],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('threat_mapping field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'threat_match',
|
||||
threat_mapping: [
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'Endpoint.capabilities',
|
||||
type: 'mapping',
|
||||
value: 'Target.dll.pe.description',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('threat_indicator_path field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'threat_match',
|
||||
threat_indicator_path: 'C:over/there.exe',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('threat_query field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'threat_match',
|
||||
threat_query: 'event.action: *',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('threat_language field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'threat_match',
|
||||
threat_language: 'lucene',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('threat_filters field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'threat_match',
|
||||
threat_filters: [
|
||||
{
|
||||
meta: {
|
||||
negate: false,
|
||||
disabled: false,
|
||||
type: 'phrase',
|
||||
key: 'test',
|
||||
params: {
|
||||
query: 'value',
|
||||
},
|
||||
},
|
||||
query: {
|
||||
term: {
|
||||
field: 'value',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
});
|
||||
|
||||
describe('threshold rule type fields', () => {
|
||||
beforeEach(async () => {
|
||||
const thresholdRuleAsset = createRuleAssetSavedObject({
|
||||
...getPrebuiltRuleMockOfType('threshold'),
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [thresholdRuleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('threshold field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'threshold',
|
||||
threshold: {
|
||||
field: ['Responses.process.pid'],
|
||||
value: 100,
|
||||
cardinality: [{ field: 'host.id', value: 2 }],
|
||||
},
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
});
|
||||
|
||||
describe('machine learning rule type fields', () => {
|
||||
beforeEach(async () => {
|
||||
const machineLearningRuleAsset = createRuleAssetSavedObject({
|
||||
...getPrebuiltRuleMockOfType('machine_learning'),
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [machineLearningRuleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('machine_learning_job_id field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'machine_learning',
|
||||
machine_learning_job_id: '123',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('anomaly_threshold field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'machine_learning',
|
||||
anomaly_threshold: 20,
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
});
|
||||
|
||||
describe('new terms rule type fields', () => {
|
||||
beforeEach(async () => {
|
||||
const newTermsRuleAsset = createRuleAssetSavedObject({
|
||||
...getPrebuiltRuleMockOfType('new_terms'),
|
||||
rule_id: 'rule_1',
|
||||
});
|
||||
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [newTermsRuleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('new_terms_fields field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'new_terms',
|
||||
new_terms_fields: ['event.action'],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('history_window_start field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
type: 'new_terms',
|
||||
history_window_start: 'now-7d',
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(true);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('is_customized calculation is not affected by', () => {
|
||||
beforeEach(async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [ruleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('actions field', async () => {
|
||||
// create connector/action
|
||||
const createConnector = async (payload: Record<string, unknown>) =>
|
||||
(
|
||||
await supertest
|
||||
.post('/api/actions/action')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(payload)
|
||||
.expect(200)
|
||||
).body;
|
||||
|
||||
const createWebHookConnector = () => createConnector(getWebHookAction());
|
||||
|
||||
const webHookAction = await createWebHookConnector();
|
||||
|
||||
const defaultRuleAction = {
|
||||
id: webHookAction.id,
|
||||
action_type_id: '.webhook' as const,
|
||||
group: 'default' as const,
|
||||
params: {
|
||||
body: '{"test":"a default action"}',
|
||||
},
|
||||
frequency: {
|
||||
notifyWhen: 'onThrottleInterval' as const,
|
||||
summary: true,
|
||||
throttle: '1h' as const,
|
||||
},
|
||||
uuid: 'd487ec3d-05f2-44ad-8a68-11c97dc92202',
|
||||
};
|
||||
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
actions: [defaultRuleAction],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(false);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('exceptions_list field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
exceptions_list: [
|
||||
{
|
||||
id: 'some_uuid',
|
||||
list_id: 'list_id_single',
|
||||
namespace_type: 'single',
|
||||
type: 'detection',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(false);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('enabled field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
enabled: true,
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(false);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
|
||||
it('meta field', async () => {
|
||||
const { body } = await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
meta: {
|
||||
severity_override_field: 'field',
|
||||
},
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.rule_source.is_customized).toEqual(false);
|
||||
expect(body.rule_source.type).toEqual('external');
|
||||
});
|
||||
});
|
||||
|
||||
describe('cannot change non-customizable rule fields', () => {
|
||||
beforeEach(async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [ruleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('id field', async () => {
|
||||
await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
id: 'new-id',
|
||||
},
|
||||
})
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it('author field', async () => {
|
||||
await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
author: ['new author'],
|
||||
},
|
||||
})
|
||||
.expect(400);
|
||||
});
|
||||
|
||||
it('license field', async () => {
|
||||
await securitySolutionApi
|
||||
.patchRule({
|
||||
body: {
|
||||
rule_id: 'rule_1',
|
||||
license: 'custom-license',
|
||||
},
|
||||
})
|
||||
.expect(400);
|
||||
});
|
||||
});
|
||||
|
||||
describe('user can revert a customized prebuilt rule to its non-customized state', () => {
|
||||
beforeEach(async () => {
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [ruleAsset]);
|
||||
await installPrebuiltRules(es, supertest);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
});
|
||||
|
||||
it('using name field', async () => {
|
||||
// Modify the prebuilt rule
|
||||
const { body: customizedRuleBody } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', name: 'new name' } })
|
||||
.expect(200);
|
||||
|
||||
expect(customizedRuleBody.rule_source.is_customized).toEqual(true);
|
||||
expect(customizedRuleBody.rule_source.type).toEqual('external');
|
||||
|
||||
// Change the name field back to the original value
|
||||
const { body: nonCustomizedRuleBody } = await securitySolutionApi
|
||||
.patchRule({ body: { rule_id: 'rule_1', name: getPrebuiltRuleMock().name } })
|
||||
.expect(200);
|
||||
|
||||
expect(nonCustomizedRuleBody.rule_source.is_customized).toEqual(false);
|
||||
expect(nonCustomizedRuleBody.rule_source.type).toEqual('external');
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue