From 6b6bfe5ef52e7734df5beb08a52a09ad917ef584 Mon Sep 17 00:00:00 2001 From: Madison Caldwell Date: Tue, 20 Oct 2020 17:03:47 -0400 Subject: [PATCH] [Security Solution][Detections] Immediately refresh exceptions when new list is created after rule creation (#81014) * ExceptionIdentifiers -> ExceptionListIdentifiers * Pass refreshRule through to alert context menu * Fix type errors and rename refreshRule to onRuleChange for consistency --- .../lists/public/exceptions/hooks/use_exception_list.ts | 2 +- x-pack/plugins/lists/public/exceptions/types.ts | 6 +++--- x-pack/plugins/lists/public/exceptions/utils.ts | 4 ++-- x-pack/plugins/lists/public/shared_exports.ts | 2 +- .../common/components/events_viewer/events_viewer.tsx | 3 +++ .../public/common/components/events_viewer/index.tsx | 3 +++ .../public/common/components/exceptions/viewer/index.tsx | 4 ++-- .../public/common/components/exceptions/viewer/reducer.ts | 6 +++--- .../public/detections/components/alerts_table/index.tsx | 3 +++ .../alerts_table/timeline_actions/alert_context_menu.tsx | 7 +++++-- .../pages/detection_engine/rules/details/index.tsx | 7 ++++--- x-pack/plugins/security_solution/public/shared_imports.ts | 2 +- .../components/timeline/body/events/event_column_view.tsx | 4 ++++ .../timelines/components/timeline/body/events/index.tsx | 3 +++ .../components/timeline/body/events/stateful_event.tsx | 4 ++++ .../public/timelines/components/timeline/body/index.tsx | 3 +++ .../timelines/components/timeline/body/stateful_body.tsx | 3 +++ 17 files changed, 48 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.ts b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.ts index 50196a1a0bcc..2fafe9de59fd 100644 --- a/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.ts +++ b/x-pack/plugins/lists/public/exceptions/hooks/use_exception_list.ts @@ -23,7 +23,7 @@ export type ReturnExceptionListAndItems = [ * Hook for using to get an ExceptionList and it's ExceptionListItems * * @param http Kibana http service - * @param lists array of ExceptionIdentifiers for all lists to fetch + * @param lists array of ExceptionListIdentifiers for all lists to fetch * @param onError error callback * @param onSuccess callback when all lists fetched successfully * @param filterOptions optional - filter by fields or tags diff --git a/x-pack/plugins/lists/public/exceptions/types.ts b/x-pack/plugins/lists/public/exceptions/types.ts index ac2128884815..64e4efb5daad 100644 --- a/x-pack/plugins/lists/public/exceptions/types.ts +++ b/x-pack/plugins/lists/public/exceptions/types.ts @@ -50,7 +50,7 @@ export interface UseExceptionListSuccess { export interface UseExceptionListProps { http: HttpStart; - lists: ExceptionIdentifiers[]; + lists: ExceptionListIdentifiers[]; onError?: (arg: string[]) => void; filterOptions: FilterExceptionsOptions[]; pagination?: Pagination; @@ -60,7 +60,7 @@ export interface UseExceptionListProps { onSuccess?: (arg: UseExceptionListSuccess) => void; } -export interface ExceptionIdentifiers { +export interface ExceptionListIdentifiers { id: string; listId: string; namespaceType: NamespaceType; @@ -91,7 +91,7 @@ export interface ApiCallMemoProps { } export interface ApiCallFindListsItemsMemoProps { - lists: ExceptionIdentifiers[]; + lists: ExceptionListIdentifiers[]; filterOptions: FilterExceptionsOptions[]; pagination: Partial; showDetectionsListsOnly: boolean; diff --git a/x-pack/plugins/lists/public/exceptions/utils.ts b/x-pack/plugins/lists/public/exceptions/utils.ts index 2acb690d3822..3a5984956b0d 100644 --- a/x-pack/plugins/lists/public/exceptions/utils.ts +++ b/x-pack/plugins/lists/public/exceptions/utils.ts @@ -6,14 +6,14 @@ import { NamespaceType } from '../../common/schemas'; -import { ExceptionIdentifiers } from './types'; +import { ExceptionListIdentifiers } from './types'; export const getIdsAndNamespaces = ({ lists, showDetection, showEndpoint, }: { - lists: ExceptionIdentifiers[]; + lists: ExceptionListIdentifiers[]; showDetection: boolean; showEndpoint: boolean; }): { ids: string[]; namespaces: NamespaceType[] } => diff --git a/x-pack/plugins/lists/public/shared_exports.ts b/x-pack/plugins/lists/public/shared_exports.ts index 16026a436f15..b8293971d14d 100644 --- a/x-pack/plugins/lists/public/shared_exports.ts +++ b/x-pack/plugins/lists/public/shared_exports.ts @@ -30,7 +30,7 @@ export { } from './exceptions/api'; export { ExceptionList, - ExceptionIdentifiers, + ExceptionListIdentifiers, Pagination, UseExceptionListSuccess, } from './exceptions/types'; diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx index 152161e2ce3a..60e7accf4945 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx @@ -104,6 +104,7 @@ interface Props { kqlMode: KqlMode; onChangeItemsPerPage: OnChangeItemsPerPage; query: Query; + onRuleChange?: () => void; start: string; sort: Sort; toggleColumn: (column: ColumnHeaderOptions) => void; @@ -131,6 +132,7 @@ const EventsViewerComponent: React.FC = ({ kqlMode, onChangeItemsPerPage, query, + onRuleChange, start, sort, toggleColumn, @@ -286,6 +288,7 @@ const EventsViewerComponent: React.FC = ({ docValueFields={docValueFields} id={id} isEventViewer={true} + onRuleChange={onRuleChange} refetch={refetch} sort={sort} toggleColumn={toggleColumn} diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx index c53d311dc136..a4f2b0536abf 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx @@ -42,6 +42,7 @@ export interface OwnProps { start: string; headerFilterGroup?: React.ReactNode; pageFilters?: Filter[]; + onRuleChange?: () => void; utilityBar?: (refetch: inputsModel.Refetch, totalCount: number) => React.ReactNode; } @@ -64,6 +65,7 @@ const StatefulEventsViewerComponent: React.FC = ({ kqlMode, pageFilters, query, + onRuleChange, removeColumn, start, scopeId, @@ -153,6 +155,7 @@ const StatefulEventsViewerComponent: React.FC = ({ kqlMode={kqlMode} onChangeItemsPerPage={onChangeItemsPerPage} query={query} + onRuleChange={onRuleChange} start={start} sort={sort} toggleColumn={toggleColumn} diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx index c97895cdfe23..f90c83bf953e 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/index.tsx @@ -18,7 +18,7 @@ import { ExceptionListItemIdentifiers, Filter } from '../types'; import { allExceptionItemsReducer, State, ViewerModalName } from './reducer'; import { useExceptionList, - ExceptionIdentifiers, + ExceptionListIdentifiers, ExceptionListTypeEnum, ExceptionListItemSchema, UseExceptionListSuccess, @@ -54,7 +54,7 @@ interface ExceptionsViewerProps { ruleId: string; ruleName: string; ruleIndices: string[]; - exceptionListsMeta: ExceptionIdentifiers[]; + exceptionListsMeta: ExceptionListIdentifiers[]; availableListTypes: ExceptionListTypeEnum[]; commentsAccordionId: string; onRuleChange?: () => void; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts index ca7471b0f823..9c2a89829b59 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/reducer.ts @@ -12,7 +12,7 @@ import { import { ExceptionListType, ExceptionListItemSchema, - ExceptionIdentifiers, + ExceptionListIdentifiers, Pagination, } from '../../../../../public/lists_plugin_deps'; @@ -36,7 +36,7 @@ export interface State { export type Action = | { type: 'setExceptions'; - lists: ExceptionIdentifiers[]; + lists: ExceptionListIdentifiers[]; exceptions: ExceptionListItemSchema[]; pagination: Pagination; } @@ -48,7 +48,7 @@ export type Action = | { type: 'updateModalOpen'; modalName: ViewerModalName } | { type: 'updateExceptionToEdit'; - lists: ExceptionIdentifiers[]; + lists: ExceptionListIdentifiers[]; exception: ExceptionListItemSchema; } | { type: 'updateLoadingItemIds'; items: ExceptionListItemIdentifiers[] } diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index d66d37a02004..a50167433cca 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -54,6 +54,7 @@ interface OwnProps { hasIndexWrite: boolean; from: string; loading: boolean; + onRuleChange?: () => void; showBuildingBlockAlerts: boolean; onShowBuildingBlockAlertsChanged: (showBuildingBlockAlerts: boolean) => void; to: string; @@ -75,6 +76,7 @@ export const AlertsTableComponent: React.FC = ({ isSelectAllChecked, loading, loadingEventIds, + onRuleChange, selectedEventIds, setEventsDeleted, setEventsLoading, @@ -330,6 +332,7 @@ export const AlertsTableComponent: React.FC = ({ end={to} headerFilterGroup={headerFilterGroup} id={timelineId} + onRuleChange={onRuleChange} scopeId={SourcererScopeName.detections} start={from} utilityBar={utilityBarCallback} diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx index 1a0b35620c9c..0315d513ee26 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx @@ -29,7 +29,7 @@ import { FILTER_OPEN, FILTER_CLOSED, FILTER_IN_PROGRESS } from '../alerts_filter import { updateAlertStatusAction } from '../actions'; import { SetEventsDeletedProps, SetEventsLoadingProps } from '../types'; import { Ecs } from '../../../../../common/ecs'; -import { AddExceptionModal as AddExceptionModalComponent } from '../../../../common/components/exceptions/add_exception_modal'; +import { AddExceptionModal } from '../../../../common/components/exceptions/add_exception_modal'; import * as i18nCommon from '../../../../common/translations'; import * as i18n from '../translations'; import { @@ -45,6 +45,7 @@ interface AlertContextMenuProps { disabled: boolean; ecsRowData: Ecs; refetch: inputsModel.Refetch; + onRuleChange?: () => void; timelineId: string; } @@ -52,6 +53,7 @@ const AlertContextMenuComponent: React.FC = ({ disabled, ecsRowData, refetch, + onRuleChange, timelineId, }) => { const dispatch = useDispatch(); @@ -376,7 +378,7 @@ const AlertContextMenuComponent: React.FC = ({ {exceptionModalType != null && ruleId != null && ecsRowData != null && ( - = ({ onCancel={onAddExceptionCancel} onConfirm={onAddExceptionConfirm} alertStatus={alertStatus} + onRuleChange={onRuleChange} /> )} diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx index b4eb40d08189..54aae5c41bd5 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx @@ -79,7 +79,7 @@ import { ExceptionsViewer } from '../../../../../common/components/exceptions/vi import { DEFAULT_INDEX_PATTERN } from '../../../../../../common/constants'; import { useFullScreen } from '../../../../../common/containers/use_full_screen'; import { Display } from '../../../../../hosts/pages/display'; -import { ExceptionListTypeEnum, ExceptionIdentifiers } from '../../../../../shared_imports'; +import { ExceptionListTypeEnum, ExceptionListIdentifiers } from '../../../../../shared_imports'; import { isMlRule } from '../../../../../../common/machine_learning/helpers'; import { isThresholdRule } from '../../../../../../common/detection_engine/utils'; import { useRuleAsync } from '../../../../containers/detection_engine/rules/use_rule_async'; @@ -354,12 +354,12 @@ export const RuleDetailsPageComponent: FC = ({ const { indicesExist, indexPattern } = useSourcererScope(SourcererScopeName.detections); const exceptionLists = useMemo((): { - lists: ExceptionIdentifiers[]; + lists: ExceptionListIdentifiers[]; allowedExceptionListTypes: ExceptionListTypeEnum[]; } => { if (rule != null && rule.exceptions_list != null) { return rule.exceptions_list.reduce<{ - lists: ExceptionIdentifiers[]; + lists: ExceptionListIdentifiers[]; allowedExceptionListTypes: ExceptionListTypeEnum[]; }>( (acc, { id, list_id: listId, namespace_type: namespaceType, type }) => { @@ -542,6 +542,7 @@ export const RuleDetailsPageComponent: FC = ({ loading={loading} showBuildingBlockAlerts={showBuildingBlockAlerts} onShowBuildingBlockAlertsChanged={onShowBuildingBlockAlertsChangedCallback} + onRuleChange={refreshRule} to={to} /> )} diff --git a/x-pack/plugins/security_solution/public/shared_imports.ts b/x-pack/plugins/security_solution/public/shared_imports.ts index f60fefc4f6df..a0484ca39c2b 100644 --- a/x-pack/plugins/security_solution/public/shared_imports.ts +++ b/x-pack/plugins/security_solution/public/shared_imports.ts @@ -49,7 +49,7 @@ export { updateExceptionListItem, fetchExceptionListById, addExceptionList, - ExceptionIdentifiers, + ExceptionListIdentifiers, ExceptionList, Pagination, UseExceptionListSuccess, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx index 3b6585013c8d..c6d4325f0073 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx @@ -54,6 +54,7 @@ interface Props { onRowSelected: OnRowSelected; onUnPinEvent: OnUnPinEvent; refetch: inputsModel.Refetch; + onRuleChange?: () => void; selectedEventIds: Readonly>; showCheckboxes: boolean; showNotes: boolean; @@ -88,6 +89,7 @@ export const EventColumnView = React.memo( onRowSelected, onUnPinEvent, refetch, + onRuleChange, selectedEventIds, showCheckboxes, showNotes, @@ -157,6 +159,7 @@ export const EventColumnView = React.memo( timelineId={timelineId} disabled={eventType !== 'signal'} refetch={refetch} + onRuleChange={onRuleChange} />, ], [ @@ -171,6 +174,7 @@ export const EventColumnView = React.memo( isEventPinned, isEventViewer, refetch, + onRuleChange, showNotes, status, timelineId, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/index.tsx index 0fc097de680e..752e0bdf2523 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/index.tsx @@ -49,6 +49,7 @@ interface Props { onUnPinEvent: OnUnPinEvent; pinnedEventIds: Readonly>; refetch: inputsModel.Refetch; + onRuleChange?: () => void; rowRenderers: RowRenderer[]; selectedEventIds: Readonly>; showCheckboxes: boolean; @@ -77,6 +78,7 @@ const EventsComponent: React.FC = ({ onUnPinEvent, pinnedEventIds, refetch, + onRuleChange, rowRenderers, selectedEventIds, showCheckboxes, @@ -108,6 +110,7 @@ const EventsComponent: React.FC = ({ onUpdateColumns={onUpdateColumns} refetch={refetch} rowRenderers={rowRenderers} + onRuleChange={onRuleChange} selectedEventIds={selectedEventIds} showCheckboxes={showCheckboxes} timelineId={id} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx index be8ce5e26b3e..4f385a465648 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx @@ -60,6 +60,7 @@ interface Props { onUpdateColumns: OnUpdateColumns; isEventPinned: boolean; refetch: inputsModel.Refetch; + onRuleChange?: () => void; rowRenderers: RowRenderer[]; selectedEventIds: Readonly>; showCheckboxes: boolean; @@ -129,6 +130,7 @@ const StatefulEventComponent: React.FC = ({ onUnPinEvent, onUpdateColumns, refetch, + onRuleChange, rowRenderers, selectedEventIds, showCheckboxes, @@ -208,6 +210,7 @@ const StatefulEventComponent: React.FC = ({ onRowSelected={onRowSelected} onUnPinEvent={onUnPinEvent} refetch={refetch} + onRuleChange={onRuleChange} selectedEventIds={selectedEventIds} showCheckboxes={showCheckboxes} showNotes={!!showNotes[event._id]} @@ -296,6 +299,7 @@ const StatefulEventComponent: React.FC = ({ onUnPinEvent, onUpdateColumns, refetch, + onRuleChange, rowRenderers, selectedEventIds, showCheckboxes, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx index 83b8b119faae..e1667ab94973 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx @@ -57,6 +57,7 @@ export interface BodyProps { onUnPinEvent: OnUnPinEvent; pinnedEventIds: Readonly>; refetch: inputsModel.Refetch; + onRuleChange?: () => void; rowRenderers: RowRenderer[]; selectedEventIds: Readonly>; show: boolean; @@ -101,6 +102,7 @@ export const Body = React.memo( pinnedEventIds, rowRenderers, refetch, + onRuleChange, selectedEventIds, show, showCheckboxes, @@ -186,6 +188,7 @@ export const Body = React.memo( pinnedEventIds={pinnedEventIds} refetch={refetch} rowRenderers={rowRenderers} + onRuleChange={onRuleChange} selectedEventIds={selectedEventIds} showCheckboxes={showCheckboxes} toggleColumn={toggleColumn} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/stateful_body.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/stateful_body.tsx index dfd646353c27..d7a05e39e76b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/stateful_body.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/stateful_body.tsx @@ -46,6 +46,7 @@ interface OwnProps { sort: Sort; toggleColumn: (column: ColumnHeaderOptions) => void; refetch: inputsModel.Refetch; + onRuleChange?: () => void; } type StatefulBodyComponentProps = OwnProps & PropsFromRedux; @@ -73,6 +74,7 @@ const StatefulBodyComponent = React.memo( selectedEventIds, setSelected, clearSelected, + onRuleChange, show, showCheckboxes, graphEventId, @@ -211,6 +213,7 @@ const StatefulBodyComponent = React.memo( onUpdateColumns={onUpdateColumns} pinnedEventIds={pinnedEventIds} refetch={refetch} + onRuleChange={onRuleChange} rowRenderers={enabledRowRenderers} selectedEventIds={selectedEventIds} show={id === TimelineId.active ? show : true}