[Security Solutions] Removes deprecation and more copied code between security solutions and lists plugin (#100150)

## Summary

* Removes deprecations 
* Removes duplicated code

### 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:
Frank Hassanabad 2021-05-14 16:56:08 -06:00 committed by GitHub
parent ca2930c719
commit bfe08d25c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 501 additions and 701 deletions

View file

@ -5,45 +5,6 @@
* 2.0.
*/
// TODO: We should remove these and instead directly import them in the security_solution project. This is to get my PR across the line without too many conflicts.
export {
CommentsArray,
Comment,
CreateComment,
CreateCommentsArray,
Entry,
EntryExists,
EntryMatch,
EntryMatchAny,
EntryMatchWildcard,
EntryNested,
EntryList,
EntriesArray,
NamespaceType,
NestedEntriesArray,
ListOperator as Operator,
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
listOperator as operator,
ExceptionListTypeEnum,
ExceptionListType,
comment,
exceptionListType,
entry,
entriesNested,
nestedEntryItem,
entriesMatch,
entriesMatchAny,
entriesMatchWildcard,
entriesExists,
entriesList,
namespaceType,
osType,
osTypeArray,
OsTypeArray,
Type,
} from '@kbn/securitysolution-io-ts-list-types';
export {
ListSchema,
ExceptionListSchema,

View file

@ -14,8 +14,8 @@ import {
EuiSuperSelect,
} from '@elastic/eui';
import { uniq } from 'lodash';
import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { OperatorTypeEnum } from '../../../../common';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { AutocompleteStart } from '../../../../../../../src/plugins/data/public';

View file

@ -8,8 +8,8 @@
import React, { useCallback, useMemo, useState } from 'react';
import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui';
import { uniq } from 'lodash';
import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { OperatorTypeEnum } from '../../../../common';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { AutocompleteStart } from '../../../../../../../src/plugins/data/public';

View file

@ -7,8 +7,9 @@
import dateMath from '@elastic/datemath';
import { EuiComboBoxOptionOption } from '@elastic/eui';
import type { Type } from '@kbn/securitysolution-io-ts-list-types';
import { ListSchema, Type } from '../../../../common';
import type { ListSchema } from '../../../../common';
import { IFieldType } from '../../../../../../../src/plugins/data/common';
import {

View file

@ -6,10 +6,10 @@
*/
import { act, renderHook } from '@testing-library/react-hooks';
import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { stubIndexPatternWithFields } from '../../../../../../../../src/plugins/data/common/index_patterns/index_pattern.stub';
import { getField } from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks';
import { OperatorTypeEnum } from '../../../../../common';
import { dataPluginMock } from '../../../../../../../../src/plugins/data/public/mocks';
import {

View file

@ -7,10 +7,10 @@
import { useEffect, useRef, useState } from 'react';
import { debounce } from 'lodash';
import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { AutocompleteStart } from '../../../../../../../../src/plugins/data/public';
import { IFieldType, IIndexPattern } from '../../../../../../../../src/plugins/data/common';
import { OperatorTypeEnum } from '../../../../../common';
interface FuncArgs {
fieldSelected: IFieldType | undefined;

View file

@ -6,8 +6,10 @@
*/
import { i18n } from '@kbn/i18n';
import { OperatorEnum, OperatorTypeEnum } from '../../../../common';
import {
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import { OperatorOption } from './types';

View file

@ -6,8 +6,10 @@
*/
import { EuiComboBoxOptionOption } from '@elastic/eui';
import { OperatorEnum, OperatorTypeEnum } from '../../../../common';
import type {
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
export interface GetGenericComboBoxPropsReturn {
comboOptions: EuiComboBoxOptionOption[];

View file

@ -9,8 +9,11 @@ import { Story } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import React from 'react';
import { HttpStart } from 'kibana/public';
import {
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import { OperatorEnum, OperatorTypeEnum } from '../../../../common';
import { AutocompleteStart } from '../../../../../../../src/plugins/data/public';
import { fields } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks';
import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common';

View file

@ -8,7 +8,11 @@
import React, { useCallback, useMemo } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
import styled from 'styled-components';
import { OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
import {
ExceptionListType,
ListOperatorTypeEnum as OperatorTypeEnum,
OsTypeArray,
} from '@kbn/securitysolution-io-ts-list-types';
import { AutocompleteStart } from '../../../../../../../src/plugins/data/public';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
@ -21,7 +25,7 @@ import { AutocompleteFieldExistsComponent } from '../autocomplete/field_value_ex
import { AutocompleteFieldMatchComponent } from '../autocomplete/field_value_match';
import { AutocompleteFieldMatchAnyComponent } from '../autocomplete/field_value_match_any';
import { AutocompleteFieldListsComponent } from '../autocomplete/field_value_lists';
import { ExceptionListType, ListSchema, OperatorTypeEnum } from '../../../../common';
import { ListSchema } from '../../../../common';
import { getEmptyValue } from '../../../common/empty_value';
import {

View file

@ -10,9 +10,8 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import styled from 'styled-components';
import { HttpStart } from 'kibana/public';
import { AutocompleteStart } from 'src/plugins/data/public';
import { OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
import { ExceptionListType, OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
import { ExceptionListType } from '../../../../common';
import { IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { BuilderEntry, ExceptionsBuilderExceptionItem, FormattedBuilderEntry } from './types';

View file

@ -10,19 +10,21 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import styled from 'styled-components';
import { HttpStart } from 'kibana/public';
import { addIdToItem } from '@kbn/securitysolution-utils';
import { OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
import {
ExceptionListType,
NamespaceType,
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
OsTypeArray,
entriesNested,
} from '@kbn/securitysolution-io-ts-list-types';
import { AutocompleteStart, IIndexPattern } from '../../../../../../../src/plugins/data/public';
import {
CreateExceptionListItemSchema,
ExceptionListItemSchema,
ExceptionListType,
NamespaceType,
OperatorEnum,
OperatorTypeEnum,
entriesNested,
exceptionListItemSchema,
} from '../../../../common';
import { AutocompleteStart, IIndexPattern } from '../../../../../../../src/plugins/data/public';
import { AndOrBadge } from '../and_or_badge';
import { CreateExceptionListItemBuilderSchema, ExceptionsBuilderExceptionItem } from './types';

View file

@ -5,6 +5,18 @@
* 2.0.
*/
import {
EntryExists,
EntryList,
EntryMatch,
EntryMatchAny,
EntryNested,
ExceptionListType,
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import { CreateExceptionListItemSchema, ExceptionListItemSchema } from '../../../../common';
import { ENTRIES_WITH_IDS } from '../../../../common/constants.mock';
import { getEntryExistsMock } from '../../../../common/schemas/types/entry_exists.mock';
import { getExceptionListItemSchemaMock } from '../../../../common/schemas/response/exception_list_item_schema.mock';
@ -23,25 +35,23 @@ import {
doesNotExistOperator,
existsOperator,
isInListOperator,
isNotInListOperator,
isNotOneOfOperator,
isNotOperator,
isOneOfOperator,
isOperator,
} from '../autocomplete/operators';
import {
EntryExists,
EntryList,
EntryMatch,
EntryMatchAny,
EntryNested,
ExceptionListType,
OperatorEnum,
OperatorTypeEnum,
} from '../../../../common';
import { OperatorOption } from '../autocomplete/types';
import { getEntryListMock } from '../../../../common/schemas/types/entry_list.mock';
import { BuilderEntry, ExceptionsBuilderExceptionItem, FormattedBuilderEntry } from './types';
import {
BuilderEntry,
EmptyEntry,
ExceptionsBuilderExceptionItem,
FormattedBuilderEntry,
} from './types';
import {
filterExceptionItems,
getCorrespondingKeywordField,
getEntryFromOperator,
getEntryOnFieldChange,
@ -49,10 +59,14 @@ import {
getEntryOnMatchAnyChange,
getEntryOnMatchChange,
getEntryOnOperatorChange,
getEntryValue,
getExceptionOperatorSelect,
getFilteredIndexPatterns,
getFormattedBuilderEntries,
getFormattedBuilderEntry,
getNewExceptionItem,
getOperatorOptions,
getOperatorType,
getUpdatedEntriesOnDelete,
isEntryNested,
} from './helpers';
@ -1426,4 +1440,298 @@ describe('Exception builder helpers', () => {
expect(output).toEqual(undefined);
});
});
describe('#getOperatorType', () => {
test('returns operator type "match" if entry.type is "match"', () => {
const payload = getEntryMatchMock();
const operatorType = getOperatorType(payload);
expect(operatorType).toEqual(OperatorTypeEnum.MATCH);
});
test('returns operator type "match_any" if entry.type is "match_any"', () => {
const payload = getEntryMatchAnyMock();
const operatorType = getOperatorType(payload);
expect(operatorType).toEqual(OperatorTypeEnum.MATCH_ANY);
});
test('returns operator type "list" if entry.type is "list"', () => {
const payload = getEntryListMock();
const operatorType = getOperatorType(payload);
expect(operatorType).toEqual(OperatorTypeEnum.LIST);
});
test('returns operator type "exists" if entry.type is "exists"', () => {
const payload = getEntryExistsMock();
const operatorType = getOperatorType(payload);
expect(operatorType).toEqual(OperatorTypeEnum.EXISTS);
});
});
describe('#getExceptionOperatorSelect', () => {
test('it returns "isOperator" when "operator" is "included" and operator type is "match"', () => {
const payload = getEntryMatchMock();
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isOperator);
});
test('it returns "isNotOperator" when "operator" is "excluded" and operator type is "match"', () => {
const payload = getEntryMatchMock();
payload.operator = 'excluded';
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isNotOperator);
});
test('it returns "isOneOfOperator" when "operator" is "included" and operator type is "match_any"', () => {
const payload = getEntryMatchAnyMock();
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isOneOfOperator);
});
test('it returns "isNotOneOfOperator" when "operator" is "excluded" and operator type is "match_any"', () => {
const payload = getEntryMatchAnyMock();
payload.operator = 'excluded';
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isNotOneOfOperator);
});
test('it returns "existsOperator" when "operator" is "included" and no operator type is provided', () => {
const payload = getEntryExistsMock();
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(existsOperator);
});
test('it returns "doesNotExistsOperator" when "operator" is "excluded" and no operator type is provided', () => {
const payload = getEntryExistsMock();
payload.operator = 'excluded';
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(doesNotExistOperator);
});
test('it returns "isInList" when "operator" is "included" and operator type is "list"', () => {
const payload = getEntryListMock();
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isInListOperator);
});
test('it returns "isNotInList" when "operator" is "excluded" and operator type is "list"', () => {
const payload = getEntryListMock();
payload.operator = 'excluded';
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isNotInListOperator);
});
});
describe('#filterExceptionItems', () => {
// Please see `x-pack/plugins/lists/public/exceptions/transforms.ts` doc notes
// for context around the temporary `id`
test('it correctly validates entries that include a temporary `id`', () => {
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{ ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS },
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }]);
});
test('it removes entry items with "value" of "undefined"', () => {
const { entries, ...rest } = getExceptionListItemSchemaMock();
const mockEmptyException: EmptyEntry = {
field: 'host.name',
id: '123',
operator: OperatorEnum.INCLUDED,
type: OperatorTypeEnum.MATCH,
value: undefined,
};
const exceptions = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(exceptions).toEqual([getExceptionListItemSchemaMock()]);
});
test('it removes "match" entry items with "value" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EmptyEntry = {
field: 'host.name',
id: '123',
operator: OperatorEnum.INCLUDED,
type: OperatorTypeEnum.MATCH,
value: '',
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes "match" entry items with "field" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EmptyEntry = {
field: '',
id: '123',
operator: OperatorEnum.INCLUDED,
type: OperatorTypeEnum.MATCH,
value: 'some value',
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes "match_any" entry items with "field" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EmptyEntry = {
field: '',
id: '123',
operator: OperatorEnum.INCLUDED,
type: OperatorTypeEnum.MATCH_ANY,
value: ['some value'],
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes "nested" entry items with "field" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EntryNested = {
entries: [getEntryMatchMock()],
field: '',
type: OperatorTypeEnum.NESTED,
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes the "nested" entry entries with "value" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EntryNested = {
entries: [getEntryMatchMock(), { ...getEntryMatchMock(), value: '' }],
field: 'host.name',
type: OperatorTypeEnum.NESTED,
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([
{
...getExceptionListItemSchemaMock(),
entries: [
...getExceptionListItemSchemaMock().entries,
{ ...mockEmptyException, entries: [getEntryMatchMock()] },
],
},
]);
});
test('it removes the "nested" entry item if all its entries are invalid', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EntryNested = {
entries: [{ ...getEntryMatchMock(), value: '' }],
field: 'host.name',
type: OperatorTypeEnum.NESTED,
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes `temporaryId` from items', () => {
const { meta, ...rest } = getNewExceptionItem({
listId: '123',
namespaceType: 'single',
ruleName: 'rule name',
});
const exceptions = filterExceptionItems([{ ...rest, meta }]);
expect(exceptions).toEqual([{ ...rest, entries: [], meta: undefined }]);
});
});
describe('#getEntryValue', () => {
it('returns "match" entry value', () => {
const payload = getEntryMatchMock();
const result = getEntryValue(payload);
const expected = 'some host name';
expect(result).toEqual(expected);
});
it('returns "match any" entry values', () => {
const payload = getEntryMatchAnyMock();
const result = getEntryValue(payload);
const expected = ['some host name'];
expect(result).toEqual(expected);
});
it('returns "exists" entry value', () => {
const payload = getEntryExistsMock();
const result = getEntryValue(payload);
const expected = undefined;
expect(result).toEqual(expected);
});
it('returns "list" entry value', () => {
const payload = getEntryListMock();
const result = getEntryValue(payload);
const expected = 'some-list-id';
expect(result).toEqual(expected);
});
});
});

View file

@ -8,27 +8,29 @@
import uuid from 'uuid';
import { addIdToItem, removeIdFromItem } from '@kbn/securitysolution-utils';
import { validate } from '@kbn/securitysolution-io-ts-utils';
import { OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/public';
import {
CreateExceptionListItemSchema,
EntriesArray,
Entry,
EntryNested,
ExceptionListItemSchema,
ExceptionListType,
ListSchema,
NamespaceType,
OperatorEnum,
OperatorTypeEnum,
createExceptionListItemSchema,
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
OsTypeArray,
entriesList,
entriesNested,
entry,
exceptionListItemSchema,
nestedEntryItem,
} from '@kbn/securitysolution-io-ts-list-types';
import {
CreateExceptionListItemSchema,
ExceptionListItemSchema,
ListSchema,
createExceptionListItemSchema,
exceptionListItemSchema,
} from '../../../../common';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/public';
import {
EXCEPTION_OPERATORS,
EXCEPTION_OPERATORS_SANS_LISTS,
@ -96,7 +98,7 @@ export const filterExceptionItems = (
return [...acc, item];
} else if (createExceptionListItemSchema.is(item)) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { meta: _, ...rest } = item;
const { meta, ...rest } = item;
const itemSansMetaId: CreateExceptionListItemSchema = { ...rest, meta: undefined };
return [...acc, itemSansMetaId];
} else {

View file

@ -5,7 +5,9 @@
* 2.0.
*/
import { ExceptionListItemSchema, OperatorTypeEnum } from '../../../../common';
import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { ExceptionListItemSchema } from '../../../../common';
import { ExceptionsBuilderExceptionItem } from './types';
import { getDefaultEmptyEntry } from './helpers';

View file

@ -5,20 +5,20 @@
* 2.0.
*/
import { IFieldType } from '../../../../../../../src/plugins/data/common';
import { OperatorOption } from '../autocomplete/types';
import {
CreateExceptionListItemSchema,
import type {
Entry,
EntryExists,
EntryMatch,
EntryMatchAny,
EntryMatchWildcard,
EntryNested,
ExceptionListItemSchema,
OperatorEnum,
OperatorTypeEnum,
} from '../../../../common';
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import type { CreateExceptionListItemSchema, ExceptionListItemSchema } from '../../../../common';
import { IFieldType } from '../../../../../../../src/plugins/data/common';
import { OperatorOption } from '../autocomplete/types';
export interface FormattedBuilderEntry {
id: string;

View file

@ -7,11 +7,10 @@
import { flow } from 'fp-ts/lib/function';
import { addIdToItem, removeIdFromItem } from '@kbn/securitysolution-utils';
import type { EntriesArray, Entry } from '@kbn/securitysolution-io-ts-list-types';
import type {
CreateExceptionListItemSchema,
EntriesArray,
Entry,
ExceptionListItemSchema,
UpdateExceptionListItemSchema,
} from '../../common';

View file

@ -7,11 +7,8 @@
// Exports to be shared with plugins
export { withOptionalSignal } from './common/with_optional_signal';
export { useIsMounted } from './common/hooks/use_is_mounted';
export { useAsync } from './common/hooks/use_async';
export { useApi } from './exceptions/hooks/use_api';
export { usePersistExceptionItem } from './exceptions/hooks/persist_exception_item';
export { usePersistExceptionList } from './exceptions/hooks/persist_exception_list';
export { useExceptionListItems } from './exceptions/hooks/use_exception_list_items';
export { useExceptionLists } from './exceptions/hooks/use_exception_lists';
export { useFindLists } from './lists/hooks/use_find_lists';
@ -24,13 +21,18 @@ export { useReadListIndex } from './lists/hooks/use_read_list_index';
export { useCreateListIndex } from './lists/hooks/use_create_list_index';
export { useReadListPrivileges } from './lists/hooks/use_read_list_privileges';
export {
addExceptionListItem,
updateExceptionListItem,
getEntryValue,
getExceptionOperatorSelect,
getOperatorType,
getNewExceptionItem,
addIdToEntries,
} from './exceptions/components/builder/helpers';
export {
fetchExceptionListById,
addExceptionList,
addEndpointExceptionList,
} from './exceptions/api';
export {
export type {
ExceptionList,
ExceptionListFilter,
ExceptionListIdentifiers,

View file

@ -7,7 +7,7 @@
import * as t from 'io-ts';
import { exceptionListType, namespaceType } from '../../../shared_imports';
import { exceptionListType, namespaceType } from '@kbn/securitysolution-io-ts-list-types';
import { NonEmptyString } from './non_empty_string';

View file

@ -13,7 +13,8 @@ import {
normalizeMachineLearningJobIds,
normalizeThresholdField,
} from './utils';
import { EntriesArray } from '../shared_imports';
import type { EntriesArray } from '@kbn/securitysolution-io-ts-list-types';
describe('#hasLargeValueList', () => {
test('it returns false if empty array', () => {

View file

@ -7,11 +7,10 @@
import { isEmpty } from 'lodash';
import {
CreateExceptionListItemSchema,
EntriesArray,
ExceptionListItemSchema,
} from '../shared_imports';
import type { EntriesArray } from '@kbn/securitysolution-io-ts-list-types';
import { CreateExceptionListItemSchema, ExceptionListItemSchema } from '../shared_imports';
import { Type, JobStatus, Threshold, ThresholdNormalized } from './schemas/common/schemas';
export const hasLargeValueItem = (

View file

@ -7,44 +7,14 @@
export {
ListSchema,
CommentsArray,
CreateCommentsArray,
Comment,
CreateComment,
ExceptionListSchema,
ExceptionListItemSchema,
CreateExceptionListSchema,
CreateExceptionListItemSchema,
UpdateExceptionListItemSchema,
Entry,
EntryExists,
EntryMatch,
EntryMatchAny,
EntryMatchWildcard,
EntryNested,
EntryList,
EntriesArray,
NamespaceType,
Operator,
OperatorEnum,
OperatorTypeEnum,
ExceptionListTypeEnum,
exceptionListItemSchema,
exceptionListType,
comment,
createExceptionListItemSchema,
listSchema,
entry,
entriesNested,
nestedEntryItem,
entriesMatch,
entriesMatchAny,
entriesMatchWildcard,
entriesExists,
entriesList,
namespaceType,
ExceptionListType,
Type,
ENDPOINT_LIST_ID,
ENDPOINT_TRUSTED_APPS_LIST_ID,
EXCEPTION_LIST_URL,
@ -52,8 +22,5 @@ export {
ENDPOINT_EVENT_FILTERS_LIST_ID,
ENDPOINT_EVENT_FILTERS_LIST_NAME,
ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION,
osType,
osTypeArray,
OsTypeArray,
buildExceptionFilter,
} from '../../lists/common';

View file

@ -15,10 +15,11 @@ import {
} from '@elastic/eui';
import { uniq } from 'lodash';
import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { useFieldValueAutocomplete } from './hooks/use_field_value_autocomplete';
import { paramIsValid, getGenericComboBoxProps } from './helpers';
import { OperatorTypeEnum } from '../../../lists_plugin_deps';
import { GetGenericComboBoxPropsReturn } from './types';
import * as i18n from './translations';

View file

@ -9,11 +9,12 @@ import React, { useState, useCallback, useMemo } from 'react';
import { EuiFormRow, EuiComboBoxOptionOption, EuiComboBox } from '@elastic/eui';
import { uniq } from 'lodash';
import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { IFieldType, IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { useFieldValueAutocomplete } from './hooks/use_field_value_autocomplete';
import { getGenericComboBoxProps, paramIsValid } from './helpers';
import { OperatorTypeEnum } from '../../../lists_plugin_deps';
import { GetGenericComboBoxPropsReturn } from './types';
import * as i18n from './translations';
interface AutocompleteFieldMatchAnyProps {

View file

@ -8,6 +8,8 @@
import dateMath from '@elastic/datemath';
import { EuiComboBoxOptionOption } from '@elastic/eui';
import type { Type } from '@kbn/securitysolution-io-ts-list-types';
import type { ListSchema } from '../../../lists_plugin_deps';
import { IFieldType } from '../../../../../../../src/plugins/data/common';
import {
@ -19,7 +21,6 @@ import {
} from './operators';
import { GetGenericComboBoxPropsReturn, OperatorOption } from './types';
import * as i18n from './translations';
import { ListSchema, Type } from '../../../lists_plugin_deps';
/**
* Returns the appropriate operators given a field type

View file

@ -15,7 +15,7 @@ import {
import { useKibana } from '../../../../common/lib/kibana';
import { stubIndexPatternWithFields } from '../../../../../../../../src/plugins/data/common/index_patterns/index_pattern.stub';
import { getField } from '../../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks';
import { OperatorTypeEnum } from '../../../../lists_plugin_deps';
import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
jest.mock('../../../../common/lib/kibana');

View file

@ -8,9 +8,9 @@
import { useEffect, useState, useRef } from 'react';
import { debounce } from 'lodash';
import { ListOperatorTypeEnum as OperatorTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { IFieldType, IIndexPattern } from '../../../../../../../../src/plugins/data/common';
import { useKibana } from '../../../../common/lib/kibana';
import { OperatorTypeEnum } from '../../../../lists_plugin_deps';
interface FuncArgs {
fieldSelected: IFieldType | undefined;

View file

@ -6,8 +6,11 @@
*/
import { i18n } from '@kbn/i18n';
import {
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import { OperatorOption } from './types';
import { OperatorEnum, OperatorTypeEnum } from '../../../lists_plugin_deps';
export const isOperator: OperatorOption = {
message: i18n.translate('xpack.securitySolution.exceptions.isOperatorLabel', {

View file

@ -7,7 +7,10 @@
import { EuiComboBoxOptionOption } from '@elastic/eui';
import { OperatorEnum, OperatorTypeEnum } from '../../../lists_plugin_deps';
import type {
ListOperatorEnum as OperatorEnum,
ListOperatorTypeEnum as OperatorTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
export interface GetGenericComboBoxPropsReturn {
comboOptions: EuiComboBoxOptionOption[];

View file

@ -17,7 +17,7 @@ import {
EuiCommentProps,
EuiText,
} from '@elastic/eui';
import { Comment } from '../../../shared_imports';
import type { Comment } from '@kbn/securitysolution-io-ts-list-types';
import * as i18n from './translations';
import { useCurrentUser } from '../../lib/kibana';
import { getFormattedComments } from './helpers';

View file

@ -49,7 +49,10 @@ jest.mock('../../../containers/source');
jest.mock('../../../../detections/containers/detection_engine/rules');
jest.mock('../use_add_exception');
jest.mock('../use_fetch_or_create_rule_exception_list');
jest.mock('../../../../shared_imports');
jest.mock('../../../../shared_imports', () => ({
...jest.requireActual('../../../../shared_imports'),
useAsync: jest.fn(),
}));
jest.mock('../../../../detections/containers/detection_engine/rules/use_rule_async');
describe('When the add exception modal is opened', () => {

View file

@ -25,6 +25,7 @@ import {
EuiComboBox,
EuiComboBoxOptionOption,
} from '@elastic/eui';
import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import {
hasEqlSequenceQuery,
isEqlRule,
@ -34,9 +35,9 @@ import { Status } from '../../../../../common/detection_engine/schemas/common/sc
import {
ExceptionListItemSchema,
CreateExceptionListItemSchema,
ExceptionListType,
ExceptionBuilder,
} from '../../../../../public/shared_imports';
import * as i18nCommon from '../../../translations';
import * as i18n from './translations';
import * as sharedI18n from '../translations';

View file

@ -22,6 +22,7 @@ import {
EuiCallOut,
} from '@elastic/eui';
import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import {
hasEqlSequenceQuery,
isEqlRule,
@ -33,9 +34,9 @@ import { useRuleAsync } from '../../../../detections/containers/detection_engine
import {
ExceptionListItemSchema,
CreateExceptionListItemSchema,
ExceptionListType,
ExceptionBuilder,
} from '../../../../../public/shared_imports';
import * as i18n from './translations';
import * as sharedI18n from '../translations';
import { useKibana } from '../../../lib/kibana';

View file

@ -10,13 +10,8 @@ import { mount } from 'enzyme';
import moment from 'moment-timezone';
import {
getOperatorType,
getExceptionOperatorSelect,
getFormattedComments,
filterExceptionItems,
getNewExceptionItem,
formatOperatingSystems,
getEntryValue,
formatExceptionItemForUpdate,
enrichNewExceptionItemsWithComments,
enrichExistingExceptionItemWithComments,
@ -32,35 +27,19 @@ import {
retrieveAlertOsTypes,
filterIndexPatterns,
} from './helpers';
import { AlertData, EmptyEntry } from './types';
import { AlertData } from './types';
import {
isOperator,
isNotOperator,
isOneOfOperator,
isNotOneOfOperator,
isInListOperator,
isNotInListOperator,
existsOperator,
doesNotExistOperator,
} from '../autocomplete/operators';
import { OperatorTypeEnum, OperatorEnum, EntryNested } from '../../../shared_imports';
ListOperatorTypeEnum as OperatorTypeEnum,
EntriesArray,
OsTypeArray,
} from '@kbn/securitysolution-io-ts-list-types';
import { getExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_item_schema.mock';
import { getEntryMatchMock } from '../../../../../lists/common/schemas/types/entry_match.mock';
import { getEntryMatchAnyMock } from '../../../../../lists/common/schemas/types/entry_match_any.mock';
import { getEntryExistsMock } from '../../../../../lists/common/schemas/types/entry_exists.mock';
import { getEntryListMock } from '../../../../../lists/common/schemas/types/entry_list.mock';
import { getCommentsArrayMock } from '../../../../../lists/common/schemas/types/comment.mock';
import { fields } from '../../../../../../../src/plugins/data/common/index_patterns/fields/fields.mocks';
import {
ENTRIES,
ENTRIES_WITH_IDS,
OLD_DATE_RELATIVE_TO_DATE_NOW,
} from '../../../../../lists/common/constants.mock';
import { EntriesArray, OsTypeArray } from '@kbn/securitysolution-io-ts-list-types';
import {
CreateExceptionListItemSchema,
ExceptionListItemSchema,
} from '../../../../../lists/common/schemas';
import { ENTRIES, OLD_DATE_RELATIVE_TO_DATE_NOW } from '../../../../../lists/common/constants.mock';
import { ExceptionListItemSchema } from '../../../../../lists/common/schemas';
import { IFieldType, IIndexPattern } from 'src/plugins/data/common';
jest.mock('uuid', () => ({
@ -162,128 +141,6 @@ describe('Exception helpers', () => {
});
});
describe('#getOperatorType', () => {
test('returns operator type "match" if entry.type is "match"', () => {
const payload = getEntryMatchMock();
const operatorType = getOperatorType(payload);
expect(operatorType).toEqual(OperatorTypeEnum.MATCH);
});
test('returns operator type "match_any" if entry.type is "match_any"', () => {
const payload = getEntryMatchAnyMock();
const operatorType = getOperatorType(payload);
expect(operatorType).toEqual(OperatorTypeEnum.MATCH_ANY);
});
test('returns operator type "list" if entry.type is "list"', () => {
const payload = getEntryListMock();
const operatorType = getOperatorType(payload);
expect(operatorType).toEqual(OperatorTypeEnum.LIST);
});
test('returns operator type "exists" if entry.type is "exists"', () => {
const payload = getEntryExistsMock();
const operatorType = getOperatorType(payload);
expect(operatorType).toEqual(OperatorTypeEnum.EXISTS);
});
});
describe('#getExceptionOperatorSelect', () => {
test('it returns "isOperator" when "operator" is "included" and operator type is "match"', () => {
const payload = getEntryMatchMock();
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isOperator);
});
test('it returns "isNotOperator" when "operator" is "excluded" and operator type is "match"', () => {
const payload = getEntryMatchMock();
payload.operator = 'excluded';
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isNotOperator);
});
test('it returns "isOneOfOperator" when "operator" is "included" and operator type is "match_any"', () => {
const payload = getEntryMatchAnyMock();
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isOneOfOperator);
});
test('it returns "isNotOneOfOperator" when "operator" is "excluded" and operator type is "match_any"', () => {
const payload = getEntryMatchAnyMock();
payload.operator = 'excluded';
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isNotOneOfOperator);
});
test('it returns "existsOperator" when "operator" is "included" and no operator type is provided', () => {
const payload = getEntryExistsMock();
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(existsOperator);
});
test('it returns "doesNotExistsOperator" when "operator" is "excluded" and no operator type is provided', () => {
const payload = getEntryExistsMock();
payload.operator = 'excluded';
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(doesNotExistOperator);
});
test('it returns "isInList" when "operator" is "included" and operator type is "list"', () => {
const payload = getEntryListMock();
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isInListOperator);
});
test('it returns "isNotInList" when "operator" is "excluded" and operator type is "list"', () => {
const payload = getEntryListMock();
payload.operator = 'excluded';
const result = getExceptionOperatorSelect(payload);
expect(result).toEqual(isNotInListOperator);
});
});
describe('#getEntryValue', () => {
it('returns "match" entry value', () => {
const payload = getEntryMatchMock();
const result = getEntryValue(payload);
const expected = 'some host name';
expect(result).toEqual(expected);
});
it('returns "match any" entry values', () => {
const payload = getEntryMatchAnyMock();
const result = getEntryValue(payload);
const expected = ['some host name'];
expect(result).toEqual(expected);
});
it('returns "exists" entry value', () => {
const payload = getEntryExistsMock();
const result = getEntryValue(payload);
const expected = undefined;
expect(result).toEqual(expected);
});
it('returns "list" entry value', () => {
const payload = getEntryListMock();
const result = getEntryValue(payload);
const expected = 'some-list-id';
expect(result).toEqual(expected);
});
});
describe('#formatOperatingSystems', () => {
test('it returns null if no operating system tag specified', () => {
const result = formatOperatingSystems(['some os', 'some other os']);
@ -324,178 +181,6 @@ describe('Exception helpers', () => {
});
});
describe('#filterExceptionItems', () => {
// Please see `x-pack/plugins/lists/public/exceptions/transforms.ts` doc notes
// for context around the temporary `id`
test('it correctly validates entries that include a temporary `id`', () => {
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{ ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS },
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock(), entries: ENTRIES_WITH_IDS }]);
});
test('it removes entry items with "value" of "undefined"', () => {
const { entries, ...rest } = getExceptionListItemSchemaMock();
const mockEmptyException: EmptyEntry = {
id: '123',
field: 'host.name',
type: OperatorTypeEnum.MATCH,
operator: OperatorEnum.INCLUDED,
value: undefined,
};
const exceptions = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(exceptions).toEqual([getExceptionListItemSchemaMock()]);
});
test('it removes "match" entry items with "value" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EmptyEntry = {
id: '123',
field: 'host.name',
type: OperatorTypeEnum.MATCH,
operator: OperatorEnum.INCLUDED,
value: '',
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes "match" entry items with "field" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EmptyEntry = {
id: '123',
field: '',
type: OperatorTypeEnum.MATCH,
operator: OperatorEnum.INCLUDED,
value: 'some value',
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes "match_any" entry items with "field" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EmptyEntry = {
id: '123',
field: '',
type: OperatorTypeEnum.MATCH_ANY,
operator: OperatorEnum.INCLUDED,
value: ['some value'],
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes "nested" entry items with "field" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EntryNested = {
field: '',
type: OperatorTypeEnum.NESTED,
entries: [getEntryMatchMock()],
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes the "nested" entry entries with "value" of empty string', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EntryNested = {
field: 'host.name',
type: OperatorTypeEnum.NESTED,
entries: [getEntryMatchMock(), { ...getEntryMatchMock(), value: '' }],
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([
{
...getExceptionListItemSchemaMock(),
entries: [
...getExceptionListItemSchemaMock().entries,
{ ...mockEmptyException, entries: [getEntryMatchMock()] },
],
},
]);
});
test('it removes the "nested" entry item if all its entries are invalid', () => {
const { entries, ...rest } = { ...getExceptionListItemSchemaMock() };
const mockEmptyException: EntryNested = {
field: 'host.name',
type: OperatorTypeEnum.NESTED,
entries: [{ ...getEntryMatchMock(), value: '' }],
};
const output: Array<
ExceptionListItemSchema | CreateExceptionListItemSchema
> = filterExceptionItems([
{
...rest,
entries: [...entries, mockEmptyException],
},
]);
expect(output).toEqual([{ ...getExceptionListItemSchemaMock() }]);
});
test('it removes `temporaryId` from items', () => {
const { meta, ...rest } = getNewExceptionItem({
listId: '123',
namespaceType: 'single',
ruleName: 'rule name',
});
const exceptions = filterExceptionItems([{ ...rest, meta }]);
expect(exceptions).toEqual([{ ...rest, entries: [], meta: undefined }]);
});
});
describe('#formatExceptionItemForUpdate', () => {
test('it should return correct update fields', () => {
const payload = getExceptionListItemSchemaMock();

View file

@ -9,46 +9,36 @@ import React from 'react';
import { EuiText, EuiCommentProps, EuiAvatar } from '@elastic/eui';
import { capitalize } from 'lodash';
import moment from 'moment';
import uuid from 'uuid';
import * as i18n from './translations';
import {
AlertData,
BuilderEntry,
CreateExceptionListItemBuilderSchema,
ExceptionsBuilderExceptionItem,
Flattened,
} from './types';
import { EXCEPTION_OPERATORS, isOperator } from '../autocomplete/operators';
import { OperatorOption } from '../autocomplete/types';
import {
comment,
osType,
CommentsArray,
Comment,
CreateComment,
Entry,
ExceptionListItemSchema,
NamespaceType,
OperatorTypeEnum,
CreateExceptionListItemSchema,
comment,
entry,
entriesNested,
nestedEntryItem,
createExceptionListItemSchema,
exceptionListItemSchema,
UpdateExceptionListItemSchema,
EntryNested,
OsTypeArray,
EntriesArray,
osType,
ExceptionListType,
ListOperatorTypeEnum as OperatorTypeEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import * as i18n from './translations';
import { AlertData, ExceptionsBuilderExceptionItem, Flattened } from './types';
import {
ExceptionListItemSchema,
CreateExceptionListItemSchema,
UpdateExceptionListItemSchema,
getOperatorType,
getNewExceptionItem,
addIdToEntries,
} from '../../../shared_imports';
import { IIndexPattern } from '../../../../../../../src/plugins/data/common';
import { validate } from '../../../../common/validate';
import { Ecs } from '../../../../common/ecs';
import { CodeSignature } from '../../../../common/ecs/file';
import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard';
import { addIdToItem, removeIdFromItem } from '../../../../common';
import exceptionableLinuxFields from './exceptionable_linux_fields.json';
import exceptionableWindowsMacFields from './exceptionable_windows_mac_fields.json';
import exceptionableEndpointFields from './exceptionable_endpoint_fields.json';
@ -84,75 +74,6 @@ export const filterIndexPatterns = (
}
};
export const addIdToEntries = (entries: EntriesArray): EntriesArray => {
return entries.map((singleEntry) => {
if (singleEntry.type === 'nested') {
return addIdToItem({
...singleEntry,
entries: singleEntry.entries.map((nestedEntry) => addIdToItem(nestedEntry)),
});
} else {
return addIdToItem(singleEntry);
}
});
};
/**
* Returns the operator type, may not need this if using io-ts types
*
* @param item a single ExceptionItem entry
*/
export const getOperatorType = (item: BuilderEntry): OperatorTypeEnum => {
switch (item.type) {
case 'match':
return OperatorTypeEnum.MATCH;
case 'match_any':
return OperatorTypeEnum.MATCH_ANY;
case 'list':
return OperatorTypeEnum.LIST;
default:
return OperatorTypeEnum.EXISTS;
}
};
/**
* Determines operator selection (is/is not/is one of, etc.)
* Default operator is "is"
*
* @param item a single ExceptionItem entry
*/
export const getExceptionOperatorSelect = (item: BuilderEntry): OperatorOption => {
if (item.type === 'nested') {
return isOperator;
} else {
const operatorType = getOperatorType(item);
const foundOperator = EXCEPTION_OPERATORS.find((operatorOption) => {
return item.operator === operatorOption.operator && operatorType === operatorOption.type;
});
return foundOperator ?? isOperator;
}
};
/**
* Returns the fields corresponding value for an entry
*
* @param item a single ExceptionItem entry
*/
export const getEntryValue = (item: BuilderEntry): string | string[] | undefined => {
switch (item.type) {
case OperatorTypeEnum.MATCH:
case OperatorTypeEnum.MATCH_ANY:
return item.value;
case OperatorTypeEnum.EXISTS:
return undefined;
case OperatorTypeEnum.LIST:
return item.list.id;
default:
return undefined;
}
};
/**
* Formats os value array to a displayable string
*/
@ -189,91 +110,6 @@ export const getFormattedComments = (comments: CommentsArray): EuiCommentProps[]
),
}));
export const getNewExceptionItem = ({
listId,
namespaceType,
ruleName,
}: {
listId: string;
namespaceType: NamespaceType;
ruleName: string;
}): CreateExceptionListItemBuilderSchema => {
return {
comments: [],
description: `${ruleName} - exception list item`,
entries: addIdToEntries([
{
field: '',
operator: 'included',
type: 'match',
value: '',
},
]),
item_id: undefined,
list_id: listId,
meta: {
temporaryUuid: uuid.v4(),
},
name: `${ruleName} - exception list item`,
namespace_type: namespaceType,
tags: [],
type: 'simple',
};
};
export const filterExceptionItems = (
exceptions: ExceptionsBuilderExceptionItem[]
): Array<ExceptionListItemSchema | CreateExceptionListItemSchema> => {
return exceptions.reduce<Array<ExceptionListItemSchema | CreateExceptionListItemSchema>>(
(acc, exception) => {
const entries = exception.entries.reduce<BuilderEntry[]>((nestedAcc, singleEntry) => {
const strippedSingleEntry = removeIdFromItem(singleEntry);
if (entriesNested.is(strippedSingleEntry)) {
const nestedEntriesArray = strippedSingleEntry.entries.filter((singleNestedEntry) => {
const noIdSingleNestedEntry = removeIdFromItem(singleNestedEntry);
const [validatedNestedEntry] = validate(noIdSingleNestedEntry, nestedEntryItem);
return validatedNestedEntry != null;
});
const noIdNestedEntries = nestedEntriesArray.map((singleNestedEntry) =>
removeIdFromItem(singleNestedEntry)
);
const [validatedNestedEntry] = validate(
{ ...strippedSingleEntry, entries: noIdNestedEntries },
entriesNested
);
if (validatedNestedEntry != null) {
return [...nestedAcc, { ...singleEntry, entries: nestedEntriesArray }];
}
return nestedAcc;
} else {
const [validatedEntry] = validate(strippedSingleEntry, entry);
if (validatedEntry != null) {
return [...nestedAcc, singleEntry];
}
return nestedAcc;
}
}, []);
const item = { ...exception, entries };
if (exceptionListItemSchema.is(item)) {
return [...acc, item];
} else if (createExceptionListItemSchema.is(item)) {
const { meta, ...rest } = item;
const itemSansMetaId: CreateExceptionListItemSchema = { ...rest, meta: undefined };
return [...acc, itemSansMetaId];
} else {
return acc;
}
},
[]
);
};
export const formatExceptionItemForUpdate = (
exceptionItem: ExceptionListItemSchema
): UpdateExceptionListItemSchema => {

View file

@ -6,23 +6,22 @@
*/
import { ReactNode } from 'react';
import { Ecs } from '../../../../common/ecs';
import { CodeSignature } from '../../../../common/ecs/file';
import { IFieldType } from '../../../../../../../src/plugins/data/common';
import { OperatorOption } from '../autocomplete/types';
import {
import type {
EntryNested,
Entry,
EntryMatch,
EntryMatchAny,
EntryMatchWildcard,
EntryExists,
ExceptionListItemSchema,
CreateExceptionListItemSchema,
NamespaceType,
OperatorTypeEnum,
OperatorEnum,
} from '../../../lists_plugin_deps';
ListOperatorTypeEnum as OperatorTypeEnum,
ListOperatorEnum as OperatorEnum,
} from '@kbn/securitysolution-io-ts-list-types';
import { Ecs } from '../../../../common/ecs';
import { CodeSignature } from '../../../../common/ecs/file';
import { IFieldType } from '../../../../../../../src/plugins/data/common';
import { OperatorOption } from '../autocomplete/types';
import { ExceptionListItemSchema, CreateExceptionListItemSchema } from '../../../lists_plugin_deps';
export interface FormattedEntry {
fieldName: string;

View file

@ -27,6 +27,7 @@ import {
ReturnUseAddOrUpdateException,
AddOrUpdateExceptionItemsFunc,
} from './use_add_exception';
import { UpdateDocumentByQueryResponse } from 'elasticsearch';
const mockKibanaHttpService = coreMock.createStart().http;
const mockKibanaServices = KibanaServices.get as jest.Mock;
@ -36,11 +37,9 @@ const fetchMock = jest.fn();
mockKibanaServices.mockReturnValue({ http: { fetch: fetchMock } });
describe('useAddOrUpdateException', () => {
let updateAlertStatus: jest.SpyInstance<ReturnType<typeof alertsApi.updateAlertStatus>>;
let addExceptionListItem: jest.SpyInstance<ReturnType<typeof listsApi.addExceptionListItem>>;
let updateExceptionListItem: jest.SpyInstance<
ReturnType<typeof listsApi.updateExceptionListItem>
>;
let updateAlertStatus: jest.SpyInstance<Promise<UpdateDocumentByQueryResponse>>;
let addExceptionListItem: jest.SpyInstance<Promise<ExceptionListItemSchema>>;
let updateExceptionListItem: jest.SpyInstance<Promise<ExceptionListItemSchema>>;
let getQueryFilter: jest.SpyInstance<ReturnType<typeof getQueryFilterHelper.getQueryFilter>>;
let buildAlertStatusFilter: jest.SpyInstance<
ReturnType<typeof buildFilterHelpers.buildAlertStatusFilter>

View file

@ -12,7 +12,7 @@ import * as rulesApi from '../../../detections/containers/detection_engine/rules
import * as listsApi from '../../../../../lists/public/exceptions/api';
import { getExceptionListSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_schema.mock';
import { savedRuleMock } from '../../../detections/containers/detection_engine/rules/mock';
import { ExceptionListType } from '../../../lists_plugin_deps';
import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import { ListArray } from '../../../../common/detection_engine/schemas/types';
import { getListArrayMock } from '../../../../common/detection_engine/schemas/types/lists.mock';
import {
@ -20,6 +20,7 @@ import {
UseFetchOrCreateRuleExceptionListProps,
ReturnUseFetchOrCreateRuleExceptionList,
} from './use_fetch_or_create_rule_exception_list';
import { ExceptionListSchema } from '../../../shared_imports';
const mockKibanaHttpService = coreMock.createStart().http;
jest.mock('../../../detections/containers/detection_engine/rules/api');
@ -31,7 +32,7 @@ describe('useFetchOrCreateRuleExceptionList', () => {
let addEndpointExceptionList: jest.SpyInstance<
ReturnType<typeof listsApi.addEndpointExceptionList>
>;
let fetchExceptionListById: jest.SpyInstance<ReturnType<typeof listsApi.fetchExceptionListById>>;
let fetchExceptionListById: jest.SpyInstance<Promise<ExceptionListSchema>>;
let render: (
listType?: UseFetchOrCreateRuleExceptionListProps['exceptionListType']
) => RenderHookResult<

View file

@ -11,8 +11,8 @@ import React from 'react';
import { ThemeProvider } from 'styled-components';
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { ExceptionsViewerHeader } from './exceptions_viewer_header';
import { ExceptionListTypeEnum } from '../../../../../public/lists_plugin_deps';
addDecorator((storyFn) => (
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>{storyFn()}</ThemeProvider>

View file

@ -9,7 +9,8 @@ import React from 'react';
import { mount } from 'enzyme';
import { ExceptionsViewerHeader } from './exceptions_viewer_header';
import { ExceptionListTypeEnum } from '../../../../../public/lists_plugin_deps';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
describe('ExceptionsViewerHeader', () => {
it('it renders all disabled if "isInitLoading" is true', () => {

View file

@ -18,9 +18,9 @@ import {
} from '@elastic/eui';
import React, { useEffect, useState, useCallback, useMemo } from 'react';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import * as i18n from '../translations';
import { Filter } from '../types';
import { ExceptionListTypeEnum } from '../../../../../public/lists_plugin_deps';
interface ExceptionsViewerHeaderProps {
isInitLoading: boolean;

View file

@ -7,8 +7,14 @@
import moment from 'moment';
import { entriesNested, ExceptionListItemSchema } from '../../../../lists_plugin_deps';
import { getEntryValue, getExceptionOperatorSelect, formatOperatingSystems } from '../helpers';
import { entriesNested } from '@kbn/securitysolution-io-ts-list-types';
import {
ExceptionListItemSchema,
getEntryValue,
getExceptionOperatorSelect,
} from '../../../../lists_plugin_deps';
import { formatOperatingSystems } from '../helpers';
import { FormattedEntry, BuilderEntry, DescriptionListItem } from '../types';
import * as i18n from '../translations';

View file

@ -11,11 +11,9 @@ import { ThemeProvider } from 'styled-components';
import { ExceptionsViewer } from './';
import { useKibana } from '../../../../common/lib/kibana';
import {
ExceptionListTypeEnum,
useExceptionListItems,
useApi,
} from '../../../../../public/lists_plugin_deps';
import { useExceptionListItems, useApi } from '../../../../../public/lists_plugin_deps';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { getExceptionListSchemaMock } from '../../../../../../lists/common/schemas/response/exception_list_schema.mock';
import { getFoundExceptionListItemSchemaMock } from '../../../../../../lists/common/schemas/response/found_exception_list_item_schema.mock';
import { getMockTheme } from '../../../lib/kibana/kibana_react.mock';

View file

@ -9,6 +9,7 @@ import React, { useCallback, useEffect, useReducer } from 'react';
import { EuiSpacer } from '@elastic/eui';
import uuid from 'uuid';
import type { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import * as i18n from '../translations';
import { useStateToaster } from '../../toasters';
import { useKibana } from '../../../../common/lib/kibana';
@ -20,11 +21,11 @@ import { allExceptionItemsReducer, State, ViewerModalName } from './reducer';
import {
useExceptionListItems,
ExceptionListIdentifiers,
ExceptionListTypeEnum,
ExceptionListItemSchema,
UseExceptionListItemsSuccess,
useApi,
} from '../../../../../public/lists_plugin_deps';
import { ExceptionsViewerPagination } from './exceptions_pagination';
import { ExceptionsViewerUtility } from './exceptions_utility';
import { ExceptionsViewerItems } from './exceptions_viewer_items';

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import {
FilterOptions,
ExceptionsPagination,
@ -12,7 +13,6 @@ import {
Filter,
} from '../types';
import {
ExceptionListType,
ExceptionListItemSchema,
ExceptionListIdentifiers,
Pagination,

View file

@ -19,6 +19,7 @@ import styled from 'styled-components';
import { getOr } from 'lodash/fp';
import { indexOf } from 'lodash';
import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types';
import { buildGetAlertByIdQuery } from '../../../../common/components/exceptions/helpers';
import { useAppToasts } from '../../../../common/hooks/use_app_toasts';
import { TimelineId } from '../../../../../common/types/timeline';
@ -44,7 +45,6 @@ import {
} from '../../../../common/components/toasters';
import { inputsModel } from '../../../../common/store';
import { useUserData } from '../../user_info';
import { ExceptionListType } from '../../../../../common/shared_imports';
import { AlertData, EcsHit } from '../../../../common/components/exceptions/types';
import { useQueryAlerts } from '../../../containers/detection_engine/alerts/use_query';
import { useSignalIndex } from '../../../containers/detection_engine/alerts/use_signal_index';

View file

@ -18,7 +18,9 @@ import {
EuiSelectOption,
} from '@elastic/eui';
import { useImportList, ListSchema, Type } from '../../../shared_imports';
import type { Type } from '@kbn/securitysolution-io-ts-list-types';
import { useImportList, ListSchema } from '../../../shared_imports';
import * as i18n from './translations';
import { useKibana } from '../../../common/lib/kibana';

View file

@ -11,8 +11,8 @@ import React from 'react';
import { EuiButtonIcon, EuiBasicTableColumn, EuiToolTip } from '@elastic/eui';
import { History } from 'history';
import { NamespaceType } from '@kbn/securitysolution-io-ts-list-types';
import { Spacer } from '../../../../../../common/components/page';
import { NamespaceType } from '../../../../../../../../lists/common';
import { FormatUrl } from '../../../../../../common/components/link_to';
import { LinkAnchor } from '../../../../../../common/components/links';
import * as i18n from './translations';

View file

@ -15,9 +15,9 @@ import {
} from '@elastic/eui';
import { History } from 'history';
import { NamespaceType } from '@kbn/securitysolution-io-ts-list-types';
import { useAppToasts } from '../../../../../../common/hooks/use_app_toasts';
import { AutoDownload } from '../../../../../../common/components/auto_download/auto_download';
import { NamespaceType } from '../../../../../../../../lists/common';
import { useKibana } from '../../../../../../common/lib/kibana';
import { ExceptionListFilter, useApi, useExceptionLists } from '../../../../../../shared_imports';
import { FormatUrl } from '../../../../../../common/components/link_to';

View file

@ -9,11 +9,12 @@ import { has, isEmpty } from 'lodash/fp';
import moment from 'moment';
import deepmerge from 'deepmerge';
import type { ExceptionListType, NamespaceType } from '@kbn/securitysolution-io-ts-list-types';
import { NOTIFICATION_THROTTLE_NO_ACTIONS } from '../../../../../../common/constants';
import { assertUnreachable } from '../../../../../../common/utility_types';
import { transformAlertToRuleAction } from '../../../../../../common/detection_engine/transform_actions';
import { List } from '../../../../../../common/detection_engine/schemas/types';
import { ENDPOINT_LIST_ID, ExceptionListType, NamespaceType } from '../../../../../shared_imports';
import { ENDPOINT_LIST_ID } from '../../../../../shared_imports';
import { Rule } from '../../../../containers/detection_engine/rules';
import {
Threats,

View file

@ -28,6 +28,7 @@ import { useDispatch } from 'react-redux';
import styled from 'styled-components';
import deepEqual from 'fast-deep-equal';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import {
useDeepEqualSelector,
useShallowEqualSelector,
@ -83,7 +84,8 @@ import { ExceptionsViewer } from '../../../../../common/components/exceptions/vi
import { DEFAULT_INDEX_PATTERN } from '../../../../../../common/constants';
import { useGlobalFullScreen } from '../../../../../common/containers/use_full_screen';
import { Display } from '../../../../../hosts/pages/display';
import { ExceptionListTypeEnum, ExceptionListIdentifiers } from '../../../../../shared_imports';
import type { ExceptionListIdentifiers } from '../../../../../shared_imports';
import {
focusUtilityBarAction,
onTimelineTabKeyPressed,

View file

@ -5,9 +5,8 @@
* 2.0.
*/
import { ExceptionListType, ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import {
ExceptionListType,
ExceptionListTypeEnum,
EXCEPTION_LIST_URL,
EXCEPTION_LIST_ITEM_URL,
ENDPOINT_EVENT_FILTERS_LIST_ID,

View file

@ -33,23 +33,23 @@ export { ERROR_CODE } from '../../../../src/plugins/es_ui_shared/static/forms/he
export {
exportList,
useIsMounted,
useCursor,
useApi,
useAsync,
useExceptionListItems,
useExceptionLists,
usePersistExceptionItem,
usePersistExceptionList,
useFindLists,
useDeleteList,
useImportList,
useCreateListIndex,
useReadListIndex,
useReadListPrivileges,
addExceptionListItem,
updateExceptionListItem,
fetchExceptionListById,
addIdToEntries,
getOperatorType,
getNewExceptionItem,
getEntryValue,
getExceptionOperatorSelect,
addExceptionList,
ExceptionListFilter,
ExceptionListIdentifiers,

View file

@ -7,17 +7,19 @@
import uuid from 'uuid';
import { OsType } from '../../../../../lists/common/schemas';
import {
import type {
EntriesArray,
EntryMatch,
EntryMatchWildcard,
EntryNested,
ExceptionListItemSchema,
NestedEntriesArray,
} from '../../../../../lists/common';
} from '@kbn/securitysolution-io-ts-list-types';
import type { ExceptionListItemSchema } from '../../../../../lists/common';
import type { OsType } from '../../../../../lists/common/schemas';
import { ENDPOINT_TRUSTED_APPS_LIST_ID } from '../../../../../lists/common/constants';
import {
import type {
CreateExceptionListItemOptions,
UpdateExceptionListItemOptions,
} from '../../../../../lists/server';

View file

@ -11,7 +11,7 @@ import { mockLogger, sampleDocWithSortId } from '../__mocks__/es_results';
import { getExceptionListItemSchemaMock } from '../../../../../../lists/common/schemas/response/exception_list_item_schema.mock';
import { listMock } from '../../../../../../lists/server/mocks';
import { getSearchListItemResponseMock } from '../../../../../../lists/common/schemas/response/search_list_item_schema.mock';
import { EntryList } from '../../../../../../lists/common';
import { EntryList } from '@kbn/securitysolution-io-ts-list-types';
import { buildRuleMessageMock as buildRuleMessage } from '../rule_messages.mock';
describe('filterEventsAgainstList', () => {

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { EntryList, entriesList } from '../../../../../../lists/common';
import { EntryList, entriesList } from '@kbn/securitysolution-io-ts-list-types';
import { createSetToFilterAgainst } from './create_set_to_filter_against';
import { CreateFieldAndSetTuplesOptions, FieldSet } from './types';