From 827442b4b064eabaabd9da2a511a97f8b4e765ef Mon Sep 17 00:00:00 2001 From: Frank Hassanabad Date: Fri, 4 Jun 2021 20:34:52 -0600 Subject: [PATCH] [Security Solution][Detection Engine] Test cases for alias failure test cases where we don't copy aliases correctly (#101437) ## Summary Test cases for signals and aliases, including a failure of where we do not copy alias data at the moment even if the target is an ECS compatible field. For example with this mapping: ```json { "dynamic": "strict", "properties": { "@timestamp": { "type": "date" }, "host": { "properties": { "name": { "type": "alias", "path": "host_alias.name" } } }, "host_alias": { "properties": { "name": { "type": "keyword" } } } } } ``` If we detect this as a signal hit we should be copying over both: * `host_alias.name` -> `host.name` * `host_alias.name` -> `host_alias.name` to the target signal index, but we only copy: * `host_alias.name` -> `host_alias.name` ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../security_and_spaces/tests/aliases.ts | 65 +++++++++++++++++++ .../security_and_spaces/tests/index.ts | 1 + .../security_solution/alias/data.json | 59 +++++++++++++++++ .../security_solution/alias/mappings.json | 36 ++++++++++ 4 files changed, 161 insertions(+) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/tests/aliases.ts create mode 100644 x-pack/test/functional/es_archives/security_solution/alias/data.json create mode 100644 x-pack/test/functional/es_archives/security_solution/alias/mappings.json diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/aliases.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/aliases.ts new file mode 100644 index 00000000000000..d21253199d733e --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/aliases.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { + createRule, + createSignalsIndex, + deleteAllAlerts, + deleteSignalsIndex, + getRuleForSignalTesting, + getSignalsById, + waitForRuleSuccessOrStatus, + waitForSignalsToBePresent, +} from '../../utils'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + interface HostAlias { + name: string; + } + + describe('Tests involving aliases of source indexes and the signals index', () => { + beforeEach(async () => { + await createSignalsIndex(supertest); + await esArchiver.load('security_solution/alias'); + }); + + afterEach(async () => { + await deleteSignalsIndex(supertest); + await deleteAllAlerts(supertest); + await esArchiver.unload('security_solution/alias'); + }); + + it('Should keep the original alias value such as "host_alias" from a source index when the value is indexed', async () => { + const rule = getRuleForSignalTesting(['alias']); + const { id } = await createRule(supertest, rule); + await waitForRuleSuccessOrStatus(supertest, id); + await waitForSignalsToBePresent(supertest, 4, [id]); + const signalsOpen = await getSignalsById(supertest, id); + const hits = signalsOpen.hits.hits.map( + (signal) => (signal._source.host_alias as HostAlias).name + ); + expect(hits).to.eql(['host name 1', 'host name 2', 'host name 3', 'host name 4']); + }); + + // TODO: Make aliases work to where we can have ECS fields such as host.name filled out + it.skip('Should copy alias data from a source index into the signals index in the same position when the target is ECS compatible', async () => { + const rule = getRuleForSignalTesting(['alias']); + const { id } = await createRule(supertest, rule); + await waitForRuleSuccessOrStatus(supertest, id); + await waitForSignalsToBePresent(supertest, 4, [id]); + const signalsOpen = await getSignalsById(supertest, id); + const hits = signalsOpen.hits.hits.map((signal) => (signal._source.host as HostAlias).name); + expect(hits).to.eql(['host name 1', 'host name 2', 'host name 3', 'host name 4']); + }); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts index 00b289a89e4c88..01fa2765ba0f07 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts @@ -13,6 +13,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => { describe('', function () { this.tags('ciGroup11'); + loadTestFile(require.resolve('./aliases')); loadTestFile(require.resolve('./add_actions')); loadTestFile(require.resolve('./update_actions')); loadTestFile(require.resolve('./add_prepackaged_rules')); diff --git a/x-pack/test/functional/es_archives/security_solution/alias/data.json b/x-pack/test/functional/es_archives/security_solution/alias/data.json new file mode 100644 index 00000000000000..a8bd64cb044eb7 --- /dev/null +++ b/x-pack/test/functional/es_archives/security_solution/alias/data.json @@ -0,0 +1,59 @@ +{ + "type": "doc", + "value": { + "id": "1", + "index": "alias", + "source": { + "@timestamp": "2020-10-28T05:00:53.000Z", + "host_alias": { + "name": "host name 1" + } + }, + "type": "_doc" + } +} + +{ + "type": "doc", + "value": { + "id": "2", + "index": "alias", + "source": { + "@timestamp": "2020-10-28T05:01:53.000Z", + "host_alias": { + "name": "host name 2" + } + }, + "type": "_doc" + } +} + +{ + "type": "doc", + "value": { + "id": "3", + "index": "alias", + "source": { + "@timestamp": "2020-10-28T05:02:53.000Z", + "host_alias": { + "name": "host name 3" + } + }, + "type": "_doc" + } +} + +{ + "type": "doc", + "value": { + "id": "4", + "index": "alias", + "source": { + "@timestamp": "2020-10-28T05:03:53.000Z", + "host_alias": { + "name": "host name 4" + } + }, + "type": "_doc" + } +} diff --git a/x-pack/test/functional/es_archives/security_solution/alias/mappings.json b/x-pack/test/functional/es_archives/security_solution/alias/mappings.json new file mode 100644 index 00000000000000..280ec9377df646 --- /dev/null +++ b/x-pack/test/functional/es_archives/security_solution/alias/mappings.json @@ -0,0 +1,36 @@ +{ + "type": "index", + "value": { + "index": "host_alias", + "mappings": { + "dynamic": "strict", + "properties": { + "@timestamp": { + "type": "date" + }, + "host": { + "properties": { + "name": { + "type": "alias", + "path": "host_alias.name" + } + } + }, + "host_alias": { + "properties": { + "name": { + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "refresh_interval": "1s", + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +}