Skip to content

Commit

Permalink
[Security Solution][Exceptions] Exception modal bulk close option onl…
Browse files Browse the repository at this point in the history
…y closes alerts generated by same rule (#77402)

* Exception modal bulk close option only closes alerts generated by same rule

* update modal text
  • Loading branch information
peluja1012 authored and spong committed Sep 17, 2020
1 parent b6be6e9 commit 4efc8e9
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -309,10 +309,11 @@ export const AddExceptionModal = memo(function AddExceptionModal({
const alertIdToClose = shouldCloseAlert && alertData ? alertData.ecsData._id : undefined;
const bulkCloseIndex =
shouldBulkCloseAlert && signalIndexName !== null ? [signalIndexName] : undefined;
addOrUpdateExceptionItems(enrichExceptionItems(), alertIdToClose, bulkCloseIndex);
addOrUpdateExceptionItems(ruleId, enrichExceptionItems(), alertIdToClose, bulkCloseIndex);
}
}, [
addOrUpdateExceptionItems,
ruleId,
enrichExceptionItems,
shouldCloseAlert,
shouldBulkCloseAlert,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,15 @@ export const ENDPOINT_QUARANTINE_TEXT = i18n.translate(
export const BULK_CLOSE_LABEL = i18n.translate(
'xpack.securitySolution.exceptions.addException.bulkCloseLabel',
{
defaultMessage:
'Close all alerts that match this exception, including alerts generated by other rules',
defaultMessage: 'Close all alerts that match this exception and were generated by this rule',
}
);

export const BULK_CLOSE_LABEL_DISABLED = i18n.translate(
'xpack.securitySolution.exceptions.addException.bulkCloseLabel.disabled',
{
defaultMessage:
'Close all alerts that match attributes in this exception (Lists and non-ECS fields are not supported)',
'Close all alerts that match this exception and were generated by this rule (Lists and non-ECS fields are not supported)',
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,15 @@ export const EditExceptionModal = memo(function EditExceptionModal({
if (addOrUpdateExceptionItems !== null) {
const bulkCloseIndex =
shouldBulkCloseAlert && signalIndexName !== null ? [signalIndexName] : undefined;
addOrUpdateExceptionItems(enrichExceptionItems(), undefined, bulkCloseIndex);
addOrUpdateExceptionItems(ruleId, enrichExceptionItems(), undefined, bulkCloseIndex);
}
}, [addOrUpdateExceptionItems, enrichExceptionItems, shouldBulkCloseAlert, signalIndexName]);
}, [
addOrUpdateExceptionItems,
ruleId,
enrichExceptionItems,
shouldBulkCloseAlert,
signalIndexName,
]);

return (
<EuiOverlayMask onClick={onCancel}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,15 @@ export const EDIT_EXCEPTION_SUCCESS = i18n.translate(
export const BULK_CLOSE_LABEL = i18n.translate(
'xpack.securitySolution.exceptions.editException.bulkCloseLabel',
{
defaultMessage:
'Close all alerts that match this exception, including alerts generated by other rules',
defaultMessage: 'Close all alerts that match this exception and were generated by this rule',
}
);

export const BULK_CLOSE_LABEL_DISABLED = i18n.translate(
'xpack.securitySolution.exceptions.editException.bulkCloseLabel.disabled',
{
defaultMessage:
'Close all alerts that match attributes in this exception (Lists and non-ECS fields are not supported)',
'Close all alerts that match this exception and were generated by this rule (Lists and non-ECS fields are not supported)',
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { KibanaServices } from '../../../common/lib/kibana';
import * as alertsApi from '../../../detections/containers/detection_engine/alerts/api';
import * as listsApi from '../../../../../lists/public/exceptions/api';
import * as getQueryFilterHelper from '../../../../common/detection_engine/get_query_filter';
import * as buildAlertStatusFilterHelper from '../../../detections/components/alerts_table/default_config';
import * as buildFilterHelpers from '../../../detections/components/alerts_table/default_config';
import { getExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_item_schema.mock';
import { getCreateExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/request/create_exception_list_item_schema.mock';
import { getUpdateExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/request/update_exception_list_item_schema.mock';
Expand Down Expand Up @@ -42,12 +42,16 @@ describe('useAddOrUpdateException', () => {
>>;
let getQueryFilter: jest.SpyInstance<ReturnType<typeof getQueryFilterHelper.getQueryFilter>>;
let buildAlertStatusFilter: jest.SpyInstance<ReturnType<
typeof buildAlertStatusFilterHelper.buildAlertStatusFilter
typeof buildFilterHelpers.buildAlertStatusFilter
>>;
let buildAlertsRuleIdFilter: jest.SpyInstance<ReturnType<
typeof buildFilterHelpers.buildAlertsRuleIdFilter
>>;
let addOrUpdateItemsArgs: Parameters<AddOrUpdateExceptionItemsFunc>;
let render: () => RenderHookResult<UseAddOrUpdateExceptionProps, ReturnUseAddOrUpdateException>;
const onError = jest.fn();
const onSuccess = jest.fn();
const ruleId = 'rule-id';
const alertIdToClose = 'idToClose';
const bulkCloseIndex = ['.custom'];
const itemsToAdd: CreateExceptionListItemSchema[] = [
Expand Down Expand Up @@ -122,9 +126,11 @@ describe('useAddOrUpdateException', () => {

getQueryFilter = jest.spyOn(getQueryFilterHelper, 'getQueryFilter');

buildAlertStatusFilter = jest.spyOn(buildAlertStatusFilterHelper, 'buildAlertStatusFilter');
buildAlertStatusFilter = jest.spyOn(buildFilterHelpers, 'buildAlertStatusFilter');

buildAlertsRuleIdFilter = jest.spyOn(buildFilterHelpers, 'buildAlertsRuleIdFilter');

addOrUpdateItemsArgs = [itemsToAddOrUpdate];
addOrUpdateItemsArgs = [ruleId, itemsToAddOrUpdate];
render = () =>
renderHook<UseAddOrUpdateExceptionProps, ReturnUseAddOrUpdateException>(() =>
useAddOrUpdateException({
Expand Down Expand Up @@ -247,7 +253,7 @@ describe('useAddOrUpdateException', () => {

describe('when alertIdToClose is passed in', () => {
beforeEach(() => {
addOrUpdateItemsArgs = [itemsToAddOrUpdate, alertIdToClose];
addOrUpdateItemsArgs = [ruleId, itemsToAddOrUpdate, alertIdToClose];
});
it('should update the alert status', async () => {
await act(async () => {
Expand Down Expand Up @@ -302,7 +308,7 @@ describe('useAddOrUpdateException', () => {

describe('when bulkCloseIndex is passed in', () => {
beforeEach(() => {
addOrUpdateItemsArgs = [itemsToAddOrUpdate, undefined, bulkCloseIndex];
addOrUpdateItemsArgs = [ruleId, itemsToAddOrUpdate, undefined, bulkCloseIndex];
});
it('should update the status of only alerts that are open', async () => {
await act(async () => {
Expand All @@ -320,6 +326,22 @@ describe('useAddOrUpdateException', () => {
expect(buildAlertStatusFilter.mock.calls[0][0]).toEqual('open');
});
});
it('should update the status of only alerts generated by the provided rule', async () => {
await act(async () => {
const { rerender, result, waitForNextUpdate } = render();
const addOrUpdateItems = await waitForAddOrUpdateFunc({
rerender,
result,
waitForNextUpdate,
});
if (addOrUpdateItems) {
addOrUpdateItems(...addOrUpdateItemsArgs);
}
await waitForNextUpdate();
expect(buildAlertsRuleIdFilter).toHaveBeenCalledTimes(1);
expect(buildAlertsRuleIdFilter.mock.calls[0][0]).toEqual(ruleId);
});
});
it('should generate the query filter using exceptions', async () => {
await act(async () => {
const { rerender, result, waitForNextUpdate } = render();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,25 @@ import {
} from '../../../lists_plugin_deps';
import { updateAlertStatus } from '../../../detections/containers/detection_engine/alerts/api';
import { getUpdateAlertsQuery } from '../../../detections/components/alerts_table/actions';
import { buildAlertStatusFilter } from '../../../detections/components/alerts_table/default_config';
import {
buildAlertStatusFilter,
buildAlertsRuleIdFilter,
} from '../../../detections/components/alerts_table/default_config';
import { getQueryFilter } from '../../../../common/detection_engine/get_query_filter';
import { Index } from '../../../../common/detection_engine/schemas/common/schemas';
import { formatExceptionItemForUpdate, prepareExceptionItemsForBulkClose } from './helpers';

/**
* Adds exception items to the list. Also optionally closes alerts.
*
* @param ruleId id of the rule where the exception updates will be applied
* @param exceptionItemsToAddOrUpdate array of ExceptionListItemSchema to add or update
* @param alertIdToClose - optional string representing alert to close
* @param bulkCloseIndex - optional index used to create bulk close query
*
*/
export type AddOrUpdateExceptionItemsFunc = (
ruleId: string,
exceptionItemsToAddOrUpdate: Array<ExceptionListItemSchema | CreateExceptionListItemSchema>,
alertIdToClose?: string,
bulkCloseIndex?: Index
Expand Down Expand Up @@ -63,9 +68,10 @@ export const useAddOrUpdateException = ({
const [isLoading, setIsLoading] = useState(false);
const addOrUpdateExceptionRef = useRef<AddOrUpdateExceptionItemsFunc | null>(null);
const addOrUpdateException = useCallback<AddOrUpdateExceptionItemsFunc>(
async (exceptionItemsToAddOrUpdate, alertIdToClose, bulkCloseIndex) => {
async (ruleId, exceptionItemsToAddOrUpdate, alertIdToClose, bulkCloseIndex) => {
if (addOrUpdateExceptionRef.current !== null) {
addOrUpdateExceptionRef.current(
ruleId,
exceptionItemsToAddOrUpdate,
alertIdToClose,
bulkCloseIndex
Expand Down Expand Up @@ -117,6 +123,7 @@ export const useAddOrUpdateException = ({
};

const addOrUpdateExceptionItems: AddOrUpdateExceptionItemsFunc = async (
ruleId,
exceptionItemsToAddOrUpdate,
alertIdToClose,
bulkCloseIndex
Expand All @@ -137,7 +144,7 @@ export const useAddOrUpdateException = ({
const filter = getQueryFilter(
'',
'kuery',
buildAlertStatusFilter('open'),
[...buildAlertsRuleIdFilter(ruleId), ...buildAlertStatusFilter('open')],
bulkCloseIndex,
prepareExceptionItemsForBulkClose(exceptionItemsToAddOrUpdate),
false
Expand Down

0 comments on commit 4efc8e9

Please sign in to comment.