From 33de72445240405867d1cee5aa40f1b63fda5f57 Mon Sep 17 00:00:00 2001
From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Date: Tue, 19 Oct 2021 13:25:49 -0400
Subject: [PATCH] [Security Solutions] Adds security detection rule actions as
importable and exportable (#115243) (#115579)
## Summary
Adds the security detection rule actions as being exportable and importable.
* Adds exportable actions for legacy notification system
* Adds exportable actions for the new throttle notification system
* Adds importable but only imports into the new throttle notification system.
* Updates unit tests
In your `ndjson` file when you have actions exported you will see them like so:
```json
"actions": [
{
"group": "default",
"id": "b55117e0-2df9-11ec-b789-7f03e3cdd668",
"params": {
"message": "Rule {{context.rule.name}} generated {{state.signals_count}} alerts"
},
"action_type_id": ".slack"
}
]
```
where before it was `actions: []` and was not provided.
**Caveats**
If you delete your connector and have an invalid connector then the rule(s) that were referring to that invalid connector will not import and you will get an error like this:
This does _not_ export your connectors at this point in time. You have to export your connector through the Saved Object Management separate like so:
However, if remove everything and import your connector without changing its saved object ID and then go to import the rules everything should import ok and you will get your actions working.
**Manual Testing**:
* You can create normal actions on an alert and then do exports and you should see the actions in your ndjson file
* You can create legacy notifications from 7.14.0 and then upgrade and export and you should see the actions in your ndjson file
* You can manually create legacy notifications by:
By getting an alert id first and ensuring that your `legacy_notifications/one_action.json` contains a valid action then running this command:
```ts
./post_legacy_notification.sh 3403c0d0-2d44-11ec-b147-3b0c6d563a60
```
* You can export your connector and remove everything and then do an import and you will have everything imported and working with your actions and connector wired up correctly.
### Checklist
- [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added
Co-authored-by: Frank Hassanabad
---
.../routes/rules/export_rules_route.ts | 13 ++++-
.../routes/rules/import_rules_route.ts | 5 +-
.../rules/perform_bulk_action_route.test.ts | 5 +-
.../routes/rules/perform_bulk_action_route.ts | 5 ++
.../routes/rules/utils.test.ts | 6 +--
.../detection_engine/routes/rules/utils.ts | 7 ++-
.../rules/get_export_all.test.ts | 26 +++++++++-
.../detection_engine/rules/get_export_all.ts | 17 ++++++-
.../rules/get_export_by_object_ids.test.ts | 49 +++++++++++++++++--
.../rules/get_export_by_object_ids.ts | 36 +++++++++++---
.../security_solution/server/routes/index.ts | 4 +-
11 files changed, 145 insertions(+), 28 deletions(-)
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/export_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/export_rules_route.ts
index e4b99e63cb6c6..c84dd8147ebcc 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/export_rules_route.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/export_rules_route.ts
@@ -6,6 +6,7 @@
*/
import { transformError } from '@kbn/securitysolution-es-utils';
+import { Logger } from 'src/core/server';
import {
exportRulesQuerySchema,
ExportRulesQuerySchemaDecoded,
@@ -24,6 +25,7 @@ import { buildSiemResponse } from '../utils';
export const exportRulesRoute = (
router: SecuritySolutionPluginRouter,
config: ConfigType,
+ logger: Logger,
isRuleRegistryEnabled: boolean
) => {
router.post(
@@ -44,6 +46,7 @@ export const exportRulesRoute = (
async (context, request, response) => {
const siemResponse = buildSiemResponse(response);
const rulesClient = context.alerting?.getRulesClient();
+ const savedObjectsClient = context.core.savedObjects.client;
if (!rulesClient) {
return siemResponse.error({ statusCode: 404 });
@@ -71,8 +74,14 @@ export const exportRulesRoute = (
const exported =
request.body?.objects != null
- ? await getExportByObjectIds(rulesClient, request.body.objects, isRuleRegistryEnabled)
- : await getExportAll(rulesClient, isRuleRegistryEnabled);
+ ? await getExportByObjectIds(
+ rulesClient,
+ savedObjectsClient,
+ request.body.objects,
+ logger,
+ isRuleRegistryEnabled
+ )
+ : await getExportAll(rulesClient, savedObjectsClient, logger, isRuleRegistryEnabled);
const responseBody = request.query.exclude_export_details
? exported.rulesNdjson
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.ts
index b09ef1a215747..3752128d3daa3 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.ts
@@ -194,6 +194,7 @@ export const importRulesRoute = (
throttle,
version,
exceptions_list: exceptionsList,
+ actions,
} = parsedRule;
try {
@@ -265,7 +266,7 @@ export const importRulesRoute = (
note,
version,
exceptionsList,
- actions: [], // Actions are not imported nor exported at this time
+ actions,
});
resolve({
rule_id: ruleId,
@@ -328,7 +329,7 @@ export const importRulesRoute = (
exceptionsList,
anomalyThreshold,
machineLearningJobId,
- actions: undefined,
+ actions,
});
resolve({
rule_id: ruleId,
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts
index 41b909bd718c0..3e85b4898d01c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts
@@ -17,6 +17,7 @@ import {
import { requestContextMock, serverMock, requestMock } from '../__mocks__';
import { performBulkActionRoute } from './perform_bulk_action_route';
import { getPerformBulkActionSchemaMock } from '../../../../../common/detection_engine/schemas/request/perform_bulk_action_schema.mock';
+import { loggingSystemMock } from 'src/core/server/mocks';
jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create());
@@ -27,15 +28,17 @@ describe.each([
let server: ReturnType;
let { clients, context } = requestContextMock.createTools();
let ml: ReturnType;
+ let logger: ReturnType;
beforeEach(() => {
server = serverMock.create();
+ logger = loggingSystemMock.createLogger();
({ clients, context } = requestContextMock.createTools());
ml = mlServicesMock.createSetupContract();
clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled));
- performBulkActionRoute(server.router, ml, isRuleRegistryEnabled);
+ performBulkActionRoute(server.router, ml, logger, isRuleRegistryEnabled);
});
describe('status codes', () => {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts
index 0eba5af4e063a..fb5a2315479da 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.ts
@@ -6,6 +6,8 @@
*/
import { transformError } from '@kbn/securitysolution-es-utils';
+import { Logger } from 'src/core/server';
+
import { DETECTION_ENGINE_RULES_BULK_ACTION } from '../../../../../common/constants';
import { BulkAction } from '../../../../../common/detection_engine/schemas/common/schemas';
import { performBulkActionSchema } from '../../../../../common/detection_engine/schemas/request/perform_bulk_action_schema';
@@ -26,6 +28,7 @@ const BULK_ACTION_RULES_LIMIT = 10000;
export const performBulkActionRoute = (
router: SecuritySolutionPluginRouter,
ml: SetupPlugins['ml'],
+ logger: Logger,
isRuleRegistryEnabled: boolean
) => {
router.post(
@@ -133,7 +136,9 @@ export const performBulkActionRoute = (
case BulkAction.export:
const exported = await getExportByObjectIds(
rulesClient,
+ savedObjectsClient,
rules.data.map(({ params }) => ({ rule_id: params.ruleId })),
+ logger,
isRuleRegistryEnabled
);
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts
index c5a30c349d497..366ae607f0ba8 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.test.ts
@@ -469,12 +469,12 @@ describe.each([
describe('transformAlertsToRules', () => {
test('given an empty array returns an empty array', () => {
- expect(transformAlertsToRules([])).toEqual([]);
+ expect(transformAlertsToRules([], {})).toEqual([]);
});
test('given single alert will return the alert transformed', () => {
const result1 = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams());
- const transformed = transformAlertsToRules([result1]);
+ const transformed = transformAlertsToRules([result1], {});
const expected = getOutputRuleAlertForRest();
expect(transformed).toEqual([expected]);
});
@@ -485,7 +485,7 @@ describe.each([
result2.id = 'some other id';
result2.params.ruleId = 'some other id';
- const transformed = transformAlertsToRules([result1, result2]);
+ const transformed = transformAlertsToRules([result1, result2], {});
const expected1 = getOutputRuleAlertForRest();
const expected2 = getOutputRuleAlertForRest();
expected2.id = 'some other id';
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts
index afc48386a2986..bb2e35d189ca1 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts
@@ -103,8 +103,11 @@ export const transformAlertToRule = (
return internalRuleToAPIResponse(alert, ruleStatus?.attributes, legacyRuleActions);
};
-export const transformAlertsToRules = (alerts: RuleAlertType[]): Array> => {
- return alerts.map((alert) => transformAlertToRule(alert));
+export const transformAlertsToRules = (
+ alerts: RuleAlertType[],
+ legacyRuleActions: Record
+): Array> => {
+ return alerts.map((alert) => transformAlertToRule(alert, undefined, legacyRuleActions[alert.id]));
};
export const transformFindAlerts = (
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.test.ts
index 3ca5960d7d4e1..92e4f0bbb4a5e 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.test.ts
@@ -9,21 +9,33 @@ import {
getAlertMock,
getFindResultWithSingleHit,
FindHit,
+ getEmptySavedObjectsResponse,
} from '../routes/__mocks__/request_responses';
import { rulesClientMock } from '../../../../../alerting/server/mocks';
import { getExportAll } from './get_export_all';
import { getListArrayMock } from '../../../../common/detection_engine/schemas/types/lists.mock';
import { getThreatMock } from '../../../../common/detection_engine/schemas/types/threat.mock';
+
import { getQueryRuleParams } from '../schemas/rule_schemas.mock';
+import { loggingSystemMock } from 'src/core/server/mocks';
+import { requestContextMock } from '../routes/__mocks__/request_context';
describe.each([
['Legacy', false],
['RAC', true],
])('getExportAll - %s', (_, isRuleRegistryEnabled) => {
+ let logger: ReturnType;
+ const { clients } = requestContextMock.createTools();
+
+ beforeEach(async () => {
+ clients.savedObjectsClient.find.mockResolvedValue(getEmptySavedObjectsResponse());
+ });
+
test('it exports everything from the alerts client', async () => {
const rulesClient = rulesClientMock.create();
const result = getFindResultWithSingleHit(isRuleRegistryEnabled);
const alert = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams());
+
alert.params = {
...alert.params,
filters: [{ query: { match_phrase: { 'host.name': 'some-host' } } }],
@@ -35,7 +47,12 @@ describe.each([
result.data = [alert];
rulesClient.find.mockResolvedValue(result);
- const exports = await getExportAll(rulesClient, isRuleRegistryEnabled);
+ const exports = await getExportAll(
+ rulesClient,
+ clients.savedObjectsClient,
+ logger,
+ isRuleRegistryEnabled
+ );
const rulesJson = JSON.parse(exports.rulesNdjson);
const detailsJson = JSON.parse(exports.exportDetails);
expect(rulesJson).toEqual({
@@ -97,7 +114,12 @@ describe.each([
rulesClient.find.mockResolvedValue(findResult);
- const exports = await getExportAll(rulesClient, isRuleRegistryEnabled);
+ const exports = await getExportAll(
+ rulesClient,
+ clients.savedObjectsClient,
+ logger,
+ isRuleRegistryEnabled
+ );
expect(exports).toEqual({
rulesNdjson: '',
exportDetails: '{"exported_count":0,"missing_rules":[],"missing_rules_count":0}\n',
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.ts
index 71079ccefc97a..cbbda5df7e2bf 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_all.ts
@@ -7,20 +7,33 @@
import { transformDataToNdjson } from '@kbn/securitysolution-utils';
-import { RulesClient } from '../../../../../alerting/server';
+import { Logger } from 'src/core/server';
+import { RulesClient, AlertServices } from '../../../../../alerting/server';
import { getNonPackagedRules } from './get_existing_prepackaged_rules';
import { getExportDetailsNdjson } from './get_export_details_ndjson';
import { transformAlertsToRules } from '../routes/rules/utils';
+// eslint-disable-next-line no-restricted-imports
+import { legacyGetBulkRuleActionsSavedObject } from '../rule_actions/legacy_get_bulk_rule_actions_saved_object';
+
export const getExportAll = async (
rulesClient: RulesClient,
+ savedObjectsClient: AlertServices['savedObjectsClient'],
+ logger: Logger,
isRuleRegistryEnabled: boolean
): Promise<{
rulesNdjson: string;
exportDetails: string;
}> => {
const ruleAlertTypes = await getNonPackagedRules({ rulesClient, isRuleRegistryEnabled });
- const rules = transformAlertsToRules(ruleAlertTypes);
+ const alertIds = ruleAlertTypes.map((rule) => rule.id);
+ const legacyActions = await legacyGetBulkRuleActionsSavedObject({
+ alertIds,
+ savedObjectsClient,
+ logger,
+ });
+
+ const rules = transformAlertsToRules(ruleAlertTypes, legacyActions);
// We do not support importing/exporting actions. When we do, delete this line of code
const rulesWithoutActions = rules.map((rule) => ({ ...rule, actions: [] }));
const rulesNdjson = transformDataToNdjson(rulesWithoutActions);
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts
index 740427e44b560..961f2c6a41866 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts
@@ -10,28 +10,43 @@ import {
getAlertMock,
getFindResultWithSingleHit,
FindHit,
+ getEmptySavedObjectsResponse,
} from '../routes/__mocks__/request_responses';
import { rulesClientMock } from '../../../../../alerting/server/mocks';
import { getListArrayMock } from '../../../../common/detection_engine/schemas/types/lists.mock';
import { getThreatMock } from '../../../../common/detection_engine/schemas/types/threat.mock';
import { getQueryRuleParams } from '../schemas/rule_schemas.mock';
+import { loggingSystemMock } from 'src/core/server/mocks';
+import { requestContextMock } from '../routes/__mocks__/request_context';
describe.each([
['Legacy', false],
['RAC', true],
])('get_export_by_object_ids - %s', (_, isRuleRegistryEnabled) => {
+ let logger: ReturnType;
+ const { clients } = requestContextMock.createTools();
+
beforeEach(() => {
jest.resetAllMocks();
jest.restoreAllMocks();
jest.clearAllMocks();
+
+ clients.savedObjectsClient.find.mockResolvedValue(getEmptySavedObjectsResponse());
});
+
describe('getExportByObjectIds', () => {
test('it exports object ids into an expected string with new line characters', async () => {
const rulesClient = rulesClientMock.create();
rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled));
const objects = [{ rule_id: 'rule-1' }];
- const exports = await getExportByObjectIds(rulesClient, objects, isRuleRegistryEnabled);
+ const exports = await getExportByObjectIds(
+ rulesClient,
+ clients.savedObjectsClient,
+ objects,
+ logger,
+ isRuleRegistryEnabled
+ );
const exportsObj = {
rulesNdjson: JSON.parse(exports.rulesNdjson),
exportDetails: JSON.parse(exports.exportDetails),
@@ -102,7 +117,13 @@ describe.each([
rulesClient.find.mockResolvedValue(findResult);
const objects = [{ rule_id: 'rule-1' }];
- const exports = await getExportByObjectIds(rulesClient, objects, isRuleRegistryEnabled);
+ const exports = await getExportByObjectIds(
+ rulesClient,
+ clients.savedObjectsClient,
+ objects,
+ logger,
+ isRuleRegistryEnabled
+ );
expect(exports).toEqual({
rulesNdjson: '',
exportDetails:
@@ -117,7 +138,13 @@ describe.each([
rulesClient.find.mockResolvedValue(getFindResultWithSingleHit(isRuleRegistryEnabled));
const objects = [{ rule_id: 'rule-1' }];
- const exports = await getRulesFromObjects(rulesClient, objects, isRuleRegistryEnabled);
+ const exports = await getRulesFromObjects(
+ rulesClient,
+ clients.savedObjectsClient,
+ objects,
+ logger,
+ isRuleRegistryEnabled
+ );
const expected: RulesErrors = {
exportedCount: 1,
missingRules: [],
@@ -192,7 +219,13 @@ describe.each([
rulesClient.find.mockResolvedValue(findResult);
const objects = [{ rule_id: 'rule-1' }];
- const exports = await getRulesFromObjects(rulesClient, objects, isRuleRegistryEnabled);
+ const exports = await getRulesFromObjects(
+ rulesClient,
+ clients.savedObjectsClient,
+ objects,
+ logger,
+ isRuleRegistryEnabled
+ );
const expected: RulesErrors = {
exportedCount: 0,
missingRules: [{ rule_id: 'rule-1' }],
@@ -215,7 +248,13 @@ describe.each([
rulesClient.find.mockResolvedValue(findResult);
const objects = [{ rule_id: 'rule-1' }];
- const exports = await getRulesFromObjects(rulesClient, objects, isRuleRegistryEnabled);
+ const exports = await getRulesFromObjects(
+ rulesClient,
+ clients.savedObjectsClient,
+ objects,
+ logger,
+ isRuleRegistryEnabled
+ );
const expected: RulesErrors = {
exportedCount: 0,
missingRules: [{ rule_id: 'rule-1' }],
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts
index 4cf3ad9133a71..8233fe6d4948c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts
@@ -8,14 +8,20 @@
import { chunk } from 'lodash';
import { transformDataToNdjson } from '@kbn/securitysolution-utils';
+import { Logger } from 'src/core/server';
import { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema';
-import { RulesClient } from '../../../../../alerting/server';
+import { RulesClient, AlertServices } from '../../../../../alerting/server';
+
import { getExportDetailsNdjson } from './get_export_details_ndjson';
+
import { isAlertType } from '../rules/types';
import { transformAlertToRule } from '../routes/rules/utils';
import { INTERNAL_RULE_ID_KEY } from '../../../../common/constants';
import { findRules } from './find_rules';
+// eslint-disable-next-line no-restricted-imports
+import { legacyGetBulkRuleActionsSavedObject } from '../rule_actions/legacy_get_bulk_rule_actions_saved_object';
+
interface ExportSuccessRule {
statusCode: 200;
rule: Partial;
@@ -34,23 +40,32 @@ export interface RulesErrors {
export const getExportByObjectIds = async (
rulesClient: RulesClient,
+ savedObjectsClient: AlertServices['savedObjectsClient'],
objects: Array<{ rule_id: string }>,
+ logger: Logger,
isRuleRegistryEnabled: boolean
): Promise<{
rulesNdjson: string;
exportDetails: string;
}> => {
- const rulesAndErrors = await getRulesFromObjects(rulesClient, objects, isRuleRegistryEnabled);
- // We do not support importing/exporting actions. When we do, delete this line of code
- const rulesWithoutActions = rulesAndErrors.rules.map((rule) => ({ ...rule, actions: [] }));
- const rulesNdjson = transformDataToNdjson(rulesWithoutActions);
- const exportDetails = getExportDetailsNdjson(rulesWithoutActions, rulesAndErrors.missingRules);
+ const rulesAndErrors = await getRulesFromObjects(
+ rulesClient,
+ savedObjectsClient,
+ objects,
+ logger,
+ isRuleRegistryEnabled
+ );
+
+ const rulesNdjson = transformDataToNdjson(rulesAndErrors.rules);
+ const exportDetails = getExportDetailsNdjson(rulesAndErrors.rules, rulesAndErrors.missingRules);
return { rulesNdjson, exportDetails };
};
export const getRulesFromObjects = async (
rulesClient: RulesClient,
+ savedObjectsClient: AlertServices['savedObjectsClient'],
objects: Array<{ rule_id: string }>,
+ logger: Logger,
isRuleRegistryEnabled: boolean
): Promise => {
// If we put more than 1024 ids in one block like "alert.attributes.tags: (id1 OR id2 OR ... OR id1100)"
@@ -78,6 +93,13 @@ export const getRulesFromObjects = async (
sortField: undefined,
sortOrder: undefined,
});
+ const alertIds = rules.data.map((rule) => rule.id);
+ const legacyActions = await legacyGetBulkRuleActionsSavedObject({
+ alertIds,
+ savedObjectsClient,
+ logger,
+ });
+
const alertsAndErrors = objects.map(({ rule_id: ruleId }) => {
const matchingRule = rules.data.find((rule) => rule.params.ruleId === ruleId);
if (
@@ -87,7 +109,7 @@ export const getRulesFromObjects = async (
) {
return {
statusCode: 200,
- rule: transformAlertToRule(matchingRule),
+ rule: transformAlertToRule(matchingRule, undefined, legacyActions[matchingRule.id]),
};
} else {
return {
diff --git a/x-pack/plugins/security_solution/server/routes/index.ts b/x-pack/plugins/security_solution/server/routes/index.ts
index d045c6b129e43..148580d5c4477 100644
--- a/x-pack/plugins/security_solution/server/routes/index.ts
+++ b/x-pack/plugins/security_solution/server/routes/index.ts
@@ -91,12 +91,12 @@ export const initRoutes = (
updateRulesBulkRoute(router, ml, isRuleRegistryEnabled);
patchRulesBulkRoute(router, ml, isRuleRegistryEnabled);
deleteRulesBulkRoute(router, isRuleRegistryEnabled);
- performBulkActionRoute(router, ml, isRuleRegistryEnabled);
+ performBulkActionRoute(router, ml, logger, isRuleRegistryEnabled);
createTimelinesRoute(router, config, security);
patchTimelinesRoute(router, config, security);
importRulesRoute(router, config, ml, isRuleRegistryEnabled);
- exportRulesRoute(router, config, isRuleRegistryEnabled);
+ exportRulesRoute(router, config, logger, isRuleRegistryEnabled);
importTimelinesRoute(router, config, security);
exportTimelinesRoute(router, config, security);