Skip to content

Commit

Permalink
[Security Solution][Case] Fix alerts push (#91638) (#92705)
Browse files Browse the repository at this point in the history
Co-authored-by: Kibana Machine <[email protected]>

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
cnasikas and kibanamachine authored Feb 24, 2021
1 parent 14b9432 commit 3abe3a9
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 34 deletions.
15 changes: 15 additions & 0 deletions x-pack/plugins/case/server/client/cases/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ConnectorMappingsAttributes,
CaseUserActionsResponse,
AssociationType,
CommentResponseAlertsType,
} from '../../../common/api';

import { BasicParams } from './types';
Expand Down Expand Up @@ -76,6 +77,20 @@ export const commentAlert: CommentResponse = {
version: 'WzEsMV0=',
};

export const commentAlertMultipleIds: CommentResponseAlertsType = {
...commentAlert,
id: 'mock-comment-2',
alertId: ['alert-id-1', 'alert-id-2'],
index: 'alert-index-1',
type: CommentType.alert as const,
};

export const commentGeneratedAlert: CommentResponseAlertsType = {
...commentAlertMultipleIds,
id: 'mock-comment-3',
type: CommentType.generatedAlert as const,
};

export const defaultPipes = ['informationCreated'];
export const basicParams: BasicParams = {
description: 'a description',
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/case/server/client/cases/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export interface TransformFieldsArgs<P, S> {

export interface ExternalServiceComment {
comment: string;
commentId: string;
commentId?: string;
}

export interface MapIncident {
Expand Down
60 changes: 42 additions & 18 deletions x-pack/plugins/case/server/client/cases/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
basicParams,
userActions,
commentAlert,
commentAlertMultipleIds,
commentGeneratedAlert,
} from './mock';

import {
Expand Down Expand Up @@ -48,7 +50,7 @@ describe('utils', () => {
{
actionType: 'overwrite',
key: 'short_description',
pipes: ['informationCreated'],
pipes: [],
value: 'a title',
},
{
Expand All @@ -71,7 +73,7 @@ describe('utils', () => {
{
actionType: 'overwrite',
key: 'short_description',
pipes: ['myTestPipe'],
pipes: [],
value: 'a title',
},
{
Expand All @@ -98,7 +100,7 @@ describe('utils', () => {
});

expect(res).toEqual({
short_description: 'a title (created at 2020-03-13T08:34:53.450Z by Elastic User)',
short_description: 'a title',
description: 'a description (created at 2020-03-13T08:34:53.450Z by Elastic User)',
});
});
Expand All @@ -122,13 +124,13 @@ describe('utils', () => {
},
fields,
currentIncident: {
short_description: 'first title (created at 2020-03-13T08:34:53.450Z by Elastic User)',
short_description: 'first title',
description: 'first description (created at 2020-03-13T08:34:53.450Z by Elastic User)',
},
});

expect(res).toEqual({
short_description: 'a title (updated at 2020-03-15T08:34:53.450Z by Another User)',
short_description: 'a title',
description:
'first description (created at 2020-03-13T08:34:53.450Z by Elastic User) \r\na description (updated at 2020-03-15T08:34:53.450Z by Another User)',
});
Expand Down Expand Up @@ -168,7 +170,7 @@ describe('utils', () => {
});

expect(res).toEqual({
short_description: 'a title (created at 2020-03-13T08:34:53.450Z by elastic)',
short_description: 'a title',
description: 'a description (created at 2020-03-13T08:34:53.450Z by elastic)',
});
});
Expand All @@ -190,7 +192,7 @@ describe('utils', () => {
});

expect(res).toEqual({
short_description: 'a title (updated at 2020-03-15T08:34:53.450Z by anotherUser)',
short_description: 'a title',
description: 'a description (updated at 2020-03-15T08:34:53.450Z by anotherUser)',
});
});
Expand Down Expand Up @@ -448,8 +450,7 @@ describe('utils', () => {
labels: ['defacement'],
issueType: null,
parent: null,
short_description:
'Super Bad Security Issue (created at 2019-11-25T21:54:48.952Z by elastic)',
short_description: 'Super Bad Security Issue',
description:
'This is a brand new case of a bad meanie defacing data (created at 2019-11-25T21:54:48.952Z by elastic)',
externalId: null,
Expand Down Expand Up @@ -504,15 +505,17 @@ describe('utils', () => {
expect(res.comments).toEqual([]);
});

it('it creates comments of type alert correctly', async () => {
it('it adds the total alert comments correctly', async () => {
const res = await createIncident({
actionsClient: actionsMock,
theCase: {
...theCase,
comments: [
{ ...commentObj, id: 'comment-user-1' },
{ ...commentAlert, id: 'comment-alert-1' },
{ ...commentAlert, id: 'comment-alert-2' },
{
...commentAlertMultipleIds,
},
],
},
// Remove second push
Expand All @@ -536,14 +539,36 @@ describe('utils', () => {
commentId: 'comment-user-1',
},
{
comment:
'Alert with ids alert-id-1 added to case (added at 2019-11-25T21:55:00.177Z by elastic)',
commentId: 'comment-alert-1',
comment: 'Elastic Security Alerts attached to the case: 3',
},
]);
});

it('it removes alerts correctly', async () => {
const res = await createIncident({
actionsClient: actionsMock,
theCase: {
...theCase,
comments: [
{ ...commentObj, id: 'comment-user-1' },
commentAlertMultipleIds,
commentGeneratedAlert,
],
},
userActions,
connector,
mappings,
alerts: [],
});

expect(res.comments).toEqual([
{
comment:
'Alert with ids alert-id-1 added to case (added at 2019-11-25T21:55:00.177Z by elastic)',
commentId: 'comment-alert-2',
'Wow, good luck catching that bad meanie! (added at 2019-11-25T21:55:00.177Z by elastic)',
commentId: 'comment-user-1',
},
{
comment: 'Elastic Security Alerts attached to the case: 4',
},
]);
});
Expand Down Expand Up @@ -578,8 +603,7 @@ describe('utils', () => {
description:
'fun description \r\nThis is a brand new case of a bad meanie defacing data (updated at 2019-11-25T21:54:48.952Z by elastic)',
externalId: 'external-id',
short_description:
'Super Bad Security Issue (updated at 2019-11-25T21:54:48.952Z by elastic)',
short_description: 'Super Bad Security Issue',
},
comments: [],
});
Expand Down
52 changes: 39 additions & 13 deletions x-pack/plugins/case/server/client/cases/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ import {
} from './types';
import { getAlertIds } from '../../routes/api/utils';

interface CreateIncidentArgs {
actionsClient: ActionsClient;
theCase: CaseResponse;
userActions: CaseUserActionsResponse;
connector: ActionConnector;
mappings: ConnectorMappingsAttributes[];
alerts: CaseClientGetAlertsResponse;
}

export const getLatestPushInfo = (
connectorId: string,
userActions: CaseUserActionsResponse
Expand Down Expand Up @@ -75,14 +84,13 @@ const getCommentContent = (comment: CommentResponse): string => {
return '';
};

interface CreateIncidentArgs {
actionsClient: ActionsClient;
theCase: CaseResponse;
userActions: CaseUserActionsResponse;
connector: ActionConnector;
mappings: ConnectorMappingsAttributes[];
alerts: CaseClientGetAlertsResponse;
}
const countAlerts = (comments: CaseResponse['comments']): number =>
comments?.reduce<number>((total, comment) => {
if (comment.type === CommentType.alert || comment.type === CommentType.generatedAlert) {
return total + (Array.isArray(comment.alertId) ? comment.alertId.length : 1);
}
return total;
}, 0) ?? 0;

export const createIncident = async ({
actionsClient,
Expand Down Expand Up @@ -152,22 +160,34 @@ export const createIncident = async ({
userActions
.slice(latestPushInfo?.index ?? 0)
.filter(
(action, index) =>
Array.isArray(action.action_field) && action.action_field[0] === 'comment'
(action) => Array.isArray(action.action_field) && action.action_field[0] === 'comment'
)
.map((action) => action.comment_id)
);
const commentsToBeUpdated = caseComments?.filter((comment) =>
commentsIdsToBeUpdated.has(comment.id)

const commentsToBeUpdated = caseComments?.filter(
(comment) =>
// We push only user's comments
comment.type === CommentType.user && commentsIdsToBeUpdated.has(comment.id)
);

const totalAlerts = countAlerts(caseComments);

let comments: ExternalServiceComment[] = [];

if (commentsToBeUpdated && Array.isArray(commentsToBeUpdated) && commentsToBeUpdated.length > 0) {
const commentsMapping = mappings.find((m) => m.source === 'comments');
if (commentsMapping?.action_type !== 'nothing') {
comments = transformComments(commentsToBeUpdated, ['informationAdded']);
}
}

if (totalAlerts > 0) {
comments.push({
comment: `Elastic Security Alerts attached to the case: ${totalAlerts}`,
});
}

return { incident, comments };
};

Expand Down Expand Up @@ -247,7 +267,13 @@ export const prepareFieldsForTransformation = ({
key: mapping.target,
value: params[mapping.source] ?? '',
actionType: mapping.action_type,
pipes: mapping.action_type === 'append' ? [...defaultPipes, 'append'] : defaultPipes,
pipes:
// Do not transform titles
mapping.source !== 'title'
? mapping.action_type === 'append'
? [...defaultPipes, 'append']
: defaultPipes
: [],
},
]
: acc,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ describe('Push case', () => {
parent: null,
priority: 'High',
labels: ['LOLBins'],
summary: 'Another bad one (created at 2019-11-25T22:32:17.947Z by elastic)',
summary: 'Another bad one',
description:
'Oh no, a bad meanie going LOLBins all over the place! (created at 2019-11-25T22:32:17.947Z by elastic)',
externalId: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const PRIORITY = i18n.translate(
export const ALERT_FIELDS_LABEL = i18n.translate(
'xpack.securitySolution.components.connectors.serviceNow.alertFieldsTitle',
{
defaultMessage: 'Fields associated with alerts',
defaultMessage: 'Select Observables to push',
}
);

Expand Down

0 comments on commit 3abe3a9

Please sign in to comment.