Skip to content

Commit 3e6d582

Browse files
committed
updated automated response actions to use alert space id when creating actions and spaces is enabled
1 parent 1224aa9 commit 3e6d582

3 files changed

Lines changed: 119 additions & 22 deletions

File tree

x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_response_actions/endpoint_response_action.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import { each } from 'lodash';
99
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
10+
import { EndpointError } from '../../../../common/endpoint/errors';
1011
import { stringify } from '../../../endpoint/utils/stringify';
1112
import type {
1213
RuleResponseEndpointAction,
@@ -31,13 +32,29 @@ export const endpointResponseAction = async (
3132
);
3233
const ruleId = alerts[0].kibana.alert?.rule.uuid;
3334
const ruleName = alerts[0].kibana.alert?.rule.name;
34-
const logMsgPrefix = `Rule [${ruleName}][${ruleId}]:`;
35-
const { comment, command } = responseAction.params;
3635
const errors: string[] = [];
36+
let spaceId = (alerts[0].kibana.space_ids ?? [])[0];
37+
38+
if (endpointAppContextService.experimentalFeatures.endpointManagementSpaceAwarenessEnabled) {
39+
if (!spaceId) {
40+
logger.error(
41+
new EndpointError(
42+
`Unable to identify the space ID from alert data ('kibana.space_ids') for rule [${ruleName}][${ruleId}]`
43+
)
44+
);
45+
return;
46+
}
47+
} else {
48+
// force the space to `default` when space awareness is not enabled
49+
spaceId = DEFAULT_SPACE_ID;
50+
}
51+
52+
const logMsgPrefix = `Rule [${ruleName}][${ruleId}][${spaceId}]:`;
53+
const { comment, command } = responseAction.params;
3754
const responseActionsClient = endpointAppContextService.getInternalResponseActionsClient({
3855
agentType: 'endpoint',
3956
username: 'unknown',
40-
spaceId: DEFAULT_SPACE_ID, // TODO:PT Will be updated with team issue #12312
57+
spaceId,
4158
});
4259

4360
const automatedProcessActionsEnabled =

x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.test.ts

Lines changed: 98 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,42 @@
88
import { getScheduleNotificationResponseActionsService } from './schedule_notification_response_actions';
99
import type { RuleResponseAction } from '../../../../common/api/detection_engine';
1010
import { ResponseActionTypesEnum } from '../../../../common/api/detection_engine';
11-
import { ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils';
11+
import { ALERT_RULE_NAME, ALERT_RULE_UUID, SPACE_IDS } from '@kbn/rule-data-utils';
1212
import { createMockEndpointAppContextService } from '../../../endpoint/mocks';
1313
import { responseActionsClientMock } from '../../../endpoint/services/actions/clients/mocks';
14+
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
1415

1516
describe('ScheduleNotificationResponseActions', () => {
16-
const signalOne = {
17-
agent: { id: 'agent-id-1', type: 'endpoint' },
18-
_id: 'alert-id-1',
19-
user: { id: 'S-1-5-20' },
20-
process: {
21-
pid: 123,
17+
const getSignals = () => [
18+
{
19+
agent: { id: 'agent-id-1', type: 'endpoint' },
20+
_id: 'alert-id-1',
21+
user: { id: 'S-1-5-20' },
22+
process: {
23+
pid: 123,
24+
},
25+
[ALERT_RULE_UUID]: 'rule-id-1',
26+
[ALERT_RULE_NAME]: 'rule-name-1',
27+
[SPACE_IDS]: [DEFAULT_SPACE_ID],
2228
},
23-
[ALERT_RULE_UUID]: 'rule-id-1',
24-
[ALERT_RULE_NAME]: 'rule-name-1',
25-
};
26-
const signalTwo = { agent: { id: 'agent-id-2', type: 'endpoint' }, _id: 'alert-id-2' };
27-
const getSignals = () => [signalOne, signalTwo];
29+
{ agent: { id: 'agent-id-2', type: 'endpoint' }, _id: 'alert-id-2' },
30+
];
2831

2932
const osqueryActionMock = {
3033
create: jest.fn(),
3134
stop: jest.fn(),
3235
};
3336
let mockedResponseActionsClient = responseActionsClientMock.create();
34-
const endpointActionMock = createMockEndpointAppContextService();
35-
(endpointActionMock.getInternalResponseActionsClient as jest.Mock).mockImplementation(() => {
37+
const endpointServiceMock = createMockEndpointAppContextService();
38+
(endpointServiceMock.getInternalResponseActionsClient as jest.Mock).mockImplementation(() => {
3639
return mockedResponseActionsClient;
3740
});
3841
// @ts-expect-error assignment to readonly property
39-
endpointActionMock.experimentalFeatures.automatedProcessActionsEnabled = true;
42+
endpointServiceMock.experimentalFeatures.automatedProcessActionsEnabled = true;
4043

4144
const scheduleNotificationResponseActions = getScheduleNotificationResponseActionsService({
4245
osqueryCreateActionService: osqueryActionMock,
43-
endpointAppContextService: endpointActionMock,
46+
endpointAppContextService: endpointServiceMock,
4447
});
4548

4649
describe('Osquery', () => {
@@ -143,7 +146,7 @@ describe('ScheduleNotificationResponseActions', () => {
143146
});
144147
describe('Endpoint', () => {
145148
beforeEach(() => {
146-
(endpointActionMock.getInternalResponseActionsClient as jest.Mock).mockClear();
149+
(endpointServiceMock.getInternalResponseActionsClient as jest.Mock).mockClear();
147150
mockedResponseActionsClient = responseActionsClientMock.create();
148151
});
149152

@@ -165,10 +168,11 @@ describe('ScheduleNotificationResponseActions', () => {
165168
responseActions,
166169
});
167170
expect(response).not.toBeUndefined();
168-
expect(endpointActionMock.getInternalResponseActionsClient).toHaveBeenCalledTimes(1);
169-
expect(endpointActionMock.getInternalResponseActionsClient).toHaveBeenCalledWith({
171+
expect(endpointServiceMock.getInternalResponseActionsClient).toHaveBeenCalledTimes(1);
172+
expect(endpointServiceMock.getInternalResponseActionsClient).toHaveBeenCalledWith({
170173
agentType: 'endpoint',
171174
username: 'unknown',
175+
spaceId: 'default',
172176
});
173177
expect(mockedResponseActionsClient.isolate).toHaveBeenCalledTimes(signals.length);
174178
expect(mockedResponseActionsClient.isolate).toHaveBeenNthCalledWith(
@@ -277,5 +281,80 @@ describe('ScheduleNotificationResponseActions', () => {
277281

278282
expect(response).toBeUndefined();
279283
});
284+
285+
it('should use default space id when space awareness is disabled', async () => {
286+
await scheduleNotificationResponseActions({
287+
signals: getSignals(),
288+
signalsCount: 2,
289+
responseActions: [
290+
{
291+
actionTypeId: ResponseActionTypesEnum['.endpoint'],
292+
params: {
293+
command: 'isolate',
294+
comment: 'test process comment',
295+
},
296+
},
297+
],
298+
});
299+
300+
expect(endpointServiceMock.getInternalResponseActionsClient).toHaveBeenCalledWith(
301+
expect.objectContaining({ spaceId: DEFAULT_SPACE_ID })
302+
);
303+
});
304+
305+
describe('and when space awareness is enabled', () => {
306+
beforeEach(() => {
307+
// @ts-expect-error
308+
endpointServiceMock.experimentalFeatures.endpointManagementSpaceAwarenessEnabled = true;
309+
});
310+
311+
it('should initialize a response action client with the alert space id when space awareness is enabled', async () => {
312+
const signals = getSignals();
313+
signals[0][SPACE_IDS] = ['foo'];
314+
await scheduleNotificationResponseActions({
315+
signals,
316+
signalsCount: 2,
317+
responseActions: [
318+
{
319+
actionTypeId: ResponseActionTypesEnum['.endpoint'],
320+
params: {
321+
command: 'isolate',
322+
comment: 'test process comment',
323+
},
324+
},
325+
],
326+
});
327+
328+
expect(endpointServiceMock.getInternalResponseActionsClient).toHaveBeenCalledWith(
329+
expect.objectContaining({ spaceId: 'foo' })
330+
);
331+
});
332+
333+
it('should log error if unable to determine space id for alerts', async () => {
334+
const signals = getSignals();
335+
signals[0][SPACE_IDS] = undefined;
336+
await scheduleNotificationResponseActions({
337+
signals,
338+
signalsCount: 2,
339+
responseActions: [
340+
{
341+
actionTypeId: ResponseActionTypesEnum['.endpoint'],
342+
params: {
343+
command: 'isolate',
344+
comment: 'test process comment',
345+
},
346+
},
347+
],
348+
});
349+
350+
expect(endpointServiceMock.createLogger().error).toHaveBeenCalledWith(
351+
expect.objectContaining({
352+
message:
353+
"Unable to identify the space ID from alert data ('kibana.space_ids') for rule [rule-name-1][rule-id-1]",
354+
})
355+
);
356+
expect(endpointServiceMock.getInternalResponseActionsClient).not.toHaveBeenCalled();
357+
});
358+
});
280359
});
281360
});

x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_response_actions/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export type Alert = ParsedTechnicalFields & {
2626
name: string;
2727
};
2828
};
29+
space_ids?: string[];
2930
};
3031
};
3132

0 commit comments

Comments
 (0)