Skip to content

Commit 08fc722

Browse files
XavierMangoraycjonathan-buttnerkibanamachinecnasikas
authored
[Security Solution] Detection rules for case UI (#91434) (#91786)
* Adding type field to client * Removing context and adding association type * Handle alerts from multiple indices * Adding flow for adding a sub case * Making progress on creating alerts from rules * Refactored add comment to handle case and sub case * Starting sub case API and refactoring of case client * Fleshing out find cases * Finished the find cases api * Filtering comments by association type * Fixing tests and types * Updating snapshots * Cleaning up comment references * Working unit tests * Fixing integration tests and got ES to work * Unit tests and api integration test working * Refactoring find and get_status * Starting patch, and update * script for sub cases * Removing converted_by and fixing type errors * Adding docs for script * Removing converted_by and fixing integration test * init expanded rows * Adding sub case id to comment routes * Removing stringify comparison * styling * clean up * add status column * styling * hide actions if it has sub-cases * Adding delete api and tests * generated alert * Updating license * missed license files * Integration tests passing * Adding more tests for sub cases * wip * Find int tests, scoped client, patch sub user actions * fixing types and call cluster * fixing get sub case param issue * Adding user actions for sub cases * Preventing alerts on collections and refactoring user * Allowing type to be updated for ind cases * subcases attached to api * combine enum on UI for simplification * Refactoring and writing tests * Fixing sub case status filtering * add alerts count * Adding more tests not allowing gen alerts patch * Working unit tests * Push to connector gets all sub case comments * Writing more tests and cleaning up * Updating push functionality for generated alerts and sub cases * Adding comment about updating collection sync * use CaseType to check if it is a sub-case * fix types and disable selection if it has subcases * isEmpty * Detection rule correctly adding alerts to sub case * update api and functionality to accept sub case * integration part I * fix integration with case connector * Fix manual attach * Fix types * Fix bug when updating * Fix bug with user actions * Fix react key error * Fix bug when pushing a lot of alerts * fix lint error * Fix limit * fix title on sub case * fix unit tests * rm bazel * fix unit tests and cypress test * enable delete case icon * revert change * review * Fix the scripts alerts generation code * temp work * Fix rule types and add migration * fix types * fix types error * Remove query alerts * Fix rules * fix types * fix lint error * fix types * delete a sub case * rm unused i18n * fix delete cases * fix unit tests * fix unit test * update Case type * fix types * fix unit test * final integration between rule and case * fix integration test * fix unit test + bring back connector in action of rule Co-authored-by: Jonathan Buttner <jonathan.buttner@elastic.co> Co-authored-by: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Christos Nasikas <christos.nasikas@elastic.co> Co-authored-by: Angela Chuang <6295984+angorayc@users.noreply.github.com> Co-authored-by: Jonathan Buttner <jonathan.buttner@elastic.co> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Christos Nasikas <christos.nasikas@elastic.co>
1 parent e54e8f4 commit 08fc722

95 files changed

Lines changed: 1916 additions & 541 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

x-pack/plugins/case/common/api/cases/case.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ export const CaseResponseRt = rt.intersection([
123123
version: rt.string,
124124
}),
125125
rt.partial({
126+
subCaseIds: rt.array(rt.string),
126127
subCases: rt.array(SubCaseResponseRt),
127128
comments: rt.array(CommentResponseRt),
128129
}),

x-pack/plugins/case/common/api/cases/comment.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ export const ContextTypeUserRt = rt.type({
5252
export const AlertCommentRequestRt = rt.type({
5353
type: rt.union([rt.literal(CommentType.generatedAlert), rt.literal(CommentType.alert)]),
5454
alertId: rt.union([rt.array(rt.string), rt.string]),
55-
index: rt.string,
55+
index: rt.union([rt.array(rt.string), rt.string]),
56+
rule: rt.type({
57+
id: rt.union([rt.string, rt.null]),
58+
name: rt.union([rt.string, rt.null]),
59+
}),
5660
});
5761

5862
const AttributesTypeUserRt = rt.intersection([ContextTypeUserRt, CommentAttributesBasicRt]);
@@ -108,6 +112,7 @@ export const CommentsResponseRt = rt.type({
108112

109113
export const AllCommentsResponseRt = rt.array(CommentResponseRt);
110114

115+
export type AttributesTypeAlerts = rt.TypeOf<typeof AttributesTypeAlertsRt>;
111116
export type CommentAttributes = rt.TypeOf<typeof CommentAttributesRt>;
112117
export type CommentRequest = rt.TypeOf<typeof CommentRequestRt>;
113118
export type CommentResponse = rt.TypeOf<typeof CommentResponseRt>;

x-pack/plugins/case/common/api/cases/user_actions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const CaseUserActionResponseRT = rt.intersection([
4949
case_id: rt.string,
5050
comment_id: rt.union([rt.string, rt.null]),
5151
}),
52+
rt.partial({ sub_case_id: rt.string }),
5253
]);
5354

5455
export const CaseUserActionAttributesRt = CaseUserActionBasicRT;

x-pack/plugins/case/common/api/helpers.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
SUB_CASE_DETAILS_URL,
1414
SUB_CASES_URL,
1515
CASE_PUSH_URL,
16+
SUB_CASE_USER_ACTIONS_URL,
1617
} from '../constants';
1718

1819
export const getCaseDetailsUrl = (id: string): string => {
@@ -38,6 +39,11 @@ export const getCaseCommentDetailsUrl = (caseId: string, commentId: string): str
3839
export const getCaseUserActionUrl = (id: string): string => {
3940
return CASE_USER_ACTIONS_URL.replace('{case_id}', id);
4041
};
42+
43+
export const getSubCaseUserActionUrl = (caseID: string, subCaseID: string): string => {
44+
return SUB_CASE_USER_ACTIONS_URL.replace('{case_id}', caseID).replace('{sub_case_id}', subCaseID);
45+
};
46+
4147
export const getCasePushUrl = (caseId: string, connectorId: string): string => {
4248
return CASE_PUSH_URL.replace('{case_id}', caseId).replace('{connector_id}', connectorId);
4349
};

x-pack/plugins/case/common/constants.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* 2.0.
66
*/
77

8+
import { DEFAULT_MAX_SIGNALS } from '../../security_solution/common/constants';
9+
810
export const APP_ID = 'case';
911

1012
/**
@@ -19,6 +21,7 @@ export const CASE_CONFIGURE_CONNECTORS_URL = `${CASE_CONFIGURE_URL}/connectors`;
1921
export const SUB_CASES_PATCH_DEL_URL = `${CASES_URL}/sub_cases`;
2022
export const SUB_CASES_URL = `${CASE_DETAILS_URL}/sub_cases`;
2123
export const SUB_CASE_DETAILS_URL = `${CASE_DETAILS_URL}/sub_cases/{sub_case_id}`;
24+
export const SUB_CASE_USER_ACTIONS_URL = `${SUB_CASE_DETAILS_URL}/user_actions`;
2225

2326
export const CASE_COMMENTS_URL = `${CASE_DETAILS_URL}/comments`;
2427
export const CASE_COMMENT_DETAILS_URL = `${CASE_DETAILS_URL}/comments/{comment_id}`;
@@ -45,3 +48,10 @@ export const SUPPORTED_CONNECTORS = [
4548
JIRA_ACTION_TYPE_ID,
4649
RESILIENT_ACTION_TYPE_ID,
4750
];
51+
52+
/**
53+
* Alerts
54+
*/
55+
56+
export const MAX_ALERTS_PER_SUB_CASE = 5000;
57+
export const MAX_GENERATED_ALERTS_PER_SUB_CASE = MAX_ALERTS_PER_SUB_CASE / DEFAULT_MAX_SIGNALS;

x-pack/plugins/case/server/client/cases/create.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ describe('create', () => {
7676
"syncAlerts": true,
7777
},
7878
"status": "open",
79+
"subCaseIds": undefined,
7980
"subCases": undefined,
8081
"tags": Array [
8182
"defacement",
@@ -174,6 +175,7 @@ describe('create', () => {
174175
"syncAlerts": true,
175176
},
176177
"status": "open",
178+
"subCaseIds": undefined,
177179
"subCases": undefined,
178180
"tags": Array [
179181
"defacement",
@@ -239,6 +241,7 @@ describe('create', () => {
239241
"syncAlerts": true,
240242
},
241243
"status": "open",
244+
"subCaseIds": undefined,
242245
"subCases": undefined,
243246
"tags": Array [
244247
"defacement",

x-pack/plugins/case/server/client/cases/get.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,24 @@ export const get = async ({
2626
includeComments = false,
2727
includeSubCaseComments = false,
2828
}: GetParams): Promise<CaseResponse> => {
29-
const theCase = await caseService.getCase({
30-
client: savedObjectsClient,
31-
id,
32-
});
29+
const [theCase, subCasesForCaseId] = await Promise.all([
30+
caseService.getCase({
31+
client: savedObjectsClient,
32+
id,
33+
}),
34+
caseService.findSubCasesByCaseId({ client: savedObjectsClient, ids: [id] }),
35+
]);
36+
37+
const subCaseIds = subCasesForCaseId.saved_objects.map((so) => so.id);
3338

3439
if (!includeComments) {
3540
return CaseResponseRt.encode(
3641
flattenCaseSavedObject({
3742
savedObject: theCase,
43+
subCaseIds,
3844
})
3945
);
4046
}
41-
4247
const theComments = await caseService.getAllCaseComments({
4348
client: savedObjectsClient,
4449
id,
@@ -53,6 +58,7 @@ export const get = async ({
5358
flattenCaseSavedObject({
5459
savedObject: theCase,
5560
comments: theComments.saved_objects,
61+
subCaseIds,
5662
totalComment: theComments.total,
5763
totalAlerts: countAlertsForID({ comments: theComments, id }),
5864
})

x-pack/plugins/case/server/client/cases/mock.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ export const commentAlert: CommentResponse = {
5454
id: 'mock-comment-1',
5555
alertId: 'alert-id-1',
5656
index: 'alert-index-1',
57+
rule: {
58+
id: 'rule-id-1',
59+
name: 'rule-name-1',
60+
},
5761
type: CommentType.alert as const,
5862
created_at: '2019-11-25T21:55:00.177Z',
5963
created_by: {

x-pack/plugins/case/server/client/cases/update.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ describe('update', () => {
7171
"syncAlerts": true,
7272
},
7373
"status": "closed",
74+
"subCaseIds": undefined,
7475
"subCases": undefined,
7576
"tags": Array [
7677
"defacement",
@@ -166,6 +167,7 @@ describe('update', () => {
166167
"syncAlerts": true,
167168
},
168169
"status": "open",
170+
"subCaseIds": undefined,
169171
"subCases": undefined,
170172
"tags": Array [
171173
"defacement",
@@ -233,6 +235,7 @@ describe('update', () => {
233235
"syncAlerts": true,
234236
},
235237
"status": "in-progress",
238+
"subCaseIds": undefined,
236239
"subCases": undefined,
237240
"tags": Array [
238241
"LOLBins",
@@ -300,6 +303,7 @@ describe('update', () => {
300303
"syncAlerts": true,
301304
},
302305
"status": "closed",
306+
"subCaseIds": undefined,
303307
"subCases": undefined,
304308
"tags": Array [
305309
"defacement",
@@ -371,6 +375,7 @@ describe('update', () => {
371375
"syncAlerts": true,
372376
},
373377
"status": "open",
378+
"subCaseIds": undefined,
374379
"subCases": undefined,
375380
"tags": Array [
376381
"LOLBins",

x-pack/plugins/case/server/client/cases/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ export const getCommentContextFromAttributes = (
314314
type: attributes.type,
315315
alertId: attributes.alertId,
316316
index: attributes.index,
317+
rule: attributes.rule,
317318
};
318319
default:
319320
return {

0 commit comments

Comments
 (0)