"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.bulkDeleteRules = void 0; var _pMap = _interopRequireDefault(require("p-map")); var _esQuery = require("@kbn/es-query"); var _apmUtils = require("@kbn/apm-utils"); var _lib = require("../../lib"); var _bulk_mark_api_keys_for_invalidation = require("../../invalidate_pending_api_keys/bulk_mark_api_keys_for_invalidation"); var _audit_events = require("../common/audit_events"); var _common = require("../common"); var _constants = require("../common/constants"); var _lib2 = require("../lib"); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const bulkDeleteRules = async (context, options) => { const { ids, filter } = (0, _common.getAndValidateCommonBulkOptions)(options); const kueryNodeFilter = ids ? (0, _lib.convertRuleIdsToKueryNode)(ids) : (0, _common.buildKueryNodeFilter)(filter); const authorizationFilter = await (0, _lib2.getAuthorizationFilter)(context, { action: 'DELETE' }); const kueryNodeFilterWithAuth = authorizationFilter && kueryNodeFilter ? _esQuery.nodeBuilder.and([kueryNodeFilter, authorizationFilter]) : kueryNodeFilter; const { total } = await (0, _lib2.checkAuthorizationAndGetTotal)(context, { filter: kueryNodeFilterWithAuth, action: 'DELETE' }); const { rules, errors, accListSpecificForBulkOperation } = await (0, _apmUtils.withSpan)({ name: 'retryIfBulkOperationConflicts', type: 'rules' }, () => (0, _common.retryIfBulkOperationConflicts)({ action: 'DELETE', logger: context.logger, bulkOperation: filterKueryNode => bulkDeleteWithOCC(context, { filter: filterKueryNode }), filter: kueryNodeFilterWithAuth })); const [apiKeysToInvalidate, taskIdsToDelete] = accListSpecificForBulkOperation; const [result] = await Promise.allSettled([(0, _common.tryToRemoveTasks)({ taskIdsToDelete, logger: context.logger, taskManager: context.taskManager }), (0, _bulk_mark_api_keys_for_invalidation.bulkMarkApiKeysForInvalidation)({ apiKeys: apiKeysToInvalidate }, context.logger, context.unsecuredSavedObjectsClient)]); const deletedRules = rules.map(({ id, attributes, references }) => { return (0, _lib2.getAlertFromRaw)(context, id, attributes.alertTypeId, attributes, references, false); }); if (result.status === 'fulfilled') { return { errors, total, rules: deletedRules, taskIdsFailedToBeDeleted: result.value }; } else { return { errors, total, rules: deletedRules, taskIdsFailedToBeDeleted: [] }; } }; exports.bulkDeleteRules = bulkDeleteRules; const bulkDeleteWithOCC = async (context, { filter }) => { const rulesFinder = await (0, _apmUtils.withSpan)({ name: 'encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser', type: 'rules' }, () => context.encryptedSavedObjectsClient.createPointInTimeFinderDecryptedAsInternalUser({ filter, type: 'alert', perPage: 100, ...(context.namespace ? { namespaces: [context.namespace] } : undefined) })); const rulesToDelete = []; const apiKeyToRuleIdMapping = {}; const taskIdToRuleIdMapping = {}; const ruleNameToRuleIdMapping = {}; await (0, _apmUtils.withSpan)({ name: 'Get rules, collect them and their attributes', type: 'rules' }, async () => { for await (const response of rulesFinder.find()) { for (const rule of response.saved_objects) { var _context$auditLogger; if (rule.attributes.apiKey && !rule.attributes.apiKeyCreatedByUser) { apiKeyToRuleIdMapping[rule.id] = rule.attributes.apiKey; } if (rule.attributes.name) { ruleNameToRuleIdMapping[rule.id] = rule.attributes.name; } if (rule.attributes.scheduledTaskId) { taskIdToRuleIdMapping[rule.id] = rule.attributes.scheduledTaskId; } rulesToDelete.push(rule); (_context$auditLogger = context.auditLogger) === null || _context$auditLogger === void 0 ? void 0 : _context$auditLogger.log((0, _audit_events.ruleAuditEvent)({ action: _audit_events.RuleAuditAction.DELETE, outcome: 'unknown', savedObject: { type: 'alert', id: rule.id } })); } } await rulesFinder.close(); }); const result = await (0, _apmUtils.withSpan)({ name: 'unsecuredSavedObjectsClient.bulkDelete', type: 'rules' }, () => context.unsecuredSavedObjectsClient.bulkDelete(rulesToDelete)); const deletedRuleIds = []; const apiKeysToInvalidate = []; const taskIdsToDelete = []; const errors = []; result.statuses.forEach(status => { if (status.error === undefined) { if (apiKeyToRuleIdMapping[status.id]) { apiKeysToInvalidate.push(apiKeyToRuleIdMapping[status.id]); } if (taskIdToRuleIdMapping[status.id]) { taskIdsToDelete.push(taskIdToRuleIdMapping[status.id]); } deletedRuleIds.push(status.id); } else { var _status$error$message, _ruleNameToRuleIdMapp; errors.push({ message: (_status$error$message = status.error.message) !== null && _status$error$message !== void 0 ? _status$error$message : 'n/a', status: status.error.statusCode, rule: { id: status.id, name: (_ruleNameToRuleIdMapp = ruleNameToRuleIdMapping[status.id]) !== null && _ruleNameToRuleIdMapp !== void 0 ? _ruleNameToRuleIdMapp : 'n/a' } }); } }); const rules = rulesToDelete.filter(rule => deletedRuleIds.includes(rule.id)); // migrate legacy actions only for SIEM rules await (0, _pMap.default)(rules, async rule => { await (0, _lib2.migrateLegacyActions)(context, { ruleId: rule.id, attributes: rule.attributes, skipActionsValidation: true }); }, // max concurrency for bulk edit operations, that is limited by api key generations, should be sufficient for bulk migrations { concurrency: _constants.API_KEY_GENERATE_CONCURRENCY }); return { errors, rules, accListSpecificForBulkOperation: [apiKeysToInvalidate, taskIdsToDelete] }; };