Skip to content

Commit

Permalink
[Security Solution] Rule Updates in bulk with conflicts (#196776)
Browse files Browse the repository at this point in the history
Resolves: #180589

## Summary

- Handles bulk updating of rules with conflicts in the Rule Upgrades
table. See detailed requirements implemented in ticket linked above.
- Changes default `pick_version` of both the `/upgrade/_perform`
endpoint, and of the request payloads for that endpoint from the
frontend, from `TARGET` to `MERGED`, when the
`isPrebuiltRulesCustomizationEnabled` is `true`.
- **Also:** handles issue in `/upgrade/_perform` endpoint with the
`index` and `data_view_id` fields. See file:
`x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/perform_rule_upgrade/diffable_rule_fields_mappings.ts`.

**See demo video:**
https://www.loom.com/share/90d94d2a8f16442b9a43a425eeab6697

**New copy in warning modal**
<img width="1660" alt="image"
src="https://github.com/user-attachments/assets/85632192-142a-4e12-b396-1eb2320ca3f4">

**Newly added tooltips:** 


![image](https://github.com/user-attachments/assets/7ada117e-57a7-4699-ad08-312c734586d9)

![image](https://github.com/user-attachments/assets/c8ed80ac-c1c3-48f1-8f8e-2433415a6772)

![image](https://github.com/user-attachments/assets/d77ed6f0-5d65-4933-9012-f6cd153a9350)


### Checklist

Delete any items that are not applicable to this PR.

- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))

### For maintainers

- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#_add_your_labels)
- [ ] This will appear in the **Release Notes** and follow the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: Nastasha Solomon <[email protected]>
Co-authored-by: Dmitrii <[email protected]>
  • Loading branch information
3 people authored Nov 11, 2024
1 parent 961796d commit 99160f5
Show file tree
Hide file tree
Showing 24 changed files with 555 additions and 163 deletions.
1 change: 0 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -1843,7 +1843,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -678,26 +679,17 @@ export const performInstallSpecificRules = async (
}),
});

export const performUpgradeAllRules = async (): Promise<PerformRuleUpgradeResponseBody> =>
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']
rules: UpgradeSpecificRulesRequest['rules'],
pickVersion: PickVersionValues
): Promise<PerformRuleUpgradeResponseBody> =>
KibanaServices.get().http.fetch(PERFORM_RULE_UPGRADE_URL, {
method: 'POST',
version: '1',
body: JSON.stringify({
mode: 'SPECIFIC_RULES',
rules,
pick_version: 'TARGET', // Setting fixed 'TARGET' temporarily for Milestone 2
pick_version: pickVersion,
}),
});

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -26,6 +27,7 @@ export const PERFORM_SPECIFIC_RULES_UPGRADE_KEY = [
];

export const usePerformSpecificRulesUpgradeMutation = (
pickVersion: PickVersionValues,
options?: UseMutationOptions<
PerformRuleUpgradeResponseBody,
Error,
Expand All @@ -43,7 +45,7 @@ export const usePerformSpecificRulesUpgradeMutation = (

return useMutation<PerformRuleUpgradeResponseBody, Error, UpgradeSpecificRulesRequest['rules']>(
(rulesToUpgrade: UpgradeSpecificRulesRequest['rules']) => {
return performUpgradeSpecificRules(rulesToUpgrade);
return performUpgradeSpecificRules(rulesToUpgrade, pickVersion);
},
{
...options,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +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 { 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 = () => {
export const usePerformUpgradeSpecificRules = ({
pickVersion,
}: {
pickVersion: PickVersionValues;
}) => {
const { addError, addSuccess } = useAppToasts();

return usePerformSpecificRulesUpgradeMutation({
return usePerformSpecificRulesUpgradeMutation(pickVersion, {
onError: (err) => {
addError(err, { title: i18n.RULE_UPGRADE_FAILED });
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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<HTMLDivElement> | React.MouseEvent<HTMLButtonElement>
) => void;
onConfirm?: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
}

const UpgradeConflictsModalComponent = ({ onCancel, onConfirm }: UpgradeConflictsModalProps) => {
return (
<EuiConfirmModal
title={i18n.UPGRADE_CONFLICTS_MODAL_TITLE}
onCancel={onCancel}
onConfirm={onConfirm}
cancelButtonText={i18n.UPGRADE_CONFLICTS_MODAL_CANCEL}
confirmButtonText={i18n.UPGRADE_CONFLICTS_MODAL_CONFIRM}
buttonColor="primary"
defaultFocusedButton="confirm"
data-test-subj="upgradeConflictsModal"
>
<EuiText>{i18n.UPGRADE_CONFLICTS_MODAL_BODY}</EuiText>
</EuiConfirmModal>
);
};

export const UpgradeConflictsModal = memo(UpgradeConflictsModalComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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: 'Update rules without conflicts?',
}
);

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: 'Update rules without conflicts',
}
);

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.",
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -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. 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. Update them individually.',
}
);

export const SEARCH_PLACEHOLDER = i18n.translate(
'xpack.securitySolution.detectionEngine.rules.upgradeRules.searchBarPlaceholder',
{
Expand All @@ -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',
Expand Down
Loading

0 comments on commit 99160f5

Please sign in to comment.