[Security Solutions][Detection Engine] Adds e2e tests for constant_keyword data type (#101234)
## Summary Adds e2e tests for the `constant_keyword` regular `keyword` to compare between the two. Bugs found with these is one where we do not copy `constant_keyword` fields into signals which I added `.skip` to the tests now. Tested these rule types: * KQL * EQL * Threshold For the mappings of the `constant_keyword` I use both the `constant_keyword` and the field `alias` like so: ```json { "properties": { "@timestamp": { "type": "date" }, "data_stream": { "properties": { "dataset": { "type": "constant_keyword", "value": "dataset_name_1" }, "module": { "type": "constant_keyword", "value": "module_name_1" } } }, "event": { "properties": { "category": { "type": "keyword" }, "dataset": { "type": "alias", "path": "data_stream.dataset" }, "module": { "type": "alias", "path": "data_stream.module" } } } } } ``` To ensure we can detect against fields. I also mix them with regular const keyword fields in another index to ensure they work also in mixed use cases. ### 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
This commit is contained in:
parent
8a793f50eb
commit
598e63b532
|
@ -49,5 +49,11 @@ export default ({ loadTestFile }: FtrProviderContext): void => {
|
|||
describe('', function () {
|
||||
loadTestFile(require.resolve('./exception_operators_data_types/index'));
|
||||
});
|
||||
|
||||
// That split here enable us on using a different ciGroup to run the tests
|
||||
// listed on ./keyword_family/index
|
||||
describe('', function () {
|
||||
loadTestFile(require.resolve('./keyword_family/index'));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
These are tests for the [keyword](https://www.elastic.co/guide/en/elasticsearch/reference/7.12/keyword.html) family where we test
|
||||
* keyword
|
||||
* const keyword
|
||||
* alias fields against each one
|
||||
|
||||
Against mock rules which contain the ECS values of:
|
||||
* event.module
|
||||
* even.dataset
|
||||
|
||||
This is to ensure that if you have field aliases we will still correctly have detections occur. This also ensures that if you have
|
||||
`keyword` mixed with `const keyword` across multiple indexes we will still have detections occur.
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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 {
|
||||
EqlCreateSchema,
|
||||
ThresholdCreateSchema,
|
||||
} from '../../../../../plugins/security_solution/common/detection_engine/schemas/request';
|
||||
|
||||
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 EventModule {
|
||||
module: string;
|
||||
dataset: string;
|
||||
}
|
||||
|
||||
describe('Rule detects against a keyword of event.dataset', () => {
|
||||
beforeEach(async () => {
|
||||
await createSignalsIndex(supertest);
|
||||
await esArchiver.load('rule_keyword_family/const_keyword');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteSignalsIndex(supertest);
|
||||
await deleteAllAlerts(supertest);
|
||||
await esArchiver.unload('rule_keyword_family/const_keyword');
|
||||
});
|
||||
|
||||
describe('"kql" rule type', () => {
|
||||
it('should detect the "dataset_name_1" from "event.dataset" and have 4 signals', async () => {
|
||||
const rule = {
|
||||
...getRuleForSignalTesting(['const_keyword']),
|
||||
query: 'event.dataset: "dataset_name_1"',
|
||||
};
|
||||
const { id } = await createRule(supertest, rule);
|
||||
await waitForRuleSuccessOrStatus(supertest, id);
|
||||
await waitForSignalsToBePresent(supertest, 4, [id]);
|
||||
const signalsOpen = await getSignalsById(supertest, id);
|
||||
expect(signalsOpen.hits.hits.length).to.eql(4);
|
||||
});
|
||||
|
||||
// TODO: Fix this bug and make this work. We currently do not write out the dataset name when it is not in _source
|
||||
it.skip('should copy the dataset_name_1 from the index into the signal', async () => {
|
||||
const rule = {
|
||||
...getRuleForSignalTesting(['const_keyword']),
|
||||
query: 'event.dataset: "dataset_name_1"',
|
||||
};
|
||||
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((hit) => (hit._source.event as EventModule).dataset)
|
||||
.sort();
|
||||
expect(hits).to.eql([
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"eql" rule type', () => {
|
||||
it('should detect the "dataset_name_1" from "event.dataset" and have 4 signals', async () => {
|
||||
const rule: EqlCreateSchema = {
|
||||
...getRuleForSignalTesting(['const_keyword']),
|
||||
rule_id: 'eql-rule',
|
||||
type: 'eql',
|
||||
language: 'eql',
|
||||
query: 'any where event.dataset=="dataset_name_1"',
|
||||
};
|
||||
|
||||
const { id } = await createRule(supertest, rule);
|
||||
await waitForRuleSuccessOrStatus(supertest, id);
|
||||
await waitForSignalsToBePresent(supertest, 4, [id]);
|
||||
const signalsOpen = await getSignalsById(supertest, id);
|
||||
expect(signalsOpen.hits.hits.length).to.eql(4);
|
||||
});
|
||||
|
||||
// TODO: Fix this bug and make this work. We currently do not write out the dataset name when it is not in _source
|
||||
it.skip('should copy the "dataset_name_1" from "event.dataset"', async () => {
|
||||
const rule: EqlCreateSchema = {
|
||||
...getRuleForSignalTesting(['const_keyword']),
|
||||
rule_id: 'eql-rule',
|
||||
type: 'eql',
|
||||
language: 'eql',
|
||||
query: 'any where event.dataset=="dataset_name_1"',
|
||||
};
|
||||
|
||||
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((hit) => (hit._source.event as EventModule).dataset)
|
||||
.sort();
|
||||
expect(hits).to.eql([
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"threshold" rule type', async () => {
|
||||
it('should detect the "dataset_name_1" from "event.dataset"', async () => {
|
||||
const rule: ThresholdCreateSchema = {
|
||||
...getRuleForSignalTesting(['const_keyword']),
|
||||
rule_id: 'threshold-rule',
|
||||
type: 'threshold',
|
||||
language: 'kuery',
|
||||
query: '*:*',
|
||||
threshold: {
|
||||
field: 'event.dataset',
|
||||
value: 1,
|
||||
},
|
||||
};
|
||||
const { id } = await createRule(supertest, rule);
|
||||
await waitForRuleSuccessOrStatus(supertest, id);
|
||||
await waitForSignalsToBePresent(supertest, 1, [id]);
|
||||
const signalsOpen = await getSignalsById(supertest, id);
|
||||
const hits = signalsOpen.hits.hits
|
||||
.map((hit) => hit._source.signal.threshold_result ?? null)
|
||||
.sort();
|
||||
expect(hits).to.eql([
|
||||
{
|
||||
count: 4,
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
terms: [
|
||||
{
|
||||
field: 'event.dataset',
|
||||
value: 'dataset_name_1',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 keyword family data types', function () {
|
||||
describe('', function () {
|
||||
this.tags('ciGroup11');
|
||||
|
||||
loadTestFile(require.resolve('./keyword'));
|
||||
loadTestFile(require.resolve('./const_keyword'));
|
||||
loadTestFile(require.resolve('./keyword_mixed_with_const'));
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* 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';
|
||||
import {
|
||||
EqlCreateSchema,
|
||||
ThresholdCreateSchema,
|
||||
} from '../../../../../plugins/security_solution/common/detection_engine/schemas/request';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
interface EventModule {
|
||||
module: string;
|
||||
dataset: string;
|
||||
}
|
||||
|
||||
describe('Rule detects against a keyword of event.dataset', () => {
|
||||
beforeEach(async () => {
|
||||
await createSignalsIndex(supertest);
|
||||
await esArchiver.load('rule_keyword_family/keyword');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteSignalsIndex(supertest);
|
||||
await deleteAllAlerts(supertest);
|
||||
await esArchiver.unload('rule_keyword_family/keyword');
|
||||
});
|
||||
|
||||
describe('"kql" rule type', () => {
|
||||
it('should detect the "dataset_name_1" from "event.dataset"', async () => {
|
||||
const rule = {
|
||||
...getRuleForSignalTesting(['keyword']),
|
||||
query: 'event.dataset: "dataset_name_1"',
|
||||
};
|
||||
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((hit) => (hit._source.event as EventModule).dataset)
|
||||
.sort();
|
||||
expect(hits).to.eql([
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"eql" rule type', () => {
|
||||
it('should detect the "dataset_name_1" from "event.dataset"', async () => {
|
||||
const rule: EqlCreateSchema = {
|
||||
...getRuleForSignalTesting(['keyword']),
|
||||
rule_id: 'eql-rule',
|
||||
type: 'eql',
|
||||
language: 'eql',
|
||||
query: 'any where event.dataset=="dataset_name_1"',
|
||||
};
|
||||
|
||||
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((hit) => (hit._source.event as EventModule).dataset)
|
||||
.sort();
|
||||
expect(hits).to.eql([
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"threshold" rule type', async () => {
|
||||
it('should detect the "dataset_name_1" from "event.dataset"', async () => {
|
||||
const rule: ThresholdCreateSchema = {
|
||||
...getRuleForSignalTesting(['keyword']),
|
||||
rule_id: 'threshold-rule',
|
||||
type: 'threshold',
|
||||
language: 'kuery',
|
||||
query: '*:*',
|
||||
threshold: {
|
||||
field: 'event.dataset',
|
||||
value: 1,
|
||||
},
|
||||
};
|
||||
const { id } = await createRule(supertest, rule);
|
||||
await waitForRuleSuccessOrStatus(supertest, id);
|
||||
await waitForSignalsToBePresent(supertest, 1, [id]);
|
||||
const signalsOpen = await getSignalsById(supertest, id);
|
||||
const hits = signalsOpen.hits.hits
|
||||
.map((hit) => hit._source.signal.threshold_result ?? null)
|
||||
.sort();
|
||||
expect(hits).to.eql([
|
||||
{
|
||||
count: 4,
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
terms: [
|
||||
{
|
||||
field: 'event.dataset',
|
||||
value: 'dataset_name_1',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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 {
|
||||
EqlCreateSchema,
|
||||
ThresholdCreateSchema,
|
||||
} from '../../../../../plugins/security_solution/common/detection_engine/schemas/request';
|
||||
|
||||
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 EventModule {
|
||||
module: string;
|
||||
dataset: string;
|
||||
}
|
||||
|
||||
describe('Rule detects against a keyword and constant_keyword of event.dataset', () => {
|
||||
beforeEach(async () => {
|
||||
await createSignalsIndex(supertest);
|
||||
await esArchiver.load('rule_keyword_family/const_keyword');
|
||||
await esArchiver.load('rule_keyword_family/keyword');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteSignalsIndex(supertest);
|
||||
await deleteAllAlerts(supertest);
|
||||
await esArchiver.unload('rule_keyword_family/const_keyword');
|
||||
await esArchiver.unload('rule_keyword_family/keyword');
|
||||
});
|
||||
|
||||
describe('"kql" rule type', () => {
|
||||
it('should detect the "dataset_name_1" from "event.dataset" and have 8 signals, 4 from each index', async () => {
|
||||
const rule = {
|
||||
...getRuleForSignalTesting(['keyword', 'const_keyword']),
|
||||
query: 'event.dataset: "dataset_name_1"',
|
||||
};
|
||||
const { id } = await createRule(supertest, rule);
|
||||
await waitForRuleSuccessOrStatus(supertest, id);
|
||||
await waitForSignalsToBePresent(supertest, 8, [id]);
|
||||
const signalsOpen = await getSignalsById(supertest, id);
|
||||
expect(signalsOpen.hits.hits.length).to.eql(8);
|
||||
});
|
||||
|
||||
// TODO: Fix this bug and make this work. We currently do not write out the dataset name when it is not in _source
|
||||
it.skip('should copy the dataset_name_1 from the index into the signal', async () => {
|
||||
const rule = {
|
||||
...getRuleForSignalTesting(['keyword', 'const_keyword']),
|
||||
query: 'event.dataset: "dataset_name_1"',
|
||||
};
|
||||
const { id } = await createRule(supertest, rule);
|
||||
await waitForRuleSuccessOrStatus(supertest, id);
|
||||
await waitForSignalsToBePresent(supertest, 8, [id]);
|
||||
const signalsOpen = await getSignalsById(supertest, id);
|
||||
const hits = signalsOpen.hits.hits
|
||||
.map((hit) => (hit._source.event as EventModule).dataset)
|
||||
.sort();
|
||||
expect(hits).to.eql([
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"eql" rule type', () => {
|
||||
it('should detect the "dataset_name_1" from "event.dataset" and have 8 signals, 4 from each index', async () => {
|
||||
const rule: EqlCreateSchema = {
|
||||
...getRuleForSignalTesting(['keyword', 'const_keyword']),
|
||||
rule_id: 'eql-rule',
|
||||
type: 'eql',
|
||||
language: 'eql',
|
||||
query: 'any where event.dataset=="dataset_name_1"',
|
||||
};
|
||||
|
||||
const { id } = await createRule(supertest, rule);
|
||||
await waitForRuleSuccessOrStatus(supertest, id);
|
||||
await waitForSignalsToBePresent(supertest, 8, [id]);
|
||||
const signalsOpen = await getSignalsById(supertest, id);
|
||||
expect(signalsOpen.hits.hits.length).to.eql(8);
|
||||
});
|
||||
|
||||
// TODO: Fix this bug and make this work. We currently do not write out the dataset name when it is not in _source
|
||||
it.skip('should copy the "dataset_name_1" from "event.dataset"', async () => {
|
||||
const rule: EqlCreateSchema = {
|
||||
...getRuleForSignalTesting(['keyword', 'const_keyword']),
|
||||
rule_id: 'eql-rule',
|
||||
type: 'eql',
|
||||
language: 'eql',
|
||||
query: 'any where event.dataset=="dataset_name_1"',
|
||||
};
|
||||
|
||||
const { id } = await createRule(supertest, rule);
|
||||
await waitForRuleSuccessOrStatus(supertest, id);
|
||||
await waitForSignalsToBePresent(supertest, 8, [id]);
|
||||
const signalsOpen = await getSignalsById(supertest, id);
|
||||
const hits = signalsOpen.hits.hits
|
||||
.map((hit) => (hit._source.event as EventModule).dataset)
|
||||
.sort();
|
||||
expect(hits).to.eql([
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
'dataset_name_1',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"threshold" rule type', async () => {
|
||||
it('should detect the "dataset_name_1" from "event.dataset"', async () => {
|
||||
const rule: ThresholdCreateSchema = {
|
||||
...getRuleForSignalTesting(['keyword', 'const_keyword']),
|
||||
rule_id: 'threshold-rule',
|
||||
type: 'threshold',
|
||||
language: 'kuery',
|
||||
query: '*:*',
|
||||
threshold: {
|
||||
field: 'event.dataset',
|
||||
value: 1,
|
||||
},
|
||||
};
|
||||
const { id } = await createRule(supertest, rule);
|
||||
await waitForRuleSuccessOrStatus(supertest, id);
|
||||
await waitForSignalsToBePresent(supertest, 1, [id]);
|
||||
const signalsOpen = await getSignalsById(supertest, id);
|
||||
const hits = signalsOpen.hits.hits
|
||||
.map((hit) => hit._source.signal.threshold_result ?? null)
|
||||
.sort();
|
||||
expect(hits).to.eql([
|
||||
{
|
||||
count: 8,
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
terms: [
|
||||
{
|
||||
field: 'event.dataset',
|
||||
value: 'dataset_name_1',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
Within this folder is input test data for tests within the folder:
|
||||
|
||||
```ts
|
||||
x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family
|
||||
```
|
||||
|
||||
where these are small ECS compliant input indexes that try to express tests that exercise different parts of
|
||||
the detection engine around creating and validating that the keyword family and field aliases all will work
|
||||
with the detection engine. These indexes might contain extra fields or different fields but should not directly
|
||||
clash with ECS or minimally clash. Nothing is stopping anyone from being ECS strict and not having additional
|
||||
extra fields but the extra fields and mappings are to just try and keep these tests simple and small.
|
||||
|
||||
Most of these tests center around the two fields of:
|
||||
* event.module
|
||||
* event.dataset
|
||||
|
||||
To ensure that if mix and match between `keyword`, `const keyword` and field aliases within them, everything should
|
||||
still be ok. It is alright if other use cases are added here if they fit within the `keyword` family as described here:
|
||||
https://www.elastic.co/guide/en/elasticsearch/reference/7.12/keyword.html
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "1",
|
||||
"index": "const_keyword",
|
||||
"source": {
|
||||
"@timestamp": "2020-10-27T05:00:53.000Z"
|
||||
},
|
||||
"type": "_doc"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "2",
|
||||
"index": "const_keyword",
|
||||
"source": {
|
||||
"@timestamp": "2020-10-27T05:01:53.000Z"
|
||||
},
|
||||
"type": "_doc"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "3",
|
||||
"index": "const_keyword",
|
||||
"source": {
|
||||
"@timestamp": "2020-10-27T05:02:53.000Z"
|
||||
},
|
||||
"type": "_doc"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "4",
|
||||
"index": "const_keyword",
|
||||
"source": {
|
||||
"@timestamp": "2020-10-27T05:03:53.000Z"
|
||||
},
|
||||
"type": "_doc"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"index": "const_keyword",
|
||||
"mappings": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"@timestamp": {
|
||||
"type": "date"
|
||||
},
|
||||
"data_stream": {
|
||||
"properties": {
|
||||
"dataset": {
|
||||
"type": "constant_keyword",
|
||||
"value": "dataset_name_1"
|
||||
},
|
||||
"module": {
|
||||
"type": "constant_keyword",
|
||||
"value": "module_name_1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"event": {
|
||||
"properties": {
|
||||
"category": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"dataset": {
|
||||
"type": "alias",
|
||||
"path": "data_stream.dataset"
|
||||
},
|
||||
"module": {
|
||||
"type": "alias",
|
||||
"path": "data_stream.module"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"index": {
|
||||
"refresh_interval": "1s",
|
||||
"number_of_replicas": "1",
|
||||
"number_of_shards": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "1",
|
||||
"index": "keyword",
|
||||
"source": {
|
||||
"@timestamp": "2020-10-28T05:00:53.000Z",
|
||||
"event": {
|
||||
"module": "module_name_1",
|
||||
"dataset": "dataset_name_1"
|
||||
}
|
||||
},
|
||||
"type": "_doc"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "2",
|
||||
"index": "keyword",
|
||||
"source": {
|
||||
"@timestamp": "2020-10-28T05:01:53.000Z",
|
||||
"event": {
|
||||
"module": "module_name_1",
|
||||
"dataset": "dataset_name_1"
|
||||
}
|
||||
},
|
||||
"type": "_doc"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "3",
|
||||
"index": "keyword",
|
||||
"source": {
|
||||
"@timestamp": "2020-10-28T05:02:53.000Z",
|
||||
"event": {
|
||||
"module": "module_name_1",
|
||||
"dataset": "dataset_name_1"
|
||||
}
|
||||
},
|
||||
"type": "_doc"
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"id": "4",
|
||||
"index": "keyword",
|
||||
"source": {
|
||||
"@timestamp": "2020-10-28T05:03:53.000Z",
|
||||
"event": {
|
||||
"module": "module_name_1",
|
||||
"dataset": "dataset_name_1"
|
||||
}
|
||||
},
|
||||
"type": "_doc"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"index": "keyword",
|
||||
"mappings": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"@timestamp": {
|
||||
"type": "date"
|
||||
},
|
||||
"event": {
|
||||
"properties": {
|
||||
"category": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"module": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"dataset": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"index": {
|
||||
"refresh_interval": "1s",
|
||||
"number_of_replicas": "1",
|
||||
"number_of_shards": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue