[Cloud Security] Findings tab redirection logic. (#162289)

## Summary

Part of the CSP teams quick wins effort, this PR aims to improve the
experience for users first landing on the Findings page, or returning to
it.

Currently we always set the "Misconfigurations" tab as default
regardless of whether there are misconfigs or not. Even if there are
vulnerabilities (the primary tab), it will still default to misconfigs.

A small component was created to handle the root route for 'findings'
and decide which Tab to be redirected to. Vulnerabilities or
Misconfigurations. If a user has never made a tab selection, there are
no vulnerabilities, but there are findings, the user will be redirected
to the "Misconfigurations" tab. If the user had previously clicked to
select a tab, it will always remember which tab they came from last.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Karl Godard 2023-07-26 16:39:55 -07:00 committed by GitHub
parent 6440075a8b
commit c37b78ef68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 9 deletions

View file

@ -18,7 +18,7 @@ import {
CLOUDBEAT_VANILLA,
CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE,
} from '../constants';
import type { BenchmarkId, Score } from '../types';
import type { BenchmarkId, Score, BaseCspSetupStatus } from '../types';
/**
* @example
@ -84,3 +84,17 @@ export const calculatePostureScore = (passed: number, failed: number): Score =>
return roundScore(passed / (passed + failed));
};
export const getStatusForIndexName = (indexName: string, status?: BaseCspSetupStatus) => {
if (status) {
const indexDetail = status.indicesDetails.find(
(details) => details.index.indexOf(indexName) !== -1
);
if (indexDetail) {
return indexDetail.status;
}
}
return 'unknown';
};

View file

@ -42,6 +42,7 @@ export const LOCAL_STORAGE_PAGE_SIZE_BENCHMARK_KEY = 'cloudPosture:benchmark:pag
export const LOCAL_STORAGE_PAGE_SIZE_RULES_KEY = 'cloudPosture:rules:pageSize';
export const LOCAL_STORAGE_DASHBOARD_CLUSTER_SORT_KEY =
'cloudPosture:complianceDashboard:clusterSort';
export const LOCAL_STORAGE_FINDINGS_LAST_SELECTED_TAB_KEY = 'cloudPosture:findings:lastSelectedTab';
export type CloudPostureIntegrations = Record<
CloudSecurityPolicyTemplate,

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import React from 'react';
import useLocalStorage from 'react-use/lib/useLocalStorage';
import {
EuiBetaBadge,
EuiFlexGroup,
@ -20,16 +21,62 @@ import { Redirect, useHistory, useLocation, matchPath } from 'react-router-dom';
import { Routes, Route } from '@kbn/shared-ux-router';
import { Configurations } from '../configurations';
import { cloudPosturePages, findingsNavigation } from '../../common/navigation/constants';
import { LOCAL_STORAGE_FINDINGS_LAST_SELECTED_TAB_KEY } from '../../common/constants';
import { VULNERABILITIES_INDEX_NAME, FINDINGS_INDEX_NAME } from '../../../common/constants';
import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api';
import { getStatusForIndexName } from '../../../common/utils/helpers';
import { Vulnerabilities } from '../vulnerabilities';
type FindingsTabKey = 'vuln_mgmt' | 'configurations';
const FindingsTabRedirecter = ({ lastTabSelected }: { lastTabSelected?: FindingsTabKey }) => {
const location = useLocation();
const getSetupStatus = useCspSetupStatusApi();
if (!getSetupStatus.data) {
return null;
}
const vulnStatus = getStatusForIndexName(VULNERABILITIES_INDEX_NAME, getSetupStatus.data);
const findingsStatus = getStatusForIndexName(FINDINGS_INDEX_NAME, getSetupStatus.data);
const hasVulnerabilities = vulnStatus === 'not-empty';
const hasFindings = findingsStatus === 'not-empty';
// if the user has not yet made a tab selection
// switch to misconfigurations page if there are misconfigurations, and no vulnerabilities
const redirectToMisconfigurationsTab =
lastTabSelected === 'configurations' ||
(!lastTabSelected && !hasVulnerabilities && hasFindings);
if (redirectToMisconfigurationsTab) {
return (
<Redirect
to={{ search: location.search, pathname: findingsNavigation.findings_default.path }}
/>
);
}
// otherwise stay on the vulnerabilities tab, since it's the first one.
return (
<Redirect to={{ search: location.search, pathname: findingsNavigation.vulnerabilities.path }} />
);
};
export const Findings = () => {
const history = useHistory();
const location = useLocation();
// restore the users most recent tab selection
const [lastTabSelected, setLastTabSelected] = useLocalStorage<FindingsTabKey>(
LOCAL_STORAGE_FINDINGS_LAST_SELECTED_TAB_KEY
);
const navigateToVulnerabilitiesTab = () => {
setLastTabSelected('vuln_mgmt');
history.push({ pathname: findingsNavigation.vulnerabilities.path });
};
const navigateToConfigurationsTab = () => {
setLastTabSelected('configurations');
history.push({ pathname: findingsNavigation.findings_default.path });
};
@ -107,14 +154,7 @@ export const Findings = () => {
<Route
exact
path={cloudPosturePages.findings.path}
render={() => (
<Redirect
to={{
pathname: findingsNavigation.findings_default.path,
search: location.search,
}}
/>
)}
render={() => <FindingsTabRedirecter lastTabSelected={lastTabSelected} />}
/>
<Route path={findingsNavigation.findings_default.path} component={Configurations} />
<Route path={findingsNavigation.findings_by_resource.path} component={Configurations} />