From 37a4691ab6b33886b20126b54120f37002f26125 Mon Sep 17 00:00:00 2001 From: Rickyanto Ang Date: Sun, 27 Oct 2024 23:47:01 +0700 Subject: [PATCH] [Cloud Security] Clicking on Contextual Flyout popout Icon now opens page in new tab (#196763) ## Summary Currently when user clicks on Popout icon on Misconfiguration or Vulnerabilities Contextual flyout, user gets redirected to Findings page but in the same tab. Popout Icon implies that it should navigate user to other page on separate Tabs as such the current behaviour is not right. This PR addresses that issue --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../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 ', })} - +