-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SIEM][Lists] Adds 90% of the REST API and client API for exception l…
…ists and exception items (#66811) ## Summary See for more details: #65938 Adds pieces of the `exception list` and `exception list item` and refactors/cleans the code up where I had parts incorrect with little things such as the javascript library io-ts. Some unit tests were added but I am holding off until more of the operations solidify before adding the unit tests. Everything is still behind a feature flag that must be enabled and not advised still at this point to use so I feel ok pushing these parts forward. Adds to the API: - Create exception list - Read exception list - Update exception list - Delete exception list (and exception list items that are associated with it) - Create exception list item - Find exception list (/_find) - Read exception list item - Update exception list item - Delete exception list items individually - Find exception list item (/_find) What is still missing from the REST and client API? - Patch exception list - Patch exception list item - Bulk versions of everything - Import/Export options for these exception lists and list items ### Manual testing and REST API endpoints Go here: ```sh /projects/kibana/x-pack/plugins/lists/server/scripts ``` See the files: ```sh delete_all_exception_lists.sh delete_exception_list.sh delete_exception_list_by_id.sh delete_exception_list_item.sh delete_exception_list_item_by_id.sh exception_lists find_exception_list_items.sh find_exception_lists.sh get_exception_list.sh get_exception_list_by_id.sh get_exception_list_item.sh get_exception_list_item_by_id.sh post_exception_list.sh post_exception_list_item.sh update_exception_list.sh update_exception_list_item.sh ``` Ensure you first run: ```sh ./hard_reset ``` and ensure you have setup your kibana.dev.yml to have: ```yml # Enable lists feature xpack.lists.enabled: true xpack.lists.listIndex: '.lists-frank' xpack.lists.listItemIndex: '.items-frank' ``` Then you can use the above scripts to create, read, update, and delete exception list and exception list items as well as perform find commands against them all. ### Checklist Delete any items that are not applicable to this PR. - [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 Note: Some but limited unit tests at this point.
- Loading branch information
1 parent
140981f
commit 4e3b9e0
Showing
130 changed files
with
3,800 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
x-pack/plugins/lists/common/schemas/request/create_exception_list_item_schema.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
/* eslint-disable @typescript-eslint/camelcase */ | ||
|
||
import * as t from 'io-ts'; | ||
|
||
import { | ||
ItemId, | ||
Tags, | ||
_Tags, | ||
_tags, | ||
comment, | ||
description, | ||
exceptionListItemType, | ||
list_id, | ||
meta, | ||
name, | ||
tags, | ||
} from '../common/schemas'; | ||
import { Identity, RequiredKeepUndefined } from '../../types'; | ||
import { DefaultEntryArray, DefaultUuid } from '../types'; | ||
import { EntriesArray } from '../types/entries'; | ||
|
||
export const createExceptionListItemSchema = t.intersection([ | ||
t.exact( | ||
t.type({ | ||
description, | ||
list_id, | ||
name, | ||
type: exceptionListItemType, | ||
}) | ||
), | ||
t.exact( | ||
t.partial({ | ||
_tags, // defaults to empty array if not set during decode | ||
comment, // defaults to empty array if not set during decode | ||
entries: DefaultEntryArray, // defaults to empty array if not set during decode | ||
item_id: DefaultUuid, // defaults to GUID (uuid v4) if not set during decode | ||
meta, // defaults to undefined if not set during decode | ||
tags, // defaults to empty array if not set during decode | ||
}) | ||
), | ||
]); | ||
|
||
export type CreateExceptionListItemSchemaPartial = Identity< | ||
t.TypeOf<typeof createExceptionListItemSchema> | ||
>; | ||
export type CreateExceptionListItemSchema = RequiredKeepUndefined< | ||
t.TypeOf<typeof createExceptionListItemSchema> | ||
>; | ||
|
||
// This type is used after a decode since the arrays turn into defaults of empty arrays | ||
// and if a item_id is not specified it turns into a default GUID | ||
export type CreateExceptionListItemSchemaDecoded = Identity< | ||
Omit<CreateExceptionListItemSchema, '_tags' | 'tags' | 'item_id' | 'entries'> & { | ||
_tags: _Tags; | ||
tags: Tags; | ||
item_id: ItemId; | ||
entries: EntriesArray; | ||
} | ||
>; |
19 changes: 19 additions & 0 deletions
19
x-pack/plugins/lists/common/schemas/request/create_exception_list_schema.mock.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { DESCRIPTION, LIST_ID, META, NAME, TYPE } from '../../constants.mock'; | ||
|
||
import { CreateExceptionListSchema } from './create_exception_list_schema'; | ||
|
||
export const getCreateExceptionListSchemaMock = (): CreateExceptionListSchema => ({ | ||
_tags: [], | ||
description: DESCRIPTION, | ||
list_id: LIST_ID, | ||
meta: META, | ||
name: NAME, | ||
tags: [], | ||
type: TYPE, | ||
}); |
96 changes: 96 additions & 0 deletions
96
x-pack/plugins/lists/common/schemas/request/create_exception_list_schema.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { left } from 'fp-ts/lib/Either'; | ||
import { pipe } from 'fp-ts/lib/pipeable'; | ||
|
||
import { exactCheck, foldLeftRight, getPaths } from '../../siem_common_deps'; | ||
|
||
import { | ||
CreateExceptionListSchema, | ||
createExceptionListSchema, | ||
} from './create_exception_list_schema'; | ||
import { getCreateExceptionListSchemaMock } from './create_exception_list_schema.mock'; | ||
|
||
describe('create_exception_list_schema', () => { | ||
test('it should validate a typical exception lists request', () => { | ||
const payload = getCreateExceptionListSchemaMock(); | ||
const decoded = createExceptionListSchema.decode(payload); | ||
const checked = exactCheck(payload, decoded); | ||
const message = pipe(checked, foldLeftRight); | ||
|
||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(payload); | ||
}); | ||
|
||
test('it should accept an undefined for meta', () => { | ||
const payload = getCreateExceptionListSchemaMock(); | ||
delete payload.meta; | ||
const decoded = createExceptionListSchema.decode(payload); | ||
const checked = exactCheck(payload, decoded); | ||
const message = pipe(checked, foldLeftRight); | ||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(payload); | ||
}); | ||
|
||
test('it should accept an undefined for tags but return an array', () => { | ||
const inputPayload = getCreateExceptionListSchemaMock(); | ||
const outputPayload = getCreateExceptionListSchemaMock(); | ||
delete inputPayload.tags; | ||
outputPayload.tags = []; | ||
const decoded = createExceptionListSchema.decode(inputPayload); | ||
const checked = exactCheck(inputPayload, decoded); | ||
const message = pipe(checked, foldLeftRight); | ||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(outputPayload); | ||
}); | ||
|
||
test('it should accept an undefined for _tags but return an array', () => { | ||
const inputPayload = getCreateExceptionListSchemaMock(); | ||
const outputPayload = getCreateExceptionListSchemaMock(); | ||
delete inputPayload._tags; | ||
outputPayload._tags = []; | ||
const decoded = createExceptionListSchema.decode(inputPayload); | ||
const checked = exactCheck(inputPayload, decoded); | ||
const message = pipe(checked, foldLeftRight); | ||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect(message.schema).toEqual(outputPayload); | ||
}); | ||
|
||
test('it should accept an undefined for list_id and auto generate a uuid', () => { | ||
const inputPayload = getCreateExceptionListSchemaMock(); | ||
delete inputPayload.list_id; | ||
const decoded = createExceptionListSchema.decode(inputPayload); | ||
const checked = exactCheck(inputPayload, decoded); | ||
const message = pipe(checked, foldLeftRight); | ||
expect(getPaths(left(message.errors))).toEqual([]); | ||
expect((message.schema as CreateExceptionListSchema).list_id).toMatch( | ||
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i | ||
); | ||
}); | ||
|
||
test('it should accept an undefined for list_id and generate a correct body not counting the uuid', () => { | ||
const inputPayload = getCreateExceptionListSchemaMock(); | ||
delete inputPayload.list_id; | ||
const decoded = createExceptionListSchema.decode(inputPayload); | ||
const checked = exactCheck(inputPayload, decoded); | ||
const message = pipe(checked, foldLeftRight); | ||
delete (message.schema as CreateExceptionListSchema).list_id; | ||
expect(message.schema).toEqual(inputPayload); | ||
}); | ||
|
||
test('it should not allow an extra key to be sent in', () => { | ||
const payload: CreateExceptionListSchema & { | ||
extraKey?: string; | ||
} = getCreateExceptionListSchemaMock(); | ||
payload.extraKey = 'some new value'; | ||
const decoded = createExceptionListSchema.decode(payload); | ||
const checked = exactCheck(payload, decoded); | ||
const message = pipe(checked, foldLeftRight); | ||
expect(getPaths(left(message.errors))).toEqual(['invalid keys "extraKey"']); | ||
expect(message.schema).toEqual({}); | ||
}); | ||
}); |
55 changes: 55 additions & 0 deletions
55
x-pack/plugins/lists/common/schemas/request/create_exception_list_schema.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
/* eslint-disable @typescript-eslint/camelcase */ | ||
|
||
import * as t from 'io-ts'; | ||
|
||
import { | ||
ListId, | ||
Tags, | ||
_Tags, | ||
_tags, | ||
description, | ||
exceptionListType, | ||
meta, | ||
name, | ||
tags, | ||
} from '../common/schemas'; | ||
import { Identity, RequiredKeepUndefined } from '../../types'; | ||
import { DefaultUuid } from '../types/default_uuid'; | ||
|
||
export const createExceptionListSchema = t.intersection([ | ||
t.exact( | ||
t.type({ | ||
description, | ||
name, | ||
type: exceptionListType, | ||
}) | ||
), | ||
t.exact( | ||
t.partial({ | ||
_tags, // defaults to empty array if not set during decode | ||
list_id: DefaultUuid, // defaults to a GUID (UUID v4) string if not set during decode | ||
meta, // defaults to undefined if not set during decode | ||
tags, // defaults to empty array if not set during decode | ||
}) | ||
), | ||
]); | ||
|
||
export type CreateExceptionListSchemaPartial = Identity<t.TypeOf<typeof createExceptionListSchema>>; | ||
export type CreateExceptionListSchema = RequiredKeepUndefined< | ||
t.TypeOf<typeof createExceptionListSchema> | ||
>; | ||
|
||
// This type is used after a decode since the arrays turn into defaults of empty arrays. | ||
export type CreateExceptionListSchemaDecoded = Identity< | ||
CreateExceptionListSchema & { | ||
_tags: _Tags; | ||
tags: Tags; | ||
list_id: ListId; | ||
} | ||
>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
x-pack/plugins/lists/common/schemas/request/delete_exception_list_item_schema.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
/* eslint-disable @typescript-eslint/camelcase */ | ||
|
||
import * as t from 'io-ts'; | ||
|
||
import { id, item_id } from '../common/schemas'; | ||
|
||
export const deleteExceptionListItemSchema = t.exact( | ||
t.partial({ | ||
id, | ||
item_id, | ||
}) | ||
); | ||
|
||
export type DeleteExceptionListItemSchema = t.TypeOf<typeof deleteExceptionListItemSchema>; |
Oops, something went wrong.