Skip to content

Commit

Permalink
[Cloud Security][Benchmark] Benchmark Page Improvement Phase I (elast…
Browse files Browse the repository at this point in the history
…ic#171703)

## Summary

This PR is for Benchmark Page Improvements
<img width="1427" alt="Screenshot 2023-11-24 at 1 57 55 PM"
src="https://github.com/elastic/kibana/assets/8703149/5b6dcfa5-399e-4ba4-a585-50f7dc94d33b">

---------

Co-authored-by: kibanamachine <[email protected]>
Co-authored-by: Kfir Peled <[email protected]>
  • Loading branch information
3 people authored Dec 13, 2023
1 parent 9e140d1 commit 780ca37
Show file tree
Hide file tree
Showing 30 changed files with 869 additions and 391 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,28 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { type TypeOf, schema } from '@kbn/config-schema';

import { schema, TypeOf } from '@kbn/config-schema';
import type { PackagePolicy } from '@kbn/fleet-plugin/common';
import type { AgentPolicy } from '@kbn/fleet-plugin/common';

export type AgentPolicyStatus = Pick<AgentPolicy, 'id' | 'name'> & { agents: number };

export const benchmarkScoreSchema = schema.object({
postureScore: schema.number({ defaultValue: 0, min: 0 }),
resourcesEvaluated: schema.number({ defaultValue: 0, min: 0 }),
totalFailed: schema.number({ defaultValue: 0, min: 0 }),
totalFindings: schema.number({ defaultValue: 0, min: 0 }),
totalPassed: schema.number({ defaultValue: 0, min: 0 }),
});

export type BenchmarkScore = TypeOf<typeof benchmarkScoreSchema>;

export interface Benchmark {
package_policy: PackagePolicy;
agent_policy: AgentPolicyStatus;
rules_count: number;
}

export const DEFAULT_BENCHMARKS_PER_PAGE = 20;
export const BENCHMARK_PACKAGE_POLICY_PREFIX = 'package_policy.';
Expand Down Expand Up @@ -60,3 +81,10 @@ export const benchmarksQueryParamsSchema = schema.object({
});

export type BenchmarksQueryParams = TypeOf<typeof benchmarksQueryParamsSchema>;

export interface GetBenchmarkResponse {
items: Benchmark[];
total: number;
page: number;
perPage: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.
*/

// Optionally, re-export the entire set of types. Interfaces and types declared after this will override v1 declarations.
import { schema } from '@kbn/config-schema';
import type { BenchmarkScore } from './v1';

export type { BenchmarkScore } from './v1';

export type BenchmarksCisId = 'cis_k8s' | 'cis_azure' | 'cis_aws' | 'cis_eks' | 'cis_gcp';

export interface Benchmark {
id: BenchmarksCisId;
name: string;
version: string;
score: BenchmarkScore;
evaluation: number;
}

export interface GetBenchmarkResponse {
items: Benchmark[];
}

export const benchmarkResponseSchema = schema.object({
items: schema.arrayOf(
schema.object({
id: schema.oneOf([
schema.literal('cis_k8s'),
schema.literal('cis_azure'),
schema.literal('cis_aws'),
schema.literal('cis_eks'),
schema.literal('cis_gcp'),
]),
name: schema.string(),
version: schema.string(),
score: schema.object({
postureScore: schema.number({ defaultValue: 0, min: 0 }),
resourcesEvaluated: schema.number({ defaultValue: 0, min: 0 }),
totalFailed: schema.number({ defaultValue: 0, min: 0 }),
totalFindings: schema.number({ defaultValue: 0, min: 0 }),
totalPassed: schema.number({ defaultValue: 0, min: 0 }),
}),
evaluation: schema.number({ defaultValue: 0, min: 0 }),
})
),
});
6 changes: 6 additions & 0 deletions x-pack/plugins/cloud_security_posture/common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@ export * as rulesV1 from './rules/v1';
export * as rulesV2 from './rules/v2';
export * as rulesV3 from './rules/v3';

export * as benchmarkV1 from './benchmarks/v1';
export * as benchmarkV2 from './benchmarks/v2';

// Explicit export of everything from latest
export type {
cspBenchmarkRuleMetadataSchema,
CspBenchmarkRuleMetadata,
CspBenchmarkRule,
FindCspBenchmarkRuleRequest,
FindCspBenchmarkRuleResponse,
BenchmarkScore,
Benchmark,
GetBenchmarkResponse,
} from './latest';
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
*/

export * from './rules/v3';
export * from './benchmarks/v2';
16 changes: 0 additions & 16 deletions x-pack/plugins/cloud_security_posture/common/types_old.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* 2.0.
*/
import { type TypeOf } from '@kbn/config-schema';
import type { PackagePolicy, AgentPolicy } from '@kbn/fleet-plugin/common';
import { CspFinding } from './schemas/csp_finding';
import { SUPPORTED_CLOUDBEAT_INPUTS, SUPPORTED_POLICY_TEMPLATES } from './constants';

Expand Down Expand Up @@ -142,14 +141,6 @@ export interface BaseCspSetupStatus {

export type CspSetupStatus = BaseCspSetupStatus;

export type AgentPolicyStatus = Pick<AgentPolicy, 'id' | 'name'> & { agents: number };

export interface Benchmark {
package_policy: PackagePolicy;
agent_policy: AgentPolicyStatus;
rules_count: number;
}

export type BenchmarkId = CspBenchmarkRuleMetadata['benchmark']['id'];
export type BenchmarkName = CspBenchmarkRuleMetadata['benchmark']['name'];
export type RuleSection = CspBenchmarkRuleMetadata['section'];
Expand All @@ -159,13 +150,6 @@ export type PostureInput = typeof SUPPORTED_CLOUDBEAT_INPUTS[number];
export type CloudSecurityPolicyTemplate = typeof SUPPORTED_POLICY_TEMPLATES[number];
export type PosturePolicyTemplate = Extract<CloudSecurityPolicyTemplate, 'kspm' | 'cspm'>;

export interface GetBenchmarkResponse {
items: Benchmark[];
total: number;
page: number;
perPage: number;
}

export type GetComplianceDashboardRequest = TypeOf<typeof getComplianceDashboardSchema>;

// CNVM DASHBOARD
Expand Down
33 changes: 33 additions & 0 deletions x-pack/plugins/cloud_security_posture/common/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import type {
AzureCredentialsType,
RuleSection,
} from '../types_old';
import type { BenchmarksCisId } from '../types/latest';

/**
* @example
Expand Down Expand Up @@ -172,3 +173,35 @@ export const cleanupCredentials = (packagePolicy: NewPackagePolicy | UpdatePacka
// nothing to do, return unmutated policy
return packagePolicy;
};

export const getBenchmarkCisName = (benchmarkId: BenchmarksCisId) => {
switch (benchmarkId) {
case 'cis_k8s':
return 'CIS Kubernetes';
case 'cis_azure':
return 'CIS Azure';
case 'cis_aws':
return 'CIS AWS';
case 'cis_eks':
return 'CIS EKS';
case 'cis_gcp':
return 'CIS GCP';
}
return null;
};

export const getBenchmarkApplicableTo = (benchmarkId: BenchmarksCisId) => {
switch (benchmarkId) {
case 'cis_k8s':
return 'Kubernetes';
case 'cis_azure':
return 'Microsoft Azure';
case 'cis_aws':
return 'Amazon Web Services';
case 'cis_eks':
return 'Amazon Elastic Kubernetes Service';
case 'cis_gcp':
return 'Google Cloud Provider';
}
return null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const NAV_ITEMS_NAMES = {
defaultMessage: 'Findings',
}),
BENCHMARKS: i18n.translate('xpack.csp.navigation.myBenchmarksNavItemLabel', {
defaultMessage: 'Benchmark rules',
defaultMessage: 'Benchmarks',
}),
RULES: i18n.translate('xpack.csp.navigation.rulesNavItemLabel', {
defaultMessage: 'Rules',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { pagePathGetters, pkgKeyFromPackageInfo } from '@kbn/fleet-plugin/public';
import { useCisKubernetesIntegration } from '../api/use_cis_kubernetes_integration';
import { useKibana } from '../hooks/use_kibana';
import { useCspBenchmarkIntegrations } from '../../pages/benchmarks/use_csp_benchmark_integrations';
import { useCspBenchmarkIntegrationsV1 } from '../../pages/benchmarks/use_csp_benchmark_integrations';
import { PostureTypes } from '../../../common/types_old';

export const useCISIntegrationPoliciesLink = ({
Expand All @@ -19,7 +19,7 @@ export const useCISIntegrationPoliciesLink = ({
const { http } = useKibana().services;
const cisIntegration = useCisKubernetesIntegration();
// using an existing hook to get agent id and package policy id
const cspBenchmarkIntegrations = useCspBenchmarkIntegrations({
const cspBenchmarkIntegrations = useCspBenchmarkIntegrationsV1({
name: '',
page: 1,
perPage: 100,
Expand All @@ -29,6 +29,7 @@ export const useCISIntegrationPoliciesLink = ({
if (!cisIntegration.isSuccess) return;

const intergrations = cspBenchmarkIntegrations.data?.items;

const matchedIntegration = intergrations?.find(
(integration) =>
integration?.package_policy?.inputs?.find((input) => input?.enabled)?.policy_template ===
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { createReactQueryResponse } from '../../test/fixtures/react_query';
import { TestProvider } from '../../test/test_provider';
import { Benchmarks } from './benchmarks';
import * as TEST_SUBJ from './test_subjects';
import { useCspBenchmarkIntegrations } from './use_csp_benchmark_integrations';
import { useCspBenchmarkIntegrationsV2 } from './use_csp_benchmark_integrations';
import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api';
import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status';
import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link';
Expand Down Expand Up @@ -65,7 +65,7 @@ describe('<Benchmarks />', () => {
const renderBenchmarks = (
queryResponse: Partial<UseQueryResult> = createReactQueryResponse()
) => {
(useCspBenchmarkIntegrations as jest.Mock).mockImplementation(() => queryResponse);
(useCspBenchmarkIntegrationsV2 as jest.Mock).mockImplementation(() => queryResponse);

return render(
<TestProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ import { CloudPosturePageTitle } from '../../components/cloud_posture_page_title
import { CloudPosturePage } from '../../components/cloud_posture_page';
import { BenchmarksTable } from './benchmarks_table';
import {
useCspBenchmarkIntegrations,
useCspBenchmarkIntegrationsV2,
UseCspBenchmarkIntegrationsProps,
} from './use_csp_benchmark_integrations';
import { extractErrorMessage } from '../../../common/utils/helpers';
import { extractErrorMessage, getBenchmarkCisName } from '../../../common/utils/helpers';
import * as TEST_SUBJ from './test_subjects';
import { LOCAL_STORAGE_PAGE_SIZE_BENCHMARK_KEY } from '../../common/constants';
import { usePageSize } from '../../common/hooks/use_page_size';
Expand Down Expand Up @@ -102,7 +102,7 @@ const TotalIntegrationsCount = ({
<EuiTextColor color="subdued">
<FormattedMessage
id="xpack.csp.benchmarks.totalIntegrationsCountMessage"
defaultMessage="Showing {pageCount} of {totalCount, plural, one {# integration} other {# integrations}}"
defaultMessage="Showing {pageCount} of {totalCount, plural, one {# benchmark} other {# benchmarks}}"
values={{ pageCount, totalCount }}
/>
</EuiTextColor>
Expand All @@ -126,7 +126,7 @@ const BenchmarkSearchField = ({
isLoading={isLoading}
placeholder={i18n.translate(
'xpack.csp.benchmarks.benchmarkSearchField.searchPlaceholder',
{ defaultMessage: 'Search by Integration Name' }
{ defaultMessage: 'Search by benchmark Name' }
)}
incremental
/>
Expand All @@ -145,17 +145,20 @@ export const Benchmarks = () => {
sortOrder: 'asc',
});

const queryResult = useCspBenchmarkIntegrations(query);
const totalItemCount = queryResult.data?.total || 0;
const queryResult = useCspBenchmarkIntegrationsV2();
const benchmarkResult =
queryResult.data?.items.filter((obj) => getBenchmarkCisName(obj.id)?.includes(query.name)) ||
[];
const totalItemCount = queryResult.data?.items.length || 0;

return (
<CloudPosturePage>
<EuiPageHeader
data-test-subj={TEST_SUBJ.BENCHMARKS_PAGE_HEADER}
pageTitle={
<CloudPosturePageTitle
title={i18n.translate('xpack.csp.benchmarks.benchmarksPageHeader.benchmarkRulesTitle', {
defaultMessage: 'Benchmark Rules',
title={i18n.translate('xpack.csp.benchmarks.benchmarksPageHeader.benchmarksTitle', {
defaultMessage: 'Benchmarks',
})}
/>
}
Expand All @@ -174,7 +177,7 @@ export const Benchmarks = () => {
/>
<EuiSpacer size="s" />
<BenchmarksTable
benchmarks={queryResult.data?.items || []}
benchmarks={benchmarkResult}
data-test-subj={TEST_SUBJ.BENCHMARKS_TABLE_DATA_TEST_SUBJ}
error={queryResult.error ? extractErrorMessage(queryResult.error) : undefined}
loading={queryResult.isFetching}
Expand All @@ -198,9 +201,7 @@ export const Benchmarks = () => {
}));
}}
noItemsMessage={
queryResult.isSuccess && !queryResult.data.total ? (
<BenchmarkEmptyState name={query.name} />
) : undefined
queryResult.isSuccess ? <BenchmarkEmptyState name={query.name} /> : undefined
}
/>
</CloudPosturePage>
Expand Down
Loading

0 comments on commit 780ca37

Please sign in to comment.