From 894baca7fdd71ad5ee20d754f50b7d299a45bbad Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 28 Oct 2024 05:26:06 +1100 Subject: [PATCH] [8.x] [Cloud Security] Clicking on Contextual Flyout popout Icon now opens page in new tab (#196763) (#197935) # Backport This will backport the following commits from `main` to `8.x`: - [[Cloud Security] Clicking on Contextual Flyout popout Icon now opens page in new tab (#196763)](https://github.com/elastic/kibana/pull/196763) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Rickyanto Ang --- .../public/index.ts | 2 +- .../hooks/use_get_navigation_url_params.ts | 33 ++++++ .../public/src/hooks/use_navigate_findings.ts | 60 ++-------- .../public/src/utils/query_utils.test.ts | 107 ++++++++++++++++++ .../public/src/utils/query_utils.ts | 62 ++++++++++ .../public/tsconfig.json | 1 + .../dashboard_sections/benchmarks_section.tsx | 2 +- .../dashboard_sections/summary_section.tsx | 2 +- .../vulnerability_table_panel_section.tsx | 2 +- ...isconfiguration_findings_details_table.tsx | 45 +++++--- ...vulnerabilities_findings_details_table.tsx | 60 ++++++---- 11 files changed, 280 insertions(+), 96 deletions(-) create mode 100644 x-pack/packages/kbn-cloud-security-posture/public/src/hooks/use_get_navigation_url_params.ts create mode 100644 x-pack/packages/kbn-cloud-security-posture/public/src/utils/query_utils.test.ts diff --git a/x-pack/packages/kbn-cloud-security-posture/public/index.ts b/x-pack/packages/kbn-cloud-security-posture/public/index.ts index c39a86f5ec64b..bf4bccda2816e 100644 --- a/x-pack/packages/kbn-cloud-security-posture/public/index.ts +++ b/x-pack/packages/kbn-cloud-security-posture/public/index.ts @@ -8,7 +8,7 @@ export * from './src/types'; export * from './src/constants/component_constants'; export * from './src/constants/navigation'; -export type { NavFilter } from './src/hooks/use_navigate_findings'; +export type { NavFilter } from './src/utils/query_utils'; export { showErrorToast } from './src/utils/show_error_toast'; export { encodeQuery, decodeQuery } from './src/utils/query_utils'; export { CspEvaluationBadge } from './src/components/csp_evaluation_badge'; diff --git a/x-pack/packages/kbn-cloud-security-posture/public/src/hooks/use_get_navigation_url_params.ts b/x-pack/packages/kbn-cloud-security-posture/public/src/hooks/use_get_navigation_url_params.ts new file mode 100644 index 0000000000000..792ac7b9c5a35 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture/public/src/hooks/use_get_navigation_url_params.ts @@ -0,0 +1,33 @@ +/* + * 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 { CoreStart } from '@kbn/core-lifecycle-browser'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useCallback } from 'react'; +import { CspClientPluginStartDeps } from '../types'; +import { NavFilter, encodeQueryUrl, composeQueryFilters } from '../utils/query_utils'; + +export const useGetNavigationUrlParams = () => { + const { services } = useKibana(); + + const getNavUrlParams = useCallback( + ( + filterParams: NavFilter = {}, + findingsType?: 'configurations' | 'vulnerabilities', + groupBy?: string[] + ) => { + const filters = composeQueryFilters(filterParams); + + const searchParams = new URLSearchParams(encodeQueryUrl(services.data, filters, groupBy)); + + return `${findingsType ? findingsType : ''}?${searchParams.toString()}`; + }, + [services.data] + ); + + return getNavUrlParams; +}; diff --git a/x-pack/packages/kbn-cloud-security-posture/public/src/hooks/use_navigate_findings.ts b/x-pack/packages/kbn-cloud-security-posture/public/src/hooks/use_navigate_findings.ts index 454c9a0056a58..5028b53b90ec9 100644 --- a/x-pack/packages/kbn-cloud-security-posture/public/src/hooks/use_navigate_findings.ts +++ b/x-pack/packages/kbn-cloud-security-posture/public/src/hooks/use_navigate_findings.ts @@ -7,74 +7,28 @@ import { useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { Filter } from '@kbn/es-query'; -import { - SECURITY_DEFAULT_DATA_VIEW_ID, - CDR_MISCONFIGURATIONS_DATA_VIEW_ID_PREFIX, -} from '@kbn/cloud-security-posture-common'; +import { CDR_MISCONFIGURATIONS_DATA_VIEW_ID_PREFIX } from '@kbn/cloud-security-posture-common'; import type { CoreStart } from '@kbn/core/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { findingsNavigation } from '../constants/navigation'; import { useDataView } from './use_data_view'; import { CspClientPluginStartDeps } from '../..'; -import { encodeQuery } from '../utils/query_utils'; +import { NavFilter, encodeQueryUrl, composeQueryFilters } from '../utils/query_utils'; -interface NegatedValue { - value: string | number; - negate: boolean; -} - -type FilterValue = string | number | NegatedValue; - -export type NavFilter = Record; - -const createFilter = (key: string, filterValue: FilterValue, dataViewId: string): Filter => { - let negate = false; - let value = filterValue; - if (typeof filterValue === 'object') { - negate = filterValue.negate; - value = filterValue.value; - } - // If the value is '*', we want to create an exists filter - if (value === '*') { - return { - query: { exists: { field: key } }, - meta: { type: 'exists', index: dataViewId }, - }; - } - return { - meta: { - alias: null, - negate, - disabled: false, - type: 'phrase', - key, - index: dataViewId, - }, - query: { match_phrase: { [key]: value } }, - }; -}; -const useNavigate = (pathname: string, dataViewId = SECURITY_DEFAULT_DATA_VIEW_ID) => { +const useNavigate = (pathname: string, dataViewId?: string) => { const history = useHistory(); - const { services } = useKibana(); + const { services } = useKibana(); return useCallback( (filterParams: NavFilter = {}, groupBy?: string[]) => { - const filters = Object.entries(filterParams).map(([key, filterValue]) => - createFilter(key, filterValue, dataViewId) - ); + const filters = composeQueryFilters(filterParams, dataViewId); history.push({ pathname, - search: encodeQuery({ - // Set query language from user's preference - query: services.data.query.queryString.getDefaultQuery(), - filters, - ...(groupBy && { groupBy }), - }), + search: encodeQueryUrl(services.data, filters, groupBy), }); }, - [history, pathname, services.data.query.queryString, dataViewId] + [dataViewId, history, pathname, services.data] ); }; diff --git a/x-pack/packages/kbn-cloud-security-posture/public/src/utils/query_utils.test.ts b/x-pack/packages/kbn-cloud-security-posture/public/src/utils/query_utils.test.ts new file mode 100644 index 0000000000000..1302702b54287 --- /dev/null +++ b/x-pack/packages/kbn-cloud-security-posture/public/src/utils/query_utils.test.ts @@ -0,0 +1,107 @@ +/* + * 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 { encodeQueryUrl, composeQueryFilters } from './query_utils'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; + +const DEFAULT_DATA_VIEW_ID = 'security-solution-default'; + +describe('composeQueryFilters', () => { + it('Should return correct filters given some filterParams', () => { + const testFilterParams = { + test_field: 'test_value', + }; + const testResult = [ + { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'test_field', + index: DEFAULT_DATA_VIEW_ID, + }, + query: { match_phrase: { test_field: 'test_value' } }, + }, + ]; + expect(composeQueryFilters(testFilterParams)).toEqual(testResult); + }); + + it('Should return empty filters given empty filterParams', () => { + expect(composeQueryFilters({})).toEqual([]); + }); + + it('Should return correct filters given some filterParams and dataviewId', () => { + const testFilterParams = { + test_field: 'test_value', + }; + const testResult = [ + { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'test_field', + index: 'test-data-view', + }, + query: { match_phrase: { test_field: 'test_value' } }, + }, + ]; + expect(composeQueryFilters(testFilterParams, 'test-data-view')).toEqual(testResult); + }); +}); + +describe('encodeQueryUrl', () => { + const getServicesMock = () => ({ + data: dataPluginMock.createStartContract(), + }); + + it('Should return correct URL given empty filters', () => { + const result = 'cspq=(filters:!())'; + expect(encodeQueryUrl(getServicesMock().data, [])).toEqual(result); + }); + + it('should return correct URL given filters', () => { + const filter = [ + { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'test_field', + index: DEFAULT_DATA_VIEW_ID, + }, + query: { match_phrase: { test_field: 'test_value' } }, + }, + ]; + const result = + 'cspq=(filters:!((meta:(alias:!n,disabled:!f,index:security-solution-default,key:test_field,negate:!f,type:phrase),query:(match_phrase:(test_field:test_value)))))'; + expect(encodeQueryUrl(getServicesMock().data, filter)).toEqual(result); + }); + + it('should return correct URL given filters and group by', () => { + const filter = [ + { + meta: { + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'test_field', + index: DEFAULT_DATA_VIEW_ID, + }, + query: { match_phrase: { test_field: 'test_value' } }, + }, + ]; + const groupByFilter = ['filterA']; + const result = + 'cspq=(filters:!((meta:(alias:!n,disabled:!f,index:security-solution-default,key:test_field,negate:!f,type:phrase),query:(match_phrase:(test_field:test_value)))),groupBy:!(filterA))'; + expect(encodeQueryUrl(getServicesMock().data, filter, groupByFilter)).toEqual(result); + }); +}); diff --git a/x-pack/packages/kbn-cloud-security-posture/public/src/utils/query_utils.ts b/x-pack/packages/kbn-cloud-security-posture/public/src/utils/query_utils.ts index 3a051456733a6..6cb5c1384e732 100644 --- a/x-pack/packages/kbn-cloud-security-posture/public/src/utils/query_utils.ts +++ b/x-pack/packages/kbn-cloud-security-posture/public/src/utils/query_utils.ts @@ -4,8 +4,21 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import { encode, decode } from '@kbn/rison'; import type { LocationDescriptorObject } from 'history'; +import { Filter } from '@kbn/es-query'; +import { SECURITY_DEFAULT_DATA_VIEW_ID } from '@kbn/cloud-security-posture-common'; +import { DataPublicPluginStart } from '@kbn/data-plugin/public'; + +interface NegatedValue { + value: string | number; + negate: boolean; +} + +type FilterValue = string | number | NegatedValue; + +export type NavFilter = Record; const encodeRison = (v: any): string | undefined => { try { @@ -38,3 +51,52 @@ export const decodeQuery = (search?: string): Partial | un if (!risonQuery) return; return decodeRison(risonQuery); }; + +export const encodeQueryUrl = ( + servicesStart: DataPublicPluginStart, + filters: Filter[], + groupBy?: string[] +): any => { + return encodeQuery({ + query: servicesStart.query.queryString.getDefaultQuery(), + filters, + ...(groupBy && { groupBy }), + }); +}; + +// dataViewId is used to prevent FilterManager from falling back to the default in the sorcerer (logs-*) +export const composeQueryFilters = ( + filterParams: NavFilter = {}, + dataViewId = SECURITY_DEFAULT_DATA_VIEW_ID +): Filter[] => { + return Object.entries(filterParams).map(([key, filterValue]) => + createFilter(key, filterValue, dataViewId) + ); +}; + +export const createFilter = (key: string, filterValue: FilterValue, dataViewId: string): Filter => { + let negate = false; + let value = filterValue; + if (typeof filterValue === 'object') { + negate = filterValue.negate; + value = filterValue.value; + } + // If the value is '*', we want to create an exists filter + if (value === '*') { + return { + query: { exists: { field: key } }, + meta: { type: 'exists', index: dataViewId }, + }; + } + return { + meta: { + alias: null, + negate, + disabled: false, + type: 'phrase', + key, + index: dataViewId, + }, + query: { match_phrase: { [key]: value } }, + }; +}; diff --git a/x-pack/packages/kbn-cloud-security-posture/public/tsconfig.json b/x-pack/packages/kbn-cloud-security-posture/public/tsconfig.json index e7f69a99c5199..8c950553c7cde 100644 --- a/x-pack/packages/kbn-cloud-security-posture/public/tsconfig.json +++ b/x-pack/packages/kbn-cloud-security-posture/public/tsconfig.json @@ -35,5 +35,6 @@ "@kbn/ui-theme", "@kbn/i18n-react", "@kbn/rison", + "@kbn/core-lifecycle-browser", ] } diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx index 4a4d4b6c1b193..f4cc7a5ba0028 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx @@ -13,7 +13,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { css } from '@emotion/react'; import { i18n } from '@kbn/i18n'; import { useNavigateFindings } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; -import type { NavFilter } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; +import type { NavFilter } from '@kbn/cloud-security-posture/src/utils/query_utils'; import type { BenchmarkData, ComplianceDashboardDataV2, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx index 9cb41910f8f83..e5ea0a9139a7e 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/summary_section.tsx @@ -16,7 +16,7 @@ import { import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '@kbn/cloud-security-posture-common'; -import type { NavFilter } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; +import type { NavFilter } from '@kbn/cloud-security-posture/src/utils/query_utils'; import { useNavigateFindings } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; import { useCspIntegrationLink } from '../../../common/navigation/use_csp_integration_link'; import { DASHBOARD_COUNTER_CARDS, DASHBOARD_SUMMARY_CONTAINER } from '../test_subjects'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx index 28012e3e8e438..a4e3dd38b28a1 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerability_dashboard/vulnerability_table_panel_section.tsx @@ -16,7 +16,7 @@ import { useEuiTheme, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { NavFilter } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; +import type { NavFilter } from '@kbn/cloud-security-posture/src/utils/query_utils'; import { useNavigateVulnerabilities } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; import type { VulnSeverity } from '@kbn/cloud-security-posture-common'; import { CVSScoreBadge, SeverityStatusBadge } from '@kbn/cloud-security-posture'; diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx index c03dc319952b5..8d4088b19f9b6 100644 --- a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx +++ b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/misconfiguration_findings_details_table.tsx @@ -7,14 +7,13 @@ import React, { memo, useEffect, useState } from 'react'; import type { Criteria, EuiBasicTableColumn } from '@elastic/eui'; -import { EuiSpacer, EuiIcon, EuiPanel, EuiLink, EuiText, EuiBasicTable } from '@elastic/eui'; +import { EuiSpacer, EuiPanel, EuiText, EuiBasicTable, EuiIcon } from '@elastic/eui'; import { useMisconfigurationFindings } from '@kbn/cloud-security-posture/src/hooks/use_misconfiguration_findings'; import { i18n } from '@kbn/i18n'; import type { CspFinding, CspFindingResult } from '@kbn/cloud-security-posture-common'; import { buildEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common'; import { euiThemeVars } from '@kbn/ui-theme'; import { DistributionBar } from '@kbn/security-solution-distribution-bar'; -import { useNavigateFindings } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; import type { CspBenchmarkRuleMetadata } from '@kbn/cloud-security-posture-common/schema/rules/latest'; import { CspEvaluationBadge } from '@kbn/cloud-security-posture'; import { @@ -24,6 +23,9 @@ import { uiMetricService, } from '@kbn/cloud-security-posture-common/utils/ui_metrics'; import { METRIC_TYPE } from '@kbn/analytics'; +import { useGetNavigationUrlParams } from '@kbn/cloud-security-posture/src/hooks/use_get_navigation_url_params'; +import { SecurityPageName } from '@kbn/deeplinks-security'; +import { SecuritySolutionLinkAnchor } from '../../../common/components/links'; type MisconfigurationFindingDetailFields = Pick; @@ -114,18 +116,14 @@ export const MisconfigurationFindingsDetailsTable = memo( } }; - const navToFindings = useNavigateFindings(); + const getNavUrlParams = useGetNavigationUrlParams(); - const navToFindingsByRuleAndResourceId = (ruleId: string, resourceId: string) => { - navToFindings({ 'rule.id': ruleId, 'resource.id': resourceId }); + const getFindingsPageUrlFilteredByRuleAndResourceId = (ruleId: string, resourceId: string) => { + return getNavUrlParams({ 'rule.id': ruleId, 'resource.id': resourceId }, 'configurations'); }; - const navToFindingsByName = (name: string, queryField: 'host.name' | 'user.name') => { - uiMetricService.trackUiMetric( - METRIC_TYPE.CLICK, - NAV_TO_FINDINGS_BY_RULE_NAME_FRPOM_ENTITY_FLYOUT - ); - navToFindings({ [queryField]: name }, ['rule.name']); + const getFindingsPageUrl = (name: string, queryField: 'host.name' | 'user.name') => { + return getNavUrlParams({ [queryField]: name }, 'configurations', ['rule.name']); }; const columns: Array> = [ @@ -134,13 +132,23 @@ export const MisconfigurationFindingsDetailsTable = memo( name: '', width: '5%', render: (rule: CspBenchmarkRuleMetadata, finding: MisconfigurationFindingDetailFields) => ( - { - navToFindingsByRuleAndResourceId(rule?.id, finding?.resource?.id); + uiMetricService.trackUiMetric( + METRIC_TYPE.CLICK, + NAV_TO_FINDINGS_BY_RULE_NAME_FRPOM_ENTITY_FLYOUT + ); }} > - + ), }, { @@ -170,13 +178,16 @@ export const MisconfigurationFindingsDetailsTable = memo( return ( <> - { uiMetricService.trackUiMetric( METRIC_TYPE.CLICK, NAV_TO_FINDINGS_BY_HOST_NAME_FRPOM_ENTITY_FLYOUT ); - navToFindingsByName(queryName, fieldName); }} > {i18n.translate( @@ -186,7 +197,7 @@ export const MisconfigurationFindingsDetailsTable = memo( } )} - + diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/vulnerabilities_findings_details_table.tsx b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/vulnerabilities_findings_details_table.tsx index f3422564186ed..82c5f91bf4250 100644 --- a/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/vulnerabilities_findings_details_table.tsx +++ b/x-pack/plugins/security_solution/public/cloud_security_posture/components/csp_details/vulnerabilities_findings_details_table.tsx @@ -7,12 +7,11 @@ import React, { memo, useEffect, useState } from 'react'; import type { Criteria, EuiBasicTableColumn } from '@elastic/eui'; -import { EuiSpacer, EuiIcon, EuiPanel, EuiLink, EuiText, EuiBasicTable } from '@elastic/eui'; +import { EuiSpacer, EuiPanel, EuiText, EuiBasicTable, EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { VulnSeverity } from '@kbn/cloud-security-posture-common'; import { buildEntityFlyoutPreviewQuery } from '@kbn/cloud-security-posture-common'; import { DistributionBar } from '@kbn/security-solution-distribution-bar'; -import { useNavigateVulnerabilities } from '@kbn/cloud-security-posture/src/hooks/use_navigate_findings'; import { useVulnerabilitiesFindings } from '@kbn/cloud-security-posture/src/hooks/use_vulnerabilities_findings'; import type { CspVulnerabilityFinding, @@ -29,6 +28,9 @@ import { uiMetricService, } from '@kbn/cloud-security-posture-common/utils/ui_metrics'; import { METRIC_TYPE } from '@kbn/analytics'; +import { SecurityPageName } from '@kbn/deeplinks-security'; +import { useGetNavigationUrlParams } from '@kbn/cloud-security-posture/src/hooks/use_get_navigation_url_params'; +import { SecuritySolutionLinkAnchor } from '../../../common/components/links'; type VulnerabilitiesFindingDetailFields = Pick< CspVulnerabilityFinding, @@ -38,6 +40,7 @@ type VulnerabilitiesFindingDetailFields = Pick< interface VulnerabilitiesPackage extends Vulnerability { package: { name: string; + version: string; }; } @@ -94,20 +97,27 @@ export const VulnerabilitiesFindingsDetailsTable = memo(({ queryName }: { queryN } }; - const navToVulnerabilities = useNavigateVulnerabilities(); + const getNavUrlParams = useGetNavigationUrlParams(); - const navToVulnerabilitiesByName = (name: string, queryField: 'host.name' | 'user.name') => { - navToVulnerabilities({ [queryField]: name }); + const getVulnerabilityUrl = (name: string, queryField: 'host.name' | 'user.name') => { + return getNavUrlParams({ [queryField]: name }, 'vulnerabilities'); }; - const navToVulnerabilityByVulnerabilityAndResourceId = ( + const getVulnerabilityUrlFilteredByVulnerabilityAndResourceId = ( vulnerabilityId: string, - resourceId: string + resourceId: string, + vulnerabilityPackageName: string, + vulnerabilityPackageVersion: string ) => { - navToVulnerabilities({ - 'vulnerability.id': vulnerabilityId, - 'resource.id': resourceId, - }); + return getNavUrlParams( + { + 'vulnerability.id': vulnerabilityId, + 'resource.id': resourceId, + 'vulnerability.package.name': vulnerabilityPackageName, + 'vulnerability.package.version': vulnerabilityPackageVersion, + }, + 'vulnerabilities' + ); }; const columns: Array> = [ @@ -119,16 +129,19 @@ export const VulnerabilitiesFindingsDetailsTable = memo(({ queryName }: { queryN vulnerability: VulnerabilitiesPackage, finding: VulnerabilitiesFindingDetailFields ) => ( - { - navToVulnerabilityByVulnerabilityAndResourceId( - vulnerability?.id, - finding?.resource?.id || '' - ); - }} + - + ), }, { @@ -189,20 +202,23 @@ export const VulnerabilitiesFindingsDetailsTable = memo(({ queryName }: { queryN return ( <> - { uiMetricService.trackUiMetric( METRIC_TYPE.CLICK, NAV_TO_FINDINGS_BY_HOST_NAME_FRPOM_ENTITY_FLYOUT ); - navToVulnerabilitiesByName(queryName, 'host.name'); }} > {i18n.translate('xpack.securitySolution.flyout.left.insights.vulnerability.tableTitle', { defaultMessage: 'Vulnerability ', })} - +