[Security Solution][Exceptions][API testing] Move and restructures exception groups in the new api integration test folder (#168700)

## Summary

- Following the initial work in this
[PR](https://github.com/elastic/kibana/pull/166755)
- Addresses part of https://github.com/elastic/kibana/issues/151902 for
exceptions
-
https://docs.google.com/document/d/1CRFfDWMzw3ob03euWIvT4-IoiLXjoiPWI8mTBqP4Zks/edit
first two rows in the new groups
- Relocated the tests promptly without focusing on refactoring, as our
priority was to obtain coverage as well as grouping them
- Transferred the relevant utilities and updated 'signal' to 'alert.'
- Temporarily marked security role-related tests as 'brokenInServerless'
until resolution.
- Moved tests linked to exceptions requiring a `trail` in ESS and
`complete` in Serverless under a new folder called `default` license.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Wafaa Nasr 2023-10-18 14:20:24 +02:00 committed by GitHub
parent f612a331a8
commit e536a0a795
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
95 changed files with 3118 additions and 2016 deletions

View file

@ -223,14 +223,9 @@ enabled:
- x-pack/test/cloud_security_posture_api/config.ts
- x-pack/test/detection_engine_api_integration/basic/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group1/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group2/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group3/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group6/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group7/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group8/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group9/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/group10/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/config.ts
- x-pack/test/detection_engine_api_integration/security_and_spaces/prebuilt_rules/config.ts
@ -451,8 +446,18 @@ enabled:
- x-pack/performance/journeys/apm_service_inventory.ts
- x-pack/test/custom_branding/config.ts
- x-pack/test/profiling_api_integration/cloud/config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/workflows/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/ess.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/configs/serverless.config.ts
- x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/configs/ess.config.ts

View file

@ -1,18 +0,0 @@
/*
* 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 { FtrConfigProviderContext } from '@kbn/test';
// eslint-disable-next-line import/no-default-export
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(require.resolve('../config.base.ts'));
return {
...functionalConfig.getAll(),
testFiles: [require.resolve('.')],
};
}

View file

@ -1,15 +0,0 @@
/*
* 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 { FtrProviderContext } from '../../common/ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile }: FtrProviderContext): void => {
describe('detection engine api security and spaces enabled - Group 2', function () {
loadTestFile(require.resolve('./create_endpoint_exceptions'));
});
};

View file

@ -1,15 +0,0 @@
/*
* 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 { FtrProviderContext } from '../../common/ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile }: FtrProviderContext): void => {
describe('detection engine api security and spaces enabled - Group 3', function () {
loadTestFile(require.resolve('./exceptions_workflows'));
});
};

View file

@ -1,15 +0,0 @@
/*
* 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 { FtrProviderContext } from '../../common/ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile }: FtrProviderContext): void => {
describe('detection engine api security and spaces enabled - Group 7', function () {
loadTestFile(require.resolve('./exception_operators_data_types'));
});
};

View file

@ -1,15 +0,0 @@
/*
* 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 { FtrProviderContext } from '../../common/ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile }: FtrProviderContext): void => {
describe('detection engine api security and spaces enabled - Group 8', function () {
loadTestFile(require.resolve('./exception_operators_data_types'));
});
};

View file

@ -1,18 +0,0 @@
/*
* 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 { FtrConfigProviderContext } from '@kbn/test';
// eslint-disable-next-line import/no-default-export
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(require.resolve('../config.base.ts'));
return {
...functionalConfig.getAll(),
testFiles: [require.resolve('.')],
};
}

View file

@ -1,15 +0,0 @@
/*
* 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 { FtrProviderContext } from '../../common/ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile }: FtrProviderContext): void => {
describe('detection engine api security and spaces enabled - Group 9', function () {
loadTestFile(require.resolve('./exception_operators_data_types'));
});
};

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { FtrConfigProviderContext } from '@kbn/test';
// import { ES_RESOURCES } from '@kbn/security-solution-plugin/scripts/endpoint/common/roles_users/serverless';
export interface CreateTestConfigOptions {
testFiles: string[];
@ -23,6 +24,9 @@ export function createTestConfig(options: CreateTestConfigOptions) {
...svlSharedConfig.get('kbnTestServer'),
serverArgs: [...svlSharedConfig.get('kbnTestServer.serverArgs'), '--serverless=security'],
},
// esServerlessOptions: {
// resources: Object.values(ES_RESOURCES),
// },
testFiles: options.testFiles,
junit: options.junit,

View file

@ -5,9 +5,25 @@
"private": true,
"license": "Elastic License 2.0",
"scripts": {
"detectionResponse:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/serverless.config.ts",
"detectionResponse:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/serverless.config.ts --grep @serverless --grep @brokenInServerless --invert",
"detectionResponse:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/ess.config.ts",
"detectionResponse:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/ess.config.ts --grep @ess"
"exception_workflows:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/exceptions/workflows/configs/serverless.config.ts",
"exception_workflows:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/exceptions/workflows/configs/serverless.config.ts --grep @serverless --grep @brokenInServerless --invert",
"exception_workflows:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/exceptions/workflows/configs/ess.config.ts",
"exception_workflows:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/exceptions/workflows/configs/ess.config.ts --grep @ess",
"exception_operators_date_numeric_types:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/serverless.config.ts",
"exception_operators_date_numeric_types:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/serverless.config.ts --grep @serverless --grep @brokenInServerless --invert",
"exception_operators_date_numeric_types:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/ess.config.ts",
"exception_operators_date_numeric_types:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/exceptions/operators_data_types/date_numeric_types/configs/ess.config.ts --grep @ess",
"exception_operators_keyword_text_long:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/serverless.config.ts",
"exception_operators_keyword_text_long:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/serverless.config.ts --grep @serverless --grep @brokenInServerless --invert",
"exception_operators_keyword_text_long:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/ess.config.ts",
"exception_operators_keyword_text_long:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/exceptions/operators_data_types/keyword_text_long/configs/ess.config.ts --grep @ess",
"exception_operators_ips_text_array:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/serverless.config.ts",
"exception_operators_ips_text_array:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/serverless.config.ts --grep @serverless --grep @brokenInServerless --invert",
"exception_operators_ips_text_array:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/ess.config.ts",
"exception_operators_ips_text_array:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/exceptions/operators_data_types/ips_text_array/configs/ess.config.ts --grep @ess",
"rule_creation:server:serverless": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/rule_creation/configs/serverless.config.ts",
"rule_creation:runner:serverless": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/rule_creation/configs/serverless.config.ts --grep @serverless --grep @brokenInServerless --invert",
"rule_creation:server:ess": "node ../../../scripts/functional_tests_server.js --config ./test_suites/detections_response/default_license/rule_creation/configs/ess.config.ts",
"rule_creation:runner:ess": "node ../../../scripts/functional_test_runner --config=test_suites/detections_response/default_license/rule_creation/configs/ess.config.ts --grep @ess"
}
}

View file

@ -0,0 +1,23 @@
/*
* 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 { FtrConfigProviderContext } from '@kbn/test';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(
require.resolve('../../../../../../../config/ess/config.base.trial')
);
return {
...functionalConfig.getAll(),
testFiles: [require.resolve('..')],
junit: {
reportName:
'Detection Engine ESS/ Exception Operators Data Types API date_numeric_types Integration Tests',
},
};
}

View file

@ -0,0 +1,16 @@
/*
* 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 { createTestConfig } from '../../../../../../../config/serverless/config.base';
export default createTestConfig({
testFiles: [require.resolve('..')],
junit: {
reportName:
'Detection Engine Serverless/ Exception Operators Data Types date_numeric_types API Integration Tests',
},
});

View file

@ -12,28 +12,27 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type date', () => {
describe('@serverless @ess Rule exception operators for data type date', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/date');
});
@ -43,7 +42,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -56,12 +55,12 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the dates from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([
'2020-10-01T05:08:53.000Z',
'2020-10-02T05:08:53.000Z',
@ -71,7 +70,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 1 single date if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -83,9 +82,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([
'2020-10-02T05:08:53.000Z',
'2020-10-03T05:08:53.000Z',
@ -94,7 +93,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 dates if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -114,14 +113,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql(['2020-10-03T05:08:53.000Z', '2020-10-04T05:08:53.000Z']);
});
it('should filter 3 dates if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -149,14 +148,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql(['2020-10-04T05:08:53.000Z']);
});
it('should filter 4 dates if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -192,15 +191,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([]);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -212,13 +211,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -230,14 +229,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql(['2020-10-01T05:08:53.000Z']);
});
it('will return 0 results if we exclude two dates', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -257,15 +256,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single date if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -277,9 +276,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([
'2020-10-02T05:08:53.000Z',
'2020-10-03T05:08:53.000Z',
@ -288,7 +287,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 dates if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -300,14 +299,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql(['2020-10-03T05:08:53.000Z', '2020-10-04T05:08:53.000Z']);
});
it('should filter 3 dates if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -323,14 +322,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql(['2020-10-04T05:08:53.000Z']);
});
it('should filter 4 dates if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -347,15 +346,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -367,13 +366,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -385,16 +384,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql(['2020-10-01T05:08:53.000Z', '2020-10-04T05:08:53.000Z']);
});
});
describe('"exists" operator', () => {
it('will return 0 results if matching against date', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -405,15 +404,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 4 results if matching against date', async () => {
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -424,9 +423,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([
'2020-10-01T05:08:53.000Z',
'2020-10-02T05:08:53.000Z',
@ -439,7 +438,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is in list" operator', () => {
it('will return 3 results if we have a list that includes 1 date', async () => {
await importFile(supertest, log, 'date', ['2020-10-01T05:08:53.000Z'], 'list_items.txt');
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -454,9 +453,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([
'2020-10-02T05:08:53.000Z',
'2020-10-03T05:08:53.000Z',
@ -472,7 +471,7 @@ export default ({ getService }: FtrProviderContext) => {
['2020-10-01T05:08:53.000Z', '2020-10-03T05:08:53.000Z'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -487,9 +486,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql(['2020-10-02T05:08:53.000Z', '2020-10-04T05:08:53.000Z']);
});
@ -506,7 +505,7 @@ export default ({ getService }: FtrProviderContext) => {
],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -521,8 +520,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([]);
});
});
@ -530,7 +529,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is not in list" operator', () => {
it('will return 1 result if we have a list that excludes 1 date', async () => {
await importFile(supertest, log, 'date', ['2020-10-01T05:08:53.000Z'], 'list_items.txt');
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -545,9 +544,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql(['2020-10-01T05:08:53.000Z']);
});
@ -559,7 +558,7 @@ export default ({ getService }: FtrProviderContext) => {
['2020-10-01T05:08:53.000Z', '2020-10-03T05:08:53.000Z'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -574,9 +573,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql(['2020-10-01T05:08:53.000Z', '2020-10-03T05:08:53.000Z']);
});
@ -593,7 +592,7 @@ export default ({ getService }: FtrProviderContext) => {
],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['date']);
const rule = getRuleForAlertTesting(['date']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -608,9 +607,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.date).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.date).sort();
expect(hits).to.eql([
'2020-10-01T05:08:53.000Z',
'2020-10-02T05:08:53.000Z',

View file

@ -12,28 +12,27 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type double', () => {
describe('@serverless @ess Rule exception operators for data type double', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/double');
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/double_as_string');
@ -47,7 +46,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -60,17 +59,17 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the double from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2', '1.3']);
});
it('should filter 1 single double if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -82,14 +81,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.1', '1.2', '1.3']);
});
it('should filter 2 double if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -109,14 +108,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.2', '1.3']);
});
it('should filter 3 double if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -144,14 +143,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.3']);
});
it('should filter 4 double if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -187,15 +186,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql([]);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -207,13 +206,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -225,14 +224,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0']);
});
it('will return 0 results if we exclude two double', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -252,15 +251,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single double if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -272,14 +271,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.1', '1.2', '1.3']);
});
it('should filter 2 double if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -291,14 +290,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.2', '1.3']);
});
it('should filter 3 double if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -310,14 +309,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.3']);
});
it('should filter 4 double if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -329,15 +328,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -349,13 +348,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -367,16 +366,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0', '1.3']);
});
});
describe('"exists" operator', () => {
it('will return 0 results if matching against double', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -387,15 +386,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 4 results if matching against double', async () => {
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -406,9 +405,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2', '1.3']);
});
});
@ -417,7 +416,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against double values in the data set', () => {
it('will return 3 results if we have a list that includes 1 double', async () => {
await importFile(supertest, log, 'double', ['1.0'], 'list_items.txt');
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -432,15 +431,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.1', '1.2', '1.3']);
});
it('will return 2 results if we have a list that includes 2 double', async () => {
await importFile(supertest, log, 'double', ['1.0', '1.2'], 'list_items.txt');
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -455,9 +454,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.1', '1.3']);
});
@ -469,7 +468,7 @@ export default ({ getService }: FtrProviderContext) => {
['1.0', '1.1', '1.2', '1.3'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -484,15 +483,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql([]);
});
});
describe('working against string values in the data set', () => {
it('will return 3 results if we have a list that includes 1 double', async () => {
await importFile(supertest, log, 'double', ['1.0'], 'list_items.txt');
const rule = getRuleForSignalTesting(['double_as_string']);
const rule = getRuleForAlertTesting(['double_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -507,15 +506,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.1', '1.2', '1.3']);
});
it('will return 2 results if we have a list that includes 2 double', async () => {
await importFile(supertest, log, 'double', ['1.0', '1.2'], 'list_items.txt');
const rule = getRuleForSignalTesting(['double_as_string']);
const rule = getRuleForAlertTesting(['double_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -530,9 +529,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.1', '1.3']);
});
@ -544,7 +543,7 @@ export default ({ getService }: FtrProviderContext) => {
['1.0', '1.1', '1.2', '1.3'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['double_as_string']);
const rule = getRuleForAlertTesting(['double_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -559,8 +558,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql([]);
});
@ -569,7 +568,7 @@ export default ({ getService }: FtrProviderContext) => {
'1.0',
'1.2',
]);
const rule = getRuleForSignalTesting(['double_as_string']);
const rule = getRuleForAlertTesting(['double_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -584,9 +583,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.3']);
});
});
@ -596,7 +595,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against double values in the data set', () => {
it('will return 1 result if we have a list that excludes 1 double', async () => {
await importFile(supertest, log, 'double', ['1.0'], 'list_items.txt');
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -611,15 +610,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0']);
});
it('will return 2 results if we have a list that excludes 2 double', async () => {
await importFile(supertest, log, 'double', ['1.0', '1.2'], 'list_items.txt');
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -634,9 +633,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0', '1.2']);
});
@ -648,7 +647,7 @@ export default ({ getService }: FtrProviderContext) => {
['1.0', '1.1', '1.2', '1.3'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['double']);
const rule = getRuleForAlertTesting(['double']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -663,9 +662,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2', '1.3']);
});
});
@ -673,7 +672,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against string values in the data set', () => {
it('will return 1 result if we have a list that excludes 1 double', async () => {
await importFile(supertest, log, 'double', ['1.0'], 'list_items.txt');
const rule = getRuleForSignalTesting(['double_as_string']);
const rule = getRuleForAlertTesting(['double_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -688,15 +687,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0']);
});
it('will return 2 results if we have a list that excludes 2 double', async () => {
await importFile(supertest, log, 'double', ['1.0', '1.2'], 'list_items.txt');
const rule = getRuleForSignalTesting(['double_as_string']);
const rule = getRuleForAlertTesting(['double_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -711,9 +710,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0', '1.2']);
});
@ -725,7 +724,7 @@ export default ({ getService }: FtrProviderContext) => {
['1.0', '1.1', '1.2', '1.3'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['double_as_string']);
const rule = getRuleForAlertTesting(['double_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -740,9 +739,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2', '1.3']);
});
@ -751,7 +750,7 @@ export default ({ getService }: FtrProviderContext) => {
'1.0',
'1.2',
]);
const rule = getRuleForSignalTesting(['double_as_string']);
const rule = getRuleForAlertTesting(['double_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -766,9 +765,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.double).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.double).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2']);
});
});

View file

@ -12,28 +12,27 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type float', () => {
describe('@serverless @ess Rule exception operators for data type float', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/float');
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/float_as_string');
@ -45,7 +44,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -58,17 +57,17 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the float from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2', '1.3']);
});
it('should filter 1 single float if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -80,14 +79,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.1', '1.2', '1.3']);
});
it('should filter 2 float if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -107,14 +106,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.2', '1.3']);
});
it('should filter 3 float if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -142,14 +141,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.3']);
});
it('should filter 4 float if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -185,15 +184,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql([]);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -205,13 +204,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -223,14 +222,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0']);
});
it('will return 0 results if we exclude two float', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -250,15 +249,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single float if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -270,14 +269,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.1', '1.2', '1.3']);
});
it('should filter 2 float if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -289,14 +288,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.2', '1.3']);
});
it('should filter 3 float if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -308,14 +307,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.3']);
});
it('should filter 4 float if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -327,15 +326,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -347,13 +346,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -365,16 +364,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0', '1.3']);
});
});
describe('"exists" operator', () => {
it('will return 0 results if matching against float', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -385,15 +384,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 4 results if matching against float', async () => {
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -404,9 +403,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2', '1.3']);
});
});
@ -415,7 +414,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against float values in the data set', () => {
it('will return 3 results if we have a list that includes 1 float', async () => {
await importFile(supertest, log, 'float', ['1.0'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -430,15 +429,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.1', '1.2', '1.3']);
});
it('will return 2 results if we have a list that includes 2 float', async () => {
await importFile(supertest, log, 'float', ['1.0', '1.2'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -453,15 +452,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.1', '1.3']);
});
it('will return 0 results if we have a list that includes all float', async () => {
await importFile(supertest, log, 'float', ['1.0', '1.1', '1.2', '1.3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -476,8 +475,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql([]);
});
});
@ -485,7 +484,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against string values in the data set', () => {
it('will return 3 results if we have a list that includes 1 float', async () => {
await importFile(supertest, log, 'float', ['1.0'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float_as_string']);
const rule = getRuleForAlertTesting(['float_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -500,15 +499,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.1', '1.2', '1.3']);
});
it('will return 2 results if we have a list that includes 2 float', async () => {
await importFile(supertest, log, 'float', ['1.0', '1.2'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float_as_string']);
const rule = getRuleForAlertTesting(['float_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -523,15 +522,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.1', '1.3']);
});
it('will return 0 results if we have a list that includes all float', async () => {
await importFile(supertest, log, 'float', ['1.0', '1.1', '1.2', '1.3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float_as_string']);
const rule = getRuleForAlertTesting(['float_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -546,8 +545,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql([]);
});
@ -556,7 +555,7 @@ export default ({ getService }: FtrProviderContext) => {
'1.0',
'1.2',
]);
const rule = getRuleForSignalTesting(['float_as_string']);
const rule = getRuleForAlertTesting(['float_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -571,9 +570,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.3']);
});
});
@ -583,7 +582,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against float values in the data set', () => {
it('will return 1 result if we have a list that excludes 1 float', async () => {
await importFile(supertest, log, 'float', ['1.0'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -598,15 +597,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0']);
});
it('will return 2 results if we have a list that excludes 2 float', async () => {
await importFile(supertest, log, 'float', ['1.0', '1.2'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -621,15 +620,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0', '1.2']);
});
it('will return 4 results if we have a list that excludes all float', async () => {
await importFile(supertest, log, 'float', ['1.0', '1.1', '1.2', '1.3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float']);
const rule = getRuleForAlertTesting(['float']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -644,9 +643,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2', '1.3']);
});
});
@ -654,7 +653,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against string values in the data set', () => {
it('will return 1 result if we have a list that excludes 1 float', async () => {
await importFile(supertest, log, 'float', ['1.0'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float_as_string']);
const rule = getRuleForAlertTesting(['float_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -669,15 +668,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0']);
});
it('will return 2 results if we have a list that excludes 2 float', async () => {
await importFile(supertest, log, 'float', ['1.0', '1.2'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float_as_string']);
const rule = getRuleForAlertTesting(['float_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -692,15 +691,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0', '1.2']);
});
it('will return 4 results if we have a list that excludes all float', async () => {
await importFile(supertest, log, 'float', ['1.0', '1.1', '1.2', '1.3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['float_as_string']);
const rule = getRuleForAlertTesting(['float_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -715,9 +714,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2', '1.3']);
});
@ -726,7 +725,7 @@ export default ({ getService }: FtrProviderContext) => {
'1.0',
'1.2',
]);
const rule = getRuleForSignalTesting(['float_as_string']);
const rule = getRuleForAlertTesting(['float_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -741,9 +740,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.float).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.float).sort();
expect(hits).to.eql(['1.0', '1.1', '1.2']);
});
});

View file

@ -4,10 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile }: FtrProviderContext): void => {
describe('Detection exceptions data types and operators', function () {
loadTestFile(require.resolve('./date'));

View file

@ -12,28 +12,27 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type integer', () => {
describe('@serverless @ess Rule exception operators for data type integer', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/integer');
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/integer_as_string');
@ -47,7 +46,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -60,17 +59,17 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the integer from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1', '2', '3', '4']);
});
it('should filter 1 single integer if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -82,14 +81,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['2', '3', '4']);
});
it('should filter 2 integer if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -109,14 +108,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['3', '4']);
});
it('should filter 3 integer if all 3 are as exceptions', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -144,14 +143,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['4']);
});
it('should filter 4 integer if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -187,15 +186,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql([]);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -207,13 +206,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -225,14 +224,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1']);
});
it('will return 0 results if we exclude two integer', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -252,15 +251,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single integer if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -272,14 +271,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['2', '3', '4']);
});
it('should filter 2 integer if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -291,14 +290,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['3', '4']);
});
it('should filter 3 integer if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -310,14 +309,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['4']);
});
it('should filter 4 integer if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -329,15 +328,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -349,13 +348,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -367,16 +366,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1', '4']);
});
});
describe('"exists" operator', () => {
it('will return 0 results if matching against integer', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -387,15 +386,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 4 results if matching against integer', async () => {
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -406,9 +405,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1', '2', '3', '4']);
});
});
@ -417,7 +416,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against integer values in the data set', () => {
it('will return 3 results if we have a list that includes 1 integer', async () => {
await importFile(supertest, log, 'integer', ['1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -432,15 +431,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['2', '3', '4']);
});
it('will return 2 results if we have a list that includes 2 integer', async () => {
await importFile(supertest, log, 'integer', ['1', '3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -455,15 +454,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['2', '4']);
});
it('will return 0 results if we have a list that includes all integer', async () => {
await importFile(supertest, log, 'integer', ['1', '2', '3', '4'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -478,8 +477,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql([]);
});
});
@ -487,7 +486,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against string values in the data set', () => {
it('will return 3 results if we have a list that includes 1 integer', async () => {
await importFile(supertest, log, 'integer', ['1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer_as_string']);
const rule = getRuleForAlertTesting(['integer_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -502,15 +501,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['2', '3', '4']);
});
it('will return 2 results if we have a list that includes 2 integer', async () => {
await importFile(supertest, log, 'integer', ['1', '3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer_as_string']);
const rule = getRuleForAlertTesting(['integer_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -525,15 +524,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['2', '4']);
});
it('will return 0 results if we have a list that includes all integer', async () => {
await importFile(supertest, log, 'integer', ['1', '2', '3', '4'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer_as_string']);
const rule = getRuleForAlertTesting(['integer_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -548,14 +547,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql([]);
});
it('will return 1 result if we have a list which contains the integer range of 1-3', async () => {
await importFile(supertest, log, 'integer_range', ['1-3'], 'list_items.txt', ['1', '2']);
const rule = getRuleForSignalTesting(['integer_as_string']);
const rule = getRuleForAlertTesting(['integer_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -570,9 +569,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['4']);
});
});
@ -582,7 +581,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against integer values in the data set', () => {
it('will return 1 result if we have a list that excludes 1 integer', async () => {
await importFile(supertest, log, 'integer', ['1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -597,15 +596,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1']);
});
it('will return 2 results if we have a list that excludes 2 integer', async () => {
await importFile(supertest, log, 'integer', ['1', '3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -620,15 +619,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1', '3']);
});
it('will return 4 results if we have a list that excludes all integer', async () => {
await importFile(supertest, log, 'integer', ['1', '2', '3', '4'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer']);
const rule = getRuleForAlertTesting(['integer']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -643,9 +642,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1', '2', '3', '4']);
});
});
@ -653,7 +652,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against string values in the data set', () => {
it('will return 1 result if we have a list that excludes 1 integer', async () => {
await importFile(supertest, log, 'integer', ['1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer_as_string']);
const rule = getRuleForAlertTesting(['integer_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -668,15 +667,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1']);
});
it('will return 2 results if we have a list that excludes 2 integer', async () => {
await importFile(supertest, log, 'integer', ['1', '3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer_as_string']);
const rule = getRuleForAlertTesting(['integer_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -691,15 +690,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1', '3']);
});
it('will return 4 results if we have a list that excludes all integer', async () => {
await importFile(supertest, log, 'integer', ['1', '2', '3', '4'], 'list_items.txt');
const rule = getRuleForSignalTesting(['integer_as_string']);
const rule = getRuleForAlertTesting(['integer_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -714,9 +713,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1', '2', '3', '4']);
});
@ -726,7 +725,7 @@ export default ({ getService }: FtrProviderContext) => {
'2',
'3',
]);
const rule = getRuleForSignalTesting(['integer_as_string']);
const rule = getRuleForAlertTesting(['integer_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -741,9 +740,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.integer).sort();
expect(hits).to.eql(['1', '2', '3']);
});
});

View file

@ -7,12 +7,17 @@
import { FtrConfigProviderContext } from '@kbn/test';
// eslint-disable-next-line import/no-default-export
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(require.resolve('../config.base.ts'));
const functionalConfig = await readConfigFile(
require.resolve('../../../../../../../config/ess/config.base.trial')
);
return {
...functionalConfig.getAll(),
testFiles: [require.resolve('.')],
testFiles: [require.resolve('..')],
junit: {
reportName:
'Detection Engine ESS/ Exception Operators Data Types API ips_text_array Integration Tests',
},
};
}

View file

@ -0,0 +1,16 @@
/*
* 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 { createTestConfig } from '../../../../../../../config/serverless/config.base';
export default createTestConfig({
testFiles: [require.resolve('..')],
junit: {
reportName:
'Detection Engine Serverless/ Exception Operators Data Types ips_text_array API Integration Tests',
},
});

View file

@ -5,9 +5,8 @@
* 2.0.
*/
import { FtrProviderContext } from '../../../common/ftr_provider_context';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile }: FtrProviderContext): void => {
describe('Detection exceptions data types and operators', function () {
loadTestFile(require.resolve('./text_array'));

View file

@ -12,28 +12,27 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type ip', () => {
describe('@serverless @ess Rule exception operators for data type ip', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/ip');
});
@ -43,7 +42,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -56,17 +55,17 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the ips from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4']);
});
it('should filter 1 single ip if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -78,14 +77,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.2', '127.0.0.3', '127.0.0.4']);
});
it('should filter 2 ips if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -105,14 +104,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.3', '127.0.0.4']);
});
it('should filter 3 ips if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -140,14 +139,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.4']);
});
it('should filter 4 ips if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -183,13 +182,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
it('should filter a CIDR range of "127.0.0.1/30"', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -201,16 +200,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.4']);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -222,13 +221,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -240,14 +239,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.1']);
});
it('will return 0 results if we exclude two ips', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -267,15 +266,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single ip if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -287,14 +286,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.2', '127.0.0.3', '127.0.0.4']);
});
it('should filter 2 ips if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -306,14 +305,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.3', '127.0.0.4']);
});
it('should filter 3 ips if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -325,14 +324,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.4']);
});
it('should filter 4 ips if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -344,15 +343,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -364,13 +363,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -382,16 +381,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.1', '127.0.0.4']);
});
});
describe('"exists" operator', () => {
it('will return 0 results if matching against ip', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -402,15 +401,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 4 results if matching against ip', async () => {
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -421,9 +420,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4']);
});
});
@ -431,7 +430,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is in list" operator', () => {
it('will return 3 results if we have a list that includes 1 ip', async () => {
await importFile(supertest, log, 'ip', ['127.0.0.1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -446,15 +445,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.2', '127.0.0.3', '127.0.0.4']);
});
it('will return 2 results if we have a list that includes 2 ips', async () => {
await importFile(supertest, log, 'ip', ['127.0.0.1', '127.0.0.3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -469,9 +468,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.2', '127.0.0.4']);
});
@ -483,7 +482,7 @@ export default ({ getService }: FtrProviderContext) => {
['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -498,8 +497,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
@ -509,7 +508,7 @@ export default ({ getService }: FtrProviderContext) => {
'127.0.0.2',
'127.0.0.3',
]);
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -524,9 +523,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.4']);
});
@ -536,7 +535,7 @@ export default ({ getService }: FtrProviderContext) => {
'127.0.0.2',
'127.0.0.3',
]);
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -551,9 +550,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.4']);
});
@ -566,7 +565,7 @@ export default ({ getService }: FtrProviderContext) => {
'list_items.txt',
['127.0.0.1', '127.0.0.2', '127.0.0.3']
);
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -581,9 +580,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.4']);
});
});
@ -591,7 +590,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is not in list" operator', () => {
it('will return 1 result if we have a list that excludes 1 ip', async () => {
await importFile(supertest, log, 'ip', ['127.0.0.1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -606,15 +605,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.1']);
});
it('will return 2 results if we have a list that excludes 2 ips', async () => {
await importFile(supertest, log, 'ip', ['127.0.0.1', '127.0.0.3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -629,9 +628,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.1', '127.0.0.3']);
});
@ -643,7 +642,7 @@ export default ({ getService }: FtrProviderContext) => {
['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -658,9 +657,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4']);
});
@ -670,7 +669,7 @@ export default ({ getService }: FtrProviderContext) => {
'127.0.0.2',
'127.0.0.3',
]);
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -685,9 +684,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.1', '127.0.0.2', '127.0.0.3']);
});
@ -697,7 +696,7 @@ export default ({ getService }: FtrProviderContext) => {
'127.0.0.2',
'127.0.0.3',
]);
const rule = getRuleForSignalTesting(['ip']);
const rule = getRuleForAlertTesting(['ip']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -712,9 +711,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql(['127.0.0.1', '127.0.0.2', '127.0.0.3']);
});
});

View file

@ -12,28 +12,27 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type ip', () => {
describe('@serverless @ess Rule exception operators for data type ip', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/ip_as_array');
});
@ -43,7 +42,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -56,12 +55,12 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the ips from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
[],
['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'],
@ -71,7 +70,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 1 single ip if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -83,9 +82,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
[],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],
@ -94,7 +93,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 ips if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -114,14 +113,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([[], ['127.0.0.8', '127.0.0.9', '127.0.0.10']]);
});
it('should filter 3 ips if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -149,14 +148,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips.flat(10)).to.eql([]);
});
it('should filter a CIDR range of "127.0.0.1/30"', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -168,9 +167,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
[],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],
@ -179,7 +178,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter a CIDR range of "127.0.0.4/31"', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -191,16 +190,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([[], ['127.0.0.8', '127.0.0.9', '127.0.0.10']]);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -212,13 +211,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -230,14 +229,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4']]);
});
it('will return just 1 result we excluded 2 from the same array elements', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -255,14 +254,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4']]);
});
it('will return 0 results if we exclude two ips', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -282,15 +281,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single ip if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -302,9 +301,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
[],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],
@ -313,7 +312,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 ips if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -325,14 +324,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([[], ['127.0.0.8', '127.0.0.9', '127.0.0.10']]);
});
it('should filter 3 ips if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -344,16 +343,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips.flat(10)).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -365,13 +364,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -383,9 +382,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],
@ -395,7 +394,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"exists" operator', () => {
it('will return 1 empty result if matching against ip', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -406,16 +405,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips.flat(10)).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 3 results if matching against ip', async () => {
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -426,9 +425,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],
@ -440,7 +439,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is in list" operator', () => {
it('will return 3 results if we have a list that includes 1 ip', async () => {
await importFile(supertest, log, 'ip', ['127.0.0.1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -455,9 +454,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
[],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],
@ -467,7 +466,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 2 results if we have a list that includes 2 ips', async () => {
await importFile(supertest, log, 'ip', ['127.0.0.1', '127.0.0.5'], 'list_items.txt');
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -482,9 +481,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([[], ['127.0.0.8', '127.0.0.9', '127.0.0.10']]);
});
@ -496,7 +495,7 @@ export default ({ getService }: FtrProviderContext) => {
['127.0.0.1', '127.0.0.5', '127.0.0.8'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -511,9 +510,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips.flat(10)).to.eql([]);
});
@ -534,7 +533,7 @@ export default ({ getService }: FtrProviderContext) => {
'127.0.0.7',
]
);
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -549,9 +548,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([[], ['127.0.0.8', '127.0.0.9', '127.0.0.10']]);
});
@ -565,7 +564,7 @@ export default ({ getService }: FtrProviderContext) => {
'127.0.0.6',
'127.0.0.7',
]);
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -580,9 +579,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([[], ['127.0.0.8', '127.0.0.9', '127.0.0.10']]);
});
});
@ -590,7 +589,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is not in list" operator', () => {
it('will return 1 result if we have a list that excludes 1 ip', async () => {
await importFile(supertest, log, 'ip', ['127.0.0.1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -605,15 +604,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4']]);
});
it('will return 2 results if we have a list that excludes 2 ips', async () => {
await importFile(supertest, log, 'ip', ['127.0.0.1', '127.0.0.5'], 'list_items.txt');
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -628,9 +627,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],
@ -645,7 +644,7 @@ export default ({ getService }: FtrProviderContext) => {
['127.0.0.1', '127.0.0.5', '127.0.0.8'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -660,9 +659,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],
@ -687,7 +686,7 @@ export default ({ getService }: FtrProviderContext) => {
'127.0.0.7',
]
);
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -702,9 +701,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],
@ -721,7 +720,7 @@ export default ({ getService }: FtrProviderContext) => {
'127.0.0.6',
'127.0.0.7',
]);
const rule = getRuleForSignalTesting(['ip_as_array']);
const rule = getRuleForAlertTesting(['ip_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -736,9 +735,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const ips = signalsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const ips = alertsOpen.hits.hits.map((hit) => hit._source?.ip).sort();
expect(ips).to.eql([
['127.0.0.1', '127.0.0.2', '127.0.0.3', '127.0.0.4'],
['127.0.0.5', null, '127.0.0.6', '127.0.0.7'],

View file

@ -12,28 +12,27 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type text', () => {
describe('@serverless @ess Rule exception operators for data type text', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/text_as_array');
});
@ -43,7 +42,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -56,12 +55,12 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the text from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -71,7 +70,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 1 single text if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -83,9 +82,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -94,7 +93,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 text if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -114,14 +113,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([[], ['word eight', 'word nine', 'word ten']]);
});
it('should filter 3 text if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -149,16 +148,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits.flat(10)).to.eql([]);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -170,13 +169,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -188,14 +187,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([['word one', 'word two', 'word three', 'word four']]);
});
it('will return 0 results if we exclude two text', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -215,15 +214,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single text if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -235,9 +234,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -246,7 +245,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 text if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -258,14 +257,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([[], ['word eight', 'word nine', 'word ten']]);
});
it('should filter 3 text if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -277,16 +276,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits.flat(10)).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -298,13 +297,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -316,9 +315,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
['word five', null, 'word six', 'word seven'],
['word one', 'word two', 'word three', 'word four'],
@ -328,7 +327,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"exists" operator', () => {
it('will return 1 results if matching against text for the empty array', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -339,16 +338,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits.flat(10)).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 3 results if matching against text', async () => {
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -359,9 +358,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
['word eight', 'word nine', 'word ten'],
['word five', null, 'word six', 'word seven'],
@ -374,7 +373,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 4 results if we have two lists with an AND contradiction text === "word one" AND text === "word five"', async () => {
await importFile(supertest, log, 'text', ['word one'], 'list_items_1.txt');
await importFile(supertest, log, 'text', ['word five'], 'list_items_2.txt');
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -398,9 +397,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -412,7 +411,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 3 results if we have two lists with an AND text === "word one" AND text === "word two" since we have an array', async () => {
await importFile(supertest, log, 'text', ['word one'], 'list_items_1.txt');
await importFile(supertest, log, 'text', ['word two'], 'list_items_2.txt');
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -436,9 +435,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -448,7 +447,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 3 results if we have a list that includes 1 text', async () => {
await importFile(supertest, log, 'text', ['word one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -463,9 +462,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -475,7 +474,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 2 results if we have a list that includes 2 text', async () => {
await importFile(supertest, log, 'text', ['word one', 'word six'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -490,9 +489,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([[], ['word eight', 'word nine', 'word ten']]);
});
@ -504,7 +503,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one', 'word five', 'word eight'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -519,9 +518,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits.flat(10)).to.eql([]);
});
});
@ -529,7 +528,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is not in list" operator', () => {
it('will return 1 result if we have a list that excludes 1 text', async () => {
await importFile(supertest, log, 'text', ['word one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -544,15 +543,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([['word one', 'word two', 'word three', 'word four']]);
});
it('will return 1 result if we have a list that excludes 1 text but repeat 2 elements from the array in the list', async () => {
await importFile(supertest, log, 'text', ['word one', 'word two'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -567,15 +566,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([['word one', 'word two', 'word three', 'word four']]);
});
it('will return 2 results if we have a list that excludes 2 text', async () => {
await importFile(supertest, log, 'text', ['word one', 'word five'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -590,9 +589,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
['word five', null, 'word six', 'word seven'],
['word one', 'word two', 'word three', 'word four'],
@ -607,7 +606,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one', 'word six', 'word ten'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['text_as_array']);
const rule = getRuleForAlertTesting(['text_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -622,9 +621,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([
['word eight', 'word nine', 'word ten'],
['word five', null, 'word six', 'word seven'],

View file

@ -7,12 +7,17 @@
import { FtrConfigProviderContext } from '@kbn/test';
// eslint-disable-next-line import/no-default-export
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(require.resolve('../config.base.ts'));
const functionalConfig = await readConfigFile(
require.resolve('../../../../../../../config/ess/config.base.trial')
);
return {
...functionalConfig.getAll(),
testFiles: [require.resolve('.')],
testFiles: [require.resolve('..')],
junit: {
reportName:
'Detection Engine ESS/ Exception Operators Data Types API keyword_text_long Integration Tests',
},
};
}

View file

@ -0,0 +1,16 @@
/*
* 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 { createTestConfig } from '../../../../../../../config/serverless/config.base';
export default createTestConfig({
testFiles: [require.resolve('..')],
junit: {
reportName:
'Detection Engine Serverless/ Exception Operators Data Types keyword_text_long API Integration Tests',
},
});

View file

@ -5,9 +5,8 @@
* 2.0.
*/
import { FtrProviderContext } from '../../../common/ftr_provider_context';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile }: FtrProviderContext): void => {
describe('Detection exceptions data types and operators', function () {
loadTestFile(require.resolve('./keyword'));

View file

@ -12,28 +12,27 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type keyword', () => {
describe('@serverless @ess Rule exception operators for data type keyword', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/keyword');
});
@ -43,7 +42,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -56,17 +55,17 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the keyword from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
it('should filter 1 single keyword if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -78,14 +77,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
it('should filter 2 keyword if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -105,14 +104,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word three']);
});
it('should filter 3 keyword if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -140,14 +139,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four']);
});
it('should filter 4 keyword if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -183,15 +182,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -203,13 +202,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -221,14 +220,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word one']);
});
it('will return 0 results if we exclude two keyword', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -248,15 +247,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single keyword if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -268,14 +267,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
it('should filter 2 keyword if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -287,14 +286,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word three']);
});
it('should filter 3 keyword if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -306,14 +305,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four']);
});
it('should filter 4 keyword if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -325,15 +324,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -345,13 +344,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -363,16 +362,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word one']);
});
});
describe('"exists" operator', () => {
it('will return 0 results if matching against keyword', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -383,15 +382,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 4 results if matching against keyword', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -402,9 +401,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
});
@ -413,7 +412,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 4 results if we have two lists with an AND contradiction keyword === "word one" AND keyword === "word two"', async () => {
await importFile(supertest, log, 'keyword', ['word one'], 'list_items_1.txt');
await importFile(supertest, log, 'keyword', ['word two'], 'list_items_2.txt');
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -437,15 +436,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
it('will return 3 results if we have a list that includes 1 keyword', async () => {
await importFile(supertest, log, 'keyword', ['word one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -460,15 +459,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
it('will return 2 results if we have a list that includes 2 keyword', async () => {
await importFile(supertest, log, 'keyword', ['word one', 'word three'], 'list_items.txt');
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -483,9 +482,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word two']);
});
@ -497,7 +496,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one', 'word two', 'word three', 'word four'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -512,8 +511,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
});
@ -521,7 +520,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is not in list" operator', () => {
it('will return 1 result if we have a list that excludes 1 keyword', async () => {
await importFile(supertest, log, 'keyword', ['word one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -536,15 +535,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word one']);
});
it('will return 2 results if we have a list that excludes 2 keyword', async () => {
await importFile(supertest, log, 'keyword', ['word one', 'word three'], 'list_items.txt');
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -559,9 +558,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word one', 'word three']);
});
@ -573,7 +572,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one', 'word two', 'word three', 'word four'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -588,16 +587,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
});
describe('"matches wildcard" operator', () => {
it('should return 0 alerts if wildcard matches all words', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -610,13 +609,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
it('should return 1 alert if wildcard exceptions match one, two, and three', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -637,14 +636,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four']);
});
it('should return 3 alerts if one is set as an exception', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -657,14 +656,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
it('should return 4 alerts if the wildcard matches nothing', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -676,16 +675,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
});
describe('"does not match wildcard" operator', () => {
it('should return 4 results if excluded wildcard matches all 4 words', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -698,14 +697,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
it('should filter in 2 keywords if using a wildcard exception', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -718,14 +717,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word three', 'word two']);
});
it('should return 1 alert if "word one" is excluded', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -738,14 +737,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql(['word one']);
});
it('should return 0 alerts if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['keyword']);
const rule = getRuleForAlertTesting(['keyword']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -757,8 +756,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
});

View file

@ -12,28 +12,28 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type keyword', () => {
describe('@serverless @ess Rule exception operators for data type keyword', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/keyword_as_array');
});
@ -45,7 +45,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -58,12 +58,12 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the keyword from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -73,7 +73,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 1 single keyword if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -85,9 +85,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -96,7 +96,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 keyword if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -116,14 +116,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([[], ['word eight', 'word nine', 'word ten']]);
});
it('should filter 3 keyword if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -151,16 +151,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits.flat(10)).to.eql([]);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -172,13 +172,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -190,14 +190,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([['word one', 'word two', 'word three', 'word four']]);
});
it('will return 0 results if we exclude two keyword', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -217,15 +217,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single keyword if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -237,9 +237,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -248,7 +248,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 keyword if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -260,14 +260,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([[], ['word eight', 'word nine', 'word ten']]);
});
it('should filter 3 keyword if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -279,16 +279,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits.flat(10)).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -300,13 +300,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -318,9 +318,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
['word five', null, 'word six', 'word seven'],
['word one', 'word two', 'word three', 'word four'],
@ -330,7 +330,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"exists" operator', () => {
it('will return 1 results if matching against keyword for the empty array', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -341,16 +341,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits.flat(10)).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 3 results if matching against keyword', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -361,9 +361,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
['word eight', 'word nine', 'word ten'],
['word five', null, 'word six', 'word seven'],
@ -376,7 +376,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 4 results if we have two lists with an AND contradiction keyword === "word one" AND keyword === "word five"', async () => {
await importFile(supertest, log, 'keyword', ['word one'], 'list_items_1.txt');
await importFile(supertest, log, 'keyword', ['word five'], 'list_items_2.txt');
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -400,9 +400,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -414,7 +414,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 3 results if we have two lists with an AND keyword === "word one" AND keyword === "word two" since we have an array', async () => {
await importFile(supertest, log, 'keyword', ['word one'], 'list_items_1.txt');
await importFile(supertest, log, 'keyword', ['word two'], 'list_items_2.txt');
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -438,9 +438,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -450,7 +450,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 3 results if we have a list that includes 1 keyword', async () => {
await importFile(supertest, log, 'keyword', ['word one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -465,9 +465,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -477,7 +477,7 @@ export default ({ getService }: FtrProviderContext) => {
it('will return 2 results if we have a list that includes 2 keyword', async () => {
await importFile(supertest, log, 'keyword', ['word one', 'word six'], 'list_items.txt');
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -492,9 +492,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([[], ['word eight', 'word nine', 'word ten']]);
});
@ -506,7 +506,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one', 'word five', 'word eight'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -521,9 +521,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits.flat(10)).to.eql([]);
});
});
@ -531,7 +531,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is not in list" operator', () => {
it('will return 1 result if we have a list that excludes 1 keyword', async () => {
await importFile(supertest, log, 'keyword', ['word one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -546,15 +546,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([['word one', 'word two', 'word three', 'word four']]);
});
it('will return 1 result if we have a list that excludes 1 keyword but repeat 2 elements from the array in the list', async () => {
await importFile(supertest, log, 'keyword', ['word one', 'word two'], 'list_items.txt');
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -569,15 +569,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([['word one', 'word two', 'word three', 'word four']]);
});
it('will return 2 results if we have a list that excludes 2 keyword', async () => {
await importFile(supertest, log, 'keyword', ['word one', 'word five'], 'list_items.txt');
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -592,9 +592,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
['word five', null, 'word six', 'word seven'],
['word one', 'word two', 'word three', 'word four'],
@ -609,7 +609,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one', 'word six', 'word ten'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -624,9 +624,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
['word eight', 'word nine', 'word ten'],
['word five', null, 'word six', 'word seven'],
@ -637,7 +637,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"matches wildcard" operator', () => {
it('should filter 1 single keyword if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -649,9 +649,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
[],
['word eight', 'word nine', 'word ten'],
@ -660,7 +660,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 keyword if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -672,14 +672,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([[], ['word five', null, 'word six', 'word seven']]);
});
it('should filter 3 keyword if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -691,16 +691,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits.flat(10)).to.eql([]);
});
});
describe('"does not match wildcard" operator', () => {
it('should filter 1 single keyword if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -712,14 +712,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([['word one', 'word two', 'word three', 'word four']]);
});
it('should filter 2 keyword if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -731,9 +731,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
['word eight', 'word nine', 'word ten'],
['word one', 'word two', 'word three', 'word four'],
@ -741,7 +741,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 3 keyword if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['keyword_as_array']);
const rule = getRuleForAlertTesting(['keyword_as_array']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -753,9 +753,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.keyword).sort();
expect(hits).to.eql([
['word eight', 'word nine', 'word ten'],
['word five', null, 'word six', 'word seven'],

View file

@ -12,28 +12,27 @@ import {
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type long', () => {
describe('@serverless @ess Rule exception operators for data type long', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/long');
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/long_as_string');
@ -45,7 +44,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -58,17 +57,17 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the long from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1', '2', '3', '4']);
});
it('should filter 1 single long if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -80,14 +79,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['2', '3', '4']);
});
it('should filter 2 long if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -107,14 +106,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['3', '4']);
});
it('should filter 3 long if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -142,14 +141,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['4']);
});
it('should filter 4 long if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -185,15 +184,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql([]);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -205,13 +204,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -223,14 +222,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1']);
});
it('will return 0 results if we exclude two long', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -250,15 +249,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql([]);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single long if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -270,14 +269,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['2', '3', '4']);
});
it('should filter 2 long if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -289,14 +288,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['3', '4']);
});
it('should filter 3 long if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -308,14 +307,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['4']);
});
it('should filter 4 long if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -327,15 +326,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -347,13 +346,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -365,16 +364,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1', '4']);
});
});
describe('"exists" operator', () => {
it('will return 0 results if matching against long', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -385,15 +384,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 4 results if matching against long', async () => {
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -404,9 +403,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1', '2', '3', '4']);
});
});
@ -415,7 +414,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against long values in the data set', () => {
it('will return 3 results if we have a list that includes 1 long', async () => {
await importFile(supertest, log, 'long', ['1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -430,15 +429,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['2', '3', '4']);
});
it('will return 2 results if we have a list that includes 2 long', async () => {
await importFile(supertest, log, 'long', ['1', '3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -453,15 +452,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['2', '4']);
});
it('will return 0 results if we have a list that includes all long', async () => {
await importFile(supertest, log, 'long', ['1', '2', '3', '4'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -476,8 +475,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql([]);
});
});
@ -485,7 +484,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against string values in the data set', () => {
it('will return 3 results if we have a list that includes 1 long', async () => {
await importFile(supertest, log, 'long', ['1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long_as_string']);
const rule = getRuleForAlertTesting(['long_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -500,15 +499,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['2', '3', '4']);
});
it('will return 2 results if we have a list that includes 2 long', async () => {
await importFile(supertest, log, 'long', ['1', '3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long_as_string']);
const rule = getRuleForAlertTesting(['long_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -523,15 +522,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['2', '4']);
});
it('will return 0 results if we have a list that includes all long', async () => {
await importFile(supertest, log, 'long', ['1', '2', '3', '4'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long_as_string']);
const rule = getRuleForAlertTesting(['long_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -546,8 +545,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql([]);
});
@ -557,7 +556,7 @@ export default ({ getService }: FtrProviderContext) => {
'2',
'3',
]);
const rule = getRuleForSignalTesting(['long_as_string']);
const rule = getRuleForAlertTesting(['long_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -572,9 +571,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['4']);
});
});
@ -584,7 +583,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against long values in the data set', () => {
it('will return 1 result if we have a list that excludes 1 long', async () => {
await importFile(supertest, log, 'long', ['1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -599,15 +598,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1']);
});
it('will return 2 results if we have a list that excludes 2 long', async () => {
await importFile(supertest, log, 'long', ['1', '3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -622,15 +621,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1', '3']);
});
it('will return 4 results if we have a list that excludes all long', async () => {
await importFile(supertest, log, 'long', ['1', '2', '3', '4'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long']);
const rule = getRuleForAlertTesting(['long']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -645,9 +644,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1', '2', '3', '4']);
});
});
@ -655,7 +654,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against string values in the data set', () => {
it('will return 1 result if we have a list that excludes 1 long', async () => {
await importFile(supertest, log, 'long', ['1'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long_as_string']);
const rule = getRuleForAlertTesting(['long_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -670,15 +669,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1']);
});
it('will return 2 results if we have a list that excludes 2 long', async () => {
await importFile(supertest, log, 'long', ['1', '3'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long_as_string']);
const rule = getRuleForAlertTesting(['long_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -693,15 +692,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1', '3']);
});
it('will return 4 results if we have a list that excludes all long', async () => {
await importFile(supertest, log, 'long', ['1', '2', '3', '4'], 'list_items.txt');
const rule = getRuleForSignalTesting(['long_as_string']);
const rule = getRuleForAlertTesting(['long_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -716,9 +715,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1', '2', '3', '4']);
});
@ -728,7 +727,7 @@ export default ({ getService }: FtrProviderContext) => {
'2',
'3',
]);
const rule = getRuleForSignalTesting(['long_as_string']);
const rule = getRuleForAlertTesting(['long_as_string']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -743,9 +742,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.long).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.long).sort();
expect(hits).to.eql(['1', '2', '3']);
});
});

View file

@ -13,28 +13,27 @@ import {
deleteListsIndex,
importFile,
importTextFile,
} from '../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
} from '../../../../../../../lists_api_integration/utils';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../../utils';
waitForAlertsToBePresent,
} from '../../../../utils';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
describe('Rule exception operators for data type text', () => {
describe('@serverless @ess Rule exception operators for data type text', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/text');
await esArchiver.load('x-pack/test/functional/es_archives/rule_exceptions/text_no_spaces');
@ -46,7 +45,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -59,17 +58,17 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should find all the text from the data set when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
it('should filter 1 single text if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -81,14 +80,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
it('should filter 2 text if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -108,14 +107,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word three']);
});
it('should filter 3 text if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -143,14 +142,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four']);
});
it('should filter 4 text if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -186,13 +185,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
it('should filter 1 single text using a single word', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -204,14 +203,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
it('should filter all words using a common piece of text', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -223,13 +222,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
it('should filter 1 single text with punctuation added', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -241,16 +240,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
});
describe('"is not" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -262,13 +261,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
it('will return just 1 result we excluded', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -280,14 +279,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word one']);
});
it('will return 0 results if we exclude two text', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -307,13 +306,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
it('should filter 1 single text using a single word', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -325,14 +324,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word one']);
});
it('should filter all words using a common piece of text', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -344,14 +343,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
it('should filter 1 single text with punctuation added', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -363,16 +362,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word one']);
});
});
describe('"is one of" operator', () => {
it('should filter 1 single text if it is set as an exception', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -384,14 +383,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
it('should filter 2 text if both are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -403,14 +402,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word three']);
});
it('should filter 3 text if all 3 are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -422,14 +421,14 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four']);
});
it('should filter 4 text if all are set as exceptions', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -441,15 +440,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
});
describe('"is not one of" operator', () => {
it('will return 0 results if it cannot find what it is excluding', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -461,13 +460,13 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
it('will return just the result we excluded', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -479,16 +478,16 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word one']);
});
});
describe('"exists" operator', () => {
it('will return 0 results if matching against text', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -499,15 +498,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
});
describe('"does not exist" operator', () => {
it('will return 4 results if matching against text', async () => {
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -518,9 +517,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
});
@ -529,7 +528,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against text values without spaces', () => {
it('will return 3 results if we have a list that includes 1 text', async () => {
await importFile(supertest, log, 'text', ['one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text_no_spaces']);
const rule = getRuleForAlertTesting(['text_no_spaces']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -544,15 +543,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['four', 'three', 'two']);
});
it('will return 2 results if we have a list that includes 2 text', async () => {
await importFile(supertest, log, 'text', ['one', 'three'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text_no_spaces']);
const rule = getRuleForAlertTesting(['text_no_spaces']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -567,9 +566,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['four', 'two']);
});
@ -581,7 +580,7 @@ export default ({ getService }: FtrProviderContext) => {
['one', 'two', 'three', 'four'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['text_no_spaces']);
const rule = getRuleForAlertTesting(['text_no_spaces']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -596,8 +595,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
});
@ -605,7 +604,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against text values with spaces', () => {
it('will return 3 results if we have a list that includes 1 text', async () => {
await importTextFile(supertest, log, 'text', ['word one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -620,9 +619,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
@ -634,7 +633,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one additional wording'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -649,15 +648,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word three', 'word two']);
});
it('will return 2 results if we have a list that includes 2 text', async () => {
await importFile(supertest, log, 'text', ['word one', 'word three'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -672,9 +671,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word two']);
});
@ -686,7 +685,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one', 'word two', 'word three', 'word four'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -701,8 +700,8 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql([]);
});
});
@ -712,7 +711,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against text values without spaces', () => {
it('will return 1 result if we have a list that excludes 1 text', async () => {
await importTextFile(supertest, log, 'text', ['one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text_no_spaces']);
const rule = getRuleForAlertTesting(['text_no_spaces']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -727,15 +726,15 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['one']);
});
it('will return 2 results if we have a list that excludes 2 text', async () => {
await importTextFile(supertest, log, 'text', ['one', 'three'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text_no_spaces']);
const rule = getRuleForAlertTesting(['text_no_spaces']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -750,9 +749,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['one', 'three']);
});
@ -764,7 +763,7 @@ export default ({ getService }: FtrProviderContext) => {
['one', 'two', 'three', 'four'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['text_no_spaces']);
const rule = getRuleForAlertTesting(['text_no_spaces']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -779,9 +778,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['four', 'one', 'three', 'two']);
});
});
@ -789,7 +788,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('working against text values with spaces', () => {
it('will return 1 result if we have a list that excludes 1 text', async () => {
await importTextFile(supertest, log, 'text', ['word one'], 'list_items.txt');
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -804,9 +803,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word one']);
});
@ -818,7 +817,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one additional wording'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -833,9 +832,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word one']);
});
@ -847,7 +846,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one', 'word three'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -862,9 +861,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word one', 'word three']);
});
@ -876,7 +875,7 @@ export default ({ getService }: FtrProviderContext) => {
['word one', 'word two', 'word three', 'word four'],
'list_items.txt'
);
const rule = getRuleForSignalTesting(['text']);
const rule = getRuleForAlertTesting(['text']);
const { id } = await createRuleWithExceptionEntries(supertest, log, rule, [
[
{
@ -891,9 +890,9 @@ export default ({ getService }: FtrProviderContext) => {
],
]);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
const signalsOpen = await getSignalsById(supertest, log, id);
const hits = signalsOpen.hits.hits.map((hit) => hit._source?.text).sort();
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const alertsOpen = await getAlertsById(supertest, log, id);
const hits = alertsOpen.hits.hits.map((hit) => hit._source?.text).sort();
expect(hits).to.eql(['word four', 'word one', 'word three', 'word two']);
});
});

View file

@ -7,12 +7,16 @@
import { FtrConfigProviderContext } from '@kbn/test';
// eslint-disable-next-line import/no-default-export
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(require.resolve('../config.base.ts'));
const functionalConfig = await readConfigFile(
require.resolve('../../../../../../config/ess/config.base.trial')
);
return {
...functionalConfig.getAll(),
testFiles: [require.resolve('.')],
testFiles: [require.resolve('..')],
junit: {
reportName: 'Detection Engine ESS/ Exception Workflows API Integration Tests',
},
};
}

View file

@ -0,0 +1,15 @@
/*
* 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 { createTestConfig } from '../../../../../../config/serverless/config.base';
export default createTestConfig({
testFiles: [require.resolve('..')],
junit: {
reportName: 'Detection Engine Serverless/ Exception Workflows API Integration Tests',
},
});

View file

@ -9,30 +9,24 @@ import { ToolingLog } from '@kbn/tooling-log';
import expect from 'expect';
import type SuperTest from 'supertest';
import { ROLES } from '@kbn/security-solution-plugin/common/test';
import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants';
import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
import { UpdateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
import { getUpdateMinimalExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/request/update_exception_list_item_schema.mock';
import { getCreateExceptionListItemMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock';
import { createUserAndRole, deleteUserAndRole } from '../../../common/services/security_solution';
import {
createRule,
createRuleWithExceptionEntries,
createSignalsIndex,
createAlertsIndex,
deleteAllRules,
deleteAllAlerts,
getRuleForSignalTesting,
getSignalsById,
getRuleForAlertTesting,
getAlertsById,
waitForRuleSuccess,
waitForSignalsToBePresent,
} from '../../utils';
import { FtrProviderContext } from '../../common/ftr_provider_context';
waitForAlertsToBePresent,
} from '../../../utils';
import {
createListsIndex,
deleteAllExceptions,
deleteListsIndex,
} from '../../../lists_api_integration/utils';
} from '../../../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../../../ftr_provider_context';
interface Host {
os: {
@ -42,10 +36,10 @@ interface Host {
}
/**
* Convenience method to get signals by host and sort them for better deterministic testing
* Convenience method to get Alerts by host and sort them for better deterministic testing
* since Elastic can return the hits back in any order we want to sort them on return for testing.
* @param supertest Super test for testing.
* @param id The signals id
* @param id The Alerts id
* @returns The array of hosts sorted
*/
export const getHostHits = async (
@ -53,8 +47,8 @@ export const getHostHits = async (
log: ToolingLog,
id: string
): Promise<Host[]> => {
const signalsOpen = await getSignalsById(supertest, log, id);
return signalsOpen.hits.hits
const AlertsOpen = await getAlertsById(supertest, log, id);
return AlertsOpen.hits.hits
.map<Host>((hit) => hit._source?.host as Host)
.sort((a, b) => {
let sortOrder = 0;
@ -74,15 +68,13 @@ export const getHostHits = async (
});
};
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const log = getService('log');
const es = getService('es');
describe('create_endpoint_exceptions', () => {
describe('@serverless @ess create_endpoint_exceptions', () => {
before(async () => {
await esArchiver.load(
'x-pack/test/functional/es_archives/rule_exceptions/endpoint_without_host_type'
@ -98,7 +90,7 @@ export default ({ getService }: FtrProviderContext) => {
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
await createListsIndex(supertest, log);
});
@ -111,10 +103,10 @@ export default ({ getService }: FtrProviderContext) => {
describe('no exceptions set', () => {
it('should find all the "hosts" from a "agent" index when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -133,10 +125,10 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should find all the "hosts" from a "endpoint_without_host_type" index when no exceptions are set on the rule', async () => {
const rule = getRuleForSignalTesting(['endpoint_without_host_type']);
const rule = getRuleForAlertTesting(['endpoint_without_host_type']);
const { id } = await createRule(supertest, log, rule);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -158,7 +150,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('operating system types (os_types)', () => {
describe('endpoints', () => {
it('should filter 1 operating system types (os_type) if it is set as part of an endpoint exception', async () => {
const rule = getRuleForSignalTesting(['endpoint_without_host_type']);
const rule = getRuleForAlertTesting(['endpoint_without_host_type']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -179,7 +171,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -195,7 +187,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 operating system types as an "OR" (os_type) if it is set as part of an endpoint exception', async () => {
const rule = getRuleForSignalTesting(['endpoint_without_host_type']);
const rule = getRuleForAlertTesting(['endpoint_without_host_type']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -216,7 +208,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -232,7 +224,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter multiple operating system types if it is set as part of an endpoint exception', async () => {
const rule = getRuleForSignalTesting(['endpoint_without_host_type']);
const rule = getRuleForAlertTesting(['endpoint_without_host_type']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -264,7 +256,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -277,7 +269,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter multiple operating system types (os_type) with multiple filter items for an endpoint', async () => {
const rule = getRuleForSignalTesting(['endpoint_without_host_type']);
const rule = getRuleForAlertTesting(['endpoint_without_host_type']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -309,7 +301,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -324,7 +316,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('agent', () => {
it('should filter 1 operating system types (os_type) if it is set as part of an endpoint exception', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -345,7 +337,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -361,7 +353,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 1 operating system type as an "OR" (os_type) if it is set as part of an endpoint exception', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -382,7 +374,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -398,7 +390,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter multiple operating system types if it is set as part of an endpoint exception', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -430,7 +422,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -443,7 +435,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter multiple operating system types (os_type) with multiple filter items for an endpoint', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -475,7 +467,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -490,7 +482,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('agent and endpoint', () => {
it('should filter 2 operating system types (os_type) if it is set as part of an endpoint exception', async () => {
const rule = getRuleForSignalTesting(['agent', 'endpoint_without_host_type']);
const rule = getRuleForAlertTesting(['agent', 'endpoint_without_host_type']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -511,7 +503,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 6, [id]);
await waitForAlertsToBePresent(supertest, log, 6, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -536,7 +528,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 operating system types as an "OR" (os_type) if it is set as part of an endpoint exception', async () => {
const rule = getRuleForSignalTesting(['agent', 'endpoint_without_host_type']);
const rule = getRuleForAlertTesting(['agent', 'endpoint_without_host_type']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -557,7 +549,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 6, [id]);
await waitForAlertsToBePresent(supertest, log, 6, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -582,7 +574,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter multiple operating system types if it is set as part of an endpoint exception', async () => {
const rule = getRuleForSignalTesting(['agent', 'endpoint_without_host_type']);
const rule = getRuleForAlertTesting(['agent', 'endpoint_without_host_type']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -614,7 +606,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -633,7 +625,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter multiple operating system types (os_type) with multiple filter items for an endpoint', async () => {
const rule = getRuleForSignalTesting(['agent', 'endpoint_without_host_type']);
const rule = getRuleForAlertTesting(['agent', 'endpoint_without_host_type']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -665,7 +657,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -687,7 +679,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is" operator', () => {
it('should filter 1 value set as an endpoint exception and 1 value set as a normal rule exception ', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -717,7 +709,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -727,7 +719,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 1 value set as an endpoint exception and 1 value set as a normal rule exception with os_type set', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -757,7 +749,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 1, [id]);
await waitForAlertsToBePresent(supertest, log, 1, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -769,7 +761,7 @@ export default ({ getService }: FtrProviderContext) => {
describe('"is one of" operator', () => {
it('should filter 1 single value if it is set as an exception and the os_type is set to only 1 value', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -790,7 +782,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 3, [id]);
await waitForAlertsToBePresent(supertest, log, 3, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -806,7 +798,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 values if it is set as an exception and the os_type is set to 2 values', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -827,7 +819,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -840,7 +832,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter 2 values if it is set as an exception and the os_type is set to undefined', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -861,7 +853,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 2, [id]);
await waitForAlertsToBePresent(supertest, log, 2, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -874,7 +866,7 @@ export default ({ getService }: FtrProviderContext) => {
});
it('should filter no values if they are set as an exception but the os_type is set to something not within the documents', async () => {
const rule = getRuleForSignalTesting(['agent']);
const rule = getRuleForAlertTesting(['agent']);
const { id } = await createRuleWithExceptionEntries(
supertest,
log,
@ -895,7 +887,7 @@ export default ({ getService }: FtrProviderContext) => {
]
);
await waitForRuleSuccess({ supertest, log, id });
await waitForSignalsToBePresent(supertest, log, 4, [id]);
await waitForAlertsToBePresent(supertest, log, 4, [id]);
const hits = await getHostHits(supertest, log, id);
expect(hits).toEqual([
{
@ -913,113 +905,5 @@ export default ({ getService }: FtrProviderContext) => {
]);
});
});
describe('Add/edit exception comments by different users', () => {
const socManager = ROLES.soc_manager;
const detectionAdmin = ROLES.detections_admin;
beforeEach(async () => {
await createUserAndRole(getService, detectionAdmin);
await createUserAndRole(getService, socManager);
});
afterEach(async () => {
await deleteUserAndRole(getService, detectionAdmin);
await deleteUserAndRole(getService, socManager);
await deleteAllExceptions(supertest, log);
});
it('Add comment on a new exception, add another comment has unicode from a different user', async () => {
await supertestWithoutAuth
.post(EXCEPTION_LIST_URL)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send(getCreateExceptionListMinimalSchemaMock())
.expect(200);
// Add comment by the Detection Admin
await supertestWithoutAuth
.post(EXCEPTION_LIST_ITEM_URL)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send({
...getCreateExceptionListItemMinimalSchemaMock(),
comments: [{ comment: 'Comment by user@detections_admin' }],
})
.expect(200);
const { body: items } = await supertestWithoutAuth
.get(
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
getCreateExceptionListMinimalSchemaMock().list_id
}`
)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send()
.expect(200);
// Validate the first user comment
expect(items.total).toEqual(1);
const [item] = items.data;
const detectionAdminComments = item.comments;
expect(detectionAdminComments.length).toEqual(1);
expect(detectionAdminComments[0]).toEqual(
expect.objectContaining({
created_by: 'detections_admin',
comment: 'Comment by user@detections_admin',
})
);
const expectedId = item.id;
// Update exception comment by different user Soc-manager
const { item_id: _, ...updateItemWithoutItemId } =
getUpdateMinimalExceptionListItemSchemaMock();
const updatePayload: UpdateExceptionListItemSchema = {
...updateItemWithoutItemId,
comments: [
...(updateItemWithoutItemId.comments || []),
{ comment: 'Comment by user@soc_manager' },
],
id: expectedId,
};
await supertestWithoutAuth
.put(EXCEPTION_LIST_ITEM_URL)
.auth(socManager, 'changeme')
.set('kbn-xsrf', 'true')
.send(updatePayload)
.expect(200);
const { body: itemsAfterUpdate } = await supertest
.get(
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
getCreateExceptionListMinimalSchemaMock().list_id
}`
)
.auth(socManager, 'changeme')
.set('kbn-xsrf', 'true')
.send()
.expect(200);
const [itemAfterUpdate] = itemsAfterUpdate.data;
const detectionAdminAndSocManagerComments = itemAfterUpdate.comments;
expect(detectionAdminAndSocManagerComments.length).toEqual(2);
expect(detectionAdminAndSocManagerComments).toEqual(
expect.arrayContaining([
expect.objectContaining({
created_by: 'detections_admin',
comment: 'Comment by user@detections_admin',
}),
expect.objectContaining({
created_by: 'soc_manager',
comment: 'Comment by user@soc_manager',
}),
])
);
});
});
});
};

View file

@ -15,8 +15,6 @@ import {
ExceptionListTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import {
getRule,
createRule,
@ -25,11 +23,12 @@ import {
deleteAllRules,
createExceptionList,
deleteAllAlerts,
} from '../../utils';
} from '../../../utils';
import {
deleteAllExceptions,
removeExceptionListItemServerGeneratedProperties,
} from '../../../../../lists_api_integration/utils';
} from '../../../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../../../ftr_provider_context';
const getRuleExceptionItemMock = (): CreateRuleExceptionListItemSchema => ({
description: 'Exception item for rule default exception list',

View file

@ -0,0 +1,230 @@
/*
* 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.
*/
/* eslint-disable @typescript-eslint/naming-convention */
import expect from '@kbn/expect';
import {
CreateExceptionListSchema,
ExceptionListTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
import {
DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL,
RuleReferencesSchema,
} from '@kbn/security-solution-plugin/common/api/detection_engine/rule_exceptions';
import { FtrProviderContext } from '../../../../../ftr_provider_context';
import {
createRule,
getSimpleRule,
deleteAllRules,
createExceptionList,
deleteAllAlerts,
createAlertsIndex,
} from '../../../utils';
import { deleteAllExceptions } from '../../../../../../lists_api_integration/utils';
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const log = getService('log');
const es = getService('es');
describe('@serverless @ess find_rule_exception_references', () => {
before(async () => {
await createAlertsIndex(supertest, log);
});
after(async () => {
await deleteAllAlerts(supertest, log, es);
await deleteAllRules(supertest, log);
});
afterEach(async () => {
await deleteAllExceptions(supertest, log);
});
it('returns empty array per list_id if no references are found', async () => {
// create exception list
const newExceptionList: CreateExceptionListSchema = {
...getCreateExceptionListMinimalSchemaMock(),
list_id: 'i_exist',
namespace_type: 'single',
type: ExceptionListTypeEnum.DETECTION,
};
const exceptionList = await createExceptionList(supertest, log, newExceptionList);
// create rule
await createRule(supertest, log, getSimpleRule('rule-1'));
const { body: references } = await supertest
.get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL)
.set('kbn-xsrf', 'true')
.set('elastic-api-version', '1')
.query({
ids: `${exceptionList.id}`,
list_ids: `${exceptionList.list_id}`,
namespace_types: `${exceptionList.namespace_type}`,
})
.expect(200);
const {
_version,
id,
created_at,
created_by,
tie_breaker_id,
updated_at,
updated_by,
...referencesWithoutServerValues
} = references.references[0].i_exist;
expect({
references: [
{
i_exist: {
...referencesWithoutServerValues,
},
},
],
}).to.eql({
references: [
{
i_exist: {
description: 'some description',
immutable: false,
list_id: 'i_exist',
name: 'some name',
namespace_type: 'single',
os_types: [],
tags: [],
type: 'detection',
version: 1,
referenced_rules: [],
},
},
],
});
});
it('returns empty array per list_id if list does not exist', async () => {
// create rule
await createRule(supertest, log, getSimpleRule('rule-1'));
const { body: references } = await supertest
.get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL)
.set('kbn-xsrf', 'true')
.set('elastic-api-version', '1')
.query({
ids: `1234`,
list_ids: `i_dont_exist`,
namespace_types: `single`,
})
.expect(200);
expect(references).to.eql({ references: [] });
});
it('returns found references', async () => {
// create exception list
const newExceptionList: CreateExceptionListSchema = {
...getCreateExceptionListMinimalSchemaMock(),
list_id: 'i_exist',
namespace_type: 'single',
type: ExceptionListTypeEnum.DETECTION,
};
const exceptionList = await createExceptionList(supertest, log, newExceptionList);
const exceptionList2 = await createExceptionList(supertest, log, {
...newExceptionList,
list_id: 'i_exist_2',
});
// create rule
await createRule(supertest, log, {
...getSimpleRule('rule-2'),
exceptions_list: [
{
id: `${exceptionList.id}`,
list_id: `${exceptionList.list_id}`,
namespace_type: `${exceptionList.namespace_type}`,
type: `${exceptionList.type}`,
},
{
id: `${exceptionList2.id}`,
list_id: `${exceptionList2.list_id}`,
namespace_type: `${exceptionList2.namespace_type}`,
type: `${exceptionList2.type}`,
},
],
});
const { body: references } = await supertest
.get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL)
.set('kbn-xsrf', 'true')
.set('elastic-api-version', '1')
.query({
ids: `${exceptionList.id},${exceptionList2.id}`,
list_ids: `${exceptionList.list_id},${exceptionList2.list_id}`,
namespace_types: `${exceptionList.namespace_type},${exceptionList2.namespace_type}`,
})
.expect(200);
const refs = references.references.flatMap((ref: RuleReferencesSchema) => Object.keys(ref));
expect(refs.sort()).to.eql(['i_exist', 'i_exist_2'].sort());
});
it('returns found references for all existing exception lists if no list id/list_id passed in', async () => {
// create exception list
const newExceptionList: CreateExceptionListSchema = {
...getCreateExceptionListMinimalSchemaMock(),
list_id: 'i_exist',
namespace_type: 'single',
type: ExceptionListTypeEnum.DETECTION,
};
const exceptionList = await createExceptionList(supertest, log, newExceptionList);
const exceptionList2 = await createExceptionList(supertest, log, {
...newExceptionList,
list_id: 'i_exist_2',
});
// create rule
await createRule(supertest, log, {
...getSimpleRule('rule-2'),
exceptions_list: [
{
id: `${exceptionList.id}`,
list_id: `${exceptionList.list_id}`,
namespace_type: `${exceptionList.namespace_type}`,
type: `${exceptionList.type}`,
},
{
id: `${exceptionList2.id}`,
list_id: `${exceptionList2.list_id}`,
namespace_type: `${exceptionList2.namespace_type}`,
type: `${exceptionList2.type}`,
},
],
});
const { body: references } = await supertest
.get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL)
.set('kbn-xsrf', 'true')
.set('elastic-api-version', '1')
.query({
namespace_types: 'single,agnostic',
})
.expect(200);
const refs = references.references.flatMap((ref: RuleReferencesSchema) => Object.keys(ref));
expect(refs.sort()).to.eql(['i_exist', 'i_exist_2', 'endpoint_list'].sort());
});
});
};

View file

@ -0,0 +1,18 @@
/*
* 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 { FtrProviderContext } from '../../../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Exceptions API', function () {
loadTestFile(require.resolve('./create_rule_exceptions'));
loadTestFile(require.resolve('./create_rule_exceptions'));
loadTestFile(require.resolve('./role_based_rule_exceptions_workflows'));
loadTestFile(require.resolve('./create_endpoint_exceptions'));
loadTestFile(require.resolve('./role_based_add_edit_comments'));
loadTestFile(require.resolve('./rule_exception_synchronizations'));
});
}

View file

@ -0,0 +1,250 @@
/*
* 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.
*/
/* eslint-disable @typescript-eslint/naming-convention */
import expect from 'expect';
import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants';
import {
getCreateExceptionListDetectionSchemaMock,
getCreateExceptionListMinimalSchemaMock,
} from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
import { getCreateExceptionListItemMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock';
import { ROLES } from '@kbn/security-solution-plugin/common/test';
import { getUpdateMinimalExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/request/update_exception_list_item_schema.mock';
import { UpdateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
import { deleteAllExceptions } from '../../../../../../lists_api_integration/utils';
import {
createUserAndRole,
deleteUserAndRole,
} from '../../../../../../common/services/security_solution';
import { FtrProviderContext } from '../../../../../ftr_provider_context';
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const log = getService('log');
const supertestWithoutAuth = getService('supertestWithoutAuth');
describe('@serverless @ess @brokenInServerless role_based_add_edit_comments', () => {
const socManager = ROLES.soc_manager;
const detectionAdmin = ROLES.detections_admin;
describe('Rule Exceptions', () => {
beforeEach(async () => {
await createUserAndRole(getService, detectionAdmin);
await createUserAndRole(getService, socManager);
});
afterEach(async () => {
await deleteUserAndRole(getService, detectionAdmin);
await deleteUserAndRole(getService, socManager);
await deleteAllExceptions(supertest, log);
});
it('Add comment on a new exception, add another comment has unicode from a different user', async () => {
await supertestWithoutAuth
.post(EXCEPTION_LIST_URL)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send(getCreateExceptionListDetectionSchemaMock())
.expect(200);
const { os_types, ...ruleException } = getCreateExceptionListItemMinimalSchemaMock();
// Add comment by the Detection Admin
await supertestWithoutAuth
.post(EXCEPTION_LIST_ITEM_URL)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send({
...ruleException,
comments: [{ comment: 'Comment by user@detections_admin' }],
})
.expect(200);
const { body: items } = await supertestWithoutAuth
.get(
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
getCreateExceptionListMinimalSchemaMock().list_id
}`
)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send()
.expect(200);
// Validate the first user comment
expect(items.total).toEqual(1);
const [item] = items.data;
const detectionAdminComments = item.comments;
expect(detectionAdminComments.length).toEqual(1);
expect(detectionAdminComments[0]).toEqual(
expect.objectContaining({
created_by: 'detections_admin',
comment: 'Comment by user@detections_admin',
})
);
const expectedId = item.id;
// Update exception comment by different user Soc-manager
const { item_id: _, ...updateItemWithoutItemId } =
getUpdateMinimalExceptionListItemSchemaMock();
const updatePayload: UpdateExceptionListItemSchema = {
...updateItemWithoutItemId,
comments: [
...(updateItemWithoutItemId.comments || []),
{ comment: 'Comment by user@soc_manager' },
],
id: expectedId,
};
await supertestWithoutAuth
.put(EXCEPTION_LIST_ITEM_URL)
.auth(socManager, 'changeme')
.set('kbn-xsrf', 'true')
.send(updatePayload)
.expect(200);
const { body: itemsAfterUpdate } = await supertest
.get(
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
getCreateExceptionListMinimalSchemaMock().list_id
}`
)
.auth(socManager, 'changeme')
.set('kbn-xsrf', 'true')
.send()
.expect(200);
const [itemAfterUpdate] = itemsAfterUpdate.data;
const detectionAdminAndSocManagerComments = itemAfterUpdate.comments;
expect(detectionAdminAndSocManagerComments.length).toEqual(2);
expect(detectionAdminAndSocManagerComments).toEqual(
expect.arrayContaining([
expect.objectContaining({
created_by: 'detections_admin',
comment: 'Comment by user@detections_admin',
}),
expect.objectContaining({
created_by: 'soc_manager',
comment: 'Comment by user@soc_manager',
}),
])
);
});
});
describe('Endpoint Exceptions', () => {
beforeEach(async () => {
await createUserAndRole(getService, detectionAdmin);
await createUserAndRole(getService, socManager);
});
afterEach(async () => {
await deleteUserAndRole(getService, detectionAdmin);
await deleteUserAndRole(getService, socManager);
await deleteAllExceptions(supertest, log);
});
it('Add comment on a new exception, add another comment has unicode from a different user', async () => {
await supertestWithoutAuth
.post(EXCEPTION_LIST_URL)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send(getCreateExceptionListMinimalSchemaMock())
.expect(200);
// Add comment by the Detection Admin
await supertestWithoutAuth
.post(EXCEPTION_LIST_ITEM_URL)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send({
...getCreateExceptionListItemMinimalSchemaMock(),
comments: [{ comment: 'Comment by user@detections_admin' }],
})
.expect(200);
const { body: items } = await supertestWithoutAuth
.get(
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
getCreateExceptionListMinimalSchemaMock().list_id
}`
)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send()
.expect(200);
// Validate the first user comment
expect(items.total).toEqual(1);
const [item] = items.data;
const detectionAdminComments = item.comments;
expect(detectionAdminComments.length).toEqual(1);
expect(detectionAdminComments[0]).toEqual(
expect.objectContaining({
created_by: 'detections_admin',
comment: 'Comment by user@detections_admin',
})
);
const expectedId = item.id;
// Update exception comment by different user Soc-manager
const { item_id: _, ...updateItemWithoutItemId } =
getUpdateMinimalExceptionListItemSchemaMock();
const updatePayload: UpdateExceptionListItemSchema = {
...updateItemWithoutItemId,
comments: [
...(updateItemWithoutItemId.comments || []),
{ comment: 'Comment by user@soc_manager' },
],
id: expectedId,
};
await supertestWithoutAuth
.put(EXCEPTION_LIST_ITEM_URL)
.auth(socManager, 'changeme')
.set('kbn-xsrf', 'true')
.send(updatePayload)
.expect(200);
const { body: itemsAfterUpdate } = await supertest
.get(
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
getCreateExceptionListMinimalSchemaMock().list_id
}`
)
.auth(socManager, 'changeme')
.set('kbn-xsrf', 'true')
.send()
.expect(200);
const [itemAfterUpdate] = itemsAfterUpdate.data;
const detectionAdminAndSocManagerComments = itemAfterUpdate.comments;
expect(detectionAdminAndSocManagerComments.length).toEqual(2);
expect(detectionAdminAndSocManagerComments).toEqual(
expect.arrayContaining([
expect.objectContaining({
created_by: 'detections_admin',
comment: 'Comment by user@detections_admin',
}),
expect.objectContaining({
created_by: 'soc_manager',
comment: 'Comment by user@soc_manager',
}),
])
);
});
});
});
};

View file

@ -8,10 +8,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import expect from 'expect';
import type {
CreateExceptionListItemSchema,
UpdateExceptionListItemSchema,
} from '@kbn/securitysolution-io-ts-list-types';
import type { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
import {
EXCEPTION_LIST_ITEM_URL,
EXCEPTION_LIST_URL,
@ -25,68 +22,76 @@ import type {
ThresholdRuleCreateProps,
} from '@kbn/security-solution-plugin/common/api/detection_engine';
import { getCreateExceptionListItemMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock';
import {
getCreateExceptionListDetectionSchemaMock,
getCreateExceptionListMinimalSchemaMock,
} from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants';
import { ROLES } from '@kbn/security-solution-plugin/common/test';
import { ELASTIC_SECURITY_RULE_ID } from '@kbn/security-solution-plugin/common';
import { getUpdateMinimalExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/request/update_exception_list_item_schema.mock';
import { FtrProviderContext } from '../../common/ftr_provider_context';
import { EsArchivePathBuilder } from '../../../../../es_archive_path_builder';
import {
createSignalsIndex,
deleteAllRules,
deleteAllAlerts,
createAlertsIndex,
getRule,
createRule,
getSimpleRule,
deleteAllRules,
createExceptionList,
createExceptionListItem,
getThresholdRuleForAlertTesting,
getSimpleRuleOutput,
removeServerGeneratedProperties,
downgradeImmutableRule,
createRule,
waitForRuleSuccess,
installMockPrebuiltRules,
getRule,
createExceptionList,
createExceptionListItem,
waitForSignalsToBePresent,
getSignalsByIds,
waitForAlertsToBePresent,
getAlertsByIds,
findImmutableRuleById,
getPrebuiltRulesAndTimelinesStatus,
getOpenSignals,
getOpenAlerts,
createRuleWithExceptionEntries,
getEqlRuleForSignalTesting,
getThresholdRuleForSignalTesting,
} from '../../utils';
getEqlRuleForAlertTesting,
SAMPLE_PREBUILT_RULES,
deleteAllAlerts,
updateUsername,
} from '../../../utils';
import {
createListsIndex,
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../lists_api_integration/utils';
import { createUserAndRole, deleteUserAndRole } from '../../../common/services/security_solution';
import { SAMPLE_PREBUILT_RULES } from '../../utils/prebuilt_rules/create_prebuilt_rule_saved_objects';
} from '../../../../../../lists_api_integration/utils';
import {
createUserAndRole,
deleteUserAndRole,
} from '../../../../../../common/services/security_solution';
import { FtrProviderContext } from '../../../../../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const esArchiver = getService('esArchiver');
const log = getService('log');
const es = getService('es');
// TODO: add a new service
const config = getService('config');
const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username');
const isServerless = config.get('serverless');
const dataPathBuilder = new EsArchivePathBuilder(isServerless);
const path = dataPathBuilder.getPath('auditbeat/hosts');
describe('create_rules_with_exceptions', () => {
describe('@serverless @ess role_based_rule_exceptions_workflows', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts');
await esArchiver.load(path);
});
after(async () => {
await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts');
await esArchiver.unload(path);
});
describe('creating rules with exceptions', () => {
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
});
afterEach(async () => {
@ -116,10 +121,10 @@ export default ({ getService }: FtrProviderContext) => {
},
],
};
const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME);
const rule = await createRule(supertest, log, ruleWithException);
const expected = {
...getSimpleRuleOutput(),
...expectedRule,
exceptions_list: [
{
id,
@ -158,9 +163,10 @@ export default ({ getService }: FtrProviderContext) => {
const rule = await createRule(supertest, log, ruleWithException);
await waitForRuleSuccess({ supertest, log, id: rule.id });
const bodyToCompare = removeServerGeneratedProperties(rule);
const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME);
const expected = {
...getSimpleRuleOutput(),
...expectedRule,
enabled: true,
exceptions_list: [
{
@ -497,7 +503,7 @@ export default ({ getService }: FtrProviderContext) => {
});
});
describe('t1_analyst', () => {
describe('@brokenInServerless t1_analyst', () => {
const role = ROLES.t1_analyst;
beforeEach(async () => {
@ -529,15 +535,15 @@ export default ({ getService }: FtrProviderContext) => {
describe('tests with auditbeat data', () => {
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts');
await esArchiver.load(path);
});
after(async () => {
await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts');
await esArchiver.unload(path);
});
beforeEach(async () => {
await createSignalsIndex(supertest, log);
await createAlertsIndex(supertest, log);
});
afterEach(async () => {
@ -546,7 +552,7 @@ export default ({ getService }: FtrProviderContext) => {
await deleteAllExceptions(supertest, log);
});
it('should be able to execute against an exception list that does not include valid entries and get back 10 signals', async () => {
it('should be able to execute against an exception list that does not include valid entries and get back 10 alerts', async () => {
const { id, list_id, namespace_type, type } = await createExceptionList(
supertest,
log,
@ -588,12 +594,12 @@ export default ({ getService }: FtrProviderContext) => {
};
const { id: createdId } = await createRule(supertest, log, ruleWithException);
await waitForRuleSuccess({ supertest, log, id: createdId });
await waitForSignalsToBePresent(supertest, log, 10, [createdId]);
const signalsOpen = await getSignalsByIds(supertest, log, [createdId]);
expect(signalsOpen.hits.hits.length).toEqual(10);
await waitForAlertsToBePresent(supertest, log, 10, [createdId]);
const alertsOpen = await getAlertsByIds(supertest, log, [createdId]);
expect(alertsOpen.hits.hits.length).toEqual(10);
});
it('should be able to execute against an exception list that does include valid entries and get back 0 signals', async () => {
it('should be able to execute against an exception list that does include valid entries and get back 0 alerts', async () => {
const rule: QueryRuleCreateProps = {
name: 'Simple Rule Query',
description: 'Simple Rule Query',
@ -616,11 +622,11 @@ export default ({ getService }: FtrProviderContext) => {
},
],
]);
const signalsOpen = await getOpenSignals(supertest, log, es, createdRule);
expect(signalsOpen.hits.hits.length).toEqual(0);
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
expect(alertsOpen.hits.hits.length).toEqual(0);
});
it('should be able to execute against an exception list that does include valid case sensitive entries and get back 0 signals', async () => {
it('should be able to execute against an exception list that does include valid case sensitive entries and get back 0 alerts', async () => {
const rule: QueryRuleCreateProps = {
name: 'Simple Rule Query',
description: 'Simple Rule Query',
@ -665,19 +671,19 @@ export default ({ getService }: FtrProviderContext) => {
},
],
]);
const signalsOpen = await getOpenSignals(supertest, log, es, createdRule);
const signalsOpen2 = await getOpenSignals(supertest, log, es, createdRule2);
// Expect signals here because all values are "Ubuntu"
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
const alertsOpen2 = await getOpenAlerts(supertest, log, es, createdRule2);
// Expect alerts here because all values are "Ubuntu"
// and exception is one of ["ubuntu"]
expect(signalsOpen.hits.hits.length).toEqual(10);
// Expect no signals here because all values are "Ubuntu"
expect(alertsOpen.hits.hits.length).toEqual(10);
// Expect no alerts here because all values are "Ubuntu"
// and exception is one of ["ubuntu", "Ubuntu"]
expect(signalsOpen2.hits.hits.length).toEqual(0);
expect(alertsOpen2.hits.hits.length).toEqual(0);
});
it('generates no signals when an exception is added for an EQL rule', async () => {
it('generates no alerts when an exception is added for an EQL rule', async () => {
const rule: EqlRuleCreateProps = {
...getEqlRuleForSignalTesting(['auditbeat-*']),
...getEqlRuleForAlertTesting(['auditbeat-*']),
query: 'configuration where agent.id=="a1d7b39c-f898-4dbe-a761-efb61939302d"',
};
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
@ -690,13 +696,13 @@ export default ({ getService }: FtrProviderContext) => {
},
],
]);
const signalsOpen = await getOpenSignals(supertest, log, es, createdRule);
expect(signalsOpen.hits.hits.length).toEqual(0);
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
expect(alertsOpen.hits.hits.length).toEqual(0);
});
it('generates no signals when an exception is added for a threshold rule', async () => {
it('generates no alerts when an exception is added for a threshold rule', async () => {
const rule: ThresholdRuleCreateProps = {
...getThresholdRuleForSignalTesting(['auditbeat-*']),
...getThresholdRuleForAlertTesting(['auditbeat-*']),
threshold: {
field: 'host.id',
value: 700,
@ -712,11 +718,11 @@ export default ({ getService }: FtrProviderContext) => {
},
],
]);
const signalsOpen = await getOpenSignals(supertest, log, es, createdRule);
expect(signalsOpen.hits.hits.length).toEqual(0);
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
expect(alertsOpen.hits.hits.length).toEqual(0);
});
it('generates no signals when an exception is added for a threat match rule', async () => {
it('generates no alerts when an exception is added for a threat match rule', async () => {
const rule: ThreatMatchRuleCreateProps = {
description: 'Detecting root and admin users',
name: 'Query with a rule id',
@ -755,8 +761,8 @@ export default ({ getService }: FtrProviderContext) => {
},
],
]);
const signalsOpen = await getOpenSignals(supertest, log, es, createdRule);
expect(signalsOpen.hits.hits.length).toEqual(0);
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
expect(alertsOpen.hits.hits.length).toEqual(0);
});
describe('rules with value list exceptions', () => {
beforeEach(async () => {
@ -767,7 +773,7 @@ export default ({ getService }: FtrProviderContext) => {
await deleteListsIndex(supertest, log);
});
it('generates no signals when a value list exception is added for a query rule', async () => {
it('generates no alerts when a value list exception is added for a query rule', async () => {
const valueListId = 'value-list-id';
await importFile(supertest, log, 'keyword', ['suricata-sensor-amsterdam'], valueListId);
const rule: QueryRuleCreateProps = {
@ -795,11 +801,11 @@ export default ({ getService }: FtrProviderContext) => {
},
],
]);
const signalsOpen = await getOpenSignals(supertest, log, es, createdRule);
expect(signalsOpen.hits.hits.length).toEqual(0);
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
expect(alertsOpen.hits.hits.length).toEqual(0);
});
it('generates no signals when a value list exception is added for a threat match rule', async () => {
it('generates no alerts when a value list exception is added for a threat match rule', async () => {
const valueListId = 'value-list-id';
await importFile(supertest, log, 'keyword', ['zeek-sensor-amsterdam'], valueListId);
const rule: ThreatMatchRuleCreateProps = {
@ -843,11 +849,11 @@ export default ({ getService }: FtrProviderContext) => {
},
],
]);
const signalsOpen = await getOpenSignals(supertest, log, es, createdRule);
expect(signalsOpen.hits.hits.length).toEqual(0);
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
expect(alertsOpen.hits.hits.length).toEqual(0);
});
it('generates no signals when a value list exception is added for a threshold rule', async () => {
it('generates no alerts when a value list exception is added for a threshold rule', async () => {
const valueListId = 'value-list-id';
await importFile(supertest, log, 'keyword', ['zeek-sensor-amsterdam'], valueListId);
const rule: ThresholdRuleCreateProps = {
@ -880,15 +886,15 @@ export default ({ getService }: FtrProviderContext) => {
},
],
]);
const signalsOpen = await getOpenSignals(supertest, log, es, createdRule);
expect(signalsOpen.hits.hits.length).toEqual(0);
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
expect(alertsOpen.hits.hits.length).toEqual(0);
});
it('generates no signals when a value list exception is added for an EQL rule', async () => {
it('generates no alerts when a value list exception is added for an EQL rule', async () => {
const valueListId = 'value-list-id';
await importFile(supertest, log, 'keyword', ['zeek-sensor-amsterdam'], valueListId);
const rule: EqlRuleCreateProps = {
...getEqlRuleForSignalTesting(['auditbeat-*']),
...getEqlRuleForAlertTesting(['auditbeat-*']),
query: 'configuration where host.name=="zeek-sensor-amsterdam"',
};
@ -905,8 +911,8 @@ export default ({ getService }: FtrProviderContext) => {
},
],
]);
const signalsOpen = await getOpenSignals(supertest, log, es, createdRule);
expect(signalsOpen.hits.hits.length).toEqual(0);
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
expect(alertsOpen.hits.hits.length).toEqual(0);
});
it('should Not allow deleting value list when there are references and ignoreReferences is false', async () => {
const valueListId = 'value-list-id';
@ -944,252 +950,5 @@ export default ({ getService }: FtrProviderContext) => {
});
});
});
describe('Synchronizations', () => {
afterEach(async () => {
await deleteAllAlerts(supertest, log, es);
await deleteAllRules(supertest, log);
await deleteAllExceptions(supertest, log);
});
/*
This test to mimic if we have two browser tabs, and the user tried to
edit an exception in a tab after deleting it in another
*/
it('should Not edit an exception after being deleted', async () => {
const { list_id: skippedListId, ...newExceptionItem } =
getCreateExceptionListDetectionSchemaMock();
const {
body: { id, list_id, namespace_type, type },
} = await supertest
.post(EXCEPTION_LIST_URL)
.set('kbn-xsrf', 'true')
.send(newExceptionItem)
.expect(200);
const ruleWithException: RuleCreateProps = {
...getSimpleRule(),
exceptions_list: [
{
id,
list_id,
namespace_type,
type,
},
],
};
await createRule(supertest, log, ruleWithException);
// Delete the exception
await supertest
.delete(`${EXCEPTION_LIST_ITEM_URL}?id=${id}&namespace_type=single`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
// Edit after delete as if it was opened in another browser tab
const { body } = await supertest
.put(`${EXCEPTION_LIST_ITEM_URL}`)
.set('kbn-xsrf', 'true')
.send({
id: list_id,
item_id: id,
name: 'edit',
entries: [{ field: 'ss', operator: 'included', type: 'match', value: 'ss' }],
namespace_type,
description: 'Exception list item - Edit',
type: 'simple',
})
.expect(404);
expect(body).toEqual({
message: `exception list item id: "${list_id}" does not exist`,
status_code: 404,
});
});
/*
This test to mimic if we have two browser tabs, and the user tried to
edit an exception with value-list was deleted in another tab
*/
it('should Not allow editing an Exception with deleted ValueList', async () => {
await createListsIndex(supertest, log);
const valueListId = 'value-list-id';
await importFile(supertest, log, 'keyword', ['suricata-sensor-amsterdam'], valueListId);
const rule: QueryRuleCreateProps = {
...getSimpleRule(),
query: 'host.name: "suricata-sensor-amsterdam"',
};
const { exceptions_list: exceptionsList } = await createRuleWithExceptionEntries(
supertest,
log,
rule,
[
[
{
field: 'host.name',
operator: 'included',
type: 'list',
list: {
id: valueListId,
type: 'keyword',
},
},
],
]
);
const deleteReferences = false;
const ignoreReferences = true;
const { id, list_id, namespace_type } = exceptionsList[0];
// Delete the value list
await supertest
.delete(
`${LIST_URL}?deleteReferences=${deleteReferences}&id=${valueListId}&ignoreReferences=${ignoreReferences}`
)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
// edit the exception with the deleted value list
await supertest
.put(`${EXCEPTION_LIST_ITEM_URL}`)
.set('kbn-xsrf', 'true')
.send({
id: list_id,
item_id: id,
name: 'edit',
entries: [
{
field: 'host.name',
operator: 'included',
type: 'list',
list: {
id: valueListId,
type: 'keyword',
},
},
],
namespace_type,
description: 'Exception list item - Edit',
type: 'simple',
})
.expect(404);
await deleteListsIndex(supertest, log);
});
});
describe('Add/edit exception comments by different users', () => {
const socManager = ROLES.soc_manager;
const detectionAdmin = ROLES.detections_admin;
beforeEach(async () => {
await createUserAndRole(getService, detectionAdmin);
await createUserAndRole(getService, socManager);
});
afterEach(async () => {
await deleteUserAndRole(getService, detectionAdmin);
await deleteUserAndRole(getService, socManager);
await deleteAllExceptions(supertest, log);
});
it('Add comment on a new exception, add another comment has unicode from a different user', async () => {
await supertestWithoutAuth
.post(EXCEPTION_LIST_URL)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send(getCreateExceptionListDetectionSchemaMock())
.expect(200);
const { os_types, ...ruleException } = getCreateExceptionListItemMinimalSchemaMock();
// Add comment by the Detection Admin
await supertestWithoutAuth
.post(EXCEPTION_LIST_ITEM_URL)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send({
...ruleException,
comments: [{ comment: 'Comment by user@detections_admin' }],
})
.expect(200);
const { body: items } = await supertestWithoutAuth
.get(
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
getCreateExceptionListMinimalSchemaMock().list_id
}`
)
.auth(detectionAdmin, 'changeme')
.set('kbn-xsrf', 'true')
.send()
.expect(200);
// Validate the first user comment
expect(items.total).toEqual(1);
const [item] = items.data;
const detectionAdminComments = item.comments;
expect(detectionAdminComments.length).toEqual(1);
expect(detectionAdminComments[0]).toEqual(
expect.objectContaining({
created_by: 'detections_admin',
comment: 'Comment by user@detections_admin',
})
);
const expectedId = item.id;
// Update exception comment by different user Soc-manager
const { item_id: _, ...updateItemWithoutItemId } =
getUpdateMinimalExceptionListItemSchemaMock();
const updatePayload: UpdateExceptionListItemSchema = {
...updateItemWithoutItemId,
comments: [
...(updateItemWithoutItemId.comments || []),
{ comment: 'Comment by user@soc_manager' },
],
id: expectedId,
};
await supertestWithoutAuth
.put(EXCEPTION_LIST_ITEM_URL)
.auth(socManager, 'changeme')
.set('kbn-xsrf', 'true')
.send(updatePayload)
.expect(200);
const { body: itemsAfterUpdate } = await supertest
.get(
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
getCreateExceptionListMinimalSchemaMock().list_id
}`
)
.auth(socManager, 'changeme')
.set('kbn-xsrf', 'true')
.send()
.expect(200);
const [itemAfterUpdate] = itemsAfterUpdate.data;
const detectionAdminAndSocManagerComments = itemAfterUpdate.comments;
expect(detectionAdminAndSocManagerComments.length).toEqual(2);
expect(detectionAdminAndSocManagerComments).toEqual(
expect.arrayContaining([
expect.objectContaining({
created_by: 'detections_admin',
comment: 'Comment by user@detections_admin',
}),
expect.objectContaining({
created_by: 'soc_manager',
comment: 'Comment by user@soc_manager',
}),
])
);
});
});
});
};

View file

@ -0,0 +1,177 @@
/*
* 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.
*/
/* eslint-disable @typescript-eslint/naming-convention */
import expect from 'expect';
import {
EXCEPTION_LIST_ITEM_URL,
EXCEPTION_LIST_URL,
LIST_URL,
} from '@kbn/securitysolution-list-constants';
import type {
QueryRuleCreateProps,
RuleCreateProps,
} from '@kbn/security-solution-plugin/common/api/detection_engine';
import { getCreateExceptionListDetectionSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
import {
deleteAllAlerts,
getSimpleRule,
createRuleWithExceptionEntries,
deleteAllRules,
createRule,
} from '../../../utils';
import {
createListsIndex,
deleteAllExceptions,
deleteListsIndex,
importFile,
} from '../../../../../../lists_api_integration/utils';
import { FtrProviderContext } from '../../../../../ftr_provider_context';
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const log = getService('log');
const es = getService('es');
describe('@serverless @ess Synchronizations', () => {
afterEach(async () => {
await deleteAllAlerts(supertest, log, es);
await deleteAllRules(supertest, log);
await deleteAllExceptions(supertest, log);
});
/*
This test to mimic if we have two browser tabs, and the user tried to
edit an exception in a tab after deleting it in another
*/
it('should Not edit an exception after being deleted', async () => {
const { list_id: skippedListId, ...newExceptionItem } =
getCreateExceptionListDetectionSchemaMock();
const {
body: { id, list_id, namespace_type, type },
} = await supertest
.post(EXCEPTION_LIST_URL)
.set('kbn-xsrf', 'true')
.send(newExceptionItem)
.expect(200);
const ruleWithException: RuleCreateProps = {
...getSimpleRule(),
exceptions_list: [
{
id,
list_id,
namespace_type,
type,
},
],
};
await createRule(supertest, log, ruleWithException);
// Delete the exception
await supertest
.delete(`${EXCEPTION_LIST_ITEM_URL}?id=${id}&namespace_type=single`)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
// Edit after delete as if it was opened in another browser tab
const { body } = await supertest
.put(`${EXCEPTION_LIST_ITEM_URL}`)
.set('kbn-xsrf', 'true')
.send({
id: list_id,
item_id: id,
name: 'edit',
entries: [{ field: 'ss', operator: 'included', type: 'match', value: 'ss' }],
namespace_type,
description: 'Exception list item - Edit',
type: 'simple',
})
.expect(404);
expect(body).toEqual({
message: `exception list item id: "${list_id}" does not exist`,
status_code: 404,
});
});
/*
This test to mimic if we have two browser tabs, and the user tried to
edit an exception with value-list was deleted in another tab
*/
it('should Not allow editing an Exception with deleted ValueList', async () => {
await createListsIndex(supertest, log);
const valueListId = 'value-list-id';
await importFile(supertest, log, 'keyword', ['suricata-sensor-amsterdam'], valueListId);
const rule: QueryRuleCreateProps = {
...getSimpleRule(),
query: 'host.name: "suricata-sensor-amsterdam"',
};
const { exceptions_list: exceptionsList } = await createRuleWithExceptionEntries(
supertest,
log,
rule,
[
[
{
field: 'host.name',
operator: 'included',
type: 'list',
list: {
id: valueListId,
type: 'keyword',
},
},
],
]
);
const deleteReferences = false;
const ignoreReferences = true;
const { id, list_id, namespace_type } = exceptionsList[0];
// Delete the value list
await supertest
.delete(
`${LIST_URL}?deleteReferences=${deleteReferences}&id=${valueListId}&ignoreReferences=${ignoreReferences}`
)
.set('kbn-xsrf', 'true')
.send()
.expect(200);
// edit the exception with the deleted value list
await supertest
.put(`${EXCEPTION_LIST_ITEM_URL}`)
.set('kbn-xsrf', 'true')
.send({
id: list_id,
item_id: id,
name: 'edit',
entries: [
{
field: 'host.name',
operator: 'included',
type: 'list',
list: {
id: valueListId,
type: 'keyword',
},
},
],
namespace_type,
description: 'Exception list item - Edit',
type: 'simple',
})
.expect(404);
await deleteListsIndex(supertest, log);
});
});
};

View file

@ -9,14 +9,14 @@ import { FtrConfigProviderContext } from '@kbn/test';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const functionalConfig = await readConfigFile(
require.resolve('../../config/ess/config.base.trial.ts')
require.resolve('../../../../../config/ess/config.base.trial')
);
return {
...functionalConfig.getAll(),
testFiles: [require.resolve('.')],
testFiles: [require.resolve('..')],
junit: {
reportName: 'Detection Engine ESS API Integration Tests',
reportName: 'Detection Engine ESS/ Rule creation API Integration Tests',
},
};
}

View file

@ -5,11 +5,11 @@
* 2.0.
*/
import { createTestConfig } from '../../config/serverless/config.base';
import { createTestConfig } from '../../../../../config/serverless/config.base';
export default createTestConfig({
testFiles: [require.resolve('.')],
testFiles: [require.resolve('..')],
junit: {
reportName: 'Detection Engine Serverless API Integration Tests',
reportName: 'Detection Engine Serverless/ Rule creation API Integration Tests',
},
});

View file

@ -17,7 +17,7 @@ import { RuleCreateProps } from '@kbn/security-solution-plugin/common/api/detect
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { ROLES } from '@kbn/security-solution-plugin/common/test';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import {
createAlertsIndex,
deleteAllRules,
@ -43,12 +43,12 @@ import {
getActionsWithoutFrequencies,
getSomeActionsWithFrequencies,
updateUsername,
} from '../utils';
} from '../../utils';
import {
createUserAndRole,
deleteUserAndRole,
} from '../../../../common/services/security_solution';
import { EsArchivePathBuilder } from '../../../es_archive_path_builder';
} from '../../../../../common/services/security_solution';
import { EsArchivePathBuilder } from '../../../../es_archive_path_builder';
export default ({ getService }: FtrProviderContext) => {
const esArchiver = getService('esArchiver');
@ -56,6 +56,7 @@ export default ({ getService }: FtrProviderContext) => {
const supertestWithoutAuth = getService('supertestWithoutAuth');
const log = getService('log');
const es = getService('es');
// TODO: add a new service
const config = getService('config');
const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username');
const isServerless = config.get('serverless');

View file

@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrProviderContext } from '../../../ftr_provider_context';
import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Rule creation API', function () {

View file

@ -1,13 +0,0 @@
/*
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Exceptions API', function () {
loadTestFile(require.resolve('./rule_exception/create_rule_exceptions'));
});
}

View file

@ -1,15 +0,0 @@
/*
* 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 { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Detections response API', function () {
loadTestFile(require.resolve('./exceptions'));
loadTestFile(require.resolve('./rule_creation'));
});
}

View file

@ -4,11 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { FtrProviderContext } from '../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Security solution API', function () {
loadTestFile(require.resolve('./detections_response'));
});
}
export * from './get_slack_action';
export * from './get_web_hook_action';
export * from './remove_uuid_from_actions';

View file

@ -0,0 +1,53 @@
/*
* 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 type { ToolingLog } from '@kbn/tooling-log';
import type SuperTest from 'supertest';
import { SearchResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { DetectionAlert } from '@kbn/security-solution-plugin/common/api/detection_engine';
import { DETECTION_ENGINE_QUERY_SIGNALS_URL as DETECTION_ENGINE_QUERY_ALERTS_URL } from '@kbn/security-solution-plugin/common/constants';
import { countDownTest } from '../count_down_test';
import { getQueryAlertsId } from './get_query_alerts_ids';
/**
* Given a single rule id this will return only alerts based on that rule id.
* @param supertest agent
* @param ids Rule id
*/
export const getAlertsById = async (
supertest: SuperTest.SuperTest<SuperTest.Test>,
log: ToolingLog,
id: string
): Promise<SearchResponse<DetectionAlert>> => {
const alertsOpen = await countDownTest<SearchResponse<DetectionAlert>>(
async () => {
const response = await supertest
.post(DETECTION_ENGINE_QUERY_ALERTS_URL)
.set('kbn-xsrf', 'true')
.send(getQueryAlertsId([id]));
if (response.status !== 200) {
return {
passed: false,
returnValue: undefined,
};
} else {
return {
passed: true,
returnValue: response.body,
};
}
},
'getAlertsById',
log
);
if (alertsOpen == null) {
throw new Error('Alerts not defined after countdown, cannot continue');
} else {
return alertsOpen;
}
};

View file

@ -0,0 +1,36 @@
/*
* 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 type SuperTest from 'supertest';
import type { Client } from '@elastic/elasticsearch';
import type { ToolingLog } from '@kbn/tooling-log';
import {
RuleExecutionStatus,
RuleExecutionStatusEnum,
} from '@kbn/security-solution-plugin/common/api/detection_engine/rule_monitoring';
import type { RuleResponse } from '@kbn/security-solution-plugin/common/api/detection_engine';
import { waitForRuleStatus } from '../rules';
import { refreshIndex } from '..';
import { getAlertsByIds } from './get_alerts_by_ids';
export const getOpenAlerts = async (
supertest: SuperTest.SuperTest<SuperTest.Test>,
log: ToolingLog,
es: Client,
rule: RuleResponse,
status: RuleExecutionStatus = RuleExecutionStatusEnum.succeeded,
size?: number,
afterDate?: Date
) => {
await waitForRuleStatus(status, { supertest, log, id: rule.id, afterDate });
// Critically important that we wait for rule success AND refresh the write index in that order before we
// assert that no Alerts were created. Otherwise, Alerts could be written but not available to query yet
// when we search, causing tests that check that Alerts are NOT created to pass when they should fail.
await refreshIndex(es, '.alerts-security.alerts-default*');
return getAlertsByIds(supertest, log, [rule.id], size);
};

View file

@ -0,0 +1,17 @@
/*
* 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.
*/
// TODO rename signal to alert
export * from './create_alerts_index';
export * from './delete_all_alerts';
export * from './wait_for_alert_to_complete';
export * from './wait_for_alerts_to_be_present';
export * from './wait_for_alert_to_complete';
export * from './get_open_alerts';
export * from './get_alerts_by_ids';
export * from './get_query_alerts_ids';
export * from './get_alerts_by_id';

View file

@ -0,0 +1,46 @@
/*
* 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 type { TransportResult } from '@elastic/elasticsearch';
import type { ToolingLog } from '@kbn/tooling-log';
import { countDownTest } from './count_down_test';
/**
* Does a plain countdown and checks against es queries for either conflicts in the error
* or for any over the wire issues such as timeouts or temp 404's to make the tests more
* reliant.
* @param esFunction The function to test against
* @param esFunctionName The name of the function to print if we encounter errors
* @param log The tooling logger
* @param retryCount The number of times to retry before giving up (has default)
* @param timeoutWait Time to wait before trying again (has default)
*/
export const countDownES = async (
esFunction: () => Promise<TransportResult<Record<string, any>, unknown>>,
esFunctionName: string,
log: ToolingLog,
retryCount: number = 50,
timeoutWait = 250
): Promise<void> => {
await countDownTest(
async () => {
const result = await esFunction();
if (result.body.version_conflicts !== 0) {
return {
passed: false,
errorMessage: 'Version conflicts for ${result.body.version_conflicts}',
};
} else {
return { passed: true };
}
},
esFunctionName,
log,
retryCount,
timeoutWait
);
};

View file

@ -0,0 +1,12 @@
/*
* 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.
*/
export * from './list/create_exception_list';
export * from './list/delete_exception_list';
export * from './list/create_container_with_entries';
export * from './list/create_container_with_endpoint_entries';
export * from './item/create_exception_list_item';

View file

@ -0,0 +1,42 @@
/*
* 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 type { ToolingLog } from '@kbn/tooling-log';
import type SuperTest from 'supertest';
import type {
CreateExceptionListItemSchema,
ExceptionListItemSchema,
} from '@kbn/securitysolution-io-ts-list-types';
import { EXCEPTION_LIST_ITEM_URL } from '@kbn/securitysolution-list-constants';
/**
* Helper to cut down on the noise in some of the tests. This checks for
* an expected 200 still and does not try to any retries. Creates exception lists
* @param supertest The supertest deps
* @param exceptionListItem The exception list item to create
* @param log The tooling logger
*/
export const createExceptionListItem = async (
supertest: SuperTest.SuperTest<SuperTest.Test>,
log: ToolingLog,
exceptionListItem: CreateExceptionListItemSchema
): Promise<ExceptionListItemSchema> => {
const response = await supertest
.post(EXCEPTION_LIST_ITEM_URL)
.set('kbn-xsrf', 'true')
.send(exceptionListItem);
if (response.status !== 200) {
log.error(
`Did not get an expected 200 "ok" when creating an exception list item (createExceptionListItem). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify(
response.body
)}, status: ${JSON.stringify(response.status)}`
);
}
return response.body;
};

View file

@ -0,0 +1,85 @@
/*
* 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 type { ToolingLog } from '@kbn/tooling-log';
import type SuperTest from 'supertest';
import type {
CreateExceptionListItemSchema,
ListArray,
NonEmptyEntriesArray,
OsTypeArray,
} from '@kbn/securitysolution-io-ts-list-types';
import { EXCEPTION_LIST_ITEM_URL } from '@kbn/securitysolution-list-constants';
import { createExceptionListItem } from '../item/create_exception_list_item';
import { waitFor } from '../../wait_for';
import { createExceptionList } from './create_exception_list';
/**
* Convenience testing function where you can pass in just the endpoint entries and you will
* get a container created with the entries.
* @param supertest super test agent
* @param endpointEntries The endpoint entries to create the rule and exception list from
* @param osTypes The os types to optionally add or not to add to the container
*/
export const createContainerWithEndpointEntries = async (
supertest: SuperTest.SuperTest<SuperTest.Test>,
log: ToolingLog,
endpointEntries: Array<{
entries: NonEmptyEntriesArray;
osTypes: OsTypeArray | undefined;
}>
): Promise<ListArray> => {
// If not given any endpoint entries, return without any
if (endpointEntries.length === 0) {
return [];
}
// create the endpoint exception list container
// eslint-disable-next-line @typescript-eslint/naming-convention
const { id, list_id, namespace_type, type } = await createExceptionList(supertest, log, {
description: 'endpoint description',
list_id: 'endpoint_list',
name: 'endpoint_list',
type: 'endpoint',
});
// Add the endpoint exception list container to the backend
await Promise.all(
endpointEntries.map((endpointEntry) => {
const exceptionListItem: CreateExceptionListItemSchema = {
description: 'endpoint description',
entries: endpointEntry.entries,
list_id: 'endpoint_list',
name: 'endpoint_list',
os_types: endpointEntry.osTypes,
type: 'simple',
};
return createExceptionListItem(supertest, log, exceptionListItem);
})
);
// To reduce the odds of in-determinism and/or bugs we ensure we have
// the same length of entries before continuing.
await waitFor(
async () => {
const { body } = await supertest.get(`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${list_id}`);
return body.data.length === endpointEntries.length;
},
`within createContainerWithEndpointEntries ${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${list_id}`,
log
);
return [
{
id,
list_id,
namespace_type,
type,
},
];
};

View file

@ -0,0 +1,76 @@
/*
* 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 type { ToolingLog } from '@kbn/tooling-log';
import type SuperTest from 'supertest';
import type { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
import type { ListArray, NonEmptyEntriesArray } from '@kbn/securitysolution-io-ts-list-types';
import { EXCEPTION_LIST_ITEM_URL } from '@kbn/securitysolution-list-constants';
import { createExceptionList } from './create_exception_list';
import { createExceptionListItem } from '../item/create_exception_list_item';
import { waitFor } from '../../wait_for';
/**
* Convenience testing function where you can pass in just the endpoint entries and you will
* get a container created with the entries.
* @param supertest super test agent
* @param entries The entries to create the rule and exception list from
* @param osTypes The os types to optionally add or not to add to the container
*/
export const createContainerWithEntries = async (
supertest: SuperTest.SuperTest<SuperTest.Test>,
log: ToolingLog,
entries: NonEmptyEntriesArray[]
): Promise<ListArray> => {
// If not given any endpoint entries, return without any
if (entries.length === 0) {
return [];
}
// Create the rule exception list container
// eslint-disable-next-line @typescript-eslint/naming-convention
const { id, list_id, namespace_type, type } = await createExceptionList(supertest, log, {
description: 'some description',
list_id: 'some-list-id',
name: 'some name',
type: 'detection',
});
// Add the rule exception list container to the backend
await Promise.all(
entries.map((entry) => {
const exceptionListItem: CreateExceptionListItemSchema = {
description: 'some description',
list_id: 'some-list-id',
name: 'some name',
type: 'simple',
entries: entry,
};
return createExceptionListItem(supertest, log, exceptionListItem);
})
);
// To reduce the odds of in-determinism and/or bugs we ensure we have
// the same length of entries before continuing.
await waitFor(
async () => {
const { body } = await supertest.get(`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${list_id}`);
return body.data.length === entries.length;
},
`within createContainerWithEntries ${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${list_id}`,
log
);
return [
{
id,
list_id,
namespace_type,
type,
},
];
};

View file

@ -4,38 +4,12 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export * from './rule/get_rule';
export * from './rule/get_simple_rule';
export * from './rule/create_rule';
export * from './rule/delete_all_rules';
export * from './rule/delete_rule';
export * from './rule/get_simple_rule_output';
export * from './rule/get_simple_rule_output_without_rule_id';
export * from './rule/get_simple_rule_without_rule_id';
export * from './rule/get_simple_rule_without_rule_id';
export * from './rule/remove_server_generated_properties';
export * from './rule/remove_server_generated_properties_including_rule_id';
export * from './rule/get_simple_ml_rule';
export * from './rule/get_simple_ml_rule_output';
export * from './rule/wait_for_rule_status';
export * from './rule/get_rule_for_alert_testing_with_timestamp_override';
export * from './rule/get_rule_for_alert_testing';
export * from './rule/get_threshold_rule_for_alert_testing';
export * from './rule/get_rule_actions';
export * from './exception_list_and_item/exception_list/create_exception_list';
export * from './exception_list_and_item/exception_list/delete_exception_list';
// TODO rename signal to alert
export * from './alert/create_alerts_index';
export * from './alert/delete_all_alerts';
export * from './alert/wait_for_alert_to_complete';
export * from './alert/wait_for_alerts_to_be_present';
export * from './alert/wait_for_alert_to_complete';
export * from './action/get_slack_action';
export * from './action/get_web_hook_action';
export * from './action/remove_uuid_from_actions';
export * from './rules';
export * from './exception_list_and_item';
export * from './alerts';
export * from './actions';
export * from './count_down_test';
export * from './count_down_es';
export * from './update_username';
export * from './refresh_index';

View file

@ -0,0 +1,19 @@
/*
* 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 type { Client } from '@elastic/elasticsearch';
/**
* Refresh an index, making changes available to search.
* Useful for tests where we want to ensure that a rule does NOT create alerts, e.g. testing exceptions.
* @param es The ElasticSearch handle
*/
export const refreshIndex = async (es: Client, index?: string) => {
await es.indices.refresh({
index,
});
};

View file

@ -0,0 +1,74 @@
/*
* 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 type { ToolingLog } from '@kbn/tooling-log';
import type SuperTest from 'supertest';
import type { NonEmptyEntriesArray, OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
import type {
RuleCreateProps,
RuleResponse,
} from '@kbn/security-solution-plugin/common/api/detection_engine';
import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants';
import {
createContainerWithEntries,
createContainerWithEndpointEntries,
} from '../exception_list_and_item';
import { createRule } from './create_rule';
/**
* Convenience testing function where you can pass in just the entries and you will
* get a rule created with the entries added to an exception list and exception list item
* all auto-created at once.
* @param supertest super test agent
* @param rule The rule to create and attach an exception list to
* @param entries The entries to create the rule and exception list from
* @param endpointEntries The endpoint entries to create the rule and exception list from
* @param osTypes The os types to optionally add or not to add to the container
*/
export const createRuleWithExceptionEntries = async (
supertest: SuperTest.SuperTest<SuperTest.Test>,
log: ToolingLog,
rule: RuleCreateProps,
entries: NonEmptyEntriesArray[],
endpointEntries?: Array<{
entries: NonEmptyEntriesArray;
osTypes: OsTypeArray | undefined;
}>
): Promise<RuleResponse> => {
const maybeExceptionList = await createContainerWithEntries(supertest, log, entries);
const maybeEndpointList = await createContainerWithEndpointEntries(
supertest,
log,
endpointEntries ?? []
);
// create the rule but don't run it immediately as running it immediately can cause
// the rule to sometimes not filter correctly the first time with an exception list
// or other timing issues. Then afterwards wait for the rule to have succeeded before
// returning.
const ruleWithException: RuleCreateProps = {
...rule,
enabled: false,
exceptions_list: [...maybeExceptionList, ...maybeEndpointList],
};
const ruleResponse = await createRule(supertest, log, ruleWithException);
const response = await supertest
.patch(DETECTION_ENGINE_RULES_URL)
.set('kbn-xsrf', 'true')
.set('elastic-api-version', '2023-10-31')
.send({ rule_id: ruleResponse.rule_id, enabled: true });
if (response.status !== 200) {
log.error(
`Did not get an expected 200 "ok" when patching a rule with exception entries (createRuleWithExceptionEntries). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify(
response.body
)}, status: ${JSON.stringify(response.status)}`
);
}
return ruleResponse;
};

View file

@ -0,0 +1,43 @@
/*
* 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 type { ToolingLog } from '@kbn/tooling-log';
import type { Client } from '@elastic/elasticsearch';
import { ALERTING_CASES_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server';
import { countDownES } from '../count_down_es';
export const downgradeImmutableRule = async (
es: Client,
log: ToolingLog,
ruleId: string
): Promise<void> => {
return countDownES(
async () => {
return es.updateByQuery(
{
index: ALERTING_CASES_SAVED_OBJECT_INDEX,
refresh: true,
wait_for_completion: true,
body: {
script: {
lang: 'painless',
source: 'ctx._source.alert.params.version--',
},
query: {
term: {
'alert.params.ruleId': ruleId,
},
},
},
},
{ meta: true }
);
},
'downgradeImmutableRule',
log
);
};

View file

@ -0,0 +1,44 @@
/*
* 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 type { ToolingLog } from '@kbn/tooling-log';
import type SuperTest from 'supertest';
import type { RuleResponse } from '@kbn/security-solution-plugin/common/api/detection_engine';
import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants';
/**
* Helper to cut down on the noise in some of the tests. This
* uses the find API to get an immutable rule by id.
* @param supertest The supertest deps
*/
export const findImmutableRuleById = async (
supertest: SuperTest.SuperTest<SuperTest.Test>,
log: ToolingLog,
ruleId: string
): Promise<{
page: number;
perPage: number;
total: number;
data: RuleResponse[];
}> => {
const response = await supertest
.get(
`${DETECTION_ENGINE_RULES_URL}/_find?filter=alert.attributes.params.immutable: true AND alert.attributes.params.ruleId: "${ruleId}"`
)
.set('kbn-xsrf', 'true')
.set('elastic-api-version', '2023-10-31')
.send();
if (response.status !== 200) {
log.error(
`Did not get an expected 200 "ok" when finding an immutable rule by id (findImmutableRuleById). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify(
response.body
)}, status: ${JSON.stringify(response.status)}`
);
}
return response.body;
};

View file

@ -0,0 +1,27 @@
/*
* 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 type { EqlRuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine';
import { getRuleForAlertTesting } from './get_rule_for_alert_testing';
/**
* This is a typical alert testing rule that is easy for most basic testing of output of EQL alerts.
* It starts out in an enabled true state. The 'from' is set very far back to test the basics of alert
* creation for EQL and testing by getting all the alerts at once.
* @param ruleId The optional ruleId which is eql-rule by default.
* @param enabled Enables the rule on creation or not. Defaulted to true.
*/
export const getEqlRuleForAlertTesting = (
index: string[],
ruleId = 'eql-rule',
enabled = true
): EqlRuleCreateProps => ({
...getRuleForAlertTesting(index, ruleId, enabled),
type: 'eql',
language: 'eql',
query: 'any where true',
});

View file

@ -0,0 +1,30 @@
/*
* 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.
*/
export * from './get_rule';
export * from './get_simple_rule';
export * from './create_rule';
export * from './delete_all_rules';
export * from './delete_rule';
export * from './get_simple_rule_output';
export * from './get_simple_rule_output_without_rule_id';
export * from './get_simple_rule_without_rule_id';
export * from './get_simple_rule_without_rule_id';
export * from './remove_server_generated_properties';
export * from './remove_server_generated_properties_including_rule_id';
export * from './get_simple_ml_rule';
export * from './get_simple_ml_rule_output';
export * from './wait_for_rule_status';
export * from './get_rule_for_alert_testing_with_timestamp_override';
export * from './get_rule_for_alert_testing';
export * from './get_threshold_rule_for_alert_testing';
export * from './get_rule_actions';
export * from './find_immutable_rule_by_id';
export * from './create_rule_with_exception_entries';
export * from './downgrade_immutable_rule';
export * from './get_eql_rule_for_alert_testing';
export * from './prebuilt_rules';

View file

@ -0,0 +1,113 @@
/*
* 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 { Client } from '@elastic/elasticsearch';
import { PrebuiltRuleAsset } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules';
import {
getPrebuiltRuleMock,
getPrebuiltRuleWithExceptionsMock,
} from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks';
import { ELASTIC_SECURITY_RULE_ID } from '@kbn/security-solution-plugin/common';
import { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server';
/**
* A helper function to create a rule asset saved object
*
* @param overrideParams Params to override the default mock
* @returns Created rule asset saved object
*/
export const createRuleAssetSavedObject = (overrideParams: Partial<PrebuiltRuleAsset>) => ({
'security-rule': {
...getPrebuiltRuleMock(),
...overrideParams,
},
type: 'security-rule',
references: [],
coreMigrationVersion: '8.6.0',
updated_at: '2022-11-01T12:56:39.717Z',
created_at: '2022-11-01T12:56:39.717Z',
});
export const SAMPLE_PREBUILT_RULES = [
createRuleAssetSavedObject({
...getPrebuiltRuleWithExceptionsMock(),
rule_id: ELASTIC_SECURITY_RULE_ID,
tags: ['test-tag-1'],
enabled: true,
}),
createRuleAssetSavedObject({
rule_id: '000047bb-b27a-47ec-8b62-ef1a5d2c9e19',
tags: ['test-tag-2'],
}),
createRuleAssetSavedObject({
rule_id: '00140285-b827-4aee-aa09-8113f58a08f3',
tags: ['test-tag-3'],
}),
];
export const SAMPLE_PREBUILT_RULES_WITH_HISTORICAL_VERSIONS = [
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 }),
createRuleAssetSavedObject({ rule_id: 'rule-1', version: 2 }),
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 1 }),
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 2 }),
createRuleAssetSavedObject({ rule_id: 'rule-2', version: 3 }),
];
/**
* Creates saved objects with prebuilt rule assets which can be used for
* installing actual prebuilt rules after that. It creates saved objects with
* only latest versions of the rules. Tha matches the behavior of a rules
* package without historical versions.
*
* NOTE: Version is not added to the rule asset saved object id.
*
* @param es Elasticsearch client
*/
export const createPrebuiltRuleAssetSavedObjects = async (
es: Client,
rules = SAMPLE_PREBUILT_RULES
): Promise<void> => {
await es.bulk({
refresh: true,
body: rules.flatMap((doc) => [
{
index: {
_index: SECURITY_SOLUTION_SAVED_OBJECT_INDEX,
_id: `security-rule:${doc['security-rule'].rule_id}`,
},
},
doc,
]),
});
};
/**
* Creates saved objects with prebuilt rule assets which can be used for
* installing actual prebuilt rules after that. It creates saved objects with
* historical versions of the rules.
*
* NOTE: Version is added to the rule asset saved object id.
*
* @param es Elasticsearch client
*/
export const createHistoricalPrebuiltRuleAssetSavedObjects = async (
es: Client,
rules = SAMPLE_PREBUILT_RULES_WITH_HISTORICAL_VERSIONS
): Promise<void> => {
await es.bulk({
refresh: true,
body: rules.flatMap((doc) => [
{
index: {
_index: SECURITY_SOLUTION_SAVED_OBJECT_INDEX,
_id: `security-rule:${doc['security-rule'].rule_id}_${doc['security-rule'].version}`,
},
},
doc,
]),
});
};

View file

@ -0,0 +1,31 @@
/*
* 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 {
GetPrebuiltRulesAndTimelinesStatusResponse,
PREBUILT_RULES_STATUS_URL,
} from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules';
import type SuperTest from 'supertest';
/**
* (LEGACY)
* Helper to retrieve the prebuilt rules status
*
* @param supertest The supertest deps
*/
export const getPrebuiltRulesAndTimelinesStatus = async (
supertest: SuperTest.SuperTest<SuperTest.Test>
): Promise<GetPrebuiltRulesAndTimelinesStatusResponse> => {
const response = await supertest
.get(PREBUILT_RULES_STATUS_URL)
.set('kbn-xsrf', 'true')
.set('elastic-api-version', '2023-10-31')
.send()
.expect(200);
return response.body;
};

View file

@ -0,0 +1,10 @@
/*
* 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.
*/
export * from './create_prebuilt_rule_saved_objects';
export * from './get_prebuilt_rules_and_timelines_status';
export * from './install_mock_prebuilt_rules';
export * from './install_prebuilt_rules_and_timelines';

View file

@ -0,0 +1,28 @@
/*
* 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 { Client } from '@elastic/elasticsearch';
import { InstallPrebuiltRulesAndTimelinesResponse } from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules';
import type SuperTest from 'supertest';
import { createPrebuiltRuleAssetSavedObjects } from './create_prebuilt_rule_saved_objects';
import { installPrebuiltRulesAndTimelines } from './install_prebuilt_rules_and_timelines';
/**
* Creates prebuilt rule mocks and installs them
*
* @param supertest Supertest instance
* @param es Elasticsearch client
* @returns Install prebuilt rules response
*/
export const installMockPrebuiltRules = async (
supertest: SuperTest.SuperTest<SuperTest.Test>,
es: Client
): Promise<InstallPrebuiltRulesAndTimelinesResponse> => {
// Ensure there are prebuilt rule saved objects before installing rules
await createPrebuiltRuleAssetSavedObjects(es);
return installPrebuiltRulesAndTimelines(es, supertest);
};

View file

@ -0,0 +1,56 @@
/*
* 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 {
InstallPrebuiltRulesAndTimelinesResponse,
PREBUILT_RULES_URL,
} from '@kbn/security-solution-plugin/common/api/detection_engine/prebuilt_rules';
import type { Client } from '@elastic/elasticsearch';
import type SuperTest from 'supertest';
import { ALL_SAVED_OBJECT_INDICES } from '@kbn/core-saved-objects-server';
/**
* (LEGACY)
* Installs all prebuilt rules and timelines available in Kibana. Rules are
* installed from the security-rule saved objects.
* This is a legacy endpoint and has been replaced by:
* POST /internal/detection_engine/prebuilt_rules/installation/_perform
*
* - No rules will be installed if there are no security-rule assets (e.g., the
* package is not installed or mocks are not created).
*
* - If some prebuilt rules are already installed, they will be upgraded in case
* there are newer versions of them in security-rule assets.
*
* @param supertest SuperTest instance
* @returns Install prebuilt rules response
*/
export const installPrebuiltRulesAndTimelines = async (
es: Client,
supertest: SuperTest.SuperTest<SuperTest.Test>
): Promise<InstallPrebuiltRulesAndTimelinesResponse> => {
const response = await supertest
.put(PREBUILT_RULES_URL)
.set('kbn-xsrf', 'true')
.set('elastic-api-version', '2023-10-31')
.send()
.expect(200);
// Before we proceed, we need to refresh saved object indices.
// At the previous step we installed the prebuilt detection rules SO of type 'security-rule'.
// The savedObjectsClient does this with a call with explicit `refresh: false`.
// So, despite of the fact that the endpoint waits until the prebuilt rule will be
// successfully indexed, it doesn't wait until they become "visible" for subsequent read
// operations.
// And this is usually what we do next in integration tests: we read these SOs with utility
// function such as getPrebuiltRulesAndTimelinesStatus().
// This can cause race condition between a write and subsequent read operation, and to
// fix it deterministically we have to refresh saved object indices and wait until it's done.
await es.indices.refresh({ index: ALL_SAVED_OBJECT_INDICES });
return response.body;
};

View file

@ -26,6 +26,7 @@
"@kbn/securitysolution-io-ts-alerting-types",
"@kbn/tooling-log",
"@kbn/rule-data-utils",
"@kbn/securitysolution-list-constants"
"@kbn/securitysolution-list-constants",
"@kbn/core-saved-objects-server"
]
}