[SIEM][Detection Engine] Fixes tags to accept characters such as AND, OR, (, ), ", * (#74003)

## Summary

If you create a rule with tags that have an AND, OR, (, ), etc... then you would blow up with an error when you try to filter based off of that like the screen shot below:
<img width="703" alt="Screen Shot 2020-07-31 at 1 55 31 PM" src="https://user-images.githubusercontent.com/1151048/89075547-b3206f80-d33b-11ea-9e7a-30d4a49ac1de.png">

Now you don't blow up:
<img width="1708" alt="Screen Shot 2020-07-31 at 2 37 11 PM" src="https://user-images.githubusercontent.com/1151048/89075553-b582c980-d33b-11ea-807a-7d6a1d1921e8.png">

This fixes it by adding double quotes around the filters and also red/green/TDD unit tests where I first exercised the error conditions then fixed them.   

### 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
This commit is contained in:
Frank Hassanabad 2020-07-31 18:20:08 -06:00 committed by GitHub
parent a216418fe7
commit be47dc4261
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 3 deletions

View file

@ -20,6 +20,7 @@ import {
getPrePackagedRulesStatus,
} from './api';
import { ruleMock, rulesMock } from './mock';
import { buildEsQuery } from 'src/plugins/data/common';
const abortCtrl = new AbortController();
const mockKibanaServices = KibanaServices.get as jest.Mock;
@ -165,7 +166,7 @@ describe('Detections Rules API', () => {
expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/rules/_find', {
method: 'GET',
query: {
filter: 'alert.attributes.tags: hello AND alert.attributes.tags: world',
filter: 'alert.attributes.tags: "hello" AND alert.attributes.tags: "world"',
page: 1,
per_page: 20,
sort_field: 'enabled',
@ -175,6 +176,75 @@ describe('Detections Rules API', () => {
});
});
test('query with tags KQL parses without errors when tags contain characters such as left parenthesis (', async () => {
await fetchRules({
filterOptions: {
filter: 'ruleName',
sortField: 'enabled',
sortOrder: 'desc',
showCustomRules: true,
showElasticRules: true,
tags: ['('],
},
signal: abortCtrl.signal,
});
const [
[
,
{
query: { filter },
},
],
] = fetchMock.mock.calls;
expect(() => buildEsQuery(undefined, { query: filter, language: 'kuery' }, [])).not.toThrow();
});
test('query KQL parses without errors when filter contains characters such as double quotes', async () => {
await fetchRules({
filterOptions: {
filter: '"test"',
sortField: 'enabled',
sortOrder: 'desc',
showCustomRules: true,
showElasticRules: true,
tags: [],
},
signal: abortCtrl.signal,
});
const [
[
,
{
query: { filter },
},
],
] = fetchMock.mock.calls;
expect(() => buildEsQuery(undefined, { query: filter, language: 'kuery' }, [])).not.toThrow();
});
test('query KQL parses without errors when tags contains characters such as double quotes', async () => {
await fetchRules({
filterOptions: {
filter: '"test"',
sortField: 'enabled',
sortOrder: 'desc',
showCustomRules: true,
showElasticRules: true,
tags: ['"test"'],
},
signal: abortCtrl.signal,
});
const [
[
,
{
query: { filter },
},
],
] = fetchMock.mock.calls;
expect(() => buildEsQuery(undefined, { query: filter, language: 'kuery' }, [])).not.toThrow();
});
test('check parameter url, query with all options', async () => {
await fetchRules({
filterOptions: {
@ -191,7 +261,7 @@ describe('Detections Rules API', () => {
method: 'GET',
query: {
filter:
'alert.attributes.name: ruleName AND alert.attributes.tags: "__internal_immutable:false" AND alert.attributes.tags: "__internal_immutable:true" AND alert.attributes.tags: hello AND alert.attributes.tags: world',
'alert.attributes.name: ruleName AND alert.attributes.tags: "__internal_immutable:false" AND alert.attributes.tags: "__internal_immutable:true" AND alert.attributes.tags: "hello" AND alert.attributes.tags: "world"',
page: 1,
per_page: 20,
sort_field: 'enabled',

View file

@ -97,7 +97,7 @@ export const fetchRules = async ({
...(filterOptions.showElasticRules
? [`alert.attributes.tags: "__internal_immutable:true"`]
: []),
...(filterOptions.tags?.map((t) => `alert.attributes.tags: ${t}`) ?? []),
...(filterOptions.tags?.map((t) => `alert.attributes.tags: "${t.replace(/"/g, '\\"')}"`) ?? []),
];
const query = {