Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution] Rule Updates in bulk with conflicts #196776

Merged
merged 20 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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',
}),
});

Comment on lines -681 to -690
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleting this since from now onwards the frontend client will never be just sending a request to update ALL rules, since some of them might have conflicts: we want to filter those out before making the request, which is done in this PR.

API users can still send this type request, and will get detailed errors if there are conflicts.

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