Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution][Cases] Fix bug with case connectors #80642

Merged
merged 2 commits into from
Oct 16, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,50 @@
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 (
XavierM marked this conversation as resolved.
Show resolved Hide resolved
![SERVICENOW_ACTION_TYPE_ID, JIRA_ACTION_TYPE_ID, RESILIENT_ACTION_TYPE_ID].includes(
action.actionTypeId
)
) {
return false;
}

if (action.config?.isCaseOwned === true) {
return true;
}

if (action.config?.incidentConfiguration?.mapping) {
return true;
}

return false;
};

/*
* Be aware that this api will only return 20 connectors
*/
Expand All @@ -34,18 +69,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