Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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 @@ -29,6 +29,7 @@ export interface CaseConnector {

export interface CaseSettings {
syncAlerts: boolean;
extractObservables: boolean;
}

export interface CaseUserProfile {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const createCasePayload: CaseCreateRequest = {
},
settings: {
syncAlerts: true,
extractObservables: false,
},
owner: '',
customFields: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import type { CodeSignature, Ext } from '../file';
import type { CodeSignature, Ext, Hash } from '../file';
import type { ProcessPe } from '../process';

export interface DllEcs {
Ext?: Ext;
path?: string;
code_signature?: CodeSignature;
pe?: ProcessPe;
hash?: Hash;
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ export interface Hash {
md5?: string[];
sha1?: string[];
sha256: string[];
cdhash?: string[];
sha384?: string[];
sha512?: string[];
ssdeep?: string[];
tlsh?: string[];
}

export interface FileEcs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ export interface ProcessHashData {
md5?: string[];
sha1?: string[];
sha256?: string[];
sha384?: string[];
sha512?: string[];
ssdeep?: string[];
tlsh?: string[];
cdhash?: string[];
}

export interface ProcessParentData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,10 @@ describe('AlertsTable', () => {
children: expect.anything(),
owner: ['cases'],
permissions: { create: true, read: true },
features: { alerts: { sync: false } },
features: {
alerts: { sync: false },
observables: { enabled: true, autoExtract: false },
},
},
{}
);
Expand All @@ -612,7 +615,10 @@ describe('AlertsTable', () => {
children: expect.anything(),
owner: [],
permissions: { create: true, read: true },
features: { alerts: { sync: false } },
features: {
alerts: { sync: false },
observables: { enabled: true, autoExtract: false },
},
},
{}
);
Expand All @@ -631,7 +637,10 @@ describe('AlertsTable', () => {
children: expect.anything(),
owner: [],
permissions: { create: false, read: false },
features: { alerts: { sync: false } },
features: {
alerts: { sync: false },
observables: { enabled: true, autoExtract: false },
},
},
{}
);
Expand All @@ -656,7 +665,7 @@ describe('AlertsTable', () => {
children: expect.anything(),
owner: ['cases'],
permissions: { create: true, read: true },
features: { alerts: { sync: true } },
features: { alerts: { sync: true }, observables: { enabled: true, autoExtract: false } },
},
{}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,13 @@ const AlertsTableContent = typedForwardRef(
<CasesContext
owner={casesConfiguration?.owner ?? []}
permissions={casesPermissions}
features={{ alerts: { sync: casesConfiguration?.syncAlerts ?? false } }}
features={{
alerts: { sync: casesConfiguration?.syncAlerts ?? false },
observables: {
enabled: true,
autoExtract: casesConfiguration?.extractObservables ?? false,
},
}}
>
<AlertsDataGrid {...dataGridProps} />
</CasesContext>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import { EuiPopover, EuiButtonEmpty, EuiContextMenu } from '@elastic/eui';
import numeral from '@elastic/numeral';
import {
ALERT_CASE_IDS,
ALERT_RULE_NAME,
ALERT_RULE_UUID,
ALERT_WORKFLOW_ASSIGNEE_IDS,
ALERT_WORKFLOW_TAGS,
} from '@kbn/rule-data-utils';
Expand Down Expand Up @@ -44,19 +42,24 @@ const selectedIdsToTimelineItemMapper = (
): TimelineItem[] => {
return Array.from(rowSelection.keys()).map((rowIndex: number) => {
const alert = alerts[rowIndex];
const data = Object.entries(alert).map(([key, value]) => ({
field: key,
value: value ? (value as string[]) : [],
}));
if (!data.some((item) => item.field === ALERT_CASE_IDS)) {
data.push({ field: ALERT_CASE_IDS, value: [] });
}
if (!data.some((item) => item.field === ALERT_WORKFLOW_TAGS)) {
data.push({ field: ALERT_WORKFLOW_TAGS, value: [] });
}
if (!data.some((item) => item.field === ALERT_WORKFLOW_ASSIGNEE_IDS)) {
data.push({ field: ALERT_WORKFLOW_ASSIGNEE_IDS, value: [] });
}

return {
_id: alert._id,
_index: alert._index,
data: [
{ field: ALERT_RULE_NAME, value: alert[ALERT_RULE_NAME] as string[] },
{ field: ALERT_RULE_UUID, value: alert[ALERT_RULE_UUID] as string[] },
{ field: ALERT_CASE_IDS, value: (alert[ALERT_CASE_IDS] ?? []) as string[] },
{ field: ALERT_WORKFLOW_TAGS, value: (alert[ALERT_WORKFLOW_TAGS] ?? []) as string[] },
{
field: ALERT_WORKFLOW_ASSIGNEE_IDS,
value: (alert[ALERT_WORKFLOW_ASSIGNEE_IDS] ?? []) as string[],
},
],
data,
ecs: {
_id: alert._id,
_index: alert._index,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,11 @@ export const useBulkAddToCaseActions = ({
const caseAttachments = alerts
? casesService?.helpers.groupAlertsByRule(alerts) ?? []
: [];

const dataArray = alerts ? alerts.map((alert) => alert.data) : [];
const observables = casesService?.helpers.getObservablesFromEcs(dataArray);
createCaseFlyout.open({
attachments: caseAttachments,
observables,
});
},
},
Expand All @@ -179,6 +181,11 @@ export const useBulkAddToCaseActions = ({
groupAlertsByRule: casesService?.helpers.groupAlertsByRule,
});
},
getObservables: ({ theCase }) => {
if (!alerts || theCase == null) return [];
const dataArray = alerts.map((alert) => alert.data);
return casesService?.helpers.getObservablesFromEcs(dataArray) ?? [];
},
});
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const helpersMock: jest.MockedObject<CasesService['helpers']> = {
canUseCases: jest.fn(),
groupAlertsByRule: jest.fn(),
getRuleIdFromEvent: jest.fn(),
getObservablesFromEcs: jest.fn(),
};

export const createCasesServiceMock = (): jest.MaybeMockedDeep<CasesService> => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,22 @@ describe('AlertsDataGrid bulk actions', () => {
_id: 'alert0',
_index: 'idx0',
data: [
{
field: '_id',
value: 'alert0',
},
{
field: '_index',
value: 'idx0',
},
{
field: 'kibana.alert.rule.name',
value: ['one'],
},
{
field: 'kibana.alert.reason',
value: ['two'],
},
{
field: 'kibana.alert.rule.uuid',
value: ['uuidone'],
Expand Down Expand Up @@ -526,10 +538,16 @@ describe('AlertsDataGrid bulk actions', () => {
_id: 'alert1',
_index: 'idx1',
data: [
{ field: '_id', value: 'alert1' },
{ field: '_index', value: 'idx1' },
{
field: 'kibana.alert.rule.name',
value: ['three'],
},
{
field: 'kibana.alert.reason',
value: ['four'],
},
{
field: 'kibana.alert.rule.uuid',
value: ['uuidtwo'],
Expand Down Expand Up @@ -740,10 +758,22 @@ describe('AlertsDataGrid bulk actions', () => {
_id: 'alert0',
_index: 'idx0',
data: [
{
field: '_id',
value: 'alert0',
},
{
field: '_index',
value: 'idx0',
},
{
field: 'kibana.alert.rule.name',
value: ['one'],
},
{
field: 'kibana.alert.reason',
value: ['two'],
},
{
field: 'kibana.alert.rule.uuid',
value: ['uuidone'],
Expand All @@ -770,10 +800,16 @@ describe('AlertsDataGrid bulk actions', () => {
_id: 'alert1',
_index: 'idx1',
data: [
{ field: '_id', value: 'alert1' },
{ field: '_index', value: 'idx1' },
{
field: 'kibana.alert.rule.name',
value: ['three'],
},
{
field: 'kibana.alert.reason',
value: ['four'],
},
{
field: 'kibana.alert.rule.uuid',
value: ['uuidtwo'],
Expand Down
12 changes: 11 additions & 1 deletion src/platform/packages/shared/response-ops/alerts-table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ export interface Consumer {
name: string;
}

interface Observable {
typeKey: string;
value: string;
description: string | null;
}

export type AlertsTableSupportedConsumers = Exclude<AlertConsumers, 'alerts' | 'streams'>;

export type CellComponent = NonNullable<AlertsTableProps['renderCellValue']>;
Expand All @@ -78,7 +84,7 @@ export interface SystemCellComponentMap {
export type SystemCellId = keyof SystemCellComponentMap;

type UseCasesAddToNewCaseFlyout = (props?: Record<string, unknown> & { onSuccess: () => void }) => {
open: ({ attachments }: { attachments: any[] }) => void;
open: ({ attachments, observables }: { attachments: any[]; observables?: any[] }) => void;
close: () => void;
};

Expand All @@ -87,8 +93,10 @@ type UseCasesAddToExistingCaseModal = (
) => {
open: ({
getAttachments,
getObservables,
}: {
getAttachments: ({ theCase }: { theCase?: { id: string } }) => any[];
getObservables?: ({ theCase }: { theCase?: { id: string } }) => any[];
}) => void;
close: () => void;
};
Expand Down Expand Up @@ -121,6 +129,7 @@ export interface CasesService {
groupAlertsByRule: (items: any[]) => any[];
canUseCases: (owners: Array<'securitySolution' | 'observability' | 'cases'>) => any;
getRuleIdFromEvent: (event: { data: any[]; ecs: Ecs }) => { id: string; name: string };
getObservablesFromEcs: (ecsArray: any[][]) => Observable[];
};
}

Expand Down Expand Up @@ -482,6 +491,7 @@ export interface PublicAlertsDataGridProps
owner: Parameters<CasesService['helpers']['canUseCases']>[0];
appId?: string;
syncAlerts?: boolean;
extractObservables?: boolean;
};
/**
* If true, hides the bulk actions controls
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13759,7 +13759,6 @@
"xpack.cases.caseView.observables.type": "Beobachtbarer Typ",
"xpack.cases.caseView.observables.updated": "Observable wurde aktualisiert",
"xpack.cases.caseView.observables.value": "Beobachtbarer Wert",
"xpack.cases.caseView.observables.valuePlaceholder": "Beobachtbarer Wert",
"xpack.cases.caseView.openCase": "Fall öffnen",
"xpack.cases.caseView.optional": "Optional",
"xpack.cases.caseView.otherEndpoints": "und {endpoints} {endpoints, plural, =1 {other} other {andere}}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13797,7 +13797,6 @@
"xpack.cases.caseView.observables.type": "Type d'observable",
"xpack.cases.caseView.observables.updated": "Observable mis à jour",
"xpack.cases.caseView.observables.value": "Valeur d'observable",
"xpack.cases.caseView.observables.valuePlaceholder": "Valeur d'observable",
"xpack.cases.caseView.openCase": "Ouvrir le cas",
"xpack.cases.caseView.optional": "Facultatif",
"xpack.cases.caseView.otherEndpoints": "et {endpoints} {endpoints, plural, =1 {other} other {autres}}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13815,7 +13815,6 @@
"xpack.cases.caseView.observables.type": "オブザーバブルタイプ",
"xpack.cases.caseView.observables.updated": "オブザーバブルが更新されました",
"xpack.cases.caseView.observables.value": "オブザーバブル値",
"xpack.cases.caseView.observables.valuePlaceholder": "オブザーバブル値",
"xpack.cases.caseView.openCase": "ケースを開く",
"xpack.cases.caseView.optional": "オプション",
"xpack.cases.caseView.otherEndpoints": "および{endpoints} {endpoints, plural, =1 {other} other {件のエンドポイント}}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13809,7 +13809,6 @@
"xpack.cases.caseView.observables.type": "可观察对象类型",
"xpack.cases.caseView.observables.updated": "可观察对象已更新",
"xpack.cases.caseView.observables.value": "可观察对象值",
"xpack.cases.caseView.observables.valuePlaceholder": "可观察对象值",
"xpack.cases.caseView.openCase": "创建案例",
"xpack.cases.caseView.optional": "可选",
"xpack.cases.caseView.otherEndpoints": "以及其他 {endpoints} 个",
Expand Down
5 changes: 5 additions & 0 deletions x-pack/platform/plugins/shared/cases/common/api/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
INTERNAL_CASE_OBSERVABLES_DELETE_URL,
INTERNAL_CASE_SUMMARY_URL,
INTERNAL_INFERENCE_CONNECTORS_URL,
INTERNAL_BULK_CREATE_CASE_OBSERVABLES_URL,
} from '../constants';

export const getCaseDetailsUrl = (id: string): string => {
Expand Down Expand Up @@ -110,6 +111,10 @@ export const getCaseDeleteObservableUrl = (id: string, observableId: string): st
);
};

export const getBulkCreateObservablesUrl = (id: string): string => {
return INTERNAL_BULK_CREATE_CASE_OBSERVABLES_URL.replace('{case_id}', id);
};

export const getCaseSimilarCasesUrl = (caseId: string) => {
return INTERNAL_CASE_SIMILAR_CASES_URL.replace('{case_id}', caseId);
};
Expand Down
Loading