From 75e0d1f20e2cfaa8f69ebcceeb0bf5100714ffca Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 17 Oct 2024 19:10:39 -0300 Subject: [PATCH 01/19] Rule Updates in bulk with conflicts --- .../rule_management/api/api.ts | 10 -- .../use_perform_all_rules_upgrade_mutation.ts | 49 ---------- .../use_perform_rule_upgrade.ts | 14 --- .../upgrade_prebuilt_rules_table_buttons.tsx | 32 +++++- .../upgrade_prebuilt_rules_table_context.tsx | 98 ++++++++++++------- .../modals/upgrade_conflicts_modal/index.tsx | 35 +++++++ .../upgrade_conflicts_modal/translations.tsx | 44 +++++++++ .../create_upgradeable_rules_payload.ts | 7 +- .../perform_rule_upgrade_route.ts | 8 +- .../prebuilt_rules/api/register_routes.ts | 9 +- .../security_solution/server/routes/index.ts | 2 +- 11 files changed, 192 insertions(+), 116 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_all_rules_upgrade_mutation.ts create mode 100644 x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/index.tsx create mode 100644 x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts index 1e2ee1be7a47..f9d7a07c450e 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts @@ -678,16 +678,6 @@ export const performInstallSpecificRules = async ( }), }); -export const performUpgradeAllRules = async (): Promise => - KibanaServices.get().http.fetch(PERFORM_RULE_UPGRADE_URL, { - method: 'POST', - version: '1', - body: JSON.stringify({ - mode: 'ALL_RULES', - pick_version: 'TARGET', - }), - }); - export const performUpgradeSpecificRules = async ( rules: UpgradeSpecificRulesRequest['rules'] ): Promise => diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_all_rules_upgrade_mutation.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_all_rules_upgrade_mutation.ts deleted file mode 100644 index 7e5385bb0c75..000000000000 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_all_rules_upgrade_mutation.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ -import type { UseMutationOptions } from '@tanstack/react-query'; -import { useMutation } from '@tanstack/react-query'; -import type { PerformRuleUpgradeResponseBody } from '../../../../../../common/api/detection_engine/prebuilt_rules'; -import { PERFORM_RULE_UPGRADE_URL } from '../../../../../../common/api/detection_engine/prebuilt_rules/urls'; -import { useInvalidateFindRulesQuery } from '../use_find_rules_query'; -import { useInvalidateFetchRuleManagementFiltersQuery } from '../use_fetch_rule_management_filters_query'; -import { useInvalidateFetchRulesSnoozeSettingsQuery } from '../use_fetch_rules_snooze_settings_query'; -import { useInvalidateFetchPrebuiltRulesUpgradeReviewQuery } from './use_fetch_prebuilt_rules_upgrade_review_query'; -import { useInvalidateFetchPrebuiltRulesStatusQuery } from './use_fetch_prebuilt_rules_status_query'; -import { performUpgradeAllRules } from '../../api'; -import { useInvalidateFetchCoverageOverviewQuery } from '../use_fetch_coverage_overview_query'; - -export const PERFORM_ALL_RULES_UPGRADE_KEY = ['POST', 'ALL_RULES', PERFORM_RULE_UPGRADE_URL]; - -export const usePerformAllRulesUpgradeMutation = ( - options?: UseMutationOptions -) => { - const invalidateFindRulesQuery = useInvalidateFindRulesQuery(); - const invalidateFetchRulesSnoozeSettings = useInvalidateFetchRulesSnoozeSettingsQuery(); - const invalidateFetchRuleManagementFilters = useInvalidateFetchRuleManagementFiltersQuery(); - const invalidateFetchPrebuiltRulesUpgradeReview = - useInvalidateFetchPrebuiltRulesUpgradeReviewQuery(); - const invalidateRuleStatus = useInvalidateFetchPrebuiltRulesStatusQuery(); - const invalidateFetchCoverageOverviewQuery = useInvalidateFetchCoverageOverviewQuery(); - - return useMutation(() => performUpgradeAllRules(), { - ...options, - mutationKey: PERFORM_ALL_RULES_UPGRADE_KEY, - onSettled: (...args) => { - invalidateFindRulesQuery(); - invalidateFetchRulesSnoozeSettings(); - invalidateFetchRuleManagementFilters(); - - invalidateFetchPrebuiltRulesUpgradeReview(); - invalidateRuleStatus(); - invalidateFetchCoverageOverviewQuery(); - - if (options?.onSettled) { - options.onSettled(...args); - } - }, - }); -}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts index aa9e38217a19..33f36ffe14da 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts @@ -5,24 +5,10 @@ * 2.0. */ import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; -import { usePerformAllRulesUpgradeMutation } from '../../api/hooks/prebuilt_rules/use_perform_all_rules_upgrade_mutation'; import { usePerformSpecificRulesUpgradeMutation } from '../../api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation'; import * as i18n from './translations'; -export const usePerformUpgradeAllRules = () => { - const { addError, addSuccess } = useAppToasts(); - - return usePerformAllRulesUpgradeMutation({ - onError: (err) => { - addError(err, { title: i18n.RULE_UPGRADE_FAILED }); - }, - onSuccess: (result) => { - addSuccess(getSuccessToastMessage(result)); - }, - }); -}; - export const usePerformUpgradeSpecificRules = () => { const { addError, addSuccess } = useAppToasts(); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx index 1d0e6adeabce..489d60bfb2ac 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx @@ -20,8 +20,15 @@ export const UpgradePrebuiltRulesTableButtons = ({ selectedRules, }: UpgradePrebuiltRulesTableButtonsProps) => { const { - state: { hasRulesToUpgrade, loadingRules, isRefetching, isUpgradingSecurityPackages }, - actions: { upgradeAllRules, upgradeRules }, + state: { + ruleUpgradeInfos, + hasRulesToUpgrade, + loadingRules, + isRefetching, + isUpgradingSecurityPackages, + isPrebuiltRulesCustomizationEnabled, + }, + actions: { upgradeRules }, } = useUpgradePrebuiltRulesTableContext(); const [{ loading: isUserDataLoading, canUserCRUD }] = useUserData(); const canUserEditRules = canUserCRUD && !isUserDataLoading; @@ -31,18 +38,30 @@ export const UpgradePrebuiltRulesTableButtons = ({ const isRuleUpgrading = loadingRules.length > 0; const isRequestInProgress = isRuleUpgrading || isRefetching || isUpgradingSecurityPackages; + const isAllSelectedRulesHaveConflicts = + isPrebuiltRulesCustomizationEnabled && + selectedRules.every((rule) => rule.diff.num_fields_with_conflicts > 0); + const isAllRulesHaveConflicts = + isPrebuiltRulesCustomizationEnabled && + ruleUpgradeInfos.every((rule) => rule.diff.num_fields_with_conflicts > 0); const upgradeSelectedRules = useCallback( () => upgradeRules(selectedRules.map((rule) => rule.rule_id)), [selectedRules, upgradeRules] ); + const upgradeAllRules = useCallback( + // Upgrade all rules, ignoring filter and selction + () => upgradeRules(ruleUpgradeInfos.map((rule) => rule.rule_id)), + [ruleUpgradeInfos, upgradeRules] + ); + return ( {shouldDisplayUpgradeSelectedRulesButton ? ( <> @@ -57,7 +76,12 @@ export const UpgradePrebuiltRulesTableButtons = ({ fill iconType="plusInCircle" onClick={upgradeAllRules} - disabled={!canUserEditRules || !hasRulesToUpgrade || isRequestInProgress} + disabled={ + !canUserEditRules || + !hasRulesToUpgrade || + isRequestInProgress || + isAllRulesHaveConflicts + } data-test-subj="upgradeAllRulesButton" > {i18n.UPDATE_ALL} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx index 6ec9ffdd02e6..94753c7e9547 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx @@ -9,6 +9,7 @@ import type { Dispatch, SetStateAction } from 'react'; import React, { createContext, useCallback, useContext, useMemo, useState } from 'react'; import { EuiButton, EuiToolTip } from '@elastic/eui'; import { useIsPrebuiltRulesCustomizationEnabled } from '../../../../rule_management/hooks/use_is_prebuilt_rules_customization_enabled'; +import type { RuleUpgradeInfoForReview } from '../../../../../../common/api/detection_engine'; import type { RulesUpgradeState } from '../../../../rule_management/model/prebuilt_rule_upgrade'; import { RuleUpgradeConflictsResolverTab } from '../../../../rule_management/components/rule_details/three_way_diff/rule_upgrade_conflicts_resolver_tab'; import { PerFieldRuleDiffTab } from '../../../../rule_management/components/rule_details/per_field_rule_diff_tab'; @@ -21,10 +22,7 @@ import type { RuleSignatureId, } from '../../../../../../common/api/detection_engine/model/rule_schema'; import { invariant } from '../../../../../../common/utils/invariant'; -import { - usePerformUpgradeAllRules, - usePerformUpgradeSpecificRules, -} from '../../../../rule_management/logic/prebuilt_rules/use_perform_rule_upgrade'; +import { usePerformUpgradeSpecificRules } from '../../../../rule_management/logic/prebuilt_rules/use_perform_rule_upgrade'; import { usePrebuiltRulesUpgradeReview } from '../../../../rule_management/logic/prebuilt_rules/use_prebuilt_rules_upgrade_review'; import type { UpgradePrebuiltRulesTableFilterOptions } from './use_filter_prebuilt_rules_to_upgrade'; import { useFilterPrebuiltRulesToUpgrade } from './use_filter_prebuilt_rules_to_upgrade'; @@ -32,12 +30,17 @@ import { useAsyncConfirmation } from '../rules_table/use_async_confirmation'; import { TabContentPadding } from '../../../../rule_management/components/rule_details/rule_details_flyout'; import { RuleDiffTab } from '../../../../rule_management/components/rule_details/rule_diff_tab'; import { MlJobUpgradeModal } from '../../../../../detections/components/modals/ml_job_upgrade_modal'; +import { UpgradeConflictsModal } from '../../../../../detections/components/modals/upgrade_conflicts_modal'; import * as ruleDetailsI18n from '../../../../rule_management/components/rule_details/translations'; import * as i18n from './translations'; import { usePrebuiltRulesUpgradeState } from './use_prebuilt_rules_upgrade_state'; import { useRulePreviewFlyout } from '../use_rule_preview_flyout'; export interface UpgradePrebuiltRulesTableState { + /** + * Rule upgrade state (all rules available for upgrade) + */ + ruleUpgradeInfos: RuleUpgradeInfoForReview[]; /** * Rule upgrade state after applying `filterOptions` */ @@ -90,7 +93,6 @@ export const PREBUILT_RULE_UPDATE_FLYOUT_ANCHOR = 'updatePrebuiltRulePreview'; export interface UpgradePrebuiltRulesTableActions { reFetchRules: () => void; upgradeRules: (ruleIds: RuleSignatureId[]) => void; - upgradeAllRules: () => void; setFilterOptions: Dispatch>; openRulePreview: (ruleId: string) => void; } @@ -144,18 +146,38 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ // Wrapper to add confirmation modal for users who may be running older ML Jobs that would // be overridden by updating their rules. For details, see: https://github.com/elastic/kibana/issues/128121 - const [isUpgradeModalVisible, showUpgradeModal, hideUpgradeModal] = useBoolState(false); + const [isLegacyMLJobsModalVisible, showLegacyMLJobsModal, hideLegacyMLJobsModal] = + useBoolState(false); + // Wrapper to add confirmation modal for rules that have conflicts in their fields + const [isConflictsModalVisible, showConflictsModal, hideConflictsModal] = useBoolState(false); + const { loading: loadingJobs, jobs } = useInstalledSecurityJobs(); const legacyJobsInstalled = jobs.filter((job) => affectedJobIds.includes(job.id)); - const [confirmUpgrade, handleUpgradeConfirm, handleUpgradeCancel] = useAsyncConfirmation({ - onInit: showUpgradeModal, - onFinish: hideUpgradeModal, - }); + const [confirmLegacyMLJobs, handleLegacyMLJobsConfirm, handleLegacyMLJobsCancel] = + useAsyncConfirmation({ + onInit: showLegacyMLJobsModal, + onFinish: hideLegacyMLJobsModal, + }); + + const [confirmConflictsUpgrade, handleConflictsConfirm, handleConflictsCancel] = + useAsyncConfirmation({ + onInit: showConflictsModal, + onFinish: hideConflictsModal, + }); - const shouldConfirmUpgrade = legacyJobsInstalled.length > 0; + const shouldConfirmMLJobs = legacyJobsInstalled.length > 0; + const getRulesWithConflicts = useCallback( + (ruleIds?: RuleSignatureId[]) => { + // If no rules are selected (update all rules case), then check all rules + const rulesSelectedForUpgrade = ruleIds ?? Object.keys(rulesUpgradeState); + const rulesToUpgrade = rulesSelectedForUpgrade.map((ruleId) => rulesUpgradeState[ruleId]); + + return rulesToUpgrade.filter((rule) => rule.diff.num_fields_with_conflicts > 0); + }, + [rulesUpgradeState] + ); - const { mutateAsync: upgradeAllRulesRequest } = usePerformUpgradeAllRules(); const { mutateAsync: upgradeSpecificRulesRequest } = usePerformUpgradeSpecificRules(); const upgradeRules = useCallback( @@ -169,32 +191,36 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ })); setLoadingRules((prev) => [...prev, ...rulesToUpgrade.map((r) => r.rule_id)]); try { - if (shouldConfirmUpgrade && !(await confirmUpgrade())) { + if (shouldConfirmMLJobs && !(await confirmLegacyMLJobs())) { return; } - await upgradeSpecificRulesRequest(rulesToUpgrade); + + const rulesWithConflicts = getRulesWithConflicts(ruleIds); + if (rulesWithConflicts.length > 0 && !(await confirmConflictsUpgrade())) { + return; + } + + const ruleIdsWithConflicts = rulesWithConflicts.map((rule) => rule.rule_id); + const rulesToUpgradeWithNoConflicts = rulesToUpgrade.filter( + (rule) => !ruleIdsWithConflicts.includes(rule.rule_id) + ); + await upgradeSpecificRulesRequest(rulesToUpgradeWithNoConflicts); } finally { setLoadingRules((prev) => prev.filter((id) => !rulesToUpgrade.some((r) => r.rule_id === id)) ); } }, - [confirmUpgrade, shouldConfirmUpgrade, rulesUpgradeState, upgradeSpecificRulesRequest] + [ + confirmLegacyMLJobs, + confirmConflictsUpgrade, + shouldConfirmMLJobs, + getRulesWithConflicts, + rulesUpgradeState, + upgradeSpecificRulesRequest, + ] ); - const upgradeAllRules = useCallback(async () => { - // Unselect all rules so that the table doesn't show the "bulk actions" bar - setLoadingRules((prev) => [...prev, ...ruleUpgradeInfos.map((r) => r.rule_id)]); - try { - if (shouldConfirmUpgrade && !(await confirmUpgrade())) { - return; - } - await upgradeAllRulesRequest(); - } finally { - setLoadingRules([]); - } - }, [confirmUpgrade, ruleUpgradeInfos, shouldConfirmUpgrade, upgradeAllRulesRequest]); - const ruleActionsFactory = useCallback( (rule: RuleResponse, closeRulePreview: () => void) => ( ({ reFetchRules: refetch, upgradeRules, - upgradeAllRules, setFilterOptions, openRulePreview, }), - [refetch, upgradeRules, upgradeAllRules, openRulePreview] + [refetch, upgradeRules, openRulePreview] ); const providerValue = useMemo(() => { return { state: { + ruleUpgradeInfos, rulesUpgradeState, hasRulesToUpgrade: isFetched && ruleUpgradeInfos.length > 0, filterOptions, @@ -343,11 +369,17 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ return ( <> - {isUpgradeModalVisible && ( + {isLegacyMLJobsModalVisible && ( + )} + {isConflictsModalVisible && ( + )} {children} diff --git a/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/index.tsx b/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/index.tsx new file mode 100644 index 000000000000..265a989e1bd2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/index.tsx @@ -0,0 +1,35 @@ +/* + * 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. + */ + +import { EuiConfirmModal, EuiText } from '@elastic/eui'; +import React, { memo } from 'react'; +import * as i18n from './translations'; + +export interface UpgradeConflictsModalProps { + onCancel: ( + event?: React.KeyboardEvent | React.MouseEvent + ) => void; + onConfirm?: (event: React.MouseEvent) => void; +} + +const UpgradeConflictsModalComponent = ({ onCancel, onConfirm }: UpgradeConflictsModalProps) => { + return ( + + {i18n.UPGRADE_CONFLICTS_MODAL_BODY} + + ); +}; + +export const UpgradeConflictsModal = memo(UpgradeConflictsModalComponent); diff --git a/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx b/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx new file mode 100644 index 000000000000..22cde17b1b07 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx @@ -0,0 +1,44 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; + +export const UPGRADE_CONFLICTS_MODAL_TITLE = i18n.translate( + 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.messageTitle', + { + defaultMessage: 'Rule with conflicts will not be updated', + } +); + +export const UPGRADE_CONFLICTS_MODAL_CANCEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.cancelTitle', + { + defaultMessage: 'Cancel', + } +); + +export const UPGRADE_CONFLICTS_MODAL_CONFIRM = i18n.translate( + 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.confirmTitle', + { + defaultMessage: 'Upgrade rules with no conflicts', + } +); + +export const UPGRADE_CONFLICTS_MODAL_BODY = i18n.translate( + 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.affectedJobsTitle', + { + defaultMessage: + 'Some of the rules selected have conflicts in one or more of their fields and will not be updated. Please resolve the conflicts on a case-per-case basis.', + } +); + +export const UPGRADE_CONFLICTS_MODAL_AFFECTED_RULES = i18n.translate( + 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.affectedJobsTitle', + { + defaultMessage: 'Affected rules:', + } +); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/create_upgradeable_rules_payload.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/create_upgradeable_rules_payload.ts index b25320e1131e..7f9f66d1019c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/create_upgradeable_rules_payload.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/create_upgradeable_rules_payload.ts @@ -26,6 +26,7 @@ import { getValueForField } from './get_value_for_field'; interface CreateModifiedPrebuiltRuleAssetsProps { upgradeableRules: RuleTriad[]; requestBody: PerformRuleUpgradeRequestBody; + prebuiltRulesCustomizationEnabled: boolean; } interface ProcessedRules { @@ -36,9 +37,13 @@ interface ProcessedRules { export const createModifiedPrebuiltRuleAssets = ({ upgradeableRules, requestBody, + prebuiltRulesCustomizationEnabled, }: CreateModifiedPrebuiltRuleAssetsProps) => { return withSecuritySpanSync(createModifiedPrebuiltRuleAssets.name, () => { - const { pick_version: globalPickVersion = PickVersionValuesEnum.MERGED, mode } = requestBody; + const defaultPickVersion = prebuiltRulesCustomizationEnabled + ? PickVersionValuesEnum.MERGED + : PickVersionValuesEnum.TARGET; + const { pick_version: globalPickVersion = defaultPickVersion, mode } = requestBody; const { modifiedPrebuiltRuleAssets, processingErrors } = upgradeableRules.reduce( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts index 085c41db3a5d..c8b5d459f678 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -25,8 +25,12 @@ import { PREBUILT_RULES_OPERATION_SOCKET_TIMEOUT_MS } from '../../constants'; import { getUpgradeableRules } from './get_upgradeable_rules'; import { createModifiedPrebuiltRuleAssets } from './create_upgradeable_rules_payload'; import { getRuleGroups } from '../../model/rule_groups/get_rule_groups'; +import type { ConfigType } from '../../../../../config'; -export const performRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => { +export const performRuleUpgradeRoute = ( + router: SecuritySolutionPluginRouter, + config: ConfigType +) => { router.versioned .post({ access: 'internal', @@ -75,10 +79,12 @@ export const performRuleUpgradeRoute = (router: SecuritySolutionPluginRouter) => mode, }); + const { prebuiltRulesCustomizationEnabled } = config.experimentalFeatures; const { modifiedPrebuiltRuleAssets, processingErrors } = createModifiedPrebuiltRuleAssets( { upgradeableRules, requestBody: request.body, + prebuiltRulesCustomizationEnabled, } ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/register_routes.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/register_routes.ts index c9871f86a43e..2a2cf8823763 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/register_routes.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/register_routes.ts @@ -6,7 +6,7 @@ */ import type { SecuritySolutionPluginRouter } from '../../../../types'; - +import type { ConfigType } from '../../../../config'; import { getPrebuiltRulesAndTimelinesStatusRoute } from './get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route'; import { getPrebuiltRulesStatusRoute } from './get_prebuilt_rules_status/get_prebuilt_rules_status_route'; import { installPrebuiltRulesAndTimelinesRoute } from './install_prebuilt_rules_and_timelines/install_prebuilt_rules_and_timelines_route'; @@ -16,7 +16,10 @@ import { performRuleInstallationRoute } from './perform_rule_installation/perfor import { performRuleUpgradeRoute } from './perform_rule_upgrade/perform_rule_upgrade_route'; import { bootstrapPrebuiltRulesRoute } from './bootstrap_prebuilt_rules/bootstrap_prebuilt_rules'; -export const registerPrebuiltRulesRoutes = (router: SecuritySolutionPluginRouter) => { +export const registerPrebuiltRulesRoutes = ( + router: SecuritySolutionPluginRouter, + config: ConfigType +) => { // Legacy endpoints that we're going to deprecate getPrebuiltRulesAndTimelinesStatusRoute(router); installPrebuiltRulesAndTimelinesRoute(router); @@ -24,7 +27,7 @@ export const registerPrebuiltRulesRoutes = (router: SecuritySolutionPluginRouter // New endpoints for the rule upgrade and installation workflows getPrebuiltRulesStatusRoute(router); performRuleInstallationRoute(router); - performRuleUpgradeRoute(router); + performRuleUpgradeRoute(router, config); reviewRuleInstallationRoute(router); reviewRuleUpgradeRoute(router); bootstrapPrebuiltRulesRoute(router); diff --git a/x-pack/plugins/security_solution/server/routes/index.ts b/x-pack/plugins/security_solution/server/routes/index.ts index 8fb74afc770b..f7d5ce7afb3d 100644 --- a/x-pack/plugins/security_solution/server/routes/index.ts +++ b/x-pack/plugins/security_solution/server/routes/index.ts @@ -81,7 +81,7 @@ export const initRoutes = ( ) => { registerFleetIntegrationsRoutes(router); registerLegacyRuleActionsRoutes(router, logger); - registerPrebuiltRulesRoutes(router); + registerPrebuiltRulesRoutes(router, config); registerRuleExceptionsRoutes(router); registerManageExceptionsRoutes(router); registerRuleManagementRoutes(router, config, ml, logger); From b7e772f9cc0d2d17d8d2af58eefac136b8f5f364 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 18 Oct 2024 16:08:07 -0300 Subject: [PATCH 02/19] Transform IndexPatterns and DataView values during upgrade --- .../api/perform_rule_upgrade/perform_rule_upgrade_route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts index c8b5d459f678..2783147a91da 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -87,7 +87,7 @@ export const performRuleUpgradeRoute = ( prebuiltRulesCustomizationEnabled, } ); - + debugger; const { results: updatedRules, errors: installationErrors } = await upgradePrebuiltRules( detectionRulesClient, modifiedPrebuiltRuleAssets From 673635edb6b4799b93af4565dd31544d6995ffe9 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 18 Oct 2024 16:09:03 -0300 Subject: [PATCH 03/19] Conditionally update to MERGED version on feature flag --- .../detection_engine/rule_management/api/api.ts | 5 +++-- ...e_perform_specific_rules_upgrade_mutation.ts | 3 ++- .../prebuilt_rules/use_perform_rule_upgrade.ts | 4 ++-- .../upgrade_prebuilt_rules_table_context.tsx | 17 ++++++++++++----- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts index f9d7a07c450e..9fab56c37432 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts @@ -679,7 +679,8 @@ export const performInstallSpecificRules = async ( }); export const performUpgradeSpecificRules = async ( - rules: UpgradeSpecificRulesRequest['rules'] + rules: UpgradeSpecificRulesRequest['rules'], + isPrebuiltRulesCustomizationEnabled: boolean ): Promise => KibanaServices.get().http.fetch(PERFORM_RULE_UPGRADE_URL, { method: 'POST', @@ -687,7 +688,7 @@ export const performUpgradeSpecificRules = async ( body: JSON.stringify({ mode: 'SPECIFIC_RULES', rules, - pick_version: 'TARGET', // Setting fixed 'TARGET' temporarily for Milestone 2 + pick_version: isPrebuiltRulesCustomizationEnabled ? 'MERGED' : 'TARGET', }), }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation.ts index c10b92ea914f..8be2c53a9590 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation.ts @@ -26,6 +26,7 @@ export const PERFORM_SPECIFIC_RULES_UPGRADE_KEY = [ ]; export const usePerformSpecificRulesUpgradeMutation = ( + isPrebuiltRulesCustomizationEnabled: boolean, options?: UseMutationOptions< PerformRuleUpgradeResponseBody, Error, @@ -43,7 +44,7 @@ export const usePerformSpecificRulesUpgradeMutation = ( return useMutation( (rulesToUpgrade: UpgradeSpecificRulesRequest['rules']) => { - return performUpgradeSpecificRules(rulesToUpgrade); + return performUpgradeSpecificRules(rulesToUpgrade, isPrebuiltRulesCustomizationEnabled); }, { ...options, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts index 33f36ffe14da..45b5760cfe11 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts @@ -9,10 +9,10 @@ import { usePerformSpecificRulesUpgradeMutation } from '../../api/hooks/prebuilt import * as i18n from './translations'; -export const usePerformUpgradeSpecificRules = () => { +export const usePerformUpgradeSpecificRules = (isPrebuiltRulesCustomizationEnabled: boolean) => { const { addError, addSuccess } = useAppToasts(); - return usePerformSpecificRulesUpgradeMutation({ + return usePerformSpecificRulesUpgradeMutation(isPrebuiltRulesCustomizationEnabled, { onError: (err) => { addError(err, { title: i18n.RULE_UPGRADE_FAILED }); }, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx index 94753c7e9547..27832df04683 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx @@ -178,7 +178,9 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ [rulesUpgradeState] ); - const { mutateAsync: upgradeSpecificRulesRequest } = usePerformUpgradeSpecificRules(); + const { mutateAsync: upgradeSpecificRulesRequest } = usePerformUpgradeSpecificRules( + isPrebuiltRulesCustomizationEnabled + ); const upgradeRules = useCallback( async (ruleIds: RuleSignatureId[]) => { @@ -196,14 +198,18 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ } const rulesWithConflicts = getRulesWithConflicts(ruleIds); - if (rulesWithConflicts.length > 0 && !(await confirmConflictsUpgrade())) { + if ( + isPrebuiltRulesCustomizationEnabled && + rulesWithConflicts.length > 0 && + !(await confirmConflictsUpgrade()) + ) { return; } const ruleIdsWithConflicts = rulesWithConflicts.map((rule) => rule.rule_id); - const rulesToUpgradeWithNoConflicts = rulesToUpgrade.filter( - (rule) => !ruleIdsWithConflicts.includes(rule.rule_id) - ); + const rulesToUpgradeWithNoConflicts = isPrebuiltRulesCustomizationEnabled + ? rulesToUpgrade.filter((rule) => !ruleIdsWithConflicts.includes(rule.rule_id)) + : rulesToUpgrade; await upgradeSpecificRulesRequest(rulesToUpgradeWithNoConflicts); } finally { setLoadingRules((prev) => @@ -218,6 +224,7 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ getRulesWithConflicts, rulesUpgradeState, upgradeSpecificRulesRequest, + isPrebuiltRulesCustomizationEnabled, ] ); From 2a5dc5570119fded7308a3dde66d8e2c6ea484f9 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 18 Oct 2024 16:09:41 -0300 Subject: [PATCH 04/19] Remove debugger --- .../api/perform_rule_upgrade/perform_rule_upgrade_route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts index 2783147a91da..c8b5d459f678 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -87,7 +87,7 @@ export const performRuleUpgradeRoute = ( prebuiltRulesCustomizationEnabled, } ); - debugger; + const { results: updatedRules, errors: installationErrors } = await upgradePrebuiltRules( detectionRulesClient, modifiedPrebuiltRuleAssets From 05c1ec8186d14076a6158a629d33f167238c63d1 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 18 Oct 2024 16:22:21 -0300 Subject: [PATCH 05/19] Fix typo --- .../api/perform_rule_upgrade/perform_rule_upgrade_route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts index c8b5d459f678..2783147a91da 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -87,7 +87,7 @@ export const performRuleUpgradeRoute = ( prebuiltRulesCustomizationEnabled, } ); - + debugger; const { results: updatedRules, errors: installationErrors } = await upgradePrebuiltRules( detectionRulesClient, modifiedPrebuiltRuleAssets From c4e804b33411583368572075e899a4d6444abc65 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 18 Oct 2024 16:39:19 -0300 Subject: [PATCH 06/19] Refactor --- .../upgrade_prebuilt_rules_table_buttons.tsx | 13 +++--- .../upgrade_prebuilt_rules_table_context.tsx | 42 ++++++++--------- .../use_upgrade_modals.tsx | 45 +++++++++++++++++++ .../upgrade_conflicts_modal/translations.tsx | 9 +--- .../perform_rule_upgrade_route.ts | 2 +- 5 files changed, 73 insertions(+), 38 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_modals.tsx diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx index 489d60bfb2ac..8fca417ba995 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx @@ -39,18 +39,17 @@ export const UpgradePrebuiltRulesTableButtons = ({ const isRuleUpgrading = loadingRules.length > 0; const isRequestInProgress = isRuleUpgrading || isRefetching || isUpgradingSecurityPackages; const isAllSelectedRulesHaveConflicts = - isPrebuiltRulesCustomizationEnabled && - selectedRules.every((rule) => rule.diff.num_fields_with_conflicts > 0); + isPrebuiltRulesCustomizationEnabled && isAllRuleHaveConflicts(selectedRules); const isAllRulesHaveConflicts = - isPrebuiltRulesCustomizationEnabled && - ruleUpgradeInfos.every((rule) => rule.diff.num_fields_with_conflicts > 0); + isPrebuiltRulesCustomizationEnabled && isAllRuleHaveConflicts(ruleUpgradeInfos); + const upgradeSelectedRules = useCallback( () => upgradeRules(selectedRules.map((rule) => rule.rule_id)), [selectedRules, upgradeRules] ); const upgradeAllRules = useCallback( - // Upgrade all rules, ignoring filter and selction + // Upgrade all rules, ignoring filter and selection () => upgradeRules(ruleUpgradeInfos.map((rule) => rule.rule_id)), [ruleUpgradeInfos, upgradeRules] ); @@ -91,3 +90,7 @@ export const UpgradePrebuiltRulesTableButtons = ({ ); }; + +function isAllRuleHaveConflicts(rules: Array<{ diff: { num_fields_with_conflicts: number } }>) { + return rules.every((rule) => rule.diff.num_fields_with_conflicts > 0); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx index 27832df04683..236e599514a8 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx @@ -14,9 +14,6 @@ import type { RulesUpgradeState } from '../../../../rule_management/model/prebui import { RuleUpgradeConflictsResolverTab } from '../../../../rule_management/components/rule_details/three_way_diff/rule_upgrade_conflicts_resolver_tab'; import { PerFieldRuleDiffTab } from '../../../../rule_management/components/rule_details/per_field_rule_diff_tab'; import { useIsUpgradingSecurityPackages } from '../../../../rule_management/logic/use_upgrade_security_packages'; -import { useInstalledSecurityJobs } from '../../../../../common/components/ml/hooks/use_installed_security_jobs'; -import { useBoolState } from '../../../../../common/hooks/use_bool_state'; -import { affectedJobIds } from '../../../../../detections/components/callouts/ml_job_compatibility_callout/affected_job_ids'; import type { RuleResponse, RuleSignatureId, @@ -26,7 +23,6 @@ import { usePerformUpgradeSpecificRules } from '../../../../rule_management/logi import { usePrebuiltRulesUpgradeReview } from '../../../../rule_management/logic/prebuilt_rules/use_prebuilt_rules_upgrade_review'; import type { UpgradePrebuiltRulesTableFilterOptions } from './use_filter_prebuilt_rules_to_upgrade'; import { useFilterPrebuiltRulesToUpgrade } from './use_filter_prebuilt_rules_to_upgrade'; -import { useAsyncConfirmation } from '../rules_table/use_async_confirmation'; import { TabContentPadding } from '../../../../rule_management/components/rule_details/rule_details_flyout'; import { RuleDiffTab } from '../../../../rule_management/components/rule_details/rule_diff_tab'; import { MlJobUpgradeModal } from '../../../../../detections/components/modals/ml_job_upgrade_modal'; @@ -35,6 +31,7 @@ import * as ruleDetailsI18n from '../../../../rule_management/components/rule_de import * as i18n from './translations'; import { usePrebuiltRulesUpgradeState } from './use_prebuilt_rules_upgrade_state'; import { useRulePreviewFlyout } from '../use_rule_preview_flyout'; +import { useMlJobUpgradeModal, useUpgradeConflictsModal } from './use_upgrade_modals'; export interface UpgradePrebuiltRulesTableState { /** @@ -144,27 +141,21 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ const { rulesUpgradeState, setRuleFieldResolvedValue } = usePrebuiltRulesUpgradeState(filteredRuleUpgradeInfos); - // Wrapper to add confirmation modal for users who may be running older ML Jobs that would - // be overridden by updating their rules. For details, see: https://github.com/elastic/kibana/issues/128121 - const [isLegacyMLJobsModalVisible, showLegacyMLJobsModal, hideLegacyMLJobsModal] = - useBoolState(false); - // Wrapper to add confirmation modal for rules that have conflicts in their fields - const [isConflictsModalVisible, showConflictsModal, hideConflictsModal] = useBoolState(false); - - const { loading: loadingJobs, jobs } = useInstalledSecurityJobs(); - const legacyJobsInstalled = jobs.filter((job) => affectedJobIds.includes(job.id)); - - const [confirmLegacyMLJobs, handleLegacyMLJobsConfirm, handleLegacyMLJobsCancel] = - useAsyncConfirmation({ - onInit: showLegacyMLJobsModal, - onFinish: hideLegacyMLJobsModal, - }); + const { + isVisible: isLegacyMLJobsModalVisible, + legacyJobsInstalled, + confirmLegacyMLJobs, + handleConfirm: handleLegacyMLJobsConfirm, + handleCancel: handleLegacyMLJobsCancel, + loadingJobs, + } = useMlJobUpgradeModal(); - const [confirmConflictsUpgrade, handleConflictsConfirm, handleConflictsCancel] = - useAsyncConfirmation({ - onInit: showConflictsModal, - onFinish: hideConflictsModal, - }); + const { + isVisible: isConflictsModalVisible, + confirmConflictsUpgrade, + handleConfirm: handleConflictsConfirm, + handleCancel: handleConflictsCancel, + } = useUpgradeConflictsModal(); const shouldConfirmMLJobs = legacyJobsInstalled.length > 0; const getRulesWithConflicts = useCallback( @@ -193,10 +184,12 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ })); setLoadingRules((prev) => [...prev, ...rulesToUpgrade.map((r) => r.rule_id)]); try { + // Handle MLJobs modal if (shouldConfirmMLJobs && !(await confirmLegacyMLJobs())) { return; } + // Handle Rule Upgrades modal const rulesWithConflicts = getRulesWithConflicts(ruleIds); if ( isPrebuiltRulesCustomizationEnabled && @@ -206,6 +199,7 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ return; } + // Prepare payload for upgrade with rules with no conflicts const ruleIdsWithConflicts = rulesWithConflicts.map((rule) => rule.rule_id); const rulesToUpgradeWithNoConflicts = isPrebuiltRulesCustomizationEnabled ? rulesToUpgrade.filter((rule) => !ruleIdsWithConflicts.includes(rule.rule_id)) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_modals.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_modals.tsx new file mode 100644 index 000000000000..39ed818011f4 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_modals.tsx @@ -0,0 +1,45 @@ +/* + * 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. + */ + +import { useInstalledSecurityJobs } from '../../../../../common/components/ml/hooks/use_installed_security_jobs'; +import { useBoolState } from '../../../../../common/hooks/use_bool_state'; +import { affectedJobIds } from '../../../../../detections/components/callouts/ml_job_compatibility_callout/affected_job_ids'; +import { useAsyncConfirmation } from '../rules_table/use_async_confirmation'; + +export const useMlJobUpgradeModal = () => { + const [isVisible, showModal, hideModal] = useBoolState(false); + const { loading: loadingJobs, jobs } = useInstalledSecurityJobs(); + const legacyJobsInstalled = jobs.filter((job) => affectedJobIds.includes(job.id)); + const [confirmLegacyMLJobs, handleConfirm, handleCancel] = useAsyncConfirmation({ + onInit: showModal, + onFinish: hideModal, + }); + + return { + isVisible, + legacyJobsInstalled, + confirmLegacyMLJobs, + handleConfirm, + handleCancel, + loadingJobs, + }; +}; + +export const useUpgradeConflictsModal = () => { + const [isVisible, showModal, hideModal] = useBoolState(false); + const [confirmConflictsUpgrade, handleConfirm, handleCancel] = useAsyncConfirmation({ + onInit: showModal, + onFinish: hideModal, + }); + + return { + isVisible, + confirmConflictsUpgrade, + handleConfirm, + handleCancel, + }; +}; diff --git a/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx b/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx index 22cde17b1b07..e1f37f0620ec 100644 --- a/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx @@ -34,11 +34,4 @@ export const UPGRADE_CONFLICTS_MODAL_BODY = i18n.translate( defaultMessage: 'Some of the rules selected have conflicts in one or more of their fields and will not be updated. Please resolve the conflicts on a case-per-case basis.', } -); - -export const UPGRADE_CONFLICTS_MODAL_AFFECTED_RULES = i18n.translate( - 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.affectedJobsTitle', - { - defaultMessage: 'Affected rules:', - } -); +); \ No newline at end of file diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts index 2783147a91da..c8b5d459f678 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/perform_rule_upgrade_route.ts @@ -87,7 +87,7 @@ export const performRuleUpgradeRoute = ( prebuiltRulesCustomizationEnabled, } ); - debugger; + const { results: updatedRules, errors: installationErrors } = await upgradePrebuiltRules( detectionRulesClient, modifiedPrebuiltRuleAssets From 99f08d1dd81d0ac46075de5ac15a8a4f731ba379 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Fri, 18 Oct 2024 17:09:08 -0300 Subject: [PATCH 07/19] fix lint --- .../components/modals/upgrade_conflicts_modal/translations.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx b/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx index e1f37f0620ec..acf5cbaefa61 100644 --- a/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx @@ -34,4 +34,4 @@ export const UPGRADE_CONFLICTS_MODAL_BODY = i18n.translate( defaultMessage: 'Some of the rules selected have conflicts in one or more of their fields and will not be updated. Please resolve the conflicts on a case-per-case basis.', } -); \ No newline at end of file +); From 98d42cb686208290063b8521ccc165e2c2f745fe Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 31 Oct 2024 15:59:32 -0300 Subject: [PATCH 08/19] Addressed comments --- .github/CODEOWNERS | 1 - config/kibana.yml | 10 ++ .../machine_learning}/affected_job_ids.ts | 0 .../rule_management/api/api.ts | 5 +- ...perform_specific_rules_upgrade_mutation.ts | 5 +- .../use_perform_rule_upgrade.ts | 9 +- .../modals/ml_job_upgrade_modal/index.tsx | 0 .../ml_job_upgrade_modal/translations.tsx | 2 +- .../modals/upgrade_conflicts_modal/index.tsx | 0 .../upgrade_conflicts_modal/translations.tsx | 6 +- .../translations.ts | 27 +++++ .../upgrade_prebuilt_rules_table_buttons.tsx | 112 +++++++++++++----- .../upgrade_prebuilt_rules_table_context.tsx | 29 +++-- .../use_upgrade_modals.tsx | 2 +- ...e_upgrade_prebuilt_rules_table_columns.tsx | 22 ++-- .../ml_job_compatibility_callout/index.tsx | 2 +- .../detection_engine/rules/translations.ts | 7 ++ 17 files changed, 180 insertions(+), 59 deletions(-) rename x-pack/plugins/security_solution/{public/detections/components/callouts/ml_job_compatibility_callout => common/machine_learning}/affected_job_ids.ts (100%) rename x-pack/plugins/security_solution/public/{detections/components => detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table}/modals/ml_job_upgrade_modal/index.tsx (100%) rename x-pack/plugins/security_solution/public/{detections/components => detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table}/modals/ml_job_upgrade_modal/translations.tsx (95%) rename x-pack/plugins/security_solution/public/{detections/components => detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table}/modals/upgrade_conflicts_modal/index.tsx (100%) rename x-pack/plugins/security_solution/public/{detections/components => detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table}/modals/upgrade_conflicts_modal/translations.tsx (82%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6dc2aa32a79a..204e3e7b1860 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1842,7 +1842,6 @@ x-pack/test/security_solution_cypress/cypress/tasks/expandable_flyout @elastic/ /x-pack/plugins/security_solution/public/detection_engine/rule_management_ui @elastic/security-detection-rule-management /x-pack/plugins/security_solution/public/detection_engine/rule_monitoring @elastic/security-detection-rule-management /x-pack/plugins/security_solution/public/detections/components/callouts @elastic/security-detection-rule-management -/x-pack/plugins/security_solution/public/detections/components/modals/ml_job_upgrade_modal @elastic/security-detection-rule-management /x-pack/plugins/security_solution/public/detections/components/rules @elastic/security-detection-rule-management /x-pack/plugins/security_solution/public/detections/components/rules/rule_preview @elastic/security-detection-engine /x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules @elastic/security-detection-rule-management diff --git a/config/kibana.yml b/config/kibana.yml index c816337f881d..ab5af7b228f4 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -1,3 +1,13 @@ +csp.strict: false +xpack.security.encryptionKey: 've4Vohnu oa0Fu9ae Eethee8c oDieg4do Nohrah1u ao9Hu2oh Aeb4Ieyi Aew1aegi' +xpack.encryptedSavedObjects.encryptionKey: 'Shah7nai Eew6izai Eir7OoW0 Gewi2ief eiSh8woo shoogh7E Quae6hal ce6Oumah' + +xpack.fleet.internal.registry.kibanaVersionCheckEnabled: false + +elasticsearch: + username: 'kibana_system' + password: 'changeme' + hosts: 'http://localhost:9200' # For more configuration options see the configuration guide for Kibana in # https://www.elastic.co/guide/index.html diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/ml_job_compatibility_callout/affected_job_ids.ts b/x-pack/plugins/security_solution/common/machine_learning/affected_job_ids.ts similarity index 100% rename from x-pack/plugins/security_solution/public/detections/components/callouts/ml_job_compatibility_callout/affected_job_ids.ts rename to x-pack/plugins/security_solution/common/machine_learning/affected_job_ids.ts diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts index 9fab56c37432..aea4b6672659 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts @@ -16,6 +16,7 @@ import type { ActionResult } from '@kbn/actions-plugin/server'; import { convertRulesFilterToKQL } from '../../../../common/detection_engine/rule_management/rule_filtering'; import type { UpgradeSpecificRulesRequest, + PickVersionValues, PerformRuleUpgradeResponseBody, InstallSpecificRulesRequest, PerformRuleInstallationResponseBody, @@ -680,7 +681,7 @@ export const performInstallSpecificRules = async ( export const performUpgradeSpecificRules = async ( rules: UpgradeSpecificRulesRequest['rules'], - isPrebuiltRulesCustomizationEnabled: boolean + pickVersion: PickVersionValues ): Promise => KibanaServices.get().http.fetch(PERFORM_RULE_UPGRADE_URL, { method: 'POST', @@ -688,7 +689,7 @@ export const performUpgradeSpecificRules = async ( body: JSON.stringify({ mode: 'SPECIFIC_RULES', rules, - pick_version: isPrebuiltRulesCustomizationEnabled ? 'MERGED' : 'TARGET', + pick_version: pickVersion, }), }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation.ts index 8be2c53a9590..08338ab9a932 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation.ts @@ -8,6 +8,7 @@ import type { UseMutationOptions } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query'; import type { PerformRuleUpgradeResponseBody, + PickVersionValues, UpgradeSpecificRulesRequest, } from '../../../../../../common/api/detection_engine/prebuilt_rules'; import { PERFORM_RULE_UPGRADE_URL } from '../../../../../../common/api/detection_engine/prebuilt_rules/urls'; @@ -26,7 +27,7 @@ export const PERFORM_SPECIFIC_RULES_UPGRADE_KEY = [ ]; export const usePerformSpecificRulesUpgradeMutation = ( - isPrebuiltRulesCustomizationEnabled: boolean, + pickVersion: PickVersionValues, options?: UseMutationOptions< PerformRuleUpgradeResponseBody, Error, @@ -44,7 +45,7 @@ export const usePerformSpecificRulesUpgradeMutation = ( return useMutation( (rulesToUpgrade: UpgradeSpecificRulesRequest['rules']) => { - return performUpgradeSpecificRules(rulesToUpgrade, isPrebuiltRulesCustomizationEnabled); + return performUpgradeSpecificRules(rulesToUpgrade, pickVersion); }, { ...options, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts index 45b5760cfe11..f82812f7ac9d 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/prebuilt_rules/use_perform_rule_upgrade.ts @@ -4,15 +4,20 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import type { PickVersionValues } from '../../../../../common/api/detection_engine'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import { usePerformSpecificRulesUpgradeMutation } from '../../api/hooks/prebuilt_rules/use_perform_specific_rules_upgrade_mutation'; import * as i18n from './translations'; -export const usePerformUpgradeSpecificRules = (isPrebuiltRulesCustomizationEnabled: boolean) => { +export const usePerformUpgradeSpecificRules = ({ + pickVersion, +}: { + pickVersion: PickVersionValues; +}) => { const { addError, addSuccess } = useAppToasts(); - return usePerformSpecificRulesUpgradeMutation(isPrebuiltRulesCustomizationEnabled, { + return usePerformSpecificRulesUpgradeMutation(pickVersion, { onError: (err) => { addError(err, { title: i18n.RULE_UPGRADE_FAILED }); }, diff --git a/x-pack/plugins/security_solution/public/detections/components/modals/ml_job_upgrade_modal/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/ml_job_upgrade_modal/index.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/detections/components/modals/ml_job_upgrade_modal/index.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/ml_job_upgrade_modal/index.tsx diff --git a/x-pack/plugins/security_solution/public/detections/components/modals/ml_job_upgrade_modal/translations.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/ml_job_upgrade_modal/translations.tsx similarity index 95% rename from x-pack/plugins/security_solution/public/detections/components/modals/ml_job_upgrade_modal/translations.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/ml_job_upgrade_modal/translations.tsx index 8163eca279cf..caf94e5c1a26 100644 --- a/x-pack/plugins/security_solution/public/detections/components/modals/ml_job_upgrade_modal/translations.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/ml_job_upgrade_modal/translations.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { MlJobCompatibilityLink } from '../../../../common/components/links_to_docs'; +import { MlJobCompatibilityLink } from '../../../../../../../common/components/links_to_docs'; export const ML_JOB_UPGRADE_MODAL_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.mlJobUpgradeModal.messageTitle', diff --git a/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/index.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/index.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/index.tsx diff --git a/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx similarity index 82% rename from x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx index acf5cbaefa61..76645dc87a57 100644 --- a/x-pack/plugins/security_solution/public/detections/components/modals/upgrade_conflicts_modal/translations.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; export const UPGRADE_CONFLICTS_MODAL_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.messageTitle', { - defaultMessage: 'Rule with conflicts will not be updated', + defaultMessage: 'Rules with conflicts will not be updated', } ); @@ -24,7 +24,7 @@ export const UPGRADE_CONFLICTS_MODAL_CANCEL = i18n.translate( export const UPGRADE_CONFLICTS_MODAL_CONFIRM = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.confirmTitle', { - defaultMessage: 'Upgrade rules with no conflicts', + defaultMessage: 'Update rules with no conflicts', } ); @@ -32,6 +32,6 @@ export const UPGRADE_CONFLICTS_MODAL_BODY = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.affectedJobsTitle', { defaultMessage: - 'Some of the rules selected have conflicts in one or more of their fields and will not be updated. Please resolve the conflicts on a case-per-case basis.', + 'Some of the selected rules have conflicts in one or more of their fields and will not be updated. Please resolve the conflicts on a case-by-case basis.', } ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts index 026c35f664bb..9090b9f109ba 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts @@ -24,6 +24,27 @@ export const UPDATE_SELECTED_RULES = (numberOfSelectedRules: number) => { ); }; +export const BULK_UPDATE_BUTTON_TOOLTIP_NO_PERMISSIONS = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.bulkButtons.noPermissions', + { + defaultMessage: "You don't have permissions to update rules", + } +); + +export const BULK_UPDATE_ALL_RULES_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.bulkButtons.allRules.conflicts', + { + defaultMessage: 'All rules have conflicts. Please update them individually.', + } +); + +export const BULK_UPDATE_SELECTED_RULES_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.bulkButtons.selectedRules.conflicts', + { + defaultMessage: 'All selected rules have conflicts. Please update them individually.', + } +); + export const SEARCH_PLACEHOLDER = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.searchBarPlaceholder', { @@ -37,6 +58,12 @@ export const UPDATE_BUTTON_LABEL = i18n.translate( defaultMessage: 'Update', } ); +export const UPDATE_ERROR = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.updateError', + { + defaultMessage: 'Update error', + } +); export const UPDATE_FLYOUT_PER_FIELD_TOOLTIP_DESCRIPTION = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.perFieldTooltip', diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx index 8fca417ba995..8a1d20114965 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_buttons.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; import React, { useCallback } from 'react'; import type { RuleUpgradeState } from '../../../../rule_management/model/prebuilt_rule_upgrade'; import { useUserData } from '../../../../../detections/components/user_info'; @@ -38,11 +38,18 @@ export const UpgradePrebuiltRulesTableButtons = ({ const isRuleUpgrading = loadingRules.length > 0; const isRequestInProgress = isRuleUpgrading || isRefetching || isUpgradingSecurityPackages; - const isAllSelectedRulesHaveConflicts = + const doAllSelectedRulesHaveConflicts = isPrebuiltRulesCustomizationEnabled && isAllRuleHaveConflicts(selectedRules); - const isAllRulesHaveConflicts = + const doAllRulesHaveConflicts = isPrebuiltRulesCustomizationEnabled && isAllRuleHaveConflicts(ruleUpgradeInfos); + const { selectedRulesButtonTooltip, allRulesButtonTooltip } = useBulkUpdateButtonsTooltipContent({ + canUserEditRules, + doAllSelectedRulesHaveConflicts, + doAllRulesHaveConflicts, + isPrebuiltRulesCustomizationEnabled, + }); + const upgradeSelectedRules = useCallback( () => upgradeRules(selectedRules.map((rule) => rule.rule_id)), [selectedRules, upgradeRules] @@ -58,39 +65,88 @@ export const UpgradePrebuiltRulesTableButtons = ({ {shouldDisplayUpgradeSelectedRulesButton ? ( - - <> - {i18n.UPDATE_SELECTED_RULES(numberOfSelectedRules)} - {isRuleUpgrading ? : undefined} - - + + + <> + {i18n.UPDATE_SELECTED_RULES(numberOfSelectedRules)} + {isRuleUpgrading ? : undefined} + + + ) : null} - - {i18n.UPDATE_ALL} - {isRuleUpgrading ? : undefined} - + + + {i18n.UPDATE_ALL} + {isRuleUpgrading ? : undefined} + + ); }; +const useBulkUpdateButtonsTooltipContent = ({ + canUserEditRules, + doAllSelectedRulesHaveConflicts, + doAllRulesHaveConflicts, + isPrebuiltRulesCustomizationEnabled, +}: { + canUserEditRules: boolean | null; + doAllSelectedRulesHaveConflicts: boolean; + doAllRulesHaveConflicts: boolean; + isPrebuiltRulesCustomizationEnabled: boolean; +}) => { + if (!canUserEditRules) { + return { + selectedRulesButtonTooltip: i18n.BULK_UPDATE_BUTTON_TOOLTIP_NO_PERMISSIONS, + allRulesButtonTooltip: i18n.BULK_UPDATE_BUTTON_TOOLTIP_NO_PERMISSIONS, + }; + } + + if (!isPrebuiltRulesCustomizationEnabled) { + return { + selectedRulesButtonTooltip: undefined, + allRulesButtonTooltip: undefined, + }; + } + + if (doAllRulesHaveConflicts) { + return { + selectedRulesButtonTooltip: i18n.BULK_UPDATE_SELECTED_RULES_BUTTON_TOOLTIP_CONFLICTS, + allRulesButtonTooltip: i18n.BULK_UPDATE_ALL_RULES_BUTTON_TOOLTIP_CONFLICTS, + }; + } + + if (doAllSelectedRulesHaveConflicts) { + return { + selectedRulesButtonTooltip: i18n.BULK_UPDATE_SELECTED_RULES_BUTTON_TOOLTIP_CONFLICTS, + allRulesButtonTooltip: undefined, + }; + } + + return { + selectedRulesButtonTooltip: undefined, + allRulesButtonTooltip: undefined, + }; +}; + function isAllRuleHaveConflicts(rules: Array<{ diff: { num_fields_with_conflicts: number } }>) { return rules.every((rule) => rule.diff.num_fields_with_conflicts > 0); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx index 236e599514a8..cbb0350da173 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/upgrade_prebuilt_rules_table_context.tsx @@ -9,6 +9,7 @@ import type { Dispatch, SetStateAction } from 'react'; import React, { createContext, useCallback, useContext, useMemo, useState } from 'react'; import { EuiButton, EuiToolTip } from '@elastic/eui'; import { useIsPrebuiltRulesCustomizationEnabled } from '../../../../rule_management/hooks/use_is_prebuilt_rules_customization_enabled'; +import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { RuleUpgradeInfoForReview } from '../../../../../../common/api/detection_engine'; import type { RulesUpgradeState } from '../../../../rule_management/model/prebuilt_rule_upgrade'; import { RuleUpgradeConflictsResolverTab } from '../../../../rule_management/components/rule_details/three_way_diff/rule_upgrade_conflicts_resolver_tab'; @@ -25,8 +26,8 @@ import type { UpgradePrebuiltRulesTableFilterOptions } from './use_filter_prebui import { useFilterPrebuiltRulesToUpgrade } from './use_filter_prebuilt_rules_to_upgrade'; import { TabContentPadding } from '../../../../rule_management/components/rule_details/rule_details_flyout'; import { RuleDiffTab } from '../../../../rule_management/components/rule_details/rule_diff_tab'; -import { MlJobUpgradeModal } from '../../../../../detections/components/modals/ml_job_upgrade_modal'; -import { UpgradeConflictsModal } from '../../../../../detections/components/modals/upgrade_conflicts_modal'; +import { MlJobUpgradeModal } from './modals/ml_job_upgrade_modal'; +import { UpgradeConflictsModal } from './modals/upgrade_conflicts_modal'; import * as ruleDetailsI18n from '../../../../rule_management/components/rule_details/translations'; import * as i18n from './translations'; import { usePrebuiltRulesUpgradeState } from './use_prebuilt_rules_upgrade_state'; @@ -117,6 +118,7 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ tags: [], ruleSource: [], }); + const { addError } = useAppToasts(); const isUpgradingSecurityPackages = useIsUpgradingSecurityPackages(); @@ -160,18 +162,22 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ const shouldConfirmMLJobs = legacyJobsInstalled.length > 0; const getRulesWithConflicts = useCallback( (ruleIds?: RuleSignatureId[]) => { - // If no rules are selected (update all rules case), then check all rules - const rulesSelectedForUpgrade = ruleIds ?? Object.keys(rulesUpgradeState); - const rulesToUpgrade = rulesSelectedForUpgrade.map((ruleId) => rulesUpgradeState[ruleId]); + const rulesToUpgrade = + ruleIds?.map((ruleId) => { + const rule = rulesUpgradeState[ruleId]; + invariant(rule, `Rule with ID ${ruleId} not found.`); + + return rule; + }) ?? []; return rulesToUpgrade.filter((rule) => rule.diff.num_fields_with_conflicts > 0); }, [rulesUpgradeState] ); - const { mutateAsync: upgradeSpecificRulesRequest } = usePerformUpgradeSpecificRules( - isPrebuiltRulesCustomizationEnabled - ); + const { mutateAsync: upgradeSpecificRulesRequest } = usePerformUpgradeSpecificRules({ + pickVersion: isPrebuiltRulesCustomizationEnabled ? 'MERGED' : 'TARGET', + }); const upgradeRules = useCallback( async (ruleIds: RuleSignatureId[]) => { @@ -200,11 +206,13 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ } // Prepare payload for upgrade with rules with no conflicts - const ruleIdsWithConflicts = rulesWithConflicts.map((rule) => rule.rule_id); + const ruleIdsWithConflicts = new Set(rulesWithConflicts.map((rule) => rule.rule_id)); const rulesToUpgradeWithNoConflicts = isPrebuiltRulesCustomizationEnabled - ? rulesToUpgrade.filter((rule) => !ruleIdsWithConflicts.includes(rule.rule_id)) + ? rulesToUpgrade.filter((rule) => !ruleIdsWithConflicts.has(rule.rule_id)) : rulesToUpgrade; await upgradeSpecificRulesRequest(rulesToUpgradeWithNoConflicts); + } catch (err) { + addError(err, { title: i18n.UPDATE_ERROR }); } finally { setLoadingRules((prev) => prev.filter((id) => !rulesToUpgrade.some((r) => r.rule_id === id)) @@ -219,6 +227,7 @@ export const UpgradePrebuiltRulesTableContextProvider = ({ rulesUpgradeState, upgradeSpecificRulesRequest, isPrebuiltRulesCustomizationEnabled, + addError, ] ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_modals.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_modals.tsx index 39ed818011f4..3e20d914dabc 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_modals.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_modals.tsx @@ -7,7 +7,7 @@ import { useInstalledSecurityJobs } from '../../../../../common/components/ml/hooks/use_installed_security_jobs'; import { useBoolState } from '../../../../../common/hooks/use_bool_state'; -import { affectedJobIds } from '../../../../../detections/components/callouts/ml_job_compatibility_callout/affected_job_ids'; +import { affectedJobIds } from '../../../../../../common/machine_learning/affected_job_ids'; import { useAsyncConfirmation } from '../rules_table/use_async_confirmation'; export const useMlJobUpgradeModal = () => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_prebuilt_rules_table_columns.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_prebuilt_rules_table_columns.tsx index 579f571f80e7..c2b1f8e3dbe4 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_prebuilt_rules_table_columns.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_prebuilt_rules_table_columns.tsx @@ -160,15 +160,21 @@ const createUpgradeButtonColumn = ( /> ); + const tooltipContent = isDisabledByConflicts + ? i18n.UPDATE_RULE_BUTTON_TOOLTIP_CONFLICTS + : undefined; + return ( - upgradeRules([ruleId])} - data-test-subj={`upgradeSinglePrebuiltRuleButton-${ruleId}`} - > - {isRuleUpgrading ? spinner : i18n.UPDATE_RULE_BUTTON} - + + upgradeRules([ruleId])} + data-test-subj={`upgradeSinglePrebuiltRuleButton-${ruleId}`} + > + {isRuleUpgrading ? spinner : i18n.UPDATE_RULE_BUTTON} + + ); }, width: '10%', diff --git a/x-pack/plugins/security_solution/public/detections/components/callouts/ml_job_compatibility_callout/index.tsx b/x-pack/plugins/security_solution/public/detections/components/callouts/ml_job_compatibility_callout/index.tsx index df4eb0a24968..92d42b70d240 100644 --- a/x-pack/plugins/security_solution/public/detections/components/callouts/ml_job_compatibility_callout/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/callouts/ml_job_compatibility_callout/index.tsx @@ -10,7 +10,7 @@ import React, { memo } from 'react'; import type { CallOutMessage } from '../../../../common/components/callouts'; import { CallOutSwitcher } from '../../../../common/components/callouts'; import { useInstalledSecurityJobs } from '../../../../common/components/ml/hooks/use_installed_security_jobs'; -import { affectedJobIds } from './affected_job_ids'; +import { affectedJobIds } from '../../../../../common/machine_learning/affected_job_ids'; import * as i18n from './translations'; const mlJobCompatibilityCalloutMessage: CallOutMessage = { diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts index b6a3bbdc0ad9..143186b143b0 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts @@ -1435,6 +1435,13 @@ export const UPDATE_RULE_BUTTON = i18n.translate( } ); +export const UPDATE_RULE_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.upgradeRules.button.conflicts', + { + defaultMessage: 'Rule has conflicts. Please resolve them manually.', + } +); + export const GO_BACK_TO_RULES_TABLE_BUTTON = i18n.translate( 'xpack.securitySolution.addRules.goBackToRulesTableButton', { From c289c6742f8fed448b400a1c6ffa9af09068d77c Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 31 Oct 2024 16:00:29 -0300 Subject: [PATCH 09/19] revert --- config/kibana.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/config/kibana.yml b/config/kibana.yml index ab5af7b228f4..c816337f881d 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -1,13 +1,3 @@ -csp.strict: false -xpack.security.encryptionKey: 've4Vohnu oa0Fu9ae Eethee8c oDieg4do Nohrah1u ao9Hu2oh Aeb4Ieyi Aew1aegi' -xpack.encryptedSavedObjects.encryptionKey: 'Shah7nai Eew6izai Eir7OoW0 Gewi2ief eiSh8woo shoogh7E Quae6hal ce6Oumah' - -xpack.fleet.internal.registry.kibanaVersionCheckEnabled: false - -elasticsearch: - username: 'kibana_system' - password: 'changeme' - hosts: 'http://localhost:9200' # For more configuration options see the configuration guide for Kibana in # https://www.elastic.co/guide/index.html From ad0bb91fa59613c3195ba7aea5b5818336af2299 Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 31 Oct 2024 16:01:11 -0300 Subject: [PATCH 10/19] revert --- config/kibana.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/kibana.yml b/config/kibana.yml index c816337f881d..6c4fb774eb37 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -181,3 +181,8 @@ # Maximum number of documents loaded by each shard to generate autocomplete suggestions. # This value must be a whole number greater than zero. Defaults to 100_000 #unifiedSearch.autocomplete.valueSuggestions.terminateAfter: 100000 + +# Must be removed before v9 release +# Requires all registry packages to add v9 as a compatible semver range +# https://github.com/elastic/kibana/issues/192624 +xpack.fleet.internal.registry.kibanaVersionCheckEnabled: false From 138a377b58f3cbc95bbdae04323a3eeff7ec1e4f Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 31 Oct 2024 17:51:00 -0300 Subject: [PATCH 11/19] Added e2e tests --- .../modals/upgrade_conflicts_modal/index.tsx | 1 + ...low_with_prebuilt_rule_customization.cy.ts | 155 +++++++++++++++++- .../cypress/screens/rule_updates.ts | 2 + .../cypress/tasks/prebuilt_rules.ts | 9 + 4 files changed, 164 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/index.tsx index 265a989e1bd2..0c664398c51f 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/index.tsx @@ -26,6 +26,7 @@ const UpgradeConflictsModalComponent = ({ onCancel, onConfirm }: UpgradeConflict confirmButtonText={i18n.UPGRADE_CONFLICTS_MODAL_CONFIRM} buttonColor="primary" defaultFocusedButton="confirm" + data-test-subj="upgradeConflictsModal" > {i18n.UPGRADE_CONFLICTS_MODAL_BODY} diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow_with_prebuilt_rule_customization.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow_with_prebuilt_rule_customization.cy.ts index 52b050f46c06..0d7b2c8f336c 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow_with_prebuilt_rule_customization.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow_with_prebuilt_rule_customization.cy.ts @@ -5,23 +5,34 @@ * 2.0. */ -import { patchRule } from '../../../../tasks/api_calls/rules'; import { createRuleAssetSavedObject } from '../../../../helpers/rules'; import { MODIFIED_RULE_BADGE, + NO_RULES_AVAILABLE_FOR_UPGRADE_MESSAGE, + RULES_UPDATES_TAB, RULES_UPDATES_TABLE, + SELECT_ALL_RULES_ON_PAGE_CHECKBOX, + UPGRADE_ALL_RULES_BUTTON, + UPGRADE_SELECTED_RULES_BUTTON, + getUpgradeSingleRuleButtonByRuleId, } from '../../../../screens/alerts_detection_rules'; +import { selectRulesByName } from '../../../../tasks/alerts_detection_rules'; import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; import { - installPrebuiltRuleAssets, createAndInstallMockedPrebuiltRules, + installPrebuiltRuleAssets, } from '../../../../tasks/api_calls/prebuilt_rules'; +import { patchRule } from '../../../../tasks/api_calls/rules'; import { resetRulesTableState } from '../../../../tasks/common'; import { login } from '../../../../tasks/login'; import { + assertRuleUpgradeConflictsModalShown, + assertRuleUpgradeSuccessToastShown, assertRulesNotPresentInRuleUpdatesTable, assertRulesPresentInRuleUpdatesTable, + assertUpgradeRequestIsComplete, clickRuleUpdatesTab, + clickUpgradeRuleWithoutConflicts, filterPrebuiltRulesUpdateTableByRuleCustomization, } from '../../../../tasks/prebuilt_rules'; import { visitRulesManagementTable } from '../../../../tasks/rules_management'; @@ -42,6 +53,90 @@ describe( }, () => { + describe('Upgrade of prebuilt rules without conflicts', () => { + const RULE_1_ID = 'rule_1'; + const RULE_2_ID = 'rule_2'; + const OUTDATED_RULE_1 = createRuleAssetSavedObject({ + name: 'Outdated rule 1', + rule_id: RULE_1_ID, + version: 1, + }); + const UPDATED_RULE_1 = createRuleAssetSavedObject({ + name: 'Updated rule 1', + rule_id: RULE_1_ID, + version: 2, + }); + const OUTDATED_RULE_2 = createRuleAssetSavedObject({ + name: 'Outdated rule 2', + rule_id: RULE_2_ID, + version: 1, + }); + const UPDATED_RULE_2 = createRuleAssetSavedObject({ + name: 'Updated rule 2', + rule_id: RULE_2_ID, + version: 2, + }); + beforeEach(() => { + login(); + resetRulesTableState(); + deleteAlertsAndRules(); + cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_perform').as( + 'updatePrebuiltRules' + ); + /* Create a new rule and install it */ + createAndInstallMockedPrebuiltRules([OUTDATED_RULE_1, OUTDATED_RULE_2]); + /* Create a second version of the rule, making it available for update */ + installPrebuiltRuleAssets([UPDATED_RULE_1, UPDATED_RULE_2]); + + visitRulesManagementTable(); + clickRuleUpdatesTab(); + }); + + it('should upgrade prebuilt rules one by one', () => { + // Attempt to upgrade rule + cy.get( + getUpgradeSingleRuleButtonByRuleId(OUTDATED_RULE_1['security-rule'].rule_id) + ).click(); + // Wait for request to complete + assertUpgradeRequestIsComplete([OUTDATED_RULE_1]); + + assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_1]); + assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_1]); + }); + + it('should upgrade multiple selected prebuilt rules by selecting them individually', () => { + selectRulesByName([ + OUTDATED_RULE_1['security-rule'].name, + OUTDATED_RULE_2['security-rule'].name, + ]); + cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); + assertUpgradeRequestIsComplete([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_1, OUTDATED_RULE_2]); + }); + + it('should upgrade multiple selected prebuilt rules by selecting all in page', () => { + cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click(); + cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); + assertUpgradeRequestIsComplete([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_1, OUTDATED_RULE_2]); + }); + + it('should upgrade all rules with available upgrades at once', () => { + cy.get(UPGRADE_ALL_RULES_BUTTON).click(); + assertUpgradeRequestIsComplete([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_1, OUTDATED_RULE_2]); + }); + + it('should display an empty screen when all rules with available updates have been upgraded', () => { + cy.get(UPGRADE_ALL_RULES_BUTTON).click(); + cy.get(RULES_UPDATES_TAB).should('not.exist'); + cy.get(NO_RULES_AVAILABLE_FOR_UPGRADE_MESSAGE).should('exist'); + }); + }); + describe('Upgrade of prebuilt rules with conflicts', () => { const RULE_1_ID = 'rule_1'; const RULE_2_ID = 'rule_2'; @@ -76,7 +171,7 @@ describe( /* Create a new rule and install it */ createAndInstallMockedPrebuiltRules([OUTDATED_RULE_1, OUTDATED_RULE_2]); /* Modify one of the rule's name to cause a conflict */ - patchRule(OUTDATED_RULE_1['security-rule'].rule_id, { + const patchedRule = patchRule(OUTDATED_RULE_1['security-rule'].rule_id, { name: patchedName, }); /* Create a second version of the rule, making it available for update */ @@ -104,6 +199,60 @@ describe( // Verify only rules with non-customized rule sources are displayed assertRulesPresentInRuleUpdatesTable([OUTDATED_RULE_2]); cy.get(patchedName).should('not.exist'); + it('should upgrade prebuilt rules without conflicts one by one', () => { + cy.get( + getUpgradeSingleRuleButtonByRuleId(OUTDATED_RULE_2['security-rule'].rule_id) + ).click(); + // Wait for request to complete + assertUpgradeRequestIsComplete([OUTDATED_RULE_2]); + + assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_2]); + assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_2]); + }); + + it('should disable individual upgrade button for prebuilt rules with conflicts one by one', () => { + // Button should be disabled because of conflicts + expect( + cy + .get(getUpgradeSingleRuleButtonByRuleId(OUTDATED_RULE_1['security-rule'].rule_id)) + .should('be.disabled') + ); + }); + + it('should warn about rules with conflicts not being updated when multiple rules are individually selected for update', () => { + selectRulesByName([patchedName, OUTDATED_RULE_2['security-rule'].name]); + cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); + assertRuleUpgradeConflictsModalShown(); + clickUpgradeRuleWithoutConflicts(); + // Assert that only rules without conflicts are updated and the other remains in the table + assertUpgradeRequestIsComplete([OUTDATED_RULE_2]); + assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_2]); + assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_2]); + cy.get(RULES_UPDATES_TABLE).contains(patchedName); + }); + + it('should warn about rules with conflicts not being updated when all rules in page are selected', () => { + cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click(); + cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); + assertRuleUpgradeConflictsModalShown(); + clickUpgradeRuleWithoutConflicts(); + // Assert that only rules without conflicts are updated and the other remains in the table + assertUpgradeRequestIsComplete([OUTDATED_RULE_2]); + assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_2]); + assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_2]); + cy.get(RULES_UPDATES_TABLE).contains(patchedName); + }); + + it('should warn about rules with conflicts not being updated when all rules with available upgrades are upgraded at once', () => { + cy.get(UPGRADE_ALL_RULES_BUTTON).click(); + assertRuleUpgradeConflictsModalShown(); + clickUpgradeRuleWithoutConflicts(); + // Assert that only rules without conflicts are updated and the other remains in the table + assertUpgradeRequestIsComplete([OUTDATED_RULE_2]); + assertRuleUpgradeSuccessToastShown([OUTDATED_RULE_2]); + assertRulesNotPresentInRuleUpdatesTable([OUTDATED_RULE_2]); + cy.get(RULES_UPDATES_TABLE).contains(patchedName); + }); }); }); } diff --git a/x-pack/test/security_solution_cypress/cypress/screens/rule_updates.ts b/x-pack/test/security_solution_cypress/cypress/screens/rule_updates.ts index 4b11a4624c3e..dbe907a9040f 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/rule_updates.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/rule_updates.ts @@ -10,3 +10,5 @@ export const RULE_UPGRADE_TABLE_MODIFICATION_FILTER_BUTTON = export const RULE_UPGRADE_TABLE_MODIFICATION_FILTER_PANEL = '[data-test-subj="rule-customization-filter-popover"]'; + +export const RULE_UPGRADE_CONFLICTS_MODAL = '[data-test-subj="upgradeConflictsModal"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules.ts b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules.ts index d4148d5e632a..0dd833810f9b 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules.ts @@ -21,6 +21,7 @@ import { RULE_UPGRADE_TABLE_MODIFICATION_FILTER_BUTTON, RULE_UPGRADE_TABLE_MODIFICATION_FILTER_PANEL, } from '../screens/rule_updates'; +import { RULE_UPGRADE_CONFLICTS_MODAL } from '../screens/rule_updates'; export const clickAddElasticRulesButton = () => { cy.get(ADD_ELASTIC_RULES_BTN).click(); @@ -160,3 +161,11 @@ export const filterPrebuiltRulesUpdateTableByRuleCustomization = (text: string) cy.get(RULE_UPGRADE_TABLE_MODIFICATION_FILTER_PANEL).contains(text).click(); cy.get(RULE_UPGRADE_TABLE_MODIFICATION_FILTER_BUTTON).click(); }; + +export const assertRuleUpgradeConflictsModalShown = () => { + cy.get(RULE_UPGRADE_CONFLICTS_MODAL).should('be.visible'); +}; + +export const clickUpgradeRuleWithoutConflicts = () => { + cy.get(RULE_UPGRADE_CONFLICTS_MODAL).contains('button', 'Update').click(); +}; From 5879218dc64ce6c075b8d17596b97b117ce482cf Mon Sep 17 00:00:00 2001 From: jpdjere Date: Thu, 31 Oct 2024 18:56:02 -0300 Subject: [PATCH 12/19] fix type --- .../update_workflow_with_prebuilt_rule_customization.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow_with_prebuilt_rule_customization.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow_with_prebuilt_rule_customization.cy.ts index 0d7b2c8f336c..7b487b3d7fdb 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow_with_prebuilt_rule_customization.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/update_workflow_with_prebuilt_rule_customization.cy.ts @@ -171,7 +171,7 @@ describe( /* Create a new rule and install it */ createAndInstallMockedPrebuiltRules([OUTDATED_RULE_1, OUTDATED_RULE_2]); /* Modify one of the rule's name to cause a conflict */ - const patchedRule = patchRule(OUTDATED_RULE_1['security-rule'].rule_id, { + patchRule(OUTDATED_RULE_1['security-rule'].rule_id, { name: patchedName, }); /* Create a second version of the rule, making it available for update */ From f9ce6d3e5ed97823f1fb4b5448560fc41ecbd0c0 Mon Sep 17 00:00:00 2001 From: Dmitrii Shevchenko Date: Fri, 8 Nov 2024 15:35:32 +0100 Subject: [PATCH 13/19] Update x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx Co-authored-by: Nastasha Solomon <79124755+nastasha-solomon@users.noreply.github.com> --- .../modals/upgrade_conflicts_modal/translations.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx index 76645dc87a57..498c0f8e4927 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx @@ -24,7 +24,7 @@ export const UPGRADE_CONFLICTS_MODAL_CANCEL = i18n.translate( export const UPGRADE_CONFLICTS_MODAL_CONFIRM = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.confirmTitle', { - defaultMessage: 'Update rules with no conflicts', + defaultMessage: 'Update rules without conflicts', } ); From 076275540fa4dde3f69918decb94ee630773abdc Mon Sep 17 00:00:00 2001 From: Dmitrii Shevchenko Date: Fri, 8 Nov 2024 15:36:07 +0100 Subject: [PATCH 14/19] Update x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx Co-authored-by: Nastasha Solomon <79124755+nastasha-solomon@users.noreply.github.com> --- .../modals/upgrade_conflicts_modal/translations.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx index 498c0f8e4927..c6054c10fb4c 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx @@ -32,6 +32,6 @@ export const UPGRADE_CONFLICTS_MODAL_BODY = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.affectedJobsTitle', { defaultMessage: - 'Some of the selected rules have conflicts in one or more of their fields and will not be updated. Please resolve the conflicts on a case-by-case basis.', + 'Some of the selected rules have conflicts and, for that reason, won't be updated. Resolve the conflicts to properly update the rules. ', } ); From 88dce8035648ff60dc4c7bc7635b696bd1421222 Mon Sep 17 00:00:00 2001 From: Dmitrii Shevchenko Date: Fri, 8 Nov 2024 15:36:22 +0100 Subject: [PATCH 15/19] Update x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts Co-authored-by: Nastasha Solomon <79124755+nastasha-solomon@users.noreply.github.com> --- .../rules_table/upgrade_prebuilt_rules_table/translations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts index 9090b9f109ba..26c2aad7fe51 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts @@ -34,7 +34,7 @@ export const BULK_UPDATE_BUTTON_TOOLTIP_NO_PERMISSIONS = i18n.translate( export const BULK_UPDATE_ALL_RULES_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.bulkButtons.allRules.conflicts', { - defaultMessage: 'All rules have conflicts. Please update them individually.', + defaultMessage: 'All rules have conflicts. Update them individually.', } ); From 231f0d39ed0c51603a96a3ec23e9e178d5fd69c4 Mon Sep 17 00:00:00 2001 From: Dmitrii Shevchenko Date: Fri, 8 Nov 2024 15:36:37 +0100 Subject: [PATCH 16/19] Update x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts Co-authored-by: Nastasha Solomon <79124755+nastasha-solomon@users.noreply.github.com> --- .../detections/pages/detection_engine/rules/translations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts index 143186b143b0..cb0570855dab 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts @@ -1438,7 +1438,7 @@ export const UPDATE_RULE_BUTTON = i18n.translate( export const UPDATE_RULE_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.button.conflicts', { - defaultMessage: 'Rule has conflicts. Please resolve them manually.', + defaultMessage: 'Rule has conflicts. Resolve them manually.', } ); From a826a698502fb78ee0a71babbd0677202a897a09 Mon Sep 17 00:00:00 2001 From: Dmitrii Shevchenko Date: Fri, 8 Nov 2024 15:40:43 +0100 Subject: [PATCH 17/19] Update x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts Co-authored-by: Nastasha Solomon <79124755+nastasha-solomon@users.noreply.github.com> --- .../rules_table/upgrade_prebuilt_rules_table/translations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts index 26c2aad7fe51..5db5d0eee748 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/translations.ts @@ -41,7 +41,7 @@ export const BULK_UPDATE_ALL_RULES_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( export const BULK_UPDATE_SELECTED_RULES_BUTTON_TOOLTIP_CONFLICTS = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.upgradeRules.bulkButtons.selectedRules.conflicts', { - defaultMessage: 'All selected rules have conflicts. Please update them individually.', + defaultMessage: 'All selected rules have conflicts. Update them individually.', } ); From f360a7d5926fa25fd4622186c5df5ce1b2a2c75c Mon Sep 17 00:00:00 2001 From: Dmitrii Date: Fri, 8 Nov 2024 16:12:42 +0100 Subject: [PATCH 18/19] Update modal title --- .../modals/upgrade_conflicts_modal/translations.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx index c6054c10fb4c..bc5738b879cc 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/modals/upgrade_conflicts_modal/translations.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; export const UPGRADE_CONFLICTS_MODAL_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.messageTitle', { - defaultMessage: 'Rules with conflicts will not be updated', + defaultMessage: 'Update rules without conflicts?', } ); @@ -32,6 +32,6 @@ export const UPGRADE_CONFLICTS_MODAL_BODY = i18n.translate( 'xpack.securitySolution.detectionEngine.upgradeConflictsModal.affectedJobsTitle', { defaultMessage: - 'Some of the selected rules have conflicts and, for that reason, won't be updated. Resolve the conflicts to properly update the rules. ', + "Some of the selected rules have conflicts and, for that reason, won't be updated. Resolve the conflicts to properly update the rules.", } ); From fe8eb54d9ff7688c017038fdc6dd63eaefdcc4fb Mon Sep 17 00:00:00 2001 From: Dmitrii Date: Fri, 8 Nov 2024 17:08:17 +0100 Subject: [PATCH 19/19] Rebase fix --- config/kibana.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/config/kibana.yml b/config/kibana.yml index 6c4fb774eb37..c816337f881d 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -181,8 +181,3 @@ # Maximum number of documents loaded by each shard to generate autocomplete suggestions. # This value must be a whole number greater than zero. Defaults to 100_000 #unifiedSearch.autocomplete.valueSuggestions.terminateAfter: 100000 - -# Must be removed before v9 release -# Requires all registry packages to add v9 as a compatible semver range -# https://github.com/elastic/kibana/issues/192624 -xpack.fleet.internal.registry.kibanaVersionCheckEnabled: false