-
+
-
+
>
);
@@ -177,23 +177,28 @@ const IntegrationPostureDashboard = ({
export const ComplianceDashboard = () => {
const [selectedTab, setSelectedTab] = useState(CSPM_POLICY_TEMPLATE);
const getSetupStatus = useCspSetupStatusApi();
- const hasFindings = getSetupStatus.data?.status === 'indexed';
+ const hasFindingsKspm =
+ getSetupStatus.data?.kspm?.status === 'indexed' ||
+ getSetupStatus.data?.indicesDetails[0].status === 'not-empty';
+ const hasFindingsCspm =
+ getSetupStatus.data?.cspm?.status === 'indexed' ||
+ getSetupStatus.data?.indicesDetails[0].status === 'not-empty';
const cspmIntegrationLink = useCspIntegrationLink(CSPM_POLICY_TEMPLATE);
const kspmIntegrationLink = useCspIntegrationLink(KSPM_POLICY_TEMPLATE);
const getCspmDashboardData = useCspmStatsApi({
- enabled: hasFindings,
+ enabled: hasFindingsCspm,
});
const getKspmDashboardData = useKspmStatsApi({
- enabled: hasFindings,
+ enabled: hasFindingsKspm,
});
useEffect(() => {
const selectInitialTab = () => {
const cspmTotalFindings = getCspmDashboardData.data?.stats.totalFindings;
const kspmTotalFindings = getKspmDashboardData.data?.stats.totalFindings;
- const installedPolicyTemplates = getSetupStatus.data?.installedPolicyTemplates;
-
+ const installedPolicyTemplatesCspm = getSetupStatus.data?.cspm?.status;
+ const installedPolicyTemplatesKspm = getSetupStatus.data?.kspm?.status;
let preferredDashboard = CSPM_POLICY_TEMPLATE;
// cspm has findings
@@ -205,21 +210,27 @@ export const ComplianceDashboard = () => {
preferredDashboard = KSPM_POLICY_TEMPLATE;
}
// cspm is installed
- else if (installedPolicyTemplates?.includes(CSPM_POLICY_TEMPLATE)) {
+ else if (
+ installedPolicyTemplatesCspm !== 'unprivileged' &&
+ installedPolicyTemplatesCspm !== 'not-installed'
+ ) {
preferredDashboard = CSPM_POLICY_TEMPLATE;
}
// kspm is installed
- else if (installedPolicyTemplates?.includes(KSPM_POLICY_TEMPLATE)) {
+ else if (
+ installedPolicyTemplatesKspm !== 'unprivileged' &&
+ installedPolicyTemplatesKspm !== 'not-installed'
+ ) {
preferredDashboard = KSPM_POLICY_TEMPLATE;
}
-
setSelectedTab(preferredDashboard);
};
selectInitialTab();
}, [
getCspmDashboardData.data?.stats.totalFindings,
getKspmDashboardData.data?.stats.totalFindings,
- getSetupStatus.data?.installedPolicyTemplates,
+ getSetupStatus.data?.cspm?.status,
+ getSetupStatus.data?.kspm?.status,
]);
const tabs = useMemo(
@@ -231,21 +242,28 @@ export const ComplianceDashboard = () => {
isSelected: selectedTab === CSPM_POLICY_TEMPLATE,
onClick: () => setSelectedTab(CSPM_POLICY_TEMPLATE),
content: (
-
-
-
-
-
+ <>
+ {hasFindingsCspm ? (
+
+
+
+
+
+ ) : (
+
+ )}
+ >
),
},
{
@@ -255,21 +273,28 @@ export const ComplianceDashboard = () => {
isSelected: selectedTab === KSPM_POLICY_TEMPLATE,
onClick: () => setSelectedTab(KSPM_POLICY_TEMPLATE),
content: (
-
-
-
-
-
+ <>
+ {hasFindingsKspm ? (
+
+
+
+
+
+ ) : (
+
+ )}
+ >
),
},
],
@@ -277,14 +302,15 @@ export const ComplianceDashboard = () => {
cspmIntegrationLink,
getCspmDashboardData,
getKspmDashboardData,
- getSetupStatus.data?.installedPolicyTemplates,
+ getSetupStatus.data?.kspm?.status,
+ getSetupStatus.data?.cspm?.status,
kspmIntegrationLink,
selectedTab,
+ hasFindingsKspm,
+ hasFindingsCspm,
]
);
- if (!hasFindings) return
;
-
return (
', () => {
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
createReactQueryResponse({
status: 'success',
- data: { status: 'not-deployed' },
+ data: {
+ kspm: { status: 'not-deployed' },
+ cspm: { status: 'not-deployed' },
+ indicesDetails: [
+ { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' },
+ { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' },
+ ],
+ },
})
);
(useCISIntegrationPoliciesLink as jest.Mock).mockImplementation(() => chance.url());
@@ -94,7 +101,14 @@ describe('', () => {
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
createReactQueryResponse({
status: 'success',
- data: { status: 'indexing' },
+ data: {
+ kspm: { status: 'indexing' },
+ cspm: { status: 'indexing' },
+ 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());
@@ -116,7 +130,14 @@ describe('', () => {
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
createReactQueryResponse({
status: 'success',
- data: { status: 'index-timeout' },
+ data: {
+ kspm: { status: 'index-timeout' },
+ cspm: { status: 'index-timeout' },
+ 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());
@@ -138,7 +159,14 @@ describe('', () => {
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
createReactQueryResponse({
status: 'success',
- data: { status: 'unprivileged' },
+ data: {
+ kspm: { status: 'unprivileged' },
+ cspm: { status: 'unprivileged' },
+ 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());
@@ -161,7 +189,15 @@ describe('', () => {
(useCspSetupStatusApi as jest.Mock).mockImplementation(() => ({
status: 'success',
- data: { status: 'indexed' },
+ data: {
+ kspm: { status: 'indexed' },
+ cspm: { status: 'indexed' },
+ indicesDetails: [
+ { index: 'logs-cloud_security_posture.findings_latest-default', status: 'not-empty' },
+ { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' },
+ { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' },
+ ],
+ },
}));
(source.fetch$ as jest.Mock).mockReturnValue(of({ rawResponse: { hits: { hits: [] } } }));
diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx
index 09983e7a6cc661..e82a38e006ce93 100644
--- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx
+++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx
@@ -20,9 +20,11 @@ export const Configurations = () => {
const location = useLocation();
const dataViewQuery = useLatestFindingsDataView();
const getSetupStatus = useCspSetupStatusApi();
-
- const hasFindings = getSetupStatus.data?.status === 'indexed';
- if (!hasFindings) return ;
+ const hasFindings =
+ getSetupStatus.data?.indicesDetails[0].status === 'not-empty' ||
+ getSetupStatus.data?.kspm.status === 'indexed' ||
+ getSetupStatus.data?.cspm.status === 'indexed';
+ if (!hasFindings) return ;
return (
diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx
index 5840a38d94ef36..118cabee95181a 100644
--- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx
+++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx
@@ -18,6 +18,8 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { css } from '@emotion/react';
import { Redirect, Switch, useHistory, useLocation } from 'react-router-dom';
import { Route } from '@kbn/shared-ux-router';
+import { NoFindingsStates } from '../../components/no_findings_states';
+import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api';
import { Configurations } from '../configurations';
import { cloudPosturePages, findingsNavigation } from '../../common/navigation/constants';
import { Vulnerabilities } from '../vulnerabilities';
@@ -25,6 +27,13 @@ import { Vulnerabilities } from '../vulnerabilities';
export const Findings = () => {
const history = useHistory();
const location = useLocation();
+ const getSetupStatus = useCspSetupStatusApi();
+
+ const hasFindings =
+ getSetupStatus.data?.indicesDetails[0].status === 'not-empty' ||
+ getSetupStatus.data?.kspm.status === 'indexed' ||
+ getSetupStatus.data?.cspm.status === 'indexed';
+ if (!hasFindings) return ;
const navigateToVulnerabilitiesTab = () => {
history.push({ pathname: findingsNavigation.vulnerabilities.path });
diff --git a/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts b/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts
index 984c68a76a6b64..c8d876a7281dad 100644
--- a/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts
+++ b/x-pack/plugins/cloud_security_posture/server/lib/check_index_status.ts
@@ -11,14 +11,28 @@ import { IndexStatus } from '../../common/types';
export const checkIndexStatus = async (
esClient: ElasticsearchClient,
index: string,
- logger: Logger
+ logger: Logger,
+ postureType: 'cspm' | 'kspm' | 'all' = 'all'
): Promise => {
+ const query =
+ postureType === 'all'
+ ? {
+ match_all: {},
+ }
+ : {
+ bool: {
+ filter: {
+ term: {
+ 'rule.benchmark.posture_type': postureType,
+ },
+ },
+ },
+ };
+
try {
const queryResult = await esClient.search({
index,
- query: {
- match_all: {},
- },
+ query,
size: 1,
});
diff --git a/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts b/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts
index 1b66a4e401311a..2696e44c8c0255 100644
--- a/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts
+++ b/x-pack/plugins/cloud_security_posture/server/lib/fleet_util.ts
@@ -18,7 +18,7 @@ import type {
PackagePolicy,
} from '@kbn/fleet-plugin/common';
import { errors } from '@elastic/elasticsearch';
-import type { CloudSecurityPolicyTemplate } from '../../common/types';
+import { CloudSecurityPolicyTemplate, PostureTypes } from '../../common/types';
import { SUPPORTED_POLICY_TEMPLATES } from '../../common/constants';
import { CSP_FLEET_PACKAGE_KUERY } from '../../common/utils/helpers';
import {
@@ -34,13 +34,25 @@ const isFleetMissingAgentHttpError = (error: unknown) =>
const isPolicyTemplate = (input: any): input is CloudSecurityPolicyTemplate =>
SUPPORTED_POLICY_TEMPLATES.includes(input);
-const getPackageNameQuery = (packageName: string, benchmarkFilter?: string): string => {
+const getPackageNameQuery = (
+ // ADD 3rd case both cspm and kspm, for findings posture type empty => kspm
+ postureType: string,
+ packageName: string,
+ benchmarkFilter?: string
+): string => {
const integrationNameQuery = `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${packageName}`;
- const kquery = benchmarkFilter
- ? `${integrationNameQuery} AND ${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: *${benchmarkFilter}*`
- : integrationNameQuery;
-
- return kquery;
+ const integrationPostureType = `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.vars.posture.value:${postureType}`;
+ if (postureType === 'all') {
+ const kquery = benchmarkFilter
+ ? `${integrationNameQuery} AND ${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: *${benchmarkFilter}*`
+ : `${integrationNameQuery}`;
+ return kquery;
+ } else {
+ const kquery = benchmarkFilter
+ ? `${integrationNameQuery} AND ${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: *${benchmarkFilter}* AND ${integrationPostureType}`
+ : `${integrationNameQuery} AND ${integrationPostureType}`;
+ return kquery;
+ }
};
export type AgentStatusByAgentPolicyMap = Record;
@@ -86,12 +98,13 @@ export const getCspPackagePolicies = (
soClient: SavedObjectsClientContract,
packagePolicyService: PackagePolicyClient,
packageName: string,
- queryParams: Partial
+ queryParams: Partial,
+ postureType: PostureTypes
): Promise> => {
const sortField = queryParams.sort_field?.replaceAll(BENCHMARK_PACKAGE_POLICY_PREFIX, '');
return packagePolicyService.list(soClient, {
- kuery: getPackageNameQuery(packageName, queryParams.benchmark_name),
+ kuery: getPackageNameQuery(postureType, packageName, queryParams.benchmark_name),
page: queryParams.page,
perPage: queryParams.per_page,
sortField,
@@ -116,7 +129,6 @@ export const getInstalledPolicyTemplates = async (
return policy.inputs.find((input) => input.enabled)?.policy_template;
})
.filter(isPolicyTemplate);
-
// removing duplicates
return [...new Set(enabledPolicyTemplates)];
} catch (e) {
diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts
index d8b432bb0391ed..210e60919fbca9 100644
--- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts
+++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts
@@ -14,6 +14,7 @@ import {
getCspPackagePolicies,
getCspAgentPolicies,
} from '../../lib/fleet_util';
+import { POSTURE_TYPE_ALL } from '../../../common/constants';
import { defineGetBenchmarksRoute, getRulesCountForPolicy } from './benchmarks';
import { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server';
@@ -157,11 +158,17 @@ describe('benchmarks API', () => {
it('should format request by package name', async () => {
const mockPackagePolicyService = createPackagePolicyServiceMock();
- await getCspPackagePolicies(mockSoClient, mockPackagePolicyService, 'myPackage', {
- page: 1,
- per_page: 100,
- sort_order: 'desc',
- });
+ await getCspPackagePolicies(
+ mockSoClient,
+ mockPackagePolicyService,
+ 'myPackage',
+ {
+ page: 1,
+ per_page: 100,
+ sort_order: 'desc',
+ },
+ POSTURE_TYPE_ALL
+ );
expect(mockPackagePolicyService.list.mock.calls[0][1]).toMatchObject(
expect.objectContaining({
@@ -175,12 +182,18 @@ describe('benchmarks API', () => {
it('should build sort request by `sort_field` and default `sort_order`', async () => {
const mockAgentPolicyService = createPackagePolicyServiceMock();
- await getCspPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', {
- page: 1,
- per_page: 100,
- sort_field: 'package_policy.name',
- sort_order: 'desc',
- });
+ await getCspPackagePolicies(
+ mockSoClient,
+ mockAgentPolicyService,
+ 'myPackage',
+ {
+ page: 1,
+ per_page: 100,
+ sort_field: 'package_policy.name',
+ sort_order: 'desc',
+ },
+ POSTURE_TYPE_ALL
+ );
expect(mockAgentPolicyService.list.mock.calls[0][1]).toMatchObject(
expect.objectContaining({
@@ -196,12 +209,18 @@ describe('benchmarks API', () => {
it('should build sort request by `sort_field` and asc `sort_order`', async () => {
const mockAgentPolicyService = createPackagePolicyServiceMock();
- await getCspPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', {
- page: 1,
- per_page: 100,
- sort_field: 'package_policy.name',
- sort_order: 'asc',
- });
+ await getCspPackagePolicies(
+ mockSoClient,
+ mockAgentPolicyService,
+ 'myPackage',
+ {
+ page: 1,
+ per_page: 100,
+ sort_field: 'package_policy.name',
+ sort_order: 'asc',
+ },
+ POSTURE_TYPE_ALL
+ );
expect(mockAgentPolicyService.list.mock.calls[0][1]).toMatchObject(
expect.objectContaining({
@@ -218,12 +237,18 @@ describe('benchmarks API', () => {
it('should format request by benchmark_name', async () => {
const mockAgentPolicyService = createPackagePolicyServiceMock();
- await getCspPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', {
- page: 1,
- per_page: 100,
- sort_order: 'desc',
- benchmark_name: 'my_cis_benchmark',
- });
+ await getCspPackagePolicies(
+ mockSoClient,
+ mockAgentPolicyService,
+ 'myPackage',
+ {
+ page: 1,
+ per_page: 100,
+ sort_order: 'desc',
+ benchmark_name: 'my_cis_benchmark',
+ },
+ POSTURE_TYPE_ALL
+ );
expect(mockAgentPolicyService.list.mock.calls[0][1]).toMatchObject(
expect.objectContaining({
diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts
index cd019c189c76f7..6012583104f359 100644
--- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts
+++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts
@@ -12,6 +12,7 @@ import { CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE } from '../../../common/constants';
import {
BENCHMARKS_ROUTE_PATH,
CLOUD_SECURITY_POSTURE_PACKAGE_NAME,
+ POSTURE_TYPE_ALL,
} from '../../../common/constants';
import { benchmarksQueryParamsSchema } from '../../../common/schemas/benchmark';
import type { Benchmark } from '../../../common/types';
@@ -104,7 +105,8 @@ export const defineGetBenchmarksRoute = (router: CspRouter): void =>
cspContext.soClient,
cspContext.packagePolicyService,
CLOUD_SECURITY_POSTURE_PACKAGE_NAME,
- request.query
+ request.query,
+ POSTURE_TYPE_ALL
);
const agentPolicies = await getCspAgentPolicies(
diff --git a/x-pack/plugins/cloud_security_posture/server/routes/status/status.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/status/status.test.ts
index 98c6536c277d38..7f1345ced245f0 100644
--- a/x-pack/plugins/cloud_security_posture/server/routes/status/status.test.ts
+++ b/x-pack/plugins/cloud_security_posture/server/routes/status/status.test.ts
@@ -5,488 +5,143 @@
* 2.0.
*/
-import { defineGetCspStatusRoute, INDEX_TIMEOUT_IN_MINUTES } from './status';
-import { httpServerMock, httpServiceMock } from '@kbn/core/server/mocks';
-import type { ESSearchResponse } from '@kbn/es-types';
-import {
- AgentClient,
- AgentPolicyServiceInterface,
- AgentService,
- PackageClient,
- PackagePolicyClient,
- PackageService,
-} from '@kbn/fleet-plugin/server';
-import {
- AgentPolicy,
- GetAgentStatusResponse,
- Installation,
- RegistryPackage,
-} from '@kbn/fleet-plugin/common';
-import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks';
-import { createCspRequestHandlerContextMock } from '../../mocks';
-import { errors } from '@elastic/elasticsearch';
-
-const mockCspPackageInfo: Installation = {
- verification_status: 'verified',
- installed_kibana: [],
- installed_kibana_space_id: 'default',
- installed_es: [],
- package_assets: [],
- es_index_patterns: { findings: 'logs-cloud_security_posture.findings-*' },
- name: 'cloud_security_posture',
- version: '0.0.14',
- install_version: '0.0.14',
- install_status: 'installed',
- install_started_at: '2022-06-16T15:24:58.281Z',
- install_source: 'registry',
-};
-
-const mockLatestCspPackageInfo: RegistryPackage = {
- format_version: 'mock',
- name: 'cloud_security_posture',
- title: 'CIS Kubernetes Benchmark',
- version: '0.0.14',
- release: 'experimental',
- description: 'Check Kubernetes cluster compliance with the Kubernetes CIS benchmark.',
- type: 'integration',
- download: '/epr/cloud_security_posture/cloud_security_posture-0.0.14.zip',
- path: '/package/cloud_security_posture/0.0.14',
- policy_templates: [],
- owner: { github: 'elastic/cloud-security-posture' },
- categories: ['containers', 'kubernetes'],
-};
-
-describe('CspSetupStatus route', () => {
- const router = httpServiceMock.createRouter();
- let mockContext: ReturnType;
- let mockPackagePolicyService: jest.Mocked;
- let mockAgentPolicyService: jest.Mocked;
- let mockAgentService: jest.Mocked;
- let mockAgentClient: jest.Mocked;
- let mockPackageService: PackageService;
- let mockPackageClient: jest.Mocked;
-
- beforeEach(() => {
- jest.clearAllMocks();
-
- mockContext = createCspRequestHandlerContextMock();
- mockPackagePolicyService = mockContext.csp.packagePolicyService;
- mockAgentPolicyService = mockContext.csp.agentPolicyService;
- mockAgentService = mockContext.csp.agentService;
- mockPackageService = mockContext.csp.packageService;
-
- mockAgentClient = mockAgentService.asInternalUser as jest.Mocked;
- mockPackageClient = mockPackageService.asInternalUser as jest.Mocked;
- });
-
- it('validate the API route path', async () => {
- defineGetCspStatusRoute(router);
- const [config, _] = router.get.mock.calls[0];
-
- expect(config.path).toEqual('/internal/cloud_security_posture/status');
- });
-
- const indices = [
- {
- index: 'logs-cloud_security_posture.findings-default*',
- expected_status: 'not-installed',
- },
- {
- index: 'logs-cloud_security_posture.findings_latest-default',
- expected_status: 'unprivileged',
- },
- {
- index: 'logs-cloud_security_posture.scores-default',
- expected_status: 'unprivileged',
- },
- ];
-
- indices.forEach((idxTestCase) => {
- it(
- 'Verify the API result when there are no permissions to index: ' + idxTestCase.index,
- async () => {
- mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseImplementation(
- (req) => {
- if (req?.index === idxTestCase.index) {
- throw new errors.ResponseError({
- body: {
- error: {
- type: 'security_exception',
- },
- },
- statusCode: 503,
- headers: {},
- warnings: [],
- meta: {} as any,
- });
- }
-
- return {
- hits: {
- hits: [{}],
- },
- } as any;
- }
- );
- mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce(mockLatestCspPackageInfo);
-
- mockPackagePolicyService.list.mockResolvedValueOnce({
- items: [],
- total: 0,
- page: 1,
- perPage: 100,
- });
-
- // Act
- defineGetCspStatusRoute(router);
- const [_, handler] = router.get.mock.calls[0];
-
- const mockResponse = httpServerMock.createResponseFactory();
- const mockRequest = httpServerMock.createKibanaRequest();
- await handler(mockContext, mockRequest, mockResponse);
-
- // Assert
- const [call] = mockResponse.ok.mock.calls;
- const body = call[0]?.body;
- expect(mockResponse.ok).toHaveBeenCalledTimes(1);
-
- await expect(body).toMatchObject({
- status: idxTestCase.expected_status,
- });
- }
+import { calculateCspStatusCode } from './status';
+import { CSPM_POLICY_TEMPLATE } from '../../../common/constants';
+
+describe('calculateCspStatusCode test', () => {
+ it('Verify status when there are no permission', async () => {
+ const statusCode = calculateCspStatusCode(
+ CSPM_POLICY_TEMPLATE,
+ {
+ findingsLatest: 'unprivileged',
+ findings: 'unprivileged',
+ score: 'unprivileged',
+ },
+ 1,
+ 1,
+ 1,
+ ['cspm']
);
+
+ expect(statusCode).toMatch('unprivileged');
});
- it('Verify the API result when there are findings and no installed policies', async () => {
- mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({
- hits: {
- hits: [{ Findings: 'foo' }],
+ it('Verify status when there are no findings, no healthy agents and no installed policy templates', async () => {
+ const statusCode = calculateCspStatusCode(
+ CSPM_POLICY_TEMPLATE,
+ {
+ findingsLatest: 'empty',
+ findings: 'empty',
+ score: 'empty',
},
- } as unknown as ESSearchResponse);
- mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce(mockLatestCspPackageInfo);
-
- mockPackagePolicyService.list.mockResolvedValueOnce({
- items: [],
- total: 0,
- page: 1,
- perPage: 100,
- });
-
- // Act
- defineGetCspStatusRoute(router);
- const [_, handler] = router.get.mock.calls[0];
-
- const mockResponse = httpServerMock.createResponseFactory();
- const mockRequest = httpServerMock.createKibanaRequest();
- await handler(mockContext, mockRequest, mockResponse);
-
- // Assert
- const [call] = mockResponse.ok.mock.calls;
- const body = call[0]?.body;
- expect(mockResponse.ok).toHaveBeenCalledTimes(1);
+ 0,
+ 0,
+ 0,
+ []
+ );
- await expect(body).toMatchObject({
- status: 'indexed',
- latestPackageVersion: '0.0.14',
- installedPackagePolicies: 0,
- healthyAgents: 0,
- installedPackageVersion: undefined,
- isPluginInitialized: false,
- });
+ expect(statusCode).toMatch('not-installed');
});
- it('Verify the API result when there are findings, installed policies, no running agents', async () => {
- mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({
- hits: {
- hits: [{ Findings: 'foo' }],
+ it('Verify status when there are findings and installed policies but no healthy agents', async () => {
+ const statusCode = calculateCspStatusCode(
+ CSPM_POLICY_TEMPLATE,
+ {
+ findingsLatest: 'empty',
+ findings: 'not-empty',
+ score: 'not-empty',
},
- } as unknown as ESSearchResponse);
-
- mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce(mockLatestCspPackageInfo);
- mockPackageClient.getInstallation.mockResolvedValueOnce(mockCspPackageInfo);
-
- mockPackagePolicyService.list.mockResolvedValueOnce({
- items: [],
- total: 3,
- page: 1,
- perPage: 100,
- });
-
- // Act
- defineGetCspStatusRoute(router);
- const [_, handler] = router.get.mock.calls[0];
-
- const mockResponse = httpServerMock.createResponseFactory();
- const mockRequest = httpServerMock.createKibanaRequest();
- await handler(mockContext, mockRequest, mockResponse);
-
- // Assert
- const [call] = mockResponse.ok.mock.calls;
- const body = call[0]?.body;
-
- expect(mockResponse.ok).toHaveBeenCalledTimes(1);
+ 1,
+ 0,
+ 10,
+ ['cspm']
+ );
- await expect(body).toMatchObject({
- status: 'indexed',
- latestPackageVersion: '0.0.14',
- installedPackagePolicies: 3,
- healthyAgents: 0,
- installedPackageVersion: '0.0.14',
- isPluginInitialized: false,
- });
+ expect(statusCode).toMatch('not-deployed');
});
- it('Verify the API result when there are findings, installed policies, running agents', async () => {
- mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({
- hits: {
- hits: [{ Findings: 'foo' }],
+ it('Verify status when there are findings ,installed policies and healthy agents', async () => {
+ const statusCode = calculateCspStatusCode(
+ CSPM_POLICY_TEMPLATE,
+ {
+ findingsLatest: 'not-empty',
+ findings: 'not-empty',
+ score: 'not-empty',
},
- } as unknown as ESSearchResponse);
-
- mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce(mockLatestCspPackageInfo);
- mockPackageClient.getInstallation.mockResolvedValueOnce(mockCspPackageInfo);
-
- mockPackagePolicyService.list.mockResolvedValueOnce({
- items: [],
- total: 3,
- page: 1,
- perPage: 100,
- });
-
- mockAgentPolicyService.getByIds.mockResolvedValue([
- { package_policies: createPackagePolicyMock() },
- ] as unknown as AgentPolicy[]);
-
- mockAgentClient.getAgentStatusForAgentPolicy.mockResolvedValue({
- online: 1,
- updating: 0,
- } as unknown as GetAgentStatusResponse['results']);
-
- // Act
- defineGetCspStatusRoute(router);
- const [_, handler] = router.get.mock.calls[0];
-
- const mockResponse = httpServerMock.createResponseFactory();
- const mockRequest = httpServerMock.createKibanaRequest();
- await handler(mockContext, mockRequest, mockResponse);
-
- // Assert
- const [call] = mockResponse.ok.mock.calls;
- const body = call[0]!.body;
-
- expect(mockResponse.ok).toHaveBeenCalledTimes(1);
+ 1,
+ 1,
+ 10,
+ ['cspm']
+ );
- await expect(body).toMatchObject({
- status: 'indexed',
- latestPackageVersion: '0.0.14',
- installedPackagePolicies: 3,
- healthyAgents: 1,
- installedPackageVersion: '0.0.14',
- isPluginInitialized: false,
- });
+ expect(statusCode).toMatch('indexed');
});
- it('Verify the API result when there are no findings and no installed policies', async () => {
- mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({
- hits: {
- hits: [],
+ it('Verify status when there are no findings ,installed policies and no healthy agents', async () => {
+ const statusCode = calculateCspStatusCode(
+ CSPM_POLICY_TEMPLATE,
+ {
+ findingsLatest: 'empty',
+ findings: 'empty',
+ score: 'empty',
},
- } as unknown as ESSearchResponse);
- mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce(mockLatestCspPackageInfo);
-
- mockPackagePolicyService.list.mockResolvedValueOnce({
- items: [],
- total: 0,
- page: 1,
- perPage: 100,
- });
- defineGetCspStatusRoute(router);
- const [_, handler] = router.get.mock.calls[0];
-
- const mockResponse = httpServerMock.createResponseFactory();
- const mockRequest = httpServerMock.createKibanaRequest();
-
- // Act
- await handler(mockContext, mockRequest, mockResponse);
-
- // Assert
- const [call] = mockResponse.ok.mock.calls;
- const body = call[0]!.body;
-
- expect(mockResponse.ok).toHaveBeenCalledTimes(1);
+ 1,
+ 0,
+ 10,
+ ['cspm']
+ );
- await expect(body).toMatchObject({
- status: 'not-installed',
- latestPackageVersion: '0.0.14',
- installedPackagePolicies: 0,
- healthyAgents: 0,
- isPluginInitialized: false,
- });
+ expect(statusCode).toMatch('not-deployed');
});
- it('Verify the API result when there are no findings, installed agent but no deployed agent', async () => {
- mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({
- hits: {
- hits: [],
+ it('Verify status when there are installed policies, healthy agents and no findings', async () => {
+ const statusCode = calculateCspStatusCode(
+ CSPM_POLICY_TEMPLATE,
+ {
+ findingsLatest: 'empty',
+ findings: 'empty',
+ score: 'empty',
},
- } as unknown as ESSearchResponse);
-
- mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce(mockLatestCspPackageInfo);
- mockPackageClient.getInstallation.mockResolvedValueOnce(mockCspPackageInfo);
-
- mockPackagePolicyService.list.mockResolvedValueOnce({
- items: [],
- total: 1,
- page: 1,
- perPage: 100,
- });
-
- mockAgentPolicyService.getByIds.mockResolvedValue([
- { package_policies: createPackagePolicyMock() },
- ] as unknown as AgentPolicy[]);
-
- mockAgentClient.getAgentStatusForAgentPolicy.mockResolvedValue({
- online: 0,
- updating: 0,
- } as unknown as GetAgentStatusResponse['results']);
-
- // Act
- defineGetCspStatusRoute(router);
-
- const [_, handler] = router.get.mock.calls[0];
-
- const mockResponse = httpServerMock.createResponseFactory();
- const mockRequest = httpServerMock.createKibanaRequest();
- await handler(mockContext, mockRequest, mockResponse);
-
- // Assert
- const [call] = mockResponse.ok.mock.calls;
- const body = call[0]!.body;
-
- expect(mockResponse.ok).toHaveBeenCalledTimes(1);
+ 1,
+ 1,
+ 9,
+ ['cspm']
+ );
- await expect(body).toMatchObject({
- status: 'not-deployed',
- latestPackageVersion: '0.0.14',
- installedPackagePolicies: 1,
- healthyAgents: 0,
- installedPackageVersion: '0.0.14',
- isPluginInitialized: false,
- });
+ expect(statusCode).toMatch('waiting_for_results');
});
- it('Verify the API result when there are no findings, installed agent, deployed agent, before index timeout', async () => {
- mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({
- hits: {
- hits: [],
+ it('Verify status when there are installed policies, healthy agents and no findings and been more than 10 minutes', async () => {
+ const statusCode = calculateCspStatusCode(
+ CSPM_POLICY_TEMPLATE,
+ {
+ findingsLatest: 'empty',
+ findings: 'empty',
+ score: 'empty',
},
- } as unknown as ESSearchResponse);
- mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce(mockLatestCspPackageInfo);
-
- const currentTime = new Date();
- mockCspPackageInfo.install_started_at = new Date(
- currentTime.setMinutes(currentTime.getMinutes() - INDEX_TIMEOUT_IN_MINUTES + 1)
- ).toUTCString();
-
- mockPackageClient.getInstallation.mockResolvedValueOnce(mockCspPackageInfo);
-
- mockPackagePolicyService.list.mockResolvedValueOnce({
- items: [],
- total: 1,
- page: 1,
- perPage: 100,
- });
-
- mockAgentPolicyService.getByIds.mockResolvedValue([
- { package_policies: createPackagePolicyMock() },
- ] as unknown as AgentPolicy[]);
-
- mockAgentClient.getAgentStatusForAgentPolicy.mockResolvedValue({
- online: 1,
- updating: 0,
- } as unknown as GetAgentStatusResponse['results']);
-
- // Act
- defineGetCspStatusRoute(router);
-
- const [_, handler] = router.get.mock.calls[0];
-
- const mockResponse = httpServerMock.createResponseFactory();
- const mockRequest = httpServerMock.createKibanaRequest();
- const [context, req, res] = [mockContext, mockRequest, mockResponse];
-
- await handler(context, req, res);
-
- // Assert
- const [call] = mockResponse.ok.mock.calls;
- const body = call[0]!.body;
-
- expect(mockResponse.ok).toHaveBeenCalledTimes(1);
+ 1,
+ 1,
+ 11,
+ ['cspm']
+ );
- await expect(body).toMatchObject({
- status: 'indexing',
- latestPackageVersion: '0.0.14',
- installedPackagePolicies: 1,
- healthyAgents: 1,
- installedPackageVersion: '0.0.14',
- isPluginInitialized: false,
- });
+ expect(statusCode).toMatch('index-timeout');
});
- it('Verify the API result when there are no findings, installed agent, deployed agent, after index timeout', async () => {
- mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({
- hits: {
- hits: [],
+ it('Verify status when there are installed policies, healthy agents past findings but no recent findings', async () => {
+ const statusCode = calculateCspStatusCode(
+ CSPM_POLICY_TEMPLATE,
+ {
+ findingsLatest: 'empty',
+ findings: 'not-empty',
+ score: 'not-empty',
},
- } as unknown as ESSearchResponse);
- mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce(mockLatestCspPackageInfo);
-
- const currentTime = new Date();
- mockCspPackageInfo.install_started_at = new Date(
- currentTime.setMinutes(currentTime.getMinutes() - INDEX_TIMEOUT_IN_MINUTES - 1)
- ).toUTCString();
-
- mockPackageClient.getInstallation.mockResolvedValueOnce(mockCspPackageInfo);
-
- mockPackagePolicyService.list.mockResolvedValueOnce({
- items: [],
- total: 1,
- page: 1,
- perPage: 100,
- });
-
- mockAgentPolicyService.getByIds.mockResolvedValue([
- { package_policies: createPackagePolicyMock() },
- ] as unknown as AgentPolicy[]);
-
- mockAgentClient.getAgentStatusForAgentPolicy.mockResolvedValue({
- online: 1,
- updating: 0,
- } as unknown as GetAgentStatusResponse['results']);
-
- // Act
- defineGetCspStatusRoute(router);
-
- const [_, handler] = router.get.mock.calls[0];
-
- const mockResponse = httpServerMock.createResponseFactory();
- const mockRequest = httpServerMock.createKibanaRequest();
-
- await handler(mockContext, mockRequest, mockResponse);
-
- // Assert
- const [call] = mockResponse.ok.mock.calls;
- const body = call[0]!.body;
-
- expect(mockResponse.ok).toHaveBeenCalledTimes(1);
+ 1,
+ 1,
+ 0,
+ ['cspm']
+ );
- await expect(body).toMatchObject({
- status: 'index-timeout',
- latestPackageVersion: '0.0.14',
- installedPackagePolicies: 1,
- healthyAgents: 1,
- installedPackageVersion: '0.0.14',
- isPluginInitialized: false,
- });
+ expect(statusCode).toMatch('indexing');
});
});
diff --git a/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts b/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts
index eead1dc267e60e..23578194422ee7 100644
--- a/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts
+++ b/x-pack/plugins/cloud_security_posture/server/routes/status/status.ts
@@ -17,9 +17,16 @@ import {
LATEST_FINDINGS_INDEX_DEFAULT_NS,
FINDINGS_INDEX_PATTERN,
BENCHMARK_SCORE_INDEX_DEFAULT_NS,
+ KSPM_POLICY_TEMPLATE,
+ CSPM_POLICY_TEMPLATE,
} from '../../../common/constants';
import type { CspApiRequestHandlerContext, CspRouter } from '../../types';
-import type { CspSetupStatus, CspStatusCode, IndexStatus } from '../../../common/types';
+import type {
+ CspSetupStatus,
+ CspStatusCode,
+ IndexStatus,
+ PostureTypes,
+} from '../../../common/types';
import {
getAgentStatusesByAgentPolicies,
getCspAgentPolicies,
@@ -60,7 +67,8 @@ const getHealthyAgents = async (
);
};
-const calculateCspStatusCode = (
+export const calculateCspStatusCode = (
+ postureType: PostureTypes,
indicesStatus: {
findingsLatest: IndexStatus;
findings: IndexStatus;
@@ -68,23 +76,37 @@ const calculateCspStatusCode = (
},
installedCspPackagePolicies: number,
healthyAgents: number,
- timeSinceInstallationInMinutes: number
+ timeSinceInstallationInMinutes: number,
+ installedPolicyTemplates: string[]
): CspStatusCode => {
// We check privileges only for the relevant indices for our pages to appear
+ const postureTypeCheck =
+ postureType === CSPM_POLICY_TEMPLATE ? CSPM_POLICY_TEMPLATE : KSPM_POLICY_TEMPLATE;
if (indicesStatus.findingsLatest === 'unprivileged' || indicesStatus.score === 'unprivileged')
return 'unprivileged';
- if (indicesStatus.findingsLatest === 'not-empty') return 'indexed';
- if (installedCspPackagePolicies === 0) return 'not-installed';
+ if (!installedPolicyTemplates.includes(postureTypeCheck)) return 'not-installed';
if (healthyAgents === 0) return 'not-deployed';
- if (timeSinceInstallationInMinutes <= INDEX_TIMEOUT_IN_MINUTES) return 'indexing';
- if (timeSinceInstallationInMinutes > INDEX_TIMEOUT_IN_MINUTES) return 'index-timeout';
+ if (
+ indicesStatus.findingsLatest === 'empty' &&
+ indicesStatus.findings === 'empty' &&
+ timeSinceInstallationInMinutes < INDEX_TIMEOUT_IN_MINUTES
+ )
+ return 'waiting_for_results';
+ if (
+ indicesStatus.findingsLatest === 'empty' &&
+ indicesStatus.findings === 'empty' &&
+ timeSinceInstallationInMinutes > INDEX_TIMEOUT_IN_MINUTES
+ )
+ return 'index-timeout';
+ if (indicesStatus.findingsLatest === 'empty') return 'indexing';
+ if (indicesStatus.findings === 'not-empty') return 'indexed';
throw new Error('Could not determine csp status');
};
const assertResponse = (resp: CspSetupStatus, logger: CspApiRequestHandlerContext['logger']) => {
if (
- resp.status === 'unprivileged' &&
+ (resp.cspm.status || resp.kspm.status) === 'unprivileged' &&
!resp.indicesDetails.some((idxDetails) => idxDetails.status === 'unprivileged')
) {
logger.warn('Returned status in `unprivileged` but response is missing the unprivileged index');
@@ -105,31 +127,70 @@ const getCspStatus = async ({
findingsLatestIndexStatus,
findingsIndexStatus,
scoreIndexStatus,
+ findingsLatestIndexStatusCspm,
+ findingsIndexStatusCspm,
+ scoreIndexStatusCspm,
+ findingsLatestIndexStatusKspm,
+ findingsIndexStatusKspm,
+ scoreIndexStatusKspm,
installation,
latestCspPackage,
- installedPackagePolicies,
+ installedPackagePoliciesKspm,
+ installedPackagePoliciesCspm,
installedPolicyTemplates,
] = await Promise.all([
checkIndexStatus(esClient.asCurrentUser, LATEST_FINDINGS_INDEX_DEFAULT_NS, logger),
checkIndexStatus(esClient.asCurrentUser, FINDINGS_INDEX_PATTERN, logger),
checkIndexStatus(esClient.asCurrentUser, BENCHMARK_SCORE_INDEX_DEFAULT_NS, logger),
+
+ checkIndexStatus(esClient.asCurrentUser, LATEST_FINDINGS_INDEX_DEFAULT_NS, logger, 'cspm'),
+ checkIndexStatus(esClient.asCurrentUser, FINDINGS_INDEX_PATTERN, logger, 'cspm'),
+ checkIndexStatus(esClient.asCurrentUser, BENCHMARK_SCORE_INDEX_DEFAULT_NS, logger, 'cspm'),
+
+ checkIndexStatus(esClient.asCurrentUser, LATEST_FINDINGS_INDEX_DEFAULT_NS, logger, 'kspm'),
+ checkIndexStatus(esClient.asCurrentUser, FINDINGS_INDEX_PATTERN, logger, 'kspm'),
+ checkIndexStatus(esClient.asCurrentUser, BENCHMARK_SCORE_INDEX_DEFAULT_NS, logger, 'kspm'),
+
packageService.asInternalUser.getInstallation(CLOUD_SECURITY_POSTURE_PACKAGE_NAME),
packageService.asInternalUser.fetchFindLatestPackage(CLOUD_SECURITY_POSTURE_PACKAGE_NAME),
- getCspPackagePolicies(soClient, packagePolicyService, CLOUD_SECURITY_POSTURE_PACKAGE_NAME, {
- per_page: 10000,
- }),
+ getCspPackagePolicies(
+ soClient,
+ packagePolicyService,
+ CLOUD_SECURITY_POSTURE_PACKAGE_NAME,
+ {
+ per_page: 10000,
+ },
+ KSPM_POLICY_TEMPLATE
+ ),
+ getCspPackagePolicies(
+ soClient,
+ packagePolicyService,
+ CLOUD_SECURITY_POSTURE_PACKAGE_NAME,
+ {
+ per_page: 10000,
+ },
+ CSPM_POLICY_TEMPLATE
+ ),
getInstalledPolicyTemplates(packagePolicyService, soClient),
]);
- const healthyAgents = await getHealthyAgents(
+ const healthyAgentsKspm = await getHealthyAgents(
soClient,
- installedPackagePolicies.items,
+ installedPackagePoliciesKspm.items,
agentPolicyService,
agentService,
logger
);
- const installedPackagePoliciesTotal = installedPackagePolicies.total;
+ const healthyAgentsCspm = await getHealthyAgents(
+ soClient,
+ installedPackagePoliciesCspm.items,
+ agentPolicyService,
+ agentService,
+ logger
+ );
+ const installedPackagePoliciesTotalKspm = installedPackagePoliciesKspm.total;
+ const installedPackagePoliciesTotalCspm = installedPackagePoliciesCspm.total;
const latestCspPackageVersion = latestCspPackage.version;
const MIN_DATE = 0;
@@ -148,35 +209,62 @@ const getCspStatus = async ({
},
];
- const status = calculateCspStatusCode(
+ const statusCspm = calculateCspStatusCode(
+ CSPM_POLICY_TEMPLATE,
+ {
+ findingsLatest: findingsLatestIndexStatusCspm,
+ findings: findingsIndexStatusCspm,
+ score: scoreIndexStatusCspm,
+ },
+ installedPackagePoliciesTotalCspm,
+ healthyAgentsCspm,
+ calculateDiffFromNowInMinutes(installation?.install_started_at || MIN_DATE),
+ installedPolicyTemplates
+ );
+
+ const statusKspm = calculateCspStatusCode(
+ KSPM_POLICY_TEMPLATE,
{
- findingsLatest: findingsLatestIndexStatus,
- findings: findingsIndexStatus,
- score: scoreIndexStatus,
+ findingsLatest: findingsLatestIndexStatusKspm,
+ findings: findingsIndexStatusKspm,
+ score: scoreIndexStatusKspm,
},
- installedPackagePoliciesTotal,
- healthyAgents,
- calculateDiffFromNowInMinutes(installation?.install_started_at || MIN_DATE)
+ installedPackagePoliciesTotalKspm,
+ healthyAgentsKspm,
+ calculateDiffFromNowInMinutes(installation?.install_started_at || MIN_DATE),
+ installedPolicyTemplates
);
- if (status === 'not-installed')
+ if ((statusCspm && statusKspm) === 'not-installed')
return {
- status,
+ cspm: {
+ status: statusCspm,
+ healthyAgents: healthyAgentsCspm,
+ installedPackagePolicies: installedPackagePoliciesTotalCspm,
+ },
+ kspm: {
+ status: statusKspm,
+ healthyAgents: healthyAgentsKspm,
+ installedPackagePolicies: installedPackagePoliciesTotalKspm,
+ },
indicesDetails,
latestPackageVersion: latestCspPackageVersion,
- installedPolicyTemplates,
- healthyAgents,
- installedPackagePolicies: installedPackagePoliciesTotal,
isPluginInitialized: isPluginInitialized(),
};
const response = {
- status,
+ cspm: {
+ status: statusCspm,
+ healthyAgents: healthyAgentsCspm,
+ installedPackagePolicies: installedPackagePoliciesTotalCspm,
+ },
+ kspm: {
+ status: statusKspm,
+ healthyAgents: healthyAgentsKspm,
+ installedPackagePolicies: installedPackagePoliciesTotalKspm,
+ },
indicesDetails,
latestPackageVersion: latestCspPackageVersion,
- healthyAgents,
- installedPolicyTemplates,
- installedPackagePolicies: installedPackagePoliciesTotal,
installedPackageVersion: installation?.install_version,
isPluginInitialized: isPluginInitialized(),
};
diff --git a/x-pack/plugins/cloud_security_posture/tsconfig.json b/x-pack/plugins/cloud_security_posture/tsconfig.json
index 60c540b422bcdd..a0fe377baf69c4 100755
--- a/x-pack/plugins/cloud_security_posture/tsconfig.json
+++ b/x-pack/plugins/cloud_security_posture/tsconfig.json
@@ -42,7 +42,6 @@
"@kbn/utility-types-jest",
"@kbn/securitysolution-es-utils",
"@kbn/core-elasticsearch-client-server-mocks",
- "@kbn/es-types",
"@kbn/core-elasticsearch-server",
"@kbn/ecs",
"@kbn/core-saved-objects-api-server",
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.test.ts
index c0b50798a822c1..16558869a7caff 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.test.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.test.ts
@@ -61,7 +61,7 @@ describe('Pagination', () => {
const builder = PaginationBuilder.createBuilder(100);
expect(builder.buildQueryFields('a', 'desc').sort).toStrictEqual([
{ '@timestamp': 'desc' },
- { a: { order: 'asc', unmapped_type: 'long' } },
+ { a: { order: 'asc', unmapped_type: 'keyword' } },
]);
});
});
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts
index 295d930ff24f59..19825ea0fd38d3 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts
@@ -179,7 +179,7 @@ export class PaginationBuilder {
): PaginationFields {
const sort: SortFields = [
{ '@timestamp': timeSort },
- { [tiebreaker]: { order: 'asc', unmapped_type: 'long' } },
+ { [tiebreaker]: { order: 'asc', unmapped_type: 'keyword' } },
];
let searchAfter: SearchAfterFields | undefined;
if (this.timestamp && this.eventID) {
diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts
index 515b5662246b7d..2f3f36b9dc34b2 100644
--- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts
+++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts
@@ -610,5 +610,83 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
});
});
}
+
+ describe('do NOT delete reference for rule type like', () => {
+ const es = getService('es');
+
+ it('.esquery', async () => {
+ const space1 = UserAtSpaceScenarios[1].space.id;
+ const { body: createdRule } = await supertest
+ .post(`${getUrlPrefix(space1)}/api/alerting/rule`)
+ .set('kbn-xsrf', 'foo')
+ .send(
+ getTestRuleData({
+ params: {
+ searchConfiguration: {
+ query: { query: 'host.name:*', language: 'kuery' },
+ index: 'logs-*',
+ },
+ timeField: '@timestamp',
+ searchType: 'searchSource',
+ timeWindowSize: 5,
+ timeWindowUnit: 'm',
+ threshold: [1000],
+ thresholdComparator: '>',
+ size: 100,
+ aggType: 'count',
+ groupBy: 'all',
+ termSize: 5,
+ excludeHitsFromPreviousRun: true,
+ },
+ consumer: 'alerts',
+ schedule: { interval: '1m' },
+ tags: [],
+ name: 'Es Query',
+ rule_type_id: '.es-query',
+ actions: [],
+ })
+ )
+ .expect(200);
+ objectRemover.add(space1, createdRule.id, 'rule', 'alerting');
+
+ const searchRule = () =>
+ es.search<{ references: unknown }>({
+ index: '.kibana*',
+ query: {
+ bool: {
+ filter: [
+ {
+ term: {
+ _id: `alert:${createdRule.id}`,
+ },
+ },
+ ],
+ },
+ },
+ fields: ['alert.params', 'references'],
+ });
+
+ const {
+ hits: { hits: alertHitsV1 },
+ } = await searchRule();
+
+ await supertest
+ .post(`${getUrlPrefix(space1)}/internal/alerting/rules/_bulk_edit`)
+ .set('kbn-xsrf', 'foo')
+ .send({
+ ids: [createdRule.id],
+ operations: [{ operation: 'set', field: 'apiKey' }],
+ });
+
+ const {
+ hits: { hits: alertHitsV2 },
+ } = await searchRule();
+
+ expect(alertHitsV1[0].fields).to.eql(alertHitsV2[0].fields);
+ expect(alertHitsV1[0]?._source?.references ?? true).to.eql(
+ alertHitsV2[0]?._source?.references ?? false
+ );
+ });
+ });
});
}
diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/status.ts b/x-pack/test/api_integration/apis/cloud_security_posture/status.ts
index 6d10aa2f60f4a8..89ba33449ec161 100644
--- a/x-pack/test/api_integration/apis/cloud_security_posture/status.ts
+++ b/x-pack/test/api_integration/apis/cloud_security_posture/status.ts
@@ -51,9 +51,10 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'xxxx')
.expect(200);
- expect(res.status).to.be('not-deployed');
- expect(res.installedPolicyTemplates).length(1).contain('kspm');
- expect(res.healthyAgents).to.be(0);
+ expect(res.kspm.status).to.be('not-deployed');
+ expect(res.cspm.status).to.be('not-installed');
+ expect(res.kspm.healthyAgents).to.be(0);
+ expect(res.kspm.installedPackagePolicies).to.be(1);
});
it(`Should return not-deployed when installed cspm`, async () => {
@@ -71,9 +72,10 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'xxxx')
.expect(200);
- expect(res.status).to.be('not-deployed');
- expect(res.installedPolicyTemplates).length(1).contain('cspm');
- expect(res.healthyAgents).to.be(0);
+ expect(res.cspm.status).to.be('not-deployed');
+ expect(res.kspm.status).to.be('not-installed');
+ expect(res.cspm.healthyAgents).to.be(0);
+ expect(res.cspm.installedPackagePolicies).to.be(1);
});
});
}
diff --git a/x-pack/test/cloud_security_posture_functional/pages/findings.ts b/x-pack/test/cloud_security_posture_functional/pages/findings.ts
index 6a1222ef1e0993..010bb788b8c70c 100644
--- a/x-pack/test/cloud_security_posture_functional/pages/findings.ts
+++ b/x-pack/test/cloud_security_posture_functional/pages/findings.ts
@@ -29,6 +29,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
section: 'Upper case section',
benchmark: {
id: 'cis_k8s',
+ posture_type: 'kspm',
name: 'CIS Kubernetes V1.23',
version: 'v1.0.0',
},
@@ -44,6 +45,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
section: 'Another upper case section',
benchmark: {
id: 'cis_k8s',
+ posture_type: 'kspm',
name: 'CIS Kubernetes V1.23',
version: 'v1.0.0',
},
@@ -59,6 +61,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
section: 'lower case section',
benchmark: {
id: 'cis_k8s',
+ posture_type: 'kspm',
name: 'CIS Kubernetes V1.23',
version: 'v1.0.0',
},
@@ -74,6 +77,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
section: 'another lower case section',
benchmark: {
id: 'cis_k8s',
+ posture_type: 'kspm',
name: 'CIS Kubernetes V1.23',
version: 'v1.0.0',
},
@@ -105,6 +109,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
resourceFindingsTable = findings.resourceFindingsTable;
distributionBar = findings.distributionBar;
+ await findings.index.remove();
await findings.index.add(data);
await findings.navigateToLatestFindingsPage();
await retry.waitFor(
diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts
index fb6f34aa24a14b..eb5e34ce0207a3 100644
--- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts
+++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts
@@ -27,6 +27,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
{
feature: {
advancedSettings: ['all'],
+ globalSettings: ['all'],
},
spaces: ['*'],
},
@@ -87,6 +88,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
{
feature: {
advancedSettings: ['read'],
+ globalSettings: ['show'],
},
spaces: ['*'],
},