Skip to content

Commit

Permalink
[Security Solution][Cases] Fix bug with case connectors (#80642)
Browse files Browse the repository at this point in the history
* Fix bug with case connectors

* Improve isCaseOwned function
  • Loading branch information
cnasikas authored Oct 16, 2020
1 parent 9157a62 commit ca8b038
Show file tree
Hide file tree
Showing 5 changed files with 327 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,45 @@ export const getActions = (): FindActionResult[] => [
isPreconfigured: false,
referencedByCount: 0,
},
{
id: '456',
actionTypeId: '.jira',
name: 'Connector without isCaseOwned',
config: {
incidentConfiguration: {
mapping: [
{
source: 'title',
target: 'short_description',
actionType: 'overwrite',
},
{
source: 'description',
target: 'description',
actionType: 'overwrite',
},
{
source: 'comments',
target: 'comments',
actionType: 'append',
},
],
},
apiUrl: 'https://elastic.jira.com',
},
isPreconfigured: false,
referencedByCount: 0,
},
{
id: '789',
actionTypeId: '.resilient',
name: 'Connector without mapping',
config: {
apiUrl: 'https://elastic.resilient.com',
},
isPreconfigured: false,
referencedByCount: 0,
},
];

export const newConfiguration: CasesConfigureRequest = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {

import { mockCaseConfigure } from '../../__fixtures__/mock_saved_objects';
import { initCaseConfigureGetActionConnector } from './get_connectors';
import { getActions } from '../../__mocks__/request_responses';
import { CASE_CONFIGURE_CONNECTORS_URL } from '../../../../../common/constants';

describe('GET connectors', () => {
Expand All @@ -24,7 +23,7 @@ describe('GET connectors', () => {
routeHandler = await createRoute(initCaseConfigureGetActionConnector, 'get');
});

it('returns the connectors', async () => {
it('returns case owned connectors', async () => {
const req = httpServerMock.createKibanaRequest({
path: `${CASE_CONFIGURE_CONNECTORS_URL}/_find`,
method: 'get',
Expand All @@ -38,9 +37,67 @@ describe('GET connectors', () => {

const res = await routeHandler(context, req, kibanaResponseFactory);
expect(res.status).toEqual(200);
expect(res.payload).toEqual(
getActions().filter((action) => action.actionTypeId === '.servicenow')
);
expect(res.payload).toEqual([
{
id: '123',
actionTypeId: '.servicenow',
name: 'ServiceNow',
config: {
incidentConfiguration: {
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',
isCaseOwned: true,
},
isPreconfigured: false,
referencedByCount: 0,
},
{
id: '456',
actionTypeId: '.jira',
name: 'Connector without isCaseOwned',
config: {
incidentConfiguration: {
mapping: [
{
source: 'title',
target: 'short_description',
actionType: 'overwrite',
},
{
source: 'description',
target: 'description',
actionType: 'overwrite',
},
{
source: 'comments',
target: 'comments',
actionType: 'append',
},
],
},
apiUrl: 'https://elastic.jira.com',
},
isPreconfigured: false,
referencedByCount: 0,
},
]);
});

it('it throws an error when actions client is null', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,44 @@
import Boom from 'boom';
import { RouteDeps } from '../../types';
import { wrapError } from '../../utils';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { FindActionResult } from '../../../../../../actions/server/types';

import {
CASE_CONFIGURE_CONNECTORS_URL,
SUPPORTED_CONNECTORS,
SERVICENOW_ACTION_TYPE_ID,
JIRA_ACTION_TYPE_ID,
RESILIENT_ACTION_TYPE_ID,
} from '../../../../../common/constants';

/**
* We need to take into account connectors that have been created within cases and
* they do not have the isCaseOwned field. Checking for the existence of
* the mapping attribute ensures that the connector is indeed a case connector.
* Cases connector should always have a mapping.
*/

interface CaseAction extends FindActionResult {
config?: {
isCaseOwned?: boolean;
incidentConfiguration?: Record<string, unknown>;
};
}

const isCaseOwned = (action: CaseAction): boolean => {
if (
[SERVICENOW_ACTION_TYPE_ID, JIRA_ACTION_TYPE_ID, RESILIENT_ACTION_TYPE_ID].includes(
action.actionTypeId
)
) {
if (action.config?.isCaseOwned === true || action.config?.incidentConfiguration?.mapping) {
return true;
}
}

return false;
};

/*
* Be aware that this api will only return 20 connectors
*/
Expand All @@ -34,18 +63,7 @@ export function initCaseConfigureGetActionConnector({ caseService, router }: Rou
throw Boom.notFound('Action client have not been found');
}

const results = (await actionsClient.getAll()).filter(
(action) =>
SUPPORTED_CONNECTORS.includes(action.actionTypeId) &&
// Need this filtering temporary to display only Case owned ServiceNow connectors
(![SERVICENOW_ACTION_TYPE_ID, JIRA_ACTION_TYPE_ID, RESILIENT_ACTION_TYPE_ID].includes(
action.actionTypeId
) ||
([SERVICENOW_ACTION_TYPE_ID, JIRA_ACTION_TYPE_ID, RESILIENT_ACTION_TYPE_ID].includes(
action.actionTypeId
) &&
action.config?.isCaseOwned === true))
);
const results = (await actionsClient.getAll()).filter(isCaseOwned);
return response.ok({ body: results });
} catch (error) {
return response.customError(wrapError(error));
Expand Down
Loading

0 comments on commit ca8b038

Please sign in to comment.