Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0c1c5d1
onboarding prompts for vul_mgmt
Omolola-Akinleye Mar 31, 2023
d8afc1c
fix unit test for current tab with vulnerabilities
Omolola-Akinleye Apr 3, 2023
7793f66
resolve conflict and broken tests
Omolola-Akinleye Apr 5, 2023
25cd773
Merge branch 'main' of github.com:Omolola-Akinleye/kibana into onboar…
Omolola-Akinleye Apr 5, 2023
45c860c
refactor boolean variables names and util functions
Omolola-Akinleye Apr 5, 2023
861e5aa
change file name and use hasVulnMgmtFindings reference
Omolola-Akinleye Apr 5, 2023
d4ff81c
refactor installation prompt
Omolola-Akinleye Apr 11, 2023
89cf766
Merge branch 'main' of github.com:Omolola-Akinleye/kibana into onboar…
Omolola-Akinleye Apr 11, 2023
b8e52c3
remove unused code
Omolola-Akinleye Apr 11, 2023
32d9de7
refactoring
kfirpeled Apr 11, 2023
9ccc13b
fixing status endpoint:
kfirpeled Apr 11, 2023
ad2d097
FTR fixes:
kfirpeled Apr 11, 2023
22aa1a8
refactoring
kfirpeled Apr 11, 2023
bb45f42
fixing status checks for compliance dashboard and removed status chec…
kfirpeled Apr 11, 2023
e9f69d7
deleted getCpmStatus
kfirpeled Apr 11, 2023
5c75f11
fix type issue
kfirpeled Apr 11, 2023
1d082bb
fix ftr
kfirpeled Apr 11, 2023
09fb0a1
fix ut
kfirpeled Apr 11, 2023
07e55b0
Merge branch 'main' into onboarding-prompts-vul-mngt
Omolola-Akinleye Apr 11, 2023
188a834
Resolve conflict and test
Omolola-Akinleye Apr 12, 2023
2288079
Merge branch 'onboarding-prompts-vul-mngt' of github.com:Omolola-Akin…
Omolola-Akinleye Apr 12, 2023
6c3fbb6
commit vulnerabilities tsx changes
Omolola-Akinleye Apr 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions x-pack/plugins/cloud_security_posture/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const STATS_ROUTE_PATH = '/internal/cloud_security_posture/stats/{policy_
export const BENCHMARKS_ROUTE_PATH = '/internal/cloud_security_posture/benchmarks';

export const CLOUD_SECURITY_POSTURE_PACKAGE_NAME = 'cloud_security_posture';

// TODO: REMOVE CSP_LATEST_FINDINGS_DATA_VIEW and replace it with LATEST_FINDINGS_INDEX_PATTERN
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove that now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CSP_LATEST_FINDINGS_DATA_VIEW is used in multiple places. We added a todo comment for now. I can create a follow PR to remove the instances where it's being used

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, we can address it in follow-up tickets

export const CSP_LATEST_FINDINGS_DATA_VIEW = 'logs-cloud_security_posture.findings_latest-*';

export const FINDINGS_INDEX_NAME = 'logs-cloud_security_posture.findings';
Expand Down Expand Up @@ -96,4 +96,7 @@ export const POSTURE_TYPES: { [x: string]: PostureTypes } = {
[CSPM_POLICY_TEMPLATE]: CSPM_POLICY_TEMPLATE,
[VULN_MGMT_POLICY_TEMPLATE]: VULN_MGMT_POLICY_TEMPLATE,
[POSTURE_TYPE_ALL]: POSTURE_TYPE_ALL,
} as const;
};

export const VULNERABILITIES = 'vulnerabilities';
export const CONFIGURATIONS = 'configurations';
1 change: 1 addition & 0 deletions x-pack/plugins/cloud_security_posture/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export interface BaseCspSetupStatus {
kspm: BaseCspSetupBothPolicy;
vuln_mgmt: BaseCspSetupBothPolicy;
isPluginInitialized: boolean;
installedPackageVersion?: string | undefined;
}

export type CspSetupStatus = BaseCspSetupStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,24 @@
import { useQuery } from '@tanstack/react-query';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import type { DataView } from '@kbn/data-plugin/common';
import { CSP_LATEST_FINDINGS_DATA_VIEW } from '../../../common/constants';
import { CspClientPluginStartDeps } from '../../types';

/**
* TODO: use perfected kibana data views
*/
export const useLatestFindingsDataView = () => {
export const useLatestFindingsDataView = (dataView: string) => {
const {
data: { dataViews },
} = useKibana<CspClientPluginStartDeps>().services;

const findDataView = async (): Promise<DataView> => {
const dataView = (await dataViews.find(CSP_LATEST_FINDINGS_DATA_VIEW))?.[0];
if (!dataView) {
throw new Error('Findings data view not found');
const dataViewObj = (await dataViews.find(dataView))?.[0];
if (!dataViewObj) {
throw new Error(`Data view not found [Name: {${dataView}}]`);
}

return dataView;
return dataViewObj;
};

return useQuery(['latest_findings_data_view'], findDataView);
return useQuery([`useDataView-${dataView}`], findDataView);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import { STATUS_ROUTE_PATH } from '../../../common/constants';

const getCspSetupStatusQueryKey = 'csp_status_key';

export const useCspSetupStatusApi = ({
options,
}: { options?: UseQueryOptions<CspSetupStatus, unknown, CspSetupStatus> } = {}) => {
export const useCspSetupStatusApi = (
options?: UseQueryOptions<CspSetupStatus, unknown, CspSetupStatus>
) => {
const { http } = useKibana().services;
return useQuery<CspSetupStatus, unknown, CspSetupStatus>(
[getCspSetupStatusQueryKey],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
*/

import { pagePathGetters, pkgKeyFromPackageInfo } from '@kbn/fleet-plugin/public';
import type { PosturePolicyTemplate } from '../../../common/types';
import type { CloudSecurityPolicyTemplate } from '../../../common/types';
import { useCisKubernetesIntegration } from '../api/use_cis_kubernetes_integration';
import { useKibana } from '../hooks/use_kibana';

export const useCspIntegrationLink = (
policyTemplate: PosturePolicyTemplate
policyTemplate: CloudSecurityPolicyTemplate
): string | undefined => {
const { http } = useKibana().services;
const cisIntegration = useCisKubernetesIntegration();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import React, { ComponentProps } from 'react';
import { UseQueryResult } from '@tanstack/react-query';
import { CloudPosturePage } from './cloud_posture_page';
import { NoDataPage } from '@kbn/kibana-react-plugin/public';
import { useCspSetupStatusApi } from '../common/api/use_setup_status_api';
import { useCspIntegrationLink } from '../common/navigation/use_csp_integration_link';

const chance = new Chance();

Expand All @@ -35,19 +33,6 @@ jest.mock('../common/navigation/use_csp_integration_link');
describe('<CloudPosturePage />', () => {
beforeEach(() => {
jest.resetAllMocks();
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
createReactQueryResponse({
status: 'success',
data: {
cspm: { status: 'indexed' },
kspm: { status: 'indexed' },
indicesDetails: [
{ index: 'logs-cloud_security_posture.findings_latest-default', status: 'not-empty' },
{ index: 'logs-cloud_security_posture.findings-default*', status: 'not-empty' },
],
},
})
);

(useSubscriptionStatus as jest.Mock).mockImplementation(() =>
createReactQueryResponse({
Expand All @@ -58,7 +43,9 @@ describe('<CloudPosturePage />', () => {
});

const renderCloudPosturePage = (
props: ComponentProps<typeof CloudPosturePage> = { children: null }
props: ComponentProps<typeof CloudPosturePage> = {
children: null,
}
) => {
const mockCore = coreMock.createStart();

Expand Down Expand Up @@ -147,69 +134,6 @@ describe('<CloudPosturePage />', () => {
expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument();
});

it('renders integrations installation prompt if integration is not installed', () => {
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
createReactQueryResponse({
status: 'success',
data: {
kspm: { status: 'not-installed' },
cspm: { status: 'not-installed' },
indicesDetails: [
{ index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' },
{ index: 'logs-cloud_security_posture.findings-default*', status: 'empty' },
],
},
})
);
(useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url());

const children = chance.sentence();
renderCloudPosturePage({ children });

expect(screen.getByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).toBeInTheDocument();
expect(screen.queryByText(children)).not.toBeInTheDocument();
expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument();
expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument();
expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument();
});

it('renders default loading state when the integration query is loading', () => {
(useCspSetupStatusApi as jest.Mock).mockImplementation(
() =>
createReactQueryResponse({
status: 'loading',
}) as unknown as UseQueryResult
);

const children = chance.sentence();
renderCloudPosturePage({ children });

expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument();
expect(screen.queryByText(children)).not.toBeInTheDocument();
expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument();
expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument();
expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument();
});

it('renders default error state when the integration query has an error', () => {
(useCspSetupStatusApi as jest.Mock).mockImplementation(
() =>
createReactQueryResponse({
status: 'error',
error: new Error('error'),
}) as unknown as UseQueryResult
);

const children = chance.sentence();
renderCloudPosturePage({ children });

expect(screen.getByTestId(ERROR_STATE_TEST_SUBJECT)).toBeInTheDocument();
expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument();
expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument();
expect(screen.queryByText(children)).not.toBeInTheDocument();
expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument();
});

it('renders default loading text when query isLoading', () => {
const query = createReactQueryResponse({
status: 'loading',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,22 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import type { UseQueryResult } from '@tanstack/react-query';
import {
EuiButton,
EuiEmptyPrompt,
EuiImage,
EuiFlexGroup,
EuiFlexItem,
EuiLink,
} from '@elastic/eui';
import { EuiEmptyPrompt } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { NoDataPage, NoDataPageProps } from '@kbn/kibana-react-plugin/public';
import { css } from '@emotion/react';
import { CSPM_POLICY_TEMPLATE, KSPM_POLICY_TEMPLATE } from '../../common/constants';
import { SubscriptionNotAllowed } from './subscription_not_allowed';
import { useSubscriptionStatus } from '../common/hooks/use_subscription_status';
import { FullSizeCenteredPage } from './full_size_centered_page';
import { useCspSetupStatusApi } from '../common/api/use_setup_status_api';
import { CspLoadingState } from './csp_loading_state';
import { useCspIntegrationLink } from '../common/navigation/use_csp_integration_link';

import noDataIllustration from '../assets/illustrations/no_data_illustration.svg';
import { cspIntegrationDocsNavigation } from '../common/navigation/constants';
import { getCpmStatus } from '../common/utils/get_cpm_status';

export const LOADING_STATE_TEST_SUBJECT = 'cloud_posture_page_loading';
export const ERROR_STATE_TEST_SUBJECT = 'cloud_posture_page_error';
export const PACKAGE_NOT_INSTALLED_TEST_SUBJECT = 'cloud_posture_page_package_not_installed';
export const CSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT = 'cloud_posture_page_cspm_not_installed';
export const KSPM_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT = 'cloud_posture_page_kspm_not_installed';
export const VULN_MGMT_INTEGRATION_NOT_INSTALLED_TEST_SUBJECT =
'cloud_posture_page_vuln_mgmt_not_installed';
export const DEFAULT_NO_DATA_TEST_SUBJECT = 'cloud_posture_page_no_data';
export const SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT = 'cloud_posture_page_subscription_not_allowed';

Expand Down Expand Up @@ -104,71 +92,6 @@ export const CspNoDataPage = ({
);
};

const packageNotInstalledRenderer = ({
kspmIntegrationLink,
cspmIntegrationLink,
}: {
kspmIntegrationLink?: string;
cspmIntegrationLink?: string;
}) => {
return (
<FullSizeCenteredPage>
<EuiEmptyPrompt
data-test-subj={PACKAGE_NOT_INSTALLED_TEST_SUBJECT}
icon={<EuiImage size="fullWidth" src={noDataIllustration} alt="no-data-illustration" />}
title={
<h2>
<FormattedMessage
id="xpack.csp.cloudPosturePage.packageNotInstalledRenderer.promptTitle"
defaultMessage="Detect security misconfigurations in your cloud infrastructure!"
/>
</h2>
}
layout="horizontal"
color="plain"
body={
<p>
<FormattedMessage
id="xpack.csp.cloudPosturePage.packageNotInstalledRenderer.promptDescription"
defaultMessage="Detect and remediate potential configuration risks in your cloud infrastructure, like publicly accessible S3 buckets, with our Cloud and Kubernetes Security Posture Management solutions. {learnMore}"
values={{
learnMore: (
<EuiLink href={cspIntegrationDocsNavigation.cspm.overviewPath} target="_blank">
<FormattedMessage
id="xpack.csp.cloudPosturePage.packageNotInstalledRenderer.learnMoreTitle"
defaultMessage="Learn more about Cloud Security Posture"
/>
</EuiLink>
),
}}
/>
</p>
}
actions={
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiButton color="primary" fill href={cspmIntegrationLink}>
<FormattedMessage
id="xpack.csp.cloudPosturePage.packageNotInstalledRenderer.addCspmIntegrationButtonTitle"
defaultMessage="Add CSPM Integration"
/>
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton color="primary" fill href={kspmIntegrationLink}>
<FormattedMessage
id="xpack.csp.cloudPosturePage.packageNotInstalledRenderer.addKspmIntegrationButtonTitle"
defaultMessage="Add KSPM Integration"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
}
/>
</FullSizeCenteredPage>
);
};

const defaultLoadingRenderer = () => (
<CspLoadingState data-test-subj={LOADING_STATE_TEST_SUBJECT}>
<FormattedMessage
Expand Down Expand Up @@ -251,10 +174,6 @@ export const CloudPosturePage = <TData, TError>({
noDataRenderer = defaultNoDataRenderer,
}: CloudPosturePageProps<TData, TError>) => {
const subscriptionStatus = useSubscriptionStatus();
const { data: getSetupStatus, isLoading, isError, error } = useCspSetupStatusApi();
const kspmIntegrationLink = useCspIntegrationLink(KSPM_POLICY_TEMPLATE);
const cspmIntegrationLink = useCspIntegrationLink(CSPM_POLICY_TEMPLATE);
const { isEmptyData, hasFindings } = getCpmStatus(getSetupStatus);

const render = () => {
if (subscriptionStatus.isError) {
Expand All @@ -269,23 +188,6 @@ export const CloudPosturePage = <TData, TError>({
return subscriptionNotAllowedRenderer();
}

if (isError) {
return defaultErrorRenderer(error);
}

if (isLoading) {
return defaultLoadingRenderer();
}

/* Checks if its a completely new user which means no integration has been installed and no latest findings default index has been found */
if (isEmptyData) {
return packageNotInstalledRenderer({ kspmIntegrationLink, cspmIntegrationLink });
}

if (!hasFindings) {
return children;
}

if (!query) {
return children;
}
Expand Down
Loading