Skip to content

Commit

Permalink
kibana-cloud-security-posture owned UX adjustment for borealis (elast…
Browse files Browse the repository at this point in the history
…ic#205136)

## Summary

This PR covers some of the changes required for the new Borealis theme:
- elastic/security-team#11230 

The detailed guide of migrating to Borealis can be found in this meta
ticket:
- elastic#199715

As the work is still in progress, here are the details of what is
included in this PR:
- the full migration is done for flows related to Cloud Security
Posture. One requirement from EUI is not fulfilled, as we switched to
hardcoded severity colors and hardcoded failed/passed misconfig finding
colors. This is because the new severity color palette built by EUI team
is not yet approved by Security Designers, see
https://elastic.slack.com/archives/C0851RDCWPP/p1736954935896329 for
more details
- I made some straightforward changes to Cloud Defend and k8s dashboard
plugins and added some todos, but these plugins are decommissioned in
Serverless and from 9.0, so no thorough testing is required
- In the Session View I made some straightforward changes according to
the EUI guide and added TODOs where feedback from designers is required.
Still waiting for the designer's feedback, but I think we can safely
merge the changes present in this PR and it will bring Session View to a
better state before 9.0 FF

Amsterdam vs Borealis comparison screenshots for CSP and Session View:

https://www.figma.com/design/XPKYLgZcoI61V3RUfHoHg9/Untitled?node-id=41-42&t=zLvulagbqCiXhrAo-0

### Checklist

Check the PR satisfies following conditions. 

Reviewers should verify this PR satisfies this list as well.

- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [x] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
maxcold and kibanamachine authored Jan 21, 2025
1 parent 4a6891f commit 35794a0
Show file tree
Hide file tree
Showing 47 changed files with 538 additions and 469 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/
import { VulnSeverity } from './types/vulnerabilities';
import { MisconfigurationEvaluationStatus } from './types/misconfigurations';

export const KSPM_POLICY_TEMPLATE = 'kspm';
export const CSPM_POLICY_TEMPLATE = 'cspm';
Expand Down Expand Up @@ -48,7 +49,8 @@ export const VULNERABILITIES_SEVERITY: Record<VulnSeverity, VulnSeverity> = {
UNKNOWN: 'UNKNOWN',
};

export const MISCONFIGURATION_STATUS: Record<string, string> = {
export const MISCONFIGURATION_STATUS: Record<string, MisconfigurationEvaluationStatus> = {
PASSED: 'passed',
FAILED: 'failed',
UNKNOWN: 'unknown',
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type {
} from './schema/vulnerabilities/csp_vulnerability_finding';
export type { BenchmarksCisId } from './types/benchmark';
export type { VulnSeverity } from './types/vulnerabilities';
export type { MisconfigurationEvaluationStatus } from './types/misconfigurations';
export * from './constants';
export {
extractErrorMessage,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export type MisconfigurationEvaluationStatus = 'passed' | 'failed' | 'unknown';
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@
* 2.0.
*/
import React from 'react';
import { euiThemeVars } from '@kbn/ui-theme';
import { EuiTitle, EuiSpacer } from '@elastic/eui';
import { DistributionBar as DistributionBarComponent } from '..';

const mockStatsFindings = [
{
key: 'passed',
count: 90,
color: euiThemeVars.euiColorVis0,
color: 'green',
label: 'Passed',
},
{
key: 'failed',
count: 10,
color: euiThemeVars.euiColorVis9,
color: 'red',
label: <>{'Failed'}</>,
},
];
Expand All @@ -28,22 +27,22 @@ const mockStatsAlerts = [
{
key: 'low',
count: 1000,
color: euiThemeVars.euiColorVis0,
color: 'green',
},
{
key: 'medium',
count: 800,
color: euiThemeVars.euiColorVis5,
color: 'gold',
},
{
key: 'high',
count: 300,
color: euiThemeVars.euiColorVis7,
color: 'orange',
},
{
key: 'critical',
count: 50,
color: euiThemeVars.euiColorVis9,
color: 'red',
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
},
"include": ["**/*.ts", "**/*.tsx"],
"kbn_references": [
"@kbn/ui-theme",
],
"exclude": ["target/**/*"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
*/

export * from './src/types';
export * from './src/constants/component_constants';
export * from './src/constants/navigation';
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';
export { getSeverityStatusColor, getCvsScoreColor } from './src/utils/get_vulnerability_colors';
export {
getSeverityStatusColor,
getCvsScoreColor,
getMisconfigurationStatusColor,
} from './src/utils/get_finding_colors';
export { getSeverityText } from './src/utils/get_vulnerability_text';
export { getVulnerabilityStats, hasVulnerabilitiesData } from './src/utils/vulnerability_helpers';
export { CVSScoreBadge, SeverityStatusBadge } from './src/components/vulnerability_badges';
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,37 @@
*/

import React from 'react';
import { EuiBadge, type EuiBadgeProps } from '@elastic/eui';
import { EuiBadge } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { css } from '@emotion/react';
import { statusColors } from '../constants/component_constants';
import { MISCONFIGURATION_STATUS } from '@kbn/cloud-security-posture-common';
import type { MisconfigurationEvaluationStatus } from '@kbn/cloud-security-posture-common';
import { getMisconfigurationStatusColor } from '../utils/get_finding_colors';

interface Props {
type?: 'passed' | 'failed';
type?: MisconfigurationEvaluationStatus;
}

// 'fail' / 'pass' are same chars length, but not same width size.
// 46px is used to make sure the badge is always the same width.
const BADGE_WIDTH = '46px';

const getColor = (type: Props['type']): EuiBadgeProps['color'] => {
if (type === 'passed') return statusColors.passed;
if (type === 'failed') return statusColors.failed;
return 'default';
};

export const CspEvaluationBadge = ({ type }: Props) => (
<EuiBadge
color={getColor(type)}
color={getMisconfigurationStatusColor(type)}
css={css`
width: ${BADGE_WIDTH};
display: flex;
justify-content: center;
`}
data-test-subj={`${type}_finding`}
>
{type === 'failed' ? (
{type === MISCONFIGURATION_STATUS.FAILED ? (
<FormattedMessage
id="securitySolutionPackages.csp.cspEvaluationBadge.failLabel"
defaultMessage="Fail"
/>
) : type === 'passed' ? (
) : type === MISCONFIGURATION_STATUS.PASSED ? (
<FormattedMessage
id="securitySolutionPackages.csp.cspEvaluationBadge.passLabel"
defaultMessage="Pass"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
* 2.0.
*/

import { EuiBadge, EuiIcon, EuiTextColor } from '@elastic/eui';
import { EuiBadge, EuiIcon, EuiTextColor, useEuiTheme } from '@elastic/eui';
import React from 'react';
import { css } from '@emotion/react';
import { float } from '@elastic/elasticsearch/lib/api/types';
import type { VulnSeverity } from '@kbn/cloud-security-posture-common';
import { getCvsScoreColor, getSeverityStatusColor } from '../utils/get_vulnerability_colors';
import { useGetCvsScoreColor } from '../hooks/use_get_cvs_score_color';
import { useGetSeverityStatusColor } from '../hooks/use_get_severity_status_color';

const VULNERABILITIES_CVSS_SCORE_BADGE_SUBJ = 'vulnerabilities_cvss_score_badge';

Expand All @@ -24,6 +25,9 @@ interface SeverityStatusBadgeProps {
}

export const CVSScoreBadge = ({ score, version }: CVSScoreBadgeProps) => {
const { euiTheme } = useEuiTheme();
const { getCvsScoreColor } = useGetCvsScoreColor();

if (!score) return null;

const color = getCvsScoreColor(score);
Expand All @@ -48,7 +52,7 @@ export const CVSScoreBadge = ({ score, version }: CVSScoreBadgeProps) => {
css={css`
width: 1px;
border: 0 none;
background-color: rgba(255, 255, 255, 0.2);
background-color: ${euiTheme.border.color};
margin: 0px 6px;
`}
/>
Expand All @@ -60,6 +64,8 @@ export const CVSScoreBadge = ({ score, version }: CVSScoreBadgeProps) => {
};

export const SeverityStatusBadge = ({ severity }: SeverityStatusBadgeProps) => {
const { getSeverityStatusColor } = useGetSeverityStatusColor();

if (!severity) return null;
const color = getSeverityStatusColor(severity);

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 { useEuiTheme } from '@elastic/eui';

import { getCvsScoreColor as getCvsScoreColorUtil } from '../..';

export const useGetCvsScoreColor = () => {
const { euiTheme } = useEuiTheme();

const getCvsScoreColor = (score: number) => {
return getCvsScoreColorUtil(score, euiTheme);
};

return { getCvsScoreColor };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 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 { useEuiTheme } from '@elastic/eui';
import { VulnSeverity } from '@kbn/cloud-security-posture-common';

import { getSeverityStatusColor as getSeverityStatusColorUtil } from '../..';

export const useGetSeverityStatusColor = () => {
const { euiTheme } = useEuiTheme();
const getSeverityStatusColor = (status: VulnSeverity) => {
return getSeverityStatusColorUtil(status, euiTheme);
};
return { getSeverityStatusColor };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* 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 { getCvsScoreColor, getSeverityStatusColor, SEVERITY_COLOR } from './get_finding_colors';
import { EuiThemeComputed } from '@elastic/eui';

const mockEuiThemeBorealis = {
themeName: 'borialis',
};

describe('getSeverityStatusColor', () => {
it('should return the correct color for LOW severity', () => {
expect(getSeverityStatusColor('LOW', mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.low
);
});

it('should return the correct color for MEDIUM severity', () => {
expect(getSeverityStatusColor('MEDIUM', mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.medium
);
});

it('should return the correct color for HIGH severity', () => {
expect(getSeverityStatusColor('HIGH', mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.high
);
});

it('should return the correct color for CRITICAL severity', () => {
expect(getSeverityStatusColor('CRITICAL', mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.critical
);
});

it('should return the correct color for an unknown severity', () => {
expect(getSeverityStatusColor('UNKNOWN', mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.unknown
);
});
});

describe('getCvsScoreColor', () => {
it('returns correct color for low severity score', () => {
expect(getCvsScoreColor(1.5, mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.low
);
});

it('returns correct color for medium severity score', () => {
expect(getCvsScoreColor(5.5, mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.medium
);
});

it('returns correct color for high severity score', () => {
expect(getCvsScoreColor(7.9, mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.high
);
});

it('returns correct color for critical severity score', () => {
expect(getCvsScoreColor(10.0, mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.critical
);
});

it('returns correct color for low severity score for undefined value', () => {
expect(getCvsScoreColor(-0.2, mockEuiThemeBorealis as EuiThemeComputed)).toBe(
SEVERITY_COLOR.unknown
);
});
});
Loading

0 comments on commit 35794a0

Please sign in to comment.