Add endpoint exception creation API validation (#71791)

This commit is contained in:
Marshall Main 2020-07-14 22:25:10 -04:00 committed by GitHub
parent 73f5dec3db
commit c5e39a24cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 2692 additions and 0 deletions

View file

@ -16,6 +16,7 @@ import {
} from '../../common/schemas';
import { getExceptionListClient } from './utils/get_exception_list_client';
import { endpointDisallowedFields } from './endpoint_disallowed_fields';
export const createExceptionListItemRoute = (router: IRouter): void => {
router.post(
@ -70,6 +71,22 @@ export const createExceptionListItemRoute = (router: IRouter): void => {
statusCode: 409,
});
} else {
if (exceptionList.type === 'endpoint') {
for (const entry of entries) {
if (entry.type === 'list') {
return siemResponse.error({
body: `cannot add exception item with entry of type "list" to endpoint exception list`,
statusCode: 400,
});
}
if (endpointDisallowedFields.includes(entry.field)) {
return siemResponse.error({
body: `cannot add endpoint exception item on field ${entry.field}`,
statusCode: 400,
});
}
}
}
const createdList = await exceptionLists.createExceptionListItem({
_tags,
comments,

View file

@ -0,0 +1,13 @@
/*
* 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.
*/
export const endpointDisallowedFields = [
'file.Ext.quarantine_path',
'file.Ext.quarantine_result',
'process.entity_id',
'process.parent.entity_id',
'process.ancestry',
];

View file

@ -31,5 +31,6 @@ export default function ({ loadTestFile }) {
loadTestFile(require.resolve('./transform'));
loadTestFile(require.resolve('./endpoint'));
loadTestFile(require.resolve('./ingest_manager'));
loadTestFile(require.resolve('./lists'));
});
}

View file

@ -0,0 +1,72 @@
/*
* 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 expect from '@kbn/expect/expect.js';
import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
describe('Lists API', () => {
before(async () => await esArchiver.load('lists'));
after(async () => await esArchiver.unload('lists'));
it('should return a 400 if an endpoint exception item with a list-based entry is provided', async () => {
const badItem = {
namespace_type: 'agnostic',
description: 'bad endpoint item for testing',
name: 'bad endpoint item',
list_id: 'endpoint_list',
type: 'simple',
entries: [
{
type: 'list',
field: 'some.field',
operator: 'included',
list: {
id: 'somelist',
type: 'keyword',
},
},
],
};
const { body } = await supertest
.post(`/api/exception_lists/items`)
.set('kbn-xsrf', 'xxx')
.send(badItem)
.expect(400);
expect(body.message).to.eql(
'cannot add exception item with entry of type "list" to endpoint exception list'
);
});
it('should return a 400 if endpoint exception entry has disallowed field', async () => {
const fieldName = 'file.Ext.quarantine_path';
const badItem = {
namespace_type: 'agnostic',
description: 'bad endpoint item for testing',
name: 'bad endpoint item',
list_id: 'endpoint_list',
type: 'simple',
entries: [
{
type: 'match',
field: fieldName,
operator: 'included',
value: 'doesnt matter',
},
],
};
const { body } = await supertest
.post(`/api/exception_lists/items`)
.set('kbn-xsrf', 'xxx')
.send(badItem)
.expect(400);
expect(body.message).to.eql(`cannot add endpoint exception item on field ${fieldName}`);
});
});
}

View file

@ -0,0 +1,13 @@
/*
* 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 { FtrProviderContext } from '../../ftr_provider_context';
export default function listsAPIIntegrationTests({ loadTestFile }: FtrProviderContext) {
describe('Lists plugin', function () {
this.tags(['lists']);
loadTestFile(require.resolve('./create_exception_list_item'));
});
}

View file

@ -0,0 +1,85 @@
{
"type": "doc",
"value": {
"id": "exception-list-agnostic:1",
"index": ".kibana",
"source": {
"type": "exception-list-agnostic",
"exception-list-agnostic": {
"_tags": [
"endpoint",
"process",
"malware",
"os:linux"
],
"created_at": "2020-04-23T00:19:13.289Z",
"created_by": "user_name",
"description": "This is a sample endpoint type exception list",
"list_id": "endpoint_list",
"list_type": "list",
"name": "Sample Endpoint Exception List",
"tags": [
"user added string for a tag",
"malware"
],
"tie_breaker_id": "77fd1909-6786-428a-a671-30229a719c1f",
"type": "endpoint",
"updated_by": "user_name"
}
}
}
}
{
"type": "doc",
"value": {
"id": "exception-list-agnostic:2",
"index": ".kibana",
"source": {
"type": "exception-list-agnostic",
"exception-list-agnostic": {
"_tags": [
"endpoint",
"process",
"malware",
"os:linux"
],
"comments": [],
"created_at": "2020-04-23T00:19:13.289Z",
"created_by": "user_name",
"description": "This is a sample endpoint type exception",
"entries": [
{
"entries": [
{
"field": "nested.field",
"operator": "included",
"type": "match",
"value": "some value"
}
],
"field": "some.parentField",
"type": "nested"
},
{
"field": "some.not.nested.field",
"operator": "included",
"type": "match",
"value": "some value"
}
],
"item_id": "endpoint_list_item",
"list_id": "endpoint_list",
"list_type": "item",
"name": "Sample Endpoint Exception List",
"tags": [
"user added string for a tag",
"malware"
],
"tie_breaker_id": "77fd1909-6786-428a-a671-30229a719c1f",
"type": "simple",
"updated_by": "user_name"
}
}
}
}

File diff suppressed because it is too large Load diff