-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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][Detection Alerts] Alert tagging #157786
Conversation
d514119
to
3ad0adf
Compare
@@ -125,3 +127,10 @@ export const privilege = t.type({ | |||
}); | |||
|
|||
export type Privilege = t.TypeOf<typeof privilege>; | |||
|
|||
export const alert_tags = t.type({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of following the rules bulk edit tags schema? It may make it easier to expand the feature by following a more reusable pattern like:
const BulkActionEditPayloadTags = t.type({
type: t.union([
t.literal(BulkActionEditType.add_tags),
t.literal(BulkActionEditType.delete_tags),
t.literal(BulkActionEditType.set_tags),
]),
value: RuleTagArray,
});
That way if we decide theres a new action type we want to introduce for tags, the schema updates are minimal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be open to more discussion on this pertaining to more reusable patterns and expandability, it's definitely a bit unusual, but the main reason we created it like this in the first place was because we have the intermediate state in the bulk actions tags dropdown, so we couldn't just handle setting all queried alerts to the same tags array. With the two different buckets of add and remove we can cover each of the possible use cases for each specific alert with one api call.
|
||
const { setAlertTags } = useSetAlertTags(); | ||
const initalTagsState = useMemo(() => { | ||
const existingTags = alertIds.map( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: can we extract this into a helper or util we can unit test?
Also, would using a set here simplify the number of iterations through the tags?
.../plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_tags.tsx
Outdated
Show resolved
Hide resolved
.../plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_tags.tsx
Outdated
Show resolved
Hide resolved
} else if (changedOption.checked === 'on') { | ||
tagsToAdd[changedOption.label] = true; | ||
delete tagsToRemove[changedOption.label]; | ||
} else if (!changedOption.checked) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are you checking if the checked
property exists or if it's null
or undefined
?
.../plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_tags.tsx
Outdated
Show resolved
Hide resolved
x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/helpers.ts
Outdated
Show resolved
Hide resolved
> | ||
{isolateHostTitle} | ||
</EuiContextMenuItem>, | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs unit test
!isEvent && actionsData.ruleId | ||
? [...statusActionItems, ...exceptionActionItems] | ||
? [...statusActionItems, ...alertTagsItems, ...exceptionActionItems] | ||
: isEndpointEvent && canCreateEndpointEventFilters | ||
? eventFilterActionItems | ||
: [], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add unit tests for rendering correct alerts actions items
@@ -88,5 +89,11 @@ export const getBulkActionHook = | |||
refetch: refetchGlobalQuery, | |||
}); | |||
|
|||
return [...alertActions, timelineAction]; | |||
const { alertTagsItems, alertTagsPanels } = useBulkAlertTagsItems({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this file does not have any unit tests to add to, but it really should have them on the new and existing behavior
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the new feature, super cool!
With Feature Freeze pending, I won't require the requested unit tests for approval, but I would request a Github issue be created noting what tests are missing.
One thing I do have to insist be done before merging is to add a mount check to any state updates that could happen after a component has dismounted (see here)
x-pack/plugins/security_solution/common/detection_engine/schemas/alerts/8.9.0/index.ts
Outdated
Show resolved
Hide resolved
refetch?: () => void; | ||
} | ||
|
||
export const useAlertTagsActions = ({ closePopover, ecsRowData, scopeId, refetch }: Props) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this hook needs unit tests
|
||
export const validateAlertTagsArrays = (tags: AlertTags) => { | ||
const { tags_to_add: tagsToAdd, tags_to_remove: tagsToRemove } = tags; | ||
const duplicates = tagsToAdd.filter((tag) => tagsToRemove.includes(tag)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs a little test here as well
if (refetchQuery) refetchQuery(); | ||
if (refresh) refresh(); | ||
if (clearSelection) clearSelection(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we group all these props under a single onUpdateSuccess
prop? And let the caller do whatever it needs when the update succeeded, outside this component.
}), | ||
[alerts, isAllSelected, items, rowSelection, setIsBulkActionsLoading, clearSelection, refresh] | ||
); | ||
const bulkActionsPanels = useMemo(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
entire file needs unit tests, especially the logic here
@@ -71,6 +72,23 @@ const getCaseAttachments = ({ | |||
return groupAlertsByRule?.(filteredAlerts) ?? []; | |||
}; | |||
|
|||
const addItemsToInitalPanel = ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const addItemsToInitalPanel = ({ | |
const addItemsToInitialPanel = ({ |
Can you also pease ensure your tests hit each of these conditions, I believe only one is currently tested
|
||
const clearSelection = () => { | ||
updateBulkActionsState({ action: BulkActionsVerbs.clear }); | ||
}; | ||
const caseBulkActions = useBulkAddToCaseActions({ casesConfig, refresh, clearSelection }); | ||
|
||
const bulkActions = [...configBulkActions, ...caseBulkActions]; | ||
const bulkActions = | ||
caseBulkActions.length !== 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another condition we should test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes this hook also probably runs too often as well, both the old way and new way.
...lugins/security_solution/public/common/components/toolbar/bulk_actions/use_set_alert_tags.ts
Outdated
Show resolved
Hide resolved
.../plugins/security_solution/public/common/components/toolbar/bulk_actions/alert_bulk_tags.tsx
Show resolved
Hide resolved
...plugins/security_solution/server/lib/detection_engine/routes/signals/set_alert_tags_route.ts
Outdated
Show resolved
Hide resolved
try { | ||
setIsLoading(true); | ||
setTableLoading(true); | ||
const response = await http.fetch<estypes.UpdateByQueryResponse>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not react-query?
x-pack/plugins/security_solution/public/common/components/toolbar/bulk_actions/index.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new warning when I apply a tag:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
at BulkAlertTagsPanelComponent (http://localhost:5601/9007199254740991/bundles/plugin/securitySolution/1.0.0/securitySolution.chunk.lazy_register_alerts_table_configuration.js:107579:3)
at div
at EuiResizeObserver (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:128128:81)
at div
at EuiContextMenuPanel (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:84005:81)
at div
at EuiContextMenu (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:83483:81)
at div
at EuiMutationObserver (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:127891:81)
at div
at http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:166047:73
at EuiPanel (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:131939:23)
at http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:166047:73
at EuiPopoverPanel (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:133242:23)
at div
at http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:366533:59
at FocusLockUI (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:362836:71)
at http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:363739:60
at EuiFocusTrap (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:105315:81)
at EuiPortal (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:133710:81)
at div
at http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:166047:73
at EuiPopover (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:132478:81)
at div
at forwardRef (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:423669:12)
at div
at AlertContextMenuComponent (http://localhost:5601/9007199254740991/bundles/plugin/securitySolution/1.0.0/securitySolution.chunk.lazy_register_alerts_table_configuration.js:142978:3)
at ConnectFunction (http://localhost:5601/9007199254740991/bundles/plugin/securitySolution/1.0.0/securitySolution.chunk.3.js:422:41)
at div
at forwardRef (http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:423669:12)
at ActionsComponent (http://localhost:5601/9007199254740991/bundles/plugin/securitySolution/1.0.0/securitySolution.chunk.lazy_register_alerts_table_configuration.js:95250:3)
at RowActionComponent (http://localhost:5601/9007199254740991/bundles/plugin/securitySolution/1.0.0/securitySolution.chunk.lazy_register_alerts_table_configuration.js:85295:3)
at div
at http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:166047:73
at http://localhost:5601/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:104071:23
at rowCellRender (http://localhost:5601/9007199254740991/bundles/plugin/triggersActionsUi/1.0.0/triggersActionsUi.chunk.24.js:1030:13)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree with needing additional unit tests, also should fix the warning(s) that appear, but overall feature works alright locally and any bugs/missing tests/warning fixes can be fixed post FF 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with @kqualters-elastic about the console warnings, that likely means we didn't catch the state updates on something dismounted. I strongly suggest updating the query to be managed either by useFetch
or react-query
to reduce risk of bad state updates. I added a comment to your unit test PR to address the console warnings as well. Thank you for the changes!
LGTM, please ping me directly for the follow up PR.
💛 Build succeeded, but was flaky
Failed CI StepsTest Failures
Metrics [docs]Module Count
Public APIs missing comments
Async chunks
Page load bundle
Unknown metric groupsAPI count
ESLint disabled line counts
Total ESLint disabled count
History
To update your PR or re-run it, just comment with: cc @dplumlee |
Summary
Epic (internal): https://github.com/elastic/security-team/issues/3273
Adds tagging feature to alerts generated by security solution detection rules. Users will now be able to tag individual alerts via a dropdown on the alerts page or via the take action menu in the alert details flyout. They will also be able to bulk manage tags within the bulk actions menu on the alerts table. Tag options are generated from a field in the advanced settings and will be defaulted to 3 options (Duplicate, False positive, Further investigation required).
From a code standpoint, alert tags will live in a new field:
kibana.alert.workflow_tags
in order to avoid merging with copied source event tags in existing schema fieldsScreenshots
From alert context menu
From bulk actions
Checklist
Delete any items that are not applicable to this PR.
For maintainers