Skip to content

Commit

Permalink
[SIEM][CASE] Tests for server's configuration API (#63099)
Browse files Browse the repository at this point in the history
* Test utils

* Test get_configure

* Test post_configure

* Test get_connectors

* Test patch_configure

* Improve test

* Fixes

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
cnasikas and elasticmachine authored Apr 14, 2020
1 parent d275d7f commit 287d477
Show file tree
Hide file tree
Showing 9 changed files with 1,213 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@ import {
SavedObjectsBulkUpdateObject,
} from 'src/core/server';

import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT } from '../../../saved_object_types';
import {
CASE_COMMENT_SAVED_OBJECT,
CASE_SAVED_OBJECT,
CASE_CONFIGURE_SAVED_OBJECT,
} from '../../../saved_object_types';

export const createMockSavedObjectsRepository = ({
caseSavedObject = [],
caseCommentSavedObject = [],
caseConfigureSavedObject = [],
}: {
caseSavedObject?: any[];
caseCommentSavedObject?: any[];
caseConfigureSavedObject?: any[];
}) => {
const mockSavedObjectsClientContract = ({
bulkGet: jest.fn((objects: SavedObjectsBulkGetObject[]) => {
Expand Down Expand Up @@ -70,6 +76,7 @@ export const createMockSavedObjectsRepository = ({
}
return result[0];
}

const result = caseSavedObject.filter(s => s.id === id);
if (!result.length) {
throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id);
Expand All @@ -81,6 +88,23 @@ export const createMockSavedObjectsRepository = ({
throw SavedObjectsErrorHelpers.createBadRequestError('Error thrown for testing');
}

if (
findArgs.type === CASE_CONFIGURE_SAVED_OBJECT &&
caseConfigureSavedObject[0] &&
caseConfigureSavedObject[0].id === 'throw-error-find'
) {
throw SavedObjectsErrorHelpers.createGenericNotFoundError('Error thrown for testing');
}

if (findArgs.type === CASE_CONFIGURE_SAVED_OBJECT) {
return {
page: 1,
per_page: 5,
total: caseConfigureSavedObject.length,
saved_objects: caseConfigureSavedObject,
};
}

if (findArgs.type === CASE_COMMENT_SAVED_OBJECT) {
return {
page: 1,
Expand All @@ -101,6 +125,13 @@ export const createMockSavedObjectsRepository = ({
throw SavedObjectsErrorHelpers.createBadRequestError('Error thrown for testing');
}

if (
type === CASE_CONFIGURE_SAVED_OBJECT &&
attributes.connector_id === 'throw-error-create'
) {
throw SavedObjectsErrorHelpers.createBadRequestError('Error thrown for testing');
}

if (type === CASE_COMMENT_SAVED_OBJECT) {
const newCommentObj = {
type,
Expand All @@ -113,6 +144,20 @@ export const createMockSavedObjectsRepository = ({
caseCommentSavedObject = [...caseCommentSavedObject, newCommentObj];
return newCommentObj;
}

if (type === CASE_CONFIGURE_SAVED_OBJECT) {
const newConfiguration = {
type,
id: 'mock-configuration',
attributes,
updated_at: '2020-04-09T09:43:51.778Z',
version: attributes.connector_id === 'no-version' ? undefined : 'WzksMV0=',
};

caseConfigureSavedObject = [newConfiguration];
return newConfiguration;
}

return {
type,
id: 'mock-it',
Expand Down Expand Up @@ -143,6 +188,16 @@ export const createMockSavedObjectsRepository = ({
}
}

if (type === CASE_CONFIGURE_SAVED_OBJECT) {
return {
id,
type,
updated_at: '2019-11-22T22:50:55.191Z',
attributes,
version: attributes.connector_id === 'no-version' ? undefined : 'WzE3LDFd',
};
}

return {
id,
type,
Expand All @@ -153,16 +208,29 @@ export const createMockSavedObjectsRepository = ({
}),
delete: jest.fn((type: string, id: string) => {
let result = caseSavedObject.filter(s => s.id === id);

if (type === CASE_COMMENT_SAVED_OBJECT) {
result = caseCommentSavedObject.filter(s => s.id === id);
}

if (type === CASE_CONFIGURE_SAVED_OBJECT) {
result = caseConfigureSavedObject.filter(s => s.id === id);
}

if (type === CASE_COMMENT_SAVED_OBJECT && id === 'bad-guy') {
throw SavedObjectsErrorHelpers.createBadRequestError('Error thrown for testing');
}

if (!result.length) {
throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id);
}

if (
type === CASE_CONFIGURE_SAVED_OBJECT &&
caseConfigureSavedObject[0].id === 'throw-error-delete'
) {
throw new Error('Error thrown for testing');
}
return {};
}),
deleteByNamespace: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
*/

import { SavedObject } from 'kibana/server';
import { CaseAttributes, CommentAttributes } from '../../../../common/api';
import {
CaseAttributes,
CommentAttributes,
CasesConfigureAttributes,
} from '../../../../common/api';

export const mockCases: Array<SavedObject<CaseAttributes>> = [
{
Expand Down Expand Up @@ -225,7 +229,33 @@ export const mockCaseComments: Array<SavedObject<CommentAttributes>> = [
},
],
updated_at: '2019-11-25T22:32:30.608Z',
version: 'WzYsMV0=',
},
];

export const mockCaseConfigure: Array<SavedObject<CasesConfigureAttributes>> = [
{
type: 'cases-configure',
id: 'mock-configuration-1',
attributes: {
connector_id: '123',
connector_name: 'My connector',
closure_type: 'close-by-user',
created_at: '2020-04-09T09:43:51.778Z',
created_by: {
full_name: 'elastic',
email: 'testemail@elastic.co',
username: 'elastic',
},
updated_at: '2020-04-09T09:43:51.778Z',
updated_by: {
full_name: 'elastic',
email: 'testemail@elastic.co',
username: 'elastic',
},
},
references: [],
updated_at: '2020-04-09T09:43:51.778Z',
version: 'WzYsMV0=',
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
*/

import { RequestHandlerContext } from 'src/core/server';
import { actionsClientMock } from '../../../../../actions/server/mocks';
import { getActions } from '../__mocks__/request_responses';

export const createRouteContext = (client: any) => {
const actionsMock = actionsClientMock.create();
actionsMock.getAll.mockImplementation(() => Promise.resolve(getActions()));

return ({
core: {
savedObjects: {
client,
},
},
actions: { getActionsClient: () => actionsMock },
} as unknown) as RequestHandlerContext;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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 { CasePostRequest, CasesConfigureRequest } from '../../../../common/api';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { FindActionResult } from '../../../../../actions/server/types';

export const newCase: CasePostRequest = {
title: 'My new case',
description: 'A description',
tags: ['new', 'case'],
};

export const getActions = (): FindActionResult[] => [
{
id: 'e90075a5-c386-41e3-ae21-ba4e61510695',
actionTypeId: '.webhook',
name: 'Test',
config: {
method: 'post',
url: 'https://example.com',
headers: null,
},
isPreconfigured: false,
referencedByCount: 0,
},
{
id: 'd611af27-3532-4da9-8034-271fee81d634',
actionTypeId: '.servicenow',
name: 'ServiceNow',
config: {
casesConfiguration: {
mapping: [
{
source: 'title',
target: 'short_description',
actionType: 'overwrite',
},
{
source: 'description',
target: 'description',
actionType: 'overwrite',
},
{
source: 'comments',
target: 'comments',
actionType: 'append',
},
],
},
apiUrl: 'https://dev102283.service-now.com',
},
isPreconfigured: false,
referencedByCount: 0,
},
];

export const newConfiguration: CasesConfigureRequest = {
connector_id: '456',
connector_name: 'My connector 2',
closure_type: 'close-by-pushing',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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 { kibanaResponseFactory, RequestHandler } from 'src/core/server';
import { httpServerMock } from 'src/core/server/mocks';

import {
createMockSavedObjectsRepository,
createRoute,
createRouteContext,
} from '../../__fixtures__';

import { mockCaseConfigure } from '../../__fixtures__/mock_saved_objects';
import { initGetCaseConfigure } from './get_configure';

describe('GET configuration', () => {
let routeHandler: RequestHandler<any, any, any>;
beforeAll(async () => {
routeHandler = await createRoute(initGetCaseConfigure, 'get');
});

it('returns the configuration', async () => {
const req = httpServerMock.createKibanaRequest({
path: '/api/cases/configure',
method: 'get',
});

const context = createRouteContext(
createMockSavedObjectsRepository({
caseConfigureSavedObject: mockCaseConfigure,
})
);

const res = await routeHandler(context, req, kibanaResponseFactory);
expect(res.status).toEqual(200);
expect(res.payload).toEqual({
...mockCaseConfigure[0].attributes,
version: mockCaseConfigure[0].version,
});
});

it('handles undefined version correctly', async () => {
const req = httpServerMock.createKibanaRequest({
path: '/api/cases/configure',
method: 'get',
});

const context = createRouteContext(
createMockSavedObjectsRepository({
caseConfigureSavedObject: [{ ...mockCaseConfigure[0], version: undefined }],
})
);

const res = await routeHandler(context, req, kibanaResponseFactory);
expect(res.status).toEqual(200);
expect(res.payload).toEqual({
connector_id: '123',
connector_name: 'My connector',
closure_type: 'close-by-user',
created_at: '2020-04-09T09:43:51.778Z',
created_by: {
full_name: 'elastic',
email: 'testemail@elastic.co',
username: 'elastic',
},
updated_at: '2020-04-09T09:43:51.778Z',
updated_by: {
full_name: 'elastic',
email: 'testemail@elastic.co',
username: 'elastic',
},
version: '',
});
});

it('returns an empty object when there is no configuration', async () => {
const req = httpServerMock.createKibanaRequest({
path: '/api/cases/configure',
method: 'get',
});

const context = createRouteContext(
createMockSavedObjectsRepository({
caseConfigureSavedObject: [],
})
);

const res = await routeHandler(context, req, kibanaResponseFactory);
expect(res.status).toEqual(200);
expect(res.payload).toEqual({});
});

it('returns an error if find throws an error', async () => {
const req = httpServerMock.createKibanaRequest({
path: '/api/cases/configure',
method: 'get',
});

const context = createRouteContext(
createMockSavedObjectsRepository({
caseConfigureSavedObject: [{ ...mockCaseConfigure[0], id: 'throw-error-find' }],
})
);

const res = await routeHandler(context, req, kibanaResponseFactory);
expect(res.status).toEqual(404);
expect(res.payload.isBoom).toEqual(true);
});
});
Loading

0 comments on commit 287d477

Please sign in to comment.