[SIEM] Fix timeline buildGlobalQuery (#68320)
This commit is contained in:
parent
2559dbe3ba
commit
48ef260e11
2 changed files with 83 additions and 44 deletions
|
@ -18,7 +18,7 @@ const endDate = new Date('2018-03-24T03:33:52.253Z').valueOf();
|
|||
|
||||
describe('Build KQL Query', () => {
|
||||
test('Build KQL query with one data provider', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 1);
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 1));
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual('name : "Provider 1"');
|
||||
});
|
||||
|
@ -56,18 +56,40 @@ describe('Build KQL Query', () => {
|
|||
});
|
||||
|
||||
test('Build KQL query with two data provider', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 2);
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 2));
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual('(name : "Provider 1" ) or (name : "Provider 2" )');
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual('(name : "Provider 1") or (name : "Provider 2")');
|
||||
});
|
||||
|
||||
test('Build KQL query with two data provider and first is disabled', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 2));
|
||||
dataProviders[0].enabled = false;
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual('name : "Provider 2"');
|
||||
});
|
||||
|
||||
test('Build KQL query with two data provider and second is disabled', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 2));
|
||||
dataProviders[1].enabled = false;
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual('name : "Provider 1"');
|
||||
});
|
||||
|
||||
test('Build KQL query with one data provider and one and', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 1));
|
||||
dataProviders[0].and = mockDataProviders.slice(1, 2);
|
||||
dataProviders[0].and = cloneDeep(mockDataProviders.slice(1, 2));
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual('name : "Provider 1" and name : "Provider 2"');
|
||||
});
|
||||
|
||||
test('Build KQL query with one disabled data provider and one and', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 1));
|
||||
dataProviders[0].enabled = false;
|
||||
dataProviders[0].and = cloneDeep(mockDataProviders.slice(1, 2));
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual('name : "Provider 2"');
|
||||
});
|
||||
|
||||
test('Build KQL query with one data provider and one and as timestamp (string input)', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 1));
|
||||
dataProviders[0].and = cloneDeep(mockDataProviders.slice(1, 2));
|
||||
|
@ -106,28 +128,50 @@ describe('Build KQL Query', () => {
|
|||
|
||||
test('Build KQL query with two data provider and multiple and', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 2));
|
||||
dataProviders[0].and = mockDataProviders.slice(2, 4);
|
||||
dataProviders[1].and = mockDataProviders.slice(4, 5);
|
||||
dataProviders[0].and = cloneDeep(mockDataProviders.slice(2, 4));
|
||||
dataProviders[1].and = cloneDeep(mockDataProviders.slice(4, 5));
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual(
|
||||
'(name : "Provider 1" and name : "Provider 3" and name : "Provider 4") or (name : "Provider 2" and name : "Provider 5")'
|
||||
);
|
||||
});
|
||||
|
||||
test('Build KQL query with two data provider and multiple and and first data provider is disabled', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 2));
|
||||
dataProviders[0].enabled = false;
|
||||
dataProviders[0].and = cloneDeep(mockDataProviders.slice(2, 4));
|
||||
dataProviders[1].and = cloneDeep(mockDataProviders.slice(4, 5));
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual(
|
||||
'(name : "Provider 3" and name : "Provider 4") or (name : "Provider 2" and name : "Provider 5")'
|
||||
);
|
||||
});
|
||||
|
||||
test('Build KQL query with two data provider and multiple and and first and provider is disabled', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 2));
|
||||
dataProviders[0].and = cloneDeep(mockDataProviders.slice(2, 4));
|
||||
dataProviders[0].and[0].enabled = false;
|
||||
dataProviders[1].and = cloneDeep(mockDataProviders.slice(4, 5));
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual(
|
||||
'(name : "Provider 1" and name : "Provider 4") or (name : "Provider 2" and name : "Provider 5")'
|
||||
);
|
||||
});
|
||||
|
||||
test('Build KQL query with all data provider', () => {
|
||||
const kqlQuery = buildGlobalQuery(mockDataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual(
|
||||
'(name : "Provider 1" ) or (name : "Provider 2" ) or (name : "Provider 3" ) or (name : "Provider 4" ) or (name : "Provider 5" ) or (name : "Provider 6" ) or (name : "Provider 7" ) or (name : "Provider 8" ) or (name : "Provider 9" ) or (name : "Provider 10" )'
|
||||
'(name : "Provider 1") or (name : "Provider 2") or (name : "Provider 3") or (name : "Provider 4") or (name : "Provider 5") or (name : "Provider 6") or (name : "Provider 7") or (name : "Provider 8") or (name : "Provider 9") or (name : "Provider 10")'
|
||||
);
|
||||
});
|
||||
|
||||
test('Build complex KQL query with and and or', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders);
|
||||
dataProviders[0].and = mockDataProviders.slice(2, 4);
|
||||
dataProviders[1].and = mockDataProviders.slice(4, 5);
|
||||
dataProviders[0].and = cloneDeep(mockDataProviders.slice(2, 4));
|
||||
dataProviders[1].and = cloneDeep(mockDataProviders.slice(4, 5));
|
||||
const kqlQuery = buildGlobalQuery(dataProviders, mockBrowserFields);
|
||||
expect(cleanUpKqlQuery(kqlQuery)).toEqual(
|
||||
'(name : "Provider 1" and name : "Provider 3" and name : "Provider 4") or (name : "Provider 2" and name : "Provider 5") or (name : "Provider 3" ) or (name : "Provider 4" ) or (name : "Provider 5" ) or (name : "Provider 6" ) or (name : "Provider 7" ) or (name : "Provider 8" ) or (name : "Provider 9" ) or (name : "Provider 10" )'
|
||||
'(name : "Provider 1" and name : "Provider 3" and name : "Provider 4") or (name : "Provider 2" and name : "Provider 5") or (name : "Provider 3") or (name : "Provider 4") or (name : "Provider 5") or (name : "Provider 6") or (name : "Provider 7") or (name : "Provider 8") or (name : "Provider 9") or (name : "Provider 10")'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -223,7 +267,7 @@ describe('Combined Queries', () => {
|
|||
});
|
||||
|
||||
test('Only Data Provider', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 1);
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 1));
|
||||
const { filterQuery } = combineQueries({
|
||||
config,
|
||||
dataProviders,
|
||||
|
@ -338,7 +382,7 @@ describe('Combined Queries', () => {
|
|||
});
|
||||
|
||||
test('Data Provider & KQL search query', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 1);
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 1));
|
||||
const { filterQuery } = combineQueries({
|
||||
config,
|
||||
dataProviders,
|
||||
|
@ -356,7 +400,7 @@ describe('Combined Queries', () => {
|
|||
});
|
||||
|
||||
test('Data Provider & KQL filter query', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 1);
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 1));
|
||||
const { filterQuery } = combineQueries({
|
||||
config,
|
||||
dataProviders,
|
||||
|
@ -375,8 +419,8 @@ describe('Combined Queries', () => {
|
|||
|
||||
test('Data Provider & KQL search query multiple', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 2));
|
||||
dataProviders[0].and = mockDataProviders.slice(2, 4);
|
||||
dataProviders[1].and = mockDataProviders.slice(4, 5);
|
||||
dataProviders[0].and = cloneDeep(mockDataProviders.slice(2, 4));
|
||||
dataProviders[1].and = cloneDeep(mockDataProviders.slice(4, 5));
|
||||
const { filterQuery } = combineQueries({
|
||||
config,
|
||||
dataProviders,
|
||||
|
@ -395,8 +439,8 @@ describe('Combined Queries', () => {
|
|||
|
||||
test('Data Provider & KQL filter query multiple', () => {
|
||||
const dataProviders = cloneDeep(mockDataProviders.slice(0, 2));
|
||||
dataProviders[0].and = mockDataProviders.slice(2, 4);
|
||||
dataProviders[1].and = mockDataProviders.slice(4, 5);
|
||||
dataProviders[0].and = cloneDeep(mockDataProviders.slice(2, 4));
|
||||
dataProviders[1].and = cloneDeep(mockDataProviders.slice(4, 5));
|
||||
const { filterQuery } = combineQueries({
|
||||
config,
|
||||
dataProviders,
|
||||
|
|
|
@ -63,35 +63,30 @@ const buildQueryMatch = (
|
|||
: `${dataProvider.queryMatch.field} ${EXISTS_OPERATOR}`
|
||||
}`.trim();
|
||||
|
||||
const buildQueryForAndProvider = (
|
||||
dataAndProviders: DataProvidersAnd[],
|
||||
browserFields: BrowserFields
|
||||
) =>
|
||||
dataAndProviders
|
||||
.reduce((andQuery, andDataProvider) => {
|
||||
const prepend = (q: string) => `${q !== '' ? `${q} and ` : ''}`;
|
||||
return andDataProvider.enabled
|
||||
? `${prepend(andQuery)} ${buildQueryMatch(andDataProvider, browserFields)}`
|
||||
: andQuery;
|
||||
}, '')
|
||||
.trim();
|
||||
|
||||
export const buildGlobalQuery = (dataProviders: DataProvider[], browserFields: BrowserFields) =>
|
||||
dataProviders
|
||||
.reduce((query, dataProvider: DataProvider, i) => {
|
||||
const prepend = (q: string) => `${q !== '' ? `${q} or ` : ''}`;
|
||||
const openParen = i >= 0 && dataProviders.length > 1 ? '(' : '';
|
||||
const closeParen = i >= 0 && dataProviders.length > 1 ? ')' : '';
|
||||
return dataProvider.enabled
|
||||
? `${prepend(query)}${openParen}${buildQueryMatch(dataProvider, browserFields)}
|
||||
${
|
||||
dataProvider.and.length > 0
|
||||
? ` and ${buildQueryForAndProvider(dataProvider.and, browserFields)}`
|
||||
: ''
|
||||
}${closeParen}`.trim()
|
||||
: query;
|
||||
}, '')
|
||||
.trim();
|
||||
.reduce((queries: string[], dataProvider: DataProvider) => {
|
||||
const flatDataProviders = [dataProvider, ...dataProvider.and];
|
||||
const activeDataProviders = flatDataProviders.filter(
|
||||
(flatDataProvider) => flatDataProvider.enabled
|
||||
);
|
||||
|
||||
if (!activeDataProviders.length) return queries;
|
||||
|
||||
const activeDataProvidersQueries = activeDataProviders.map((activeDataProvider) =>
|
||||
buildQueryMatch(activeDataProvider, browserFields)
|
||||
);
|
||||
|
||||
const activeDataProvidersQueryMatch = activeDataProvidersQueries.join(' and ');
|
||||
|
||||
return [...queries, activeDataProvidersQueryMatch];
|
||||
}, [])
|
||||
.filter((queriesItem) => !isEmpty(queriesItem))
|
||||
.reduce((globalQuery: string, queryMatch: string, index: number, queries: string[]) => {
|
||||
if (queries.length <= 1) return queryMatch;
|
||||
|
||||
return !index ? `(${queryMatch})` : `${globalQuery} or (${queryMatch})`;
|
||||
}, '');
|
||||
|
||||
export const combineQueries = ({
|
||||
config,
|
||||
|
|
Loading…
Reference in a new issue