Skip to content

Commit fd6b63e

Browse files
[SIEM][Detection Engine] Adds backend e2e tests for basic license testing
## Summary Adds backend e2e basic license type tests for the detection engine API. Previously we only had tests for full security space that was platinum based licensing. These tests now cover the basic license test cases. This covers test cases for machine learning to ensure you cannot create machine learning based detection rules under the basic license. Instead those tests will return the expected 403 forbidden. Testing just the subset of the tests from this PR locally: ```sh node scripts/functional_tests --config x-pack/test/detection_engine_api_integration/basic/config.ts ``` You do want to go to the jenkins tests on CI and ensure you can see some of the strings such as the newer forbidden messages showing up as passing. ### Checklist - [x] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios
1 parent c0c7dcc commit fd6b63e

39 files changed

+3117
-24
lines changed

x-pack/scripts/functional_tests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const onlyNotInCoverageTests = [
2121
require.resolve('../test/alerting_api_integration/spaces_only/config.ts'),
2222
require.resolve('../test/alerting_api_integration/security_and_spaces/config.ts'),
2323
require.resolve('../test/detection_engine_api_integration/security_and_spaces/config.ts'),
24+
require.resolve('../test/detection_engine_api_integration/basic/config.ts'),
2425
require.resolve('../test/plugin_api_integration/config.ts'),
2526
require.resolve('../test/kerberos_api_integration/config.ts'),
2627
require.resolve('../test/kerberos_api_integration/anonymous_access.config.ts'),
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { createTestConfig } from '../common/config';
8+
9+
// eslint-disable-next-line import/no-default-export
10+
export default createTestConfig('basic', {
11+
disabledPlugins: [],
12+
license: 'basic',
13+
ssl: true,
14+
});
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import expect from '@kbn/expect';
8+
9+
import { DETECTION_ENGINE_PREPACKAGED_URL } from '../../../../plugins/siem/common/constants';
10+
import { FtrProviderContext } from '../../common/ftr_provider_context';
11+
import { createSignalsIndex, deleteAllAlerts, deleteSignalsIndex } from '../../utils';
12+
13+
// eslint-disable-next-line import/no-default-export
14+
export default ({ getService }: FtrProviderContext): void => {
15+
const supertest = getService('supertest');
16+
const es = getService('legacyEs');
17+
18+
describe('add_prepackaged_rules', () => {
19+
describe('validation errors', () => {
20+
it('should give an error that the index must exist first if it does not exist before adding prepackaged rules', async () => {
21+
const { body } = await supertest
22+
.put(DETECTION_ENGINE_PREPACKAGED_URL)
23+
.set('kbn-xsrf', 'true')
24+
.send()
25+
.expect(400);
26+
27+
expect(body).to.eql({
28+
message:
29+
'Pre-packaged rules cannot be installed until the signals index is created: .siem-signals-default',
30+
status_code: 400,
31+
});
32+
});
33+
});
34+
35+
describe('creating prepackaged rules', () => {
36+
beforeEach(async () => {
37+
await createSignalsIndex(supertest);
38+
});
39+
40+
afterEach(async () => {
41+
await deleteSignalsIndex(supertest);
42+
await deleteAllAlerts(es);
43+
});
44+
45+
it('should contain two output keys of rules_installed and rules_updated', async () => {
46+
const { body } = await supertest
47+
.put(DETECTION_ENGINE_PREPACKAGED_URL)
48+
.set('kbn-xsrf', 'true')
49+
.send()
50+
.expect(200);
51+
52+
expect(Object.keys(body)).to.eql(['rules_installed', 'rules_updated']);
53+
});
54+
55+
it('should create the prepackaged rules and return a count greater than zero', async () => {
56+
const { body } = await supertest
57+
.put(DETECTION_ENGINE_PREPACKAGED_URL)
58+
.set('kbn-xsrf', 'true')
59+
.send()
60+
.expect(200);
61+
62+
expect(body.rules_installed).to.be.greaterThan(0);
63+
});
64+
65+
it('should create the prepackaged rules that the rules_updated is of size zero', async () => {
66+
const { body } = await supertest
67+
.put(DETECTION_ENGINE_PREPACKAGED_URL)
68+
.set('kbn-xsrf', 'true')
69+
.send()
70+
.expect(200);
71+
72+
expect(body.rules_updated).to.eql(0);
73+
});
74+
75+
it('should be possible to call the API twice and the second time the number of rules installed should be zero', async () => {
76+
await supertest
77+
.put(DETECTION_ENGINE_PREPACKAGED_URL)
78+
.set('kbn-xsrf', 'true')
79+
.send()
80+
.expect(200);
81+
82+
const { body } = await supertest
83+
.put(DETECTION_ENGINE_PREPACKAGED_URL)
84+
.set('kbn-xsrf', 'true')
85+
.send()
86+
.expect(200);
87+
88+
expect(body.rules_installed).to.eql(0);
89+
});
90+
});
91+
});
92+
};
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import expect from '@kbn/expect';
8+
9+
import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/siem/common/constants';
10+
import { FtrProviderContext } from '../../common/ftr_provider_context';
11+
import {
12+
createSignalsIndex,
13+
deleteAllAlerts,
14+
deleteSignalsIndex,
15+
getSimpleRule,
16+
getSimpleRuleOutput,
17+
getSimpleRuleOutputWithoutRuleId,
18+
getSimpleRuleWithoutRuleId,
19+
removeServerGeneratedProperties,
20+
removeServerGeneratedPropertiesIncludingRuleId,
21+
getSimpleMlRule,
22+
} from '../../utils';
23+
24+
// eslint-disable-next-line import/no-default-export
25+
export default ({ getService }: FtrProviderContext) => {
26+
const supertest = getService('supertest');
27+
const es = getService('legacyEs');
28+
29+
describe('create_rules', () => {
30+
describe('validation errors', () => {
31+
it('should give an error that the index must exist first if it does not exist before creating a rule', async () => {
32+
const { body } = await supertest
33+
.post(DETECTION_ENGINE_RULES_URL)
34+
.set('kbn-xsrf', 'true')
35+
.send(getSimpleRule())
36+
.expect(400);
37+
38+
expect(body).to.eql({
39+
message:
40+
'To create a rule, the index must exist first. Index .siem-signals-default does not exist',
41+
status_code: 400,
42+
});
43+
});
44+
});
45+
46+
describe('creating rules', () => {
47+
beforeEach(async () => {
48+
await createSignalsIndex(supertest);
49+
});
50+
51+
afterEach(async () => {
52+
await deleteSignalsIndex(supertest);
53+
await deleteAllAlerts(es);
54+
});
55+
56+
it('should create a single rule with a rule_id', async () => {
57+
const { body } = await supertest
58+
.post(DETECTION_ENGINE_RULES_URL)
59+
.set('kbn-xsrf', 'true')
60+
.send(getSimpleRule())
61+
.expect(200);
62+
63+
const bodyToCompare = removeServerGeneratedProperties(body);
64+
expect(bodyToCompare).to.eql(getSimpleRuleOutput());
65+
});
66+
67+
it('should create a single rule without an input index', async () => {
68+
const { index, ...payload } = getSimpleRule();
69+
const { index: _index, ...expected } = getSimpleRuleOutput();
70+
71+
const { body } = await supertest
72+
.post(DETECTION_ENGINE_RULES_URL)
73+
.set('kbn-xsrf', 'true')
74+
.send(payload)
75+
.expect(200);
76+
77+
const bodyToCompare = removeServerGeneratedProperties(body);
78+
expect(bodyToCompare).to.eql(expected);
79+
});
80+
81+
it('should create a single rule without a rule_id', async () => {
82+
const { body } = await supertest
83+
.post(DETECTION_ENGINE_RULES_URL)
84+
.set('kbn-xsrf', 'true')
85+
.send(getSimpleRuleWithoutRuleId())
86+
.expect(200);
87+
88+
const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body);
89+
expect(bodyToCompare).to.eql(getSimpleRuleOutputWithoutRuleId());
90+
});
91+
92+
it('should give a 403 when trying to create a single Machine Learning rule since the license is basic', async () => {
93+
const { body } = await supertest
94+
.post(DETECTION_ENGINE_RULES_URL)
95+
.set('kbn-xsrf', 'true')
96+
.send(getSimpleMlRule())
97+
.expect(403);
98+
99+
const bodyToCompare = removeServerGeneratedProperties(body);
100+
expect(bodyToCompare).to.eql({
101+
message: 'Your license does not support machine learning. Please upgrade your license.',
102+
status_code: 403,
103+
});
104+
});
105+
106+
it('should cause a 409 conflict if we attempt to create the same rule_id twice', async () => {
107+
await supertest
108+
.post(DETECTION_ENGINE_RULES_URL)
109+
.set('kbn-xsrf', 'true')
110+
.send(getSimpleRule())
111+
.expect(200);
112+
113+
const { body } = await supertest
114+
.post(DETECTION_ENGINE_RULES_URL)
115+
.set('kbn-xsrf', 'true')
116+
.send(getSimpleRule())
117+
.expect(409);
118+
119+
expect(body).to.eql({
120+
message: 'rule_id: "rule-1" already exists',
121+
status_code: 409,
122+
});
123+
});
124+
});
125+
});
126+
};
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import expect from '@kbn/expect';
8+
9+
import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/siem/common/constants';
10+
import { FtrProviderContext } from '../../common/ftr_provider_context';
11+
import {
12+
createSignalsIndex,
13+
deleteAllAlerts,
14+
deleteSignalsIndex,
15+
getSimpleRule,
16+
getSimpleRuleOutput,
17+
getSimpleRuleOutputWithoutRuleId,
18+
getSimpleRuleWithoutRuleId,
19+
removeServerGeneratedProperties,
20+
removeServerGeneratedPropertiesIncludingRuleId,
21+
} from '../../utils';
22+
23+
// eslint-disable-next-line import/no-default-export
24+
export default ({ getService }: FtrProviderContext): void => {
25+
const supertest = getService('supertest');
26+
const es = getService('legacyEs');
27+
28+
describe('create_rules_bulk', () => {
29+
describe('validation errors', () => {
30+
it('should give a 200 even if the index does not exist as all bulks return a 200 but have an error of 409 bad request in the body', async () => {
31+
const { body } = await supertest
32+
.post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`)
33+
.set('kbn-xsrf', 'true')
34+
.send([getSimpleRule()])
35+
.expect(200);
36+
37+
expect(body).to.eql([
38+
{
39+
error: {
40+
message:
41+
'To create a rule, the index must exist first. Index .siem-signals-default does not exist',
42+
status_code: 400,
43+
},
44+
rule_id: 'rule-1',
45+
},
46+
]);
47+
});
48+
});
49+
50+
describe('creating rules in bulk', () => {
51+
beforeEach(async () => {
52+
await createSignalsIndex(supertest);
53+
});
54+
55+
afterEach(async () => {
56+
await deleteSignalsIndex(supertest);
57+
await deleteAllAlerts(es);
58+
});
59+
60+
it('should create a single rule with a rule_id', async () => {
61+
const { body } = await supertest
62+
.post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`)
63+
.set('kbn-xsrf', 'true')
64+
.send([getSimpleRule()])
65+
.expect(200);
66+
67+
const bodyToCompare = removeServerGeneratedProperties(body[0]);
68+
expect(bodyToCompare).to.eql(getSimpleRuleOutput());
69+
});
70+
71+
it('should create a single rule without a rule_id', async () => {
72+
const { body } = await supertest
73+
.post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`)
74+
.set('kbn-xsrf', 'true')
75+
.send([getSimpleRuleWithoutRuleId()])
76+
.expect(200);
77+
78+
const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]);
79+
expect(bodyToCompare).to.eql(getSimpleRuleOutputWithoutRuleId());
80+
});
81+
82+
it('should return a 200 ok but have a 409 conflict if we attempt to create the same rule_id twice', async () => {
83+
const { body } = await supertest
84+
.post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`)
85+
.set('kbn-xsrf', 'true')
86+
.send([getSimpleRule(), getSimpleRule()])
87+
.expect(200);
88+
89+
expect(body).to.eql([
90+
{
91+
error: {
92+
message: 'rule_id: "rule-1" already exists',
93+
status_code: 409,
94+
},
95+
rule_id: 'rule-1',
96+
},
97+
]);
98+
});
99+
100+
it('should return a 200 ok but have a 409 conflict if we attempt to create the same rule_id that already exists', async () => {
101+
await supertest
102+
.post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`)
103+
.set('kbn-xsrf', 'true')
104+
.send([getSimpleRule()])
105+
.expect(200);
106+
107+
const { body } = await supertest
108+
.post(`${DETECTION_ENGINE_RULES_URL}/_bulk_create`)
109+
.set('kbn-xsrf', 'foo')
110+
.send([getSimpleRule()])
111+
.expect(200);
112+
113+
expect(body).to.eql([
114+
{
115+
error: {
116+
message: 'rule_id: "rule-1" already exists',
117+
status_code: 409,
118+
},
119+
rule_id: 'rule-1',
120+
},
121+
]);
122+
});
123+
});
124+
});
125+
};

0 commit comments

Comments
 (0)