From 49ebd28e257912cc942276b8072025088dc13997 Mon Sep 17 00:00:00 2001 From: semd Date: Tue, 10 Aug 2021 21:06:12 +0200 Subject: [PATCH 01/16] use rac alerts bulk_update --- ...te_old_security_solution_alert_by_query.sh | 6 +- .../common/experimental_features.ts | 2 +- .../routes/index/signal_aad_mapping.json | 2 +- .../public/components/t_grid/body/index.tsx | 8 +++ .../public/components/t_grid/helpers.tsx | 62 +++++++++++++++---- .../components/t_grid/integrated/index.tsx | 26 +++++++- .../components/t_grid/standalone/index.tsx | 26 +++++++- .../alert_status_bulk_actions.tsx | 8 ++- .../public/container/use_update_alerts.ts | 20 +++--- .../hooks/use_status_bulk_action_items.tsx | 15 +++-- .../server/search_strategy/timeline/index.ts | 13 ++-- 11 files changed, 154 insertions(+), 34 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/scripts/bulk_update_old_security_solution_alert_by_query.sh b/x-pack/plugins/rule_registry/server/scripts/bulk_update_old_security_solution_alert_by_query.sh index 8725e791d8efa..08cb22d5e4976 100755 --- a/x-pack/plugins/rule_registry/server/scripts/bulk_update_old_security_solution_alert_by_query.sh +++ b/x-pack/plugins/rule_registry/server/scripts/bulk_update_old_security_solution_alert_by_query.sh @@ -20,9 +20,9 @@ cd ../observer && sh ./post_detections_role.sh && sh ./post_detections_user.sh cd .. # Example: ./update_observability_alert.sh "kibana.rac.alert.stats: open" -curl -s -k \ +curl -v \ -H 'Content-Type: application/json' \ -H 'kbn-xsrf: 123' \ -u hunter:changeme \ - -X POST ${KIBANA_URL}${SPACE_URL}/internal/rac/alerts/bulk_update \ --d "{\"query\": \"$QUERY\", \"status\":\"$STATUS\", \"index\":\".siem-signals*\"}" | jq . + -X POST ${KIBANA_URL}/internal/rac/alerts/bulk_update \ +-d "{\"ids\": [\"cf2b7bf9b224c5ca9b4080ebf7a0ee0e1556898633cca169913482f5664a8a04\"], \"status\":\"open\", \"index\":\".siem-signals*\"}" diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 0ae42d4baaec4..a474ae602fab2 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -14,7 +14,7 @@ export type ExperimentalFeatures = typeof allowedExperimentalValues; export const allowedExperimentalValues = Object.freeze({ metricsEntitiesEnabled: false, ruleRegistryEnabled: false, - tGridEnabled: false, + tGridEnabled: true, trustedAppsByPolicyEnabled: false, excludePoliciesInFilterEnabled: false, uebaEnabled: false, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json index 066fdbc87f906..59f8b9db827be 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/signal_aad_mapping.json @@ -83,7 +83,7 @@ "signal.rule.updated_at": "kibana.alert.rule.updated_at", "signal.rule.updated_by": "kibana.alert.rule.updated_by", "signal.rule.version": "kibana.alert.rule.version", - "signal.status": "kibana.alert.workflow_status", + "signal.status": "kibana.alert.status", "signal.threshold_result.from": "kibana.alert.threshold_result.from", "signal.threshold_result.terms.field": "kibana.alert.threshold_result.terms.field", "signal.threshold_result.terms.value": "kibana.alert.threshold_result.terms.value", diff --git a/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx index cc94f901446a7..ab104ea8e438b 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx @@ -74,6 +74,7 @@ interface OwnProps { activePage: number; additionalControls?: React.ReactNode; browserFields: BrowserFields; + filterQuery: string; data: TimelineItem[]; defaultCellActions?: TGridCellAction[]; id: string; @@ -90,6 +91,7 @@ interface OwnProps { filterStatus?: AlertStatus; unit?: (total: number) => React.ReactNode; onRuleChange?: () => void; + indexNames: string[]; refetch: Refetch; } @@ -225,6 +227,7 @@ export const BodyComponent = React.memo( activePage, additionalControls, browserFields, + filterQuery, columnHeaders, data, defaultCellActions, @@ -250,6 +253,7 @@ export const BodyComponent = React.memo( unit = basicUnit, leadingControlColumns = EMPTY_CONTROL_COLUMNS, trailingControlColumns = EMPTY_CONTROL_COLUMNS, + indexNames, refetch, }) => { const dispatch = useDispatch(); @@ -337,6 +341,8 @@ export const BodyComponent = React.memo( id={id} totalItems={totalItems} filterStatus={filterStatus} + query={filterQuery} + indexName={indexNames.join(',')} onActionSuccess={onAlertStatusActionSuccess} onActionFailure={onAlertStatusActionFailure} refetch={refetch} @@ -375,7 +381,9 @@ export const BodyComponent = React.memo( alertCountText, totalItems, filterStatus, + filterQuery, browserFields, + indexNames, columnHeaders, additionalControls, showBulkActions, diff --git a/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx b/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx index 58d92c5f47f29..6044c868ef089 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx @@ -15,7 +15,7 @@ import { handleSkipFocus, stopPropagationAndPreventDefault, } from '../../../common'; -import type { IIndexPattern } from '../../../../../../src/plugins/data/public'; +import { esFilters, IIndexPattern } from '../../../../../../src/plugins/data/public'; import type { BrowserFields } from '../../../common/search_strategy/index_fields'; import { DataProviderType, EXISTS_OPERATOR } from '../../../common/types/timeline'; import type { DataProvider, DataProvidersAnd } from '../../../common/types/timeline'; @@ -133,6 +133,17 @@ export const buildGlobalQuery = (dataProviders: DataProvider[], browserFields: B return !index ? `(${queryMatch})` : `${globalQuery} or (${queryMatch})`; }, ''); +interface CombineQueries { + config: EsQueryConfig; + dataProviders: DataProvider[]; + indexPattern: IIndexPattern; + browserFields: BrowserFields; + filters: Filter[]; + kqlQuery: Query; + kqlMode: string; + isEventViewer?: boolean; +} + export const combineQueries = ({ config, dataProviders, @@ -142,16 +153,7 @@ export const combineQueries = ({ kqlQuery, kqlMode, isEventViewer, -}: { - config: EsQueryConfig; - dataProviders: DataProvider[]; - indexPattern: IIndexPattern; - browserFields: BrowserFields; - filters: Filter[]; - kqlQuery: Query; - kqlMode: string; - isEventViewer?: boolean; -}): { filterQuery: string } | null => { +}: CombineQueries): { filterQuery: string } | null => { const kuery: Query = { query: '', language: kqlQuery.language }; if (isEmpty(dataProviders) && isEmpty(kqlQuery.query) && isEmpty(filters) && !isEventViewer) { return null; @@ -184,6 +186,44 @@ export const combineQueries = ({ }; }; +export const buildTimeRangeFilter = (from: string, to: string): Filter => + ({ + range: { + '@timestamp': { + gte: from, + lt: to, + format: 'strict_date_optional_time', + }, + }, + meta: { + type: 'range', + disabled: false, + negate: false, + alias: null, + key: '@timestamp', + params: { + gte: from, + lt: to, + format: 'strict_date_optional_time', + }, + }, + $state: { + store: esFilters.FilterStateStore.APP_STATE, + }, + } as Filter); + +export const getCombinedFilterQuery = ({ + from, + to, + filters, + ...combineQueriesParams +}: CombineQueries & { from: string; to: string }): string => { + return combineQueries({ + ...combineQueriesParams, + filters: [...filters, buildTimeRangeFilter(from, to)], + })!.filterQuery; +}; + /** * The CSS class name of a "stateful event", which appears in both * the `Timeline` and the `Events Viewer` widget diff --git a/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx index 36b5537eb3010..49a187b8aeada 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx @@ -35,7 +35,12 @@ import { } from '../../../../../../../src/plugins/data/public'; import { useDeepEqualSelector } from '../../../hooks/use_selector'; import { defaultHeaders } from '../body/column_headers/default_headers'; -import { calculateTotalPages, combineQueries, resolverIsShowing } from '../helpers'; +import { + calculateTotalPages, + combineQueries, + getCombinedFilterQuery, + resolverIsShowing, +} from '../helpers'; import { tGridActions, tGridSelectors } from '../../../store/t_grid'; import { useTimelineEvents } from '../../../container'; import { HeaderSection } from '../header_section'; @@ -253,6 +258,23 @@ const TGridIntegratedComponent: React.FC = ({ data, }); + const filterQuery = useMemo( + () => + getCombinedFilterQuery({ + config: esQuery.getEsQueryConfig(uiSettings), + dataProviders, + indexPattern, + browserFields, + filters, + kqlQuery: query, + kqlMode, + isEventViewer: true, + from: start, + to: end, + }), + [uiSettings, dataProviders, indexPattern, browserFields, filters, start, end, query, kqlMode] + ); + const totalCountMinusDeleted = useMemo( () => (totalCount > 0 ? totalCount - deletedEventIds.length : 0), [deletedEventIds.length, totalCount] @@ -311,6 +333,7 @@ const TGridIntegratedComponent: React.FC = ({ = ({ leadingControlColumns={leadingControlColumns} trailingControlColumns={trailingControlColumns} refetch={refetch} + indexNames={indexNames} />