[Cloud Security] Set up first api integration tests in serverless (#167169)

## Summary

This PR is copying over part of the API integration tests for the
`cloud_security_posture` plugin. It's a part of the work on
https://github.com/elastic/security-team/issues/7439.

Some tests are not yet copied over as they need more research, as they
rely on either creating new users in Kibana or on fleet utils. This
functionality is not yet available in serverless out of the box.

Why copy?
From [Kibana Serverless e2e Test
Guide](https://docs.google.com/document/d/1tiax7xoDYwFXYZjRTgVKkVMjN-SQzBWk4yn1JY6Z5UY/edit):
> Stateful tests should be copied over and modified as required for
these features to ensure thorough coverage.

which tests are copied and adopted for serverless:

`tests/api_integration/apis/cloud_security_posture/status/status_not_deployed_not_installed`

`tests/api_integration/apis/cloud_security_posture/status/status_indexed`

`tests/api_integration/apis/cloud_security_posture/status/status_indexing`
`tests/api_integration/apis/cloud_security_posture/benchmark`

`tests/api_integration/apis/cloud_security_posture/get_csp_rule_template`
`tests/cloud_security_posture_api/telemetry`

which tests are not yet adopted for serverless:

`tests/api_integration/apis/cloud_security_posture/status/status_unprivileged`
(user/roles model is different in serverless)

`tests/api_integration/apis/cloud_security_posture/status/status_waiting_for_results`
(fleet test utils are not available)

`tests/api_integration/apis/cloud_security_posture/status/status_index_timeout`
(fleet test utils are not available)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Maxim Kholod 2023-10-11 13:39:40 +02:00 committed by GitHub
parent 650c156b76
commit 31f285a1e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 1307 additions and 126 deletions

1
.github/CODEOWNERS vendored
View file

@ -1395,6 +1395,7 @@ x-pack/test/detection_engine_api_integration/security_and_spaces/group10/risk_en
/x-pack/test/cloud_security_posture_api/ @elastic/kibana-cloud-security-posture
/x-pack/test_serverless/functional/test_suites/security/ftr/cloud_security_posture/ @elastic/kibana-cloud-security-posture
/x-pack/test_serverless/functional/test_suites/security/config.cloud_security_posture.ts @elastic/kibana-cloud-security-posture
/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/ @elastic/kibana-cloud-security-posture
# Security Solution onboarding tour
/x-pack/plugins/security_solution/public/common/components/guided_onboarding @elastic/security-threat-hunting-explore

View file

@ -6,10 +6,9 @@
*/
import expect from '@kbn/expect';
import type { GetBenchmarkResponse } from '@kbn/cloud-security-posture-plugin/common/types';
import type { SuperTest, Test } from 'supertest';
import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common';
import { FtrProviderContext } from '../../ftr_provider_context';
import { createPackagePolicy } from './helper';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
@ -156,64 +155,3 @@ export default function ({ getService }: FtrProviderContext) {
});
});
}
export async function createPackagePolicy(
supertest: SuperTest<Test>,
agentPolicyId: string,
policyTemplate: string,
input: string,
deployment: string,
posture: string,
packageName: string
) {
const version = posture === 'kspm' || posture === 'cspm' ? '1.2.8' : '1.3.0-preview2';
const title = 'Security Posture Management';
const streams = [
{
enabled: false,
data_stream: {
type: 'logs',
dataset: 'cloud_security_posture.vulnerabilities',
},
},
];
const inputTemplate = {
enabled: true,
type: input,
policy_template: policyTemplate,
};
const inputs = posture === 'vuln_mgmt' ? { ...inputTemplate, streams } : { ...inputTemplate };
const { body: postPackageResponse } = await supertest
.post(`/api/fleet/package_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
force: true,
name: packageName,
description: '',
namespace: 'default',
policy_id: agentPolicyId,
enabled: true,
inputs: [inputs],
package: {
name: 'cloud_security_posture',
title,
version,
},
vars: {
deployment: {
value: deployment,
type: 'text',
},
posture: {
value: posture,
type: 'text',
},
},
})
.expect(200);
return postPackageResponse.item;
}

View file

@ -7,9 +7,9 @@
import expect from '@kbn/expect';
import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common';
import type { GetCspRuleTemplateResponse } from '@kbn/cloud-security-posture-plugin/common/types';
import type { SuperTest, Test } from 'supertest';
import { CspRuleTemplate } from '@kbn/cloud-security-posture-plugin/common/schemas';
import { FtrProviderContext } from '../../ftr_provider_context';
import { createPackagePolicy } from './helper';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -232,63 +232,3 @@ export default function ({ getService }: FtrProviderContext) {
});
});
}
export async function createPackagePolicy(
supertest: SuperTest<Test>,
agentPolicyId: string,
policyTemplate: string,
input: string,
deployment: string,
posture: string
) {
const version = posture === 'kspm' || posture === 'cspm' ? '1.2.8' : '1.3.0-preview2';
const title = 'Security Posture Management';
const streams = [
{
enabled: false,
data_stream: {
type: 'logs',
dataset: 'cloud_security_posture.vulnerabilities',
},
},
];
const inputTemplate = {
enabled: true,
type: input,
policy_template: policyTemplate,
};
const inputs = posture === 'vuln_mgmt' ? { ...inputTemplate, streams } : { ...inputTemplate };
const { body: postPackageResponse } = await supertest
.post(`/api/fleet/package_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
force: true,
name: 'cloud_security_posture-1',
description: '',
namespace: 'default',
policy_id: agentPolicyId,
enabled: true,
inputs: [inputs],
package: {
name: 'cloud_security_posture',
title,
version,
},
vars: {
deployment: {
value: deployment,
type: 'text',
},
posture: {
value: posture,
type: 'text',
},
},
})
.expect(200);
return postPackageResponse.item;
}

View file

@ -47,7 +47,8 @@ export async function createPackagePolicy(
policyTemplate: string,
input: string,
deployment: string,
posture: string
posture: string,
packageName: string = 'cloud_security_posture-1'
) {
const version = '1.3.0';
const title = 'Security Posture Management';
@ -74,7 +75,7 @@ export async function createPackagePolicy(
.set('kbn-xsrf', 'xxxx')
.send({
force: true,
name: 'cloud_security_posture-1',
name: packageName,
description: '',
namespace: 'default',
policy_id: agentPolicyId,

View file

@ -0,0 +1,165 @@
/*
* 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 expect from '@kbn/expect';
import type { GetBenchmarkResponse } from '@kbn/cloud-security-posture-plugin/common/types';
import {
ELASTIC_HTTP_VERSION_HEADER,
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
} from '@kbn/core-http-common';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { createPackagePolicy } from '../../../../../test/api_integration/apis/cloud_security_posture/helper'; // eslint-disable-line @kbn/imports/no_boundary_crossing
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
describe('GET /internal/cloud_security_posture/benchmark', () => {
let agentPolicyId: string;
let agentPolicyId2: string;
let agentPolicyId3: string;
let agentPolicyId4: string;
beforeEach(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
const { body: agentPolicyResponse } = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Test policy',
namespace: 'default',
});
agentPolicyId = agentPolicyResponse.item.id;
const { body: agentPolicyResponse2 } = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Test policy 2',
namespace: 'default',
});
agentPolicyId2 = agentPolicyResponse2.item.id;
const { body: agentPolicyResponse3 } = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Test policy 3',
namespace: 'default',
});
agentPolicyId3 = agentPolicyResponse3.item.id;
const { body: agentPolicyResponse4 } = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Test policy 4',
namespace: 'default',
});
agentPolicyId4 = agentPolicyResponse4.item.id;
await createPackagePolicy(
supertest,
agentPolicyId,
'cspm',
'cloudbeat/cis_aws',
'aws',
'cspm',
'CSPM-1'
);
await createPackagePolicy(
supertest,
agentPolicyId2,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm',
'KSPM-1'
);
await createPackagePolicy(
supertest,
agentPolicyId3,
'vuln_mgmt',
'cloudbeat/vuln_mgmt_aws',
'aws',
'vuln_mgmt',
'CNVM-1'
);
await createPackagePolicy(
supertest,
agentPolicyId4,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm',
'KSPM-2'
);
});
afterEach(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
});
it(`Should return non-empty array filled with Rules if user has CSP integrations`, async () => {
const { body: res }: { body: GetBenchmarkResponse } = await supertest
.get(`/internal/cloud_security_posture/benchmarks`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.items.length).equal(3);
expect(res.total).equal(3);
});
it(`Should return array size 2 when we set per page to be only 2 (total element is still 3)`, async () => {
const { body: res }: { body: GetBenchmarkResponse } = await supertest
.get(`/internal/cloud_security_posture/benchmarks?per_page=2`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.items.length).equal(2);
expect(res.total).equal(3);
});
it(`Should return array size 2 when we set per page to be only 2 (total element is still 3)`, async () => {
const { body: res }: { body: GetBenchmarkResponse } = await supertest
.get(`/internal/cloud_security_posture/benchmarks?per_page=2&page=2`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.items.length).equal(1);
expect(res.total).equal(3);
});
it(`Should return empty array when we set page to be above the last page number`, async () => {
const { body: res }: { body: GetBenchmarkResponse } = await supertest
.get(`/internal/cloud_security_posture/benchmarks?per_page=2&page=3`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.items.length).equal(0);
expect(res.total).equal(3);
});
});
}

View file

@ -0,0 +1,244 @@
/*
* 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 expect from '@kbn/expect';
import {
ELASTIC_HTTP_VERSION_HEADER,
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
} from '@kbn/core-http-common';
import type { GetCspRuleTemplateResponse } from '@kbn/cloud-security-posture-plugin/common/types';
import { CspRuleTemplate } from '@kbn/cloud-security-posture-plugin/common/schemas';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { createPackagePolicy } from '../../../../../test/api_integration/apis/cloud_security_posture/helper'; // eslint-disable-line @kbn/imports/no_boundary_crossing
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
describe('GET internal/cloud_security_posture/rules/_find', () => {
let agentPolicyId: string;
beforeEach(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
const { body: agentPolicyResponse } = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Test policy',
namespace: 'default',
});
agentPolicyId = agentPolicyResponse.item.id;
});
afterEach(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
});
it(`Should return 500 error code when not provide package policy id or benchmark id`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm'
);
const { body }: { body: { message: string } } = await supertest
.get(`/internal/cloud_security_posture/rules/_find`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(500);
expect(body.message).to.eql(
'Please provide either benchmarkId or packagePolicyId, but not both',
`expected message to be 'Please provide either benchmarkId or packagePolicyId, but not both' but got ${body.message} instead`
);
});
it(`Should return 500 error code when provide both package policy id and benchmark id`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm'
);
const { body }: { body: { message: string } } = await supertest
.get(`/internal/cloud_security_posture/rules/_find`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.query({
packagePolicyId: 'your-package-policy-id',
benchmarkId: 'cis_aws',
})
.expect(500);
expect(body.message).to.eql(
'Please provide either benchmarkId or packagePolicyId, but not both',
`expected message to be 'Please provide either benchmarkId or packagePolicyId, but not both' but got ${body.message} instead`
);
});
it(`Should return 404 status code when the package policy ID does not exist`, async () => {
const { body }: { body: { statusCode: number; error: string } } = await supertest
.get(`/internal/cloud_security_posture/rules/_find`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.query({
packagePolicyId: 'non-existing-packagePolicy-id',
})
.expect(404);
expect(body.statusCode).to.eql(
404,
`expected status code to be 404 but got ${body.statusCode} instead`
);
expect(body.error).to.eql(
'Not Found',
`expected error message to be 'Not Found' but got ${body.error} instead`
);
});
it(`Should return 200 status code and filter rules by benchmarkId`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm'
);
const { body }: { body: GetCspRuleTemplateResponse } = await supertest
.get(`/internal/cloud_security_posture/rules/_find`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.query({
benchmarkId: 'cis_k8s',
})
.expect(200);
expect(body.items.length).greaterThan(0);
const allRulesHaveCorrectBenchmarkId = body.items.every(
(rule: CspRuleTemplate) => rule.metadata.benchmark.id === 'cis_k8s'
);
expect(allRulesHaveCorrectBenchmarkId).to.eql(
true,
`expected true but got ${allRulesHaveCorrectBenchmarkId} instead`
);
});
it(`Should return 200 status code, and only requested fields in the response`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm'
);
const { body }: { body: GetCspRuleTemplateResponse } = await supertest
.get(`/internal/cloud_security_posture/rules/_find`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.query({
benchmarkId: 'cis_k8s',
fields: ['metadata.name', 'metadata.section', 'metadata.id'],
})
.expect(200);
expect(body.items.length).greaterThan(0);
const allowedFields = ['name', 'section', 'id'];
const fieldsMatched = body.items.every((rule: CspRuleTemplate) => {
const keys = Object.keys(rule.metadata);
return (
keys.length === allowedFields.length && keys.every((key) => allowedFields.includes(key))
);
});
expect(fieldsMatched).to.eql(true, `expected true but got ${fieldsMatched} instead`);
});
it(`Should return 200 status code, items sorted by metadata.section field`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm'
);
const { body }: { body: GetCspRuleTemplateResponse } = await supertest
.get(`/internal/cloud_security_posture/rules/_find`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.query({
benchmarkId: 'cis_k8s',
sortField: 'metadata.section',
sortOrder: 'asc',
})
.expect(200);
expect(body.items.length).greaterThan(0);
// check if the items are sorted by metadata.section field
const sections = body.items.map((rule: CspRuleTemplate) => rule.metadata.section);
const isSorted = sections.every(
(section, index) => index === 0 || section >= sections[index - 1]
);
expect(isSorted).to.eql(true, `expected true but got ${isSorted} instead`);
});
it(`Should return 200 status code and paginate rules with a limit of PerPage`, async () => {
const perPage = 10;
await createPackagePolicy(
supertest,
agentPolicyId,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm'
);
const { body }: { body: GetCspRuleTemplateResponse } = await supertest
.get(`/internal/cloud_security_posture/rules/_find`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set('kbn-xsrf', 'xxxx')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.query({
benchmarkId: 'cis_k8s',
perPage,
})
.expect(200);
expect(body.items.length).to.eql(
perPage,
`expected length to be ${perPage} but got ${body.items.length} instead`
);
});
});
}

View file

@ -0,0 +1,27 @@
/*
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('cloud_security_posture', function () {
this.tags(['cloud_security_posture']);
loadTestFile(require.resolve('./status/status_not_deployed_not_installed'));
loadTestFile(require.resolve('./status/status_indexed'));
loadTestFile(require.resolve('./status/status_indexing'));
loadTestFile(require.resolve('./benchmark'));
loadTestFile(require.resolve('./get_csp_rule_template'));
loadTestFile(require.resolve('./telemetry'));
// TODO: migrate status_unprivileged tests from stateful, if it feasible in serverless with the new security model
// loadTestFile(require.resolve('./status/status_unprivileged'));
// TODO: migrate tests relying on fleet_api_integration helpers from stateful
// loadTestFile(require.resolve('./status/status_waiting_for_results'));
// loadTestFile(require.resolve('./status/status_index_timeout'));
});
}

View file

@ -0,0 +1,143 @@
/*
* 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 expect from '@kbn/expect';
import {
ELASTIC_HTTP_VERSION_HEADER,
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
} from '@kbn/core-http-common';
import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types';
import {
FINDINGS_INDEX_DEFAULT_NS,
LATEST_FINDINGS_INDEX_DEFAULT_NS,
LATEST_VULNERABILITIES_INDEX_DEFAULT_NS,
VULNERABILITIES_INDEX_DEFAULT_NS,
} from '@kbn/cloud-security-posture-plugin/common/constants';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import {
deleteIndex,
addIndex,
createPackagePolicy,
} from '../../../../../../test/api_integration/apis/cloud_security_posture/helper'; // eslint-disable-line @kbn/imports/no_boundary_crossing
import {
findingsMockData,
vulnerabilityMockData,
} from '../../../../../../test/api_integration/apis/cloud_security_posture/mock_data'; // eslint-disable-line @kbn/imports/no_boundary_crossing
const INDEX_ARRAY = [
FINDINGS_INDEX_DEFAULT_NS,
LATEST_FINDINGS_INDEX_DEFAULT_NS,
LATEST_VULNERABILITIES_INDEX_DEFAULT_NS,
VULNERABILITIES_INDEX_DEFAULT_NS,
];
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
describe('GET /internal/cloud_security_posture/status', () => {
let agentPolicyId: string;
describe('STATUS = INDEXED TEST', () => {
beforeEach(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
const { body: agentPolicyResponse } = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Test policy',
namespace: 'default',
});
agentPolicyId = agentPolicyResponse.item.id;
await deleteIndex(es, INDEX_ARRAY);
await addIndex(es, findingsMockData, LATEST_FINDINGS_INDEX_DEFAULT_NS);
await addIndex(es, vulnerabilityMockData, LATEST_VULNERABILITIES_INDEX_DEFAULT_NS);
});
afterEach(async () => {
await deleteIndex(es, INDEX_ARRAY);
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
});
it(`Return kspm status indexed when logs-cloud_security_posture.findings_latest-default contains new kspm documents`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm'
);
const { body: res }: { body: CspSetupStatus } = await supertest
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.kspm.status).to.eql(
'indexed',
`expected kspm status to be indexed but got ${res.kspm.status} instead`
);
});
it(`Return cspm status indexed when logs-cloud_security_posture.findings_latest-default contains new cspm documents`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'cspm',
'cloudbeat/cis_aws',
'aws',
'cspm'
);
const { body: res }: { body: CspSetupStatus } = await supertest
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.cspm.status).to.eql(
'indexed',
`expected cspm status to be indexed but got ${res.cspm.status} instead`
);
});
it(`Return vuln status indexed when logs-cloud_security_posture.vulnerabilities_latest-default contains new documents`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'vuln_mgmt',
'cloudbeat/vuln_mgmt_aws',
'aws',
'vuln_mgmt'
);
const { body: res }: { body: CspSetupStatus } = await supertest
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.vuln_mgmt.status).to.eql(
'indexed',
`expected vuln_mgmt status to be indexed but got ${res.vuln_mgmt.status} instead`
);
});
});
});
}

View file

@ -0,0 +1,142 @@
/*
* 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 expect from '@kbn/expect';
import {
ELASTIC_HTTP_VERSION_HEADER,
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
} from '@kbn/core-http-common';
import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types';
import {
FINDINGS_INDEX_DEFAULT_NS,
LATEST_FINDINGS_INDEX_DEFAULT_NS,
LATEST_VULNERABILITIES_INDEX_DEFAULT_NS,
VULNERABILITIES_INDEX_DEFAULT_NS,
} from '@kbn/cloud-security-posture-plugin/common/constants';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import {
deleteIndex,
addIndex,
createPackagePolicy,
} from '../../../../../../test/api_integration/apis/cloud_security_posture/helper'; // eslint-disable-line @kbn/imports/no_boundary_crossing
import {
findingsMockData,
vulnerabilityMockData,
} from '../../../../../../test/api_integration/apis/cloud_security_posture/mock_data'; // eslint-disable-line @kbn/imports/no_boundary_crossing
const INDEX_ARRAY = [
FINDINGS_INDEX_DEFAULT_NS,
LATEST_FINDINGS_INDEX_DEFAULT_NS,
LATEST_VULNERABILITIES_INDEX_DEFAULT_NS,
VULNERABILITIES_INDEX_DEFAULT_NS,
];
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const supertest = getService('supertest');
const es = getService('es');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
describe('GET /internal/cloud_security_posture/status', () => {
let agentPolicyId: string;
describe('STATUS = INDEXING TEST', () => {
beforeEach(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
const { body: agentPolicyResponse } = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Test policy',
namespace: 'default',
});
agentPolicyId = agentPolicyResponse.item.id;
await deleteIndex(es, INDEX_ARRAY);
await addIndex(es, findingsMockData, FINDINGS_INDEX_DEFAULT_NS);
await addIndex(es, vulnerabilityMockData, VULNERABILITIES_INDEX_DEFAULT_NS);
});
afterEach(async () => {
await deleteIndex(es, INDEX_ARRAY);
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
});
it(`Return kspm status indexing when logs-cloud_security_posture.findings_latest-default doesn't contain new kspm documents, but has newly connected agents`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm'
);
const { body: res }: { body: CspSetupStatus } = await supertest
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.kspm.status).to.eql(
'indexing',
`expected kspm status to be indexing but got ${res.kspm.status} instead`
);
});
it(`Return cspm status indexing when logs-cloud_security_posture.findings_latest-default doesn't contain new cspm documents, but has newly connected agents `, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'cspm',
'cloudbeat/cis_aws',
'aws',
'cspm'
);
const { body: res }: { body: CspSetupStatus } = await supertest
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.cspm.status).to.eql(
'indexing',
`expected cspm status to be indexing but got ${res.cspm.status} instead`
);
});
it(`Return vuln status indexing when logs-cloud_security_posture.vulnerabilities_latest-default doesn't contain vuln new documents, but has newly connected agents`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'vuln_mgmt',
'cloudbeat/vuln_mgmt_aws',
'aws',
'vuln_mgmt'
);
const { body: res }: { body: CspSetupStatus } = await supertest
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.vuln_mgmt.status).to.eql(
'indexing',
`expected vuln_mgmt status to be indexing but got ${res.vuln_mgmt.status} instead`
);
});
});
});
}

View file

@ -0,0 +1,163 @@
/*
* 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 expect from '@kbn/expect';
import type { CspSetupStatus } from '@kbn/cloud-security-posture-plugin/common/types';
import {
ELASTIC_HTTP_VERSION_HEADER,
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
} from '@kbn/core-http-common';
import { FtrProviderContext } from '../../../../ftr_provider_context';
import { createPackagePolicy } from '../../../../../../test/api_integration/apis/cloud_security_posture/helper'; // eslint-disable-line @kbn/imports/no_boundary_crossing
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
describe('GET /internal/cloud_security_posture/status', () => {
let agentPolicyId: string;
describe('STATUS = NOT-DEPLOYED and STATUS = NOT-INSTALLED TEST', () => {
beforeEach(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
const { body: agentPolicyResponse } = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Test policy',
namespace: 'default',
});
agentPolicyId = agentPolicyResponse.item.id;
});
afterEach(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
});
it(`Should return not-deployed when installed kspm, no findings on either indices and no healthy agents`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'kspm',
'cloudbeat/cis_k8s',
'vanilla',
'kspm'
);
const { body: res }: { body: CspSetupStatus } = await supertest
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.kspm.status).to.eql(
'not-deployed',
`expected kspm status to be not-deployed but got ${res.kspm.status} instead`
);
expect(res.cspm.status).to.eql(
'not-installed',
`expected cspm status to be not-installed but got ${res.cspm.status} instead`
);
expect(res.vuln_mgmt.status).to.eql(
'not-installed',
`expected vuln_mgmt status to be not-installed but got ${res.vuln_mgmt.status} instead`
);
expect(res.kspm.healthyAgents).to.eql(
0,
`expected number of kspm healthy agents to be 0 but got ${res.kspm.healthyAgents} instead`
);
expect(res.kspm.installedPackagePolicies).to.eql(
1,
`expected number of kspm installed package policies to be 1 but got ${res.kspm.installedPackagePolicies} instead`
);
});
it(`Should return not-deployed when installed cspm, no findings on either indices and no healthy agents`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'cspm',
'cloudbeat/cis_aws',
'aws',
'cspm'
);
const { body: res }: { body: CspSetupStatus } = await supertest
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.cspm.status).to.eql(
'not-deployed',
`expected cspm status to be not-deployed but got ${res.cspm.status} instead`
);
expect(res.kspm.status).to.eql(
'not-installed',
`expected kspm status to be not-installed but got ${res.kspm.status} instead`
);
expect(res.vuln_mgmt.status).to.eql(
'not-installed',
`expected vuln_mgmt status to be not-installed but got ${res.vuln_mgmt.status} instead`
);
expect(res.cspm.healthyAgents).to.eql(
0,
`expected number of cspm healthy agents to be 0 but got ${res.cspm.healthyAgents} instead`
);
expect(res.cspm.installedPackagePolicies).to.eql(
1,
`expected number of cspm installed package policies to be 1 but got ${res.cspm.installedPackagePolicies} instead`
);
});
it(`Should return not-deployed when installed cnvm, no findings on either indices and no healthy agents`, async () => {
await createPackagePolicy(
supertest,
agentPolicyId,
'vuln_mgmt',
'cloudbeat/vuln_mgmt_aws',
'aws',
'vuln_mgmt'
);
const { body: res }: { body: CspSetupStatus } = await supertest
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.set('kbn-xsrf', 'xxxx')
.expect(200);
expect(res.cspm.status).to.eql(
'not-installed',
`expected cspm status to be not-installed but got ${res.cspm.status} instead`
);
expect(res.kspm.status).to.eql(
'not-installed',
`expected kspm status to be not-installed but got ${res.kspm.status} instead`
);
expect(res.vuln_mgmt.status).to.eql(
'not-deployed',
`expected vuln_mgmt status to be not-deployed but got ${res.vuln_mgmt.status} instead`
);
expect(res.vuln_mgmt.healthyAgents).to.eql(
0,
`expected number of vuln_mgmt healthy agents to be 0 but got ${res.vuln_mgmt.healthyAgents} instead`
);
expect(res.vuln_mgmt.installedPackagePolicies).to.eql(
1,
`expected number of vuln_mgmt installed package policies to be 1 but got ${res.vuln_mgmt.installedPackagePolicies} instead`
);
});
});
});
}

View file

@ -0,0 +1,415 @@
/*
* 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 expect from '@kbn/expect';
import {
ELASTIC_HTTP_VERSION_HEADER,
X_ELASTIC_INTERNAL_ORIGIN_REQUEST,
} from '@kbn/core-http-common';
import type { FtrProviderContext } from '../../../ftr_provider_context';
import {
data as telemetryMockData,
MockTelemetryFindings,
} from '../../../../../test/cloud_security_posture_api/telemetry/data'; // eslint-disable-line @kbn/imports/no_boundary_crossing
import { createPackagePolicy } from '../../../../../test/api_integration/apis/cloud_security_posture/helper'; // eslint-disable-line @kbn/imports/no_boundary_crossing
const FINDINGS_INDEX = 'logs-cloud_security_posture.findings_latest-default';
export default function ({ getService }: FtrProviderContext) {
const retry = getService('retry');
const es = getService('es');
const supertest = getService('supertest');
const log = getService('log');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
/**
* required before indexing findings
*/
const waitForPluginInitialized = (): Promise<void> =>
retry.try(async () => {
log.debug('Check CSP plugin is initialized');
const response = await supertest
.get('/internal/cloud_security_posture/status?check=init')
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'xxx')
.expect(200);
expect(response.body).to.eql({ isPluginInitialized: true });
log.debug('CSP plugin is initialized');
});
const index = {
remove: () =>
es.deleteByQuery({
index: FINDINGS_INDEX,
query: { match_all: {} },
refresh: true,
}),
add: async (mockTelemetryFindings: MockTelemetryFindings[]) => {
const operations = mockTelemetryFindings.flatMap((doc) => [
{ index: { _index: FINDINGS_INDEX } },
doc,
]);
const response = await es.bulk({ refresh: 'wait_for', index: FINDINGS_INDEX, operations });
expect(response.errors).to.eql(false);
},
};
describe('Verify cloud_security_posture telemetry payloads', async () => {
let agentPolicyId: string;
before(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.load('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
const { body: agentPolicyResponse } = await supertest
.post(`/api/fleet/agent_policies`)
.set('kbn-xsrf', 'xxxx')
.send({
name: 'Test policy',
namespace: 'default',
});
agentPolicyId = agentPolicyResponse.item.id;
await createPackagePolicy(
supertest,
agentPolicyId,
'cspm',
'cloudbeat/cis_aws',
'aws',
'cspm',
'CSPM-1'
);
await waitForPluginInitialized();
});
after(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server');
});
afterEach(async () => {
await index.remove();
});
it('includes only KSPM findings', async () => {
await index.add(telemetryMockData.kspmFindings);
const {
body: [{ stats: apiResponse }],
} = await supertest
.post(`/internal/telemetry/clusters/_stats`)
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.set('kbn-xsrf', 'xxxx')
.send({
unencrypted: true,
refreshCache: true,
})
.expect(200);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.accounts_stats).to.eql([
{
account_id: 'my-k8s-cluster-5555',
latest_findings_doc_count: 2,
posture_score: 100,
passed_findings_count: 2,
failed_findings_count: 0,
benchmark_name: 'CIS Kubernetes V1.23',
benchmark_id: 'cis_k8s',
kubernetes_version: 'v1.23.0',
benchmark_version: 'v1.0.0',
agents_count: 2,
nodes_count: 2,
pods_count: 0,
},
]);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.resources_stats).to.eql([
{
account_id: 'my-k8s-cluster-5555',
resource_type: 'k8s_object',
resource_type_doc_count: 1,
resource_sub_type: 'ServiceAccount',
resource_sub_type_doc_count: 1,
passed_findings_count: 1,
failed_findings_count: 0,
},
{
account_id: 'my-k8s-cluster-5555',
resource_type: 'process',
resource_type_doc_count: 1,
resource_sub_type: 'process',
resource_sub_type_doc_count: 1,
passed_findings_count: 1,
failed_findings_count: 0,
},
]);
});
it('includes only CSPM findings', async () => {
await index.add(telemetryMockData.cspmFindings);
const {
body: [{ stats: apiResponse }],
} = await supertest
.post(`/internal/telemetry/clusters/_stats`)
.set('kbn-xsrf', 'xxxx')
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send({
unencrypted: true,
refreshCache: true,
})
.expect(200);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.accounts_stats).to.eql([
{
account_id: 'my-aws-12345',
latest_findings_doc_count: 2,
posture_score: 50,
passed_findings_count: 1,
failed_findings_count: 1,
benchmark_name: 'CIS Amazon Web Services Foundations',
benchmark_id: 'cis_aws',
benchmark_version: 'v1.5.0',
kubernetes_version: null,
agents_count: 1,
nodes_count: 1,
pods_count: 0,
},
]);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.resources_stats).to.eql([
{
account_id: 'my-aws-12345',
resource_type: 'identifyingType',
resource_type_doc_count: 2,
resource_sub_type: 'aws-password-policy',
resource_sub_type_doc_count: 2,
passed_findings_count: 1,
failed_findings_count: 1,
},
]);
});
it('includes CSPM and KSPM findings', async () => {
await index.add(telemetryMockData.kspmFindings);
await index.add(telemetryMockData.cspmFindings);
const {
body: [{ stats: apiResponse }],
} = await supertest
.post(`/internal/telemetry/clusters/_stats`)
.set('kbn-xsrf', 'xxxx')
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send({
unencrypted: true,
refreshCache: true,
})
.expect(200);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.accounts_stats).to.eql([
{
account_id: 'my-aws-12345',
latest_findings_doc_count: 2,
posture_score: 50,
passed_findings_count: 1,
failed_findings_count: 1,
benchmark_name: 'CIS Amazon Web Services Foundations',
benchmark_id: 'cis_aws',
benchmark_version: 'v1.5.0',
kubernetes_version: null,
agents_count: 1,
nodes_count: 1,
pods_count: 0,
},
{
account_id: 'my-k8s-cluster-5555',
latest_findings_doc_count: 2,
posture_score: 100,
passed_findings_count: 2,
failed_findings_count: 0,
benchmark_name: 'CIS Kubernetes V1.23',
benchmark_id: 'cis_k8s',
benchmark_version: 'v1.0.0',
kubernetes_version: 'v1.23.0',
agents_count: 2,
nodes_count: 2,
pods_count: 0,
},
]);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.resources_stats).to.eql([
{
account_id: 'my-aws-12345',
resource_type: 'identifyingType',
resource_type_doc_count: 2,
resource_sub_type: 'aws-password-policy',
resource_sub_type_doc_count: 2,
passed_findings_count: 1,
failed_findings_count: 1,
},
{
account_id: 'my-k8s-cluster-5555',
resource_type: 'k8s_object',
resource_type_doc_count: 1,
resource_sub_type: 'ServiceAccount',
resource_sub_type_doc_count: 1,
passed_findings_count: 1,
failed_findings_count: 0,
},
{
account_id: 'my-k8s-cluster-5555',
resource_type: 'process',
resource_type_doc_count: 1,
resource_sub_type: 'process',
resource_sub_type_doc_count: 1,
passed_findings_count: 1,
failed_findings_count: 0,
},
]);
});
it(`'includes only KSPM findings without posture_type'`, async () => {
await index.add(telemetryMockData.kspmFindingsNoPostureType);
const {
body: [{ stats: apiResponse }],
} = await supertest
.post(`/internal/telemetry/clusters/_stats`)
.set('kbn-xsrf', 'xxxx')
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send({
unencrypted: true,
refreshCache: true,
})
.expect(200);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.accounts_stats).to.eql([
{
account_id: 'my-k8s-cluster-5555',
latest_findings_doc_count: 2,
posture_score: 100,
passed_findings_count: 2,
failed_findings_count: 0,
benchmark_name: 'CIS Kubernetes V1.23',
benchmark_id: 'cis_k8s',
benchmark_version: 'v1.0.0',
kubernetes_version: 'v1.23.0',
agents_count: 2,
nodes_count: 2,
pods_count: 0,
},
]);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.resources_stats).to.eql([
{
account_id: 'my-k8s-cluster-5555',
resource_type: 'k8s_object',
resource_type_doc_count: 1,
resource_sub_type: 'ServiceAccount',
resource_sub_type_doc_count: 1,
passed_findings_count: 1,
failed_findings_count: 0,
},
{
account_id: 'my-k8s-cluster-5555',
resource_type: 'process',
resource_type_doc_count: 1,
resource_sub_type: 'process',
resource_sub_type_doc_count: 1,
passed_findings_count: 1,
failed_findings_count: 0,
},
]);
});
it('includes KSPM findings without posture_type and CSPM findings as well', async () => {
await index.add(telemetryMockData.kspmFindingsNoPostureType);
await index.add(telemetryMockData.cspmFindings);
const {
body: [{ stats: apiResponse }],
} = await supertest
.post(`/internal/telemetry/clusters/_stats`)
.set('kbn-xsrf', 'xxxx')
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send({
unencrypted: true,
refreshCache: true,
})
.expect(200);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.accounts_stats).to.eql([
{
account_id: 'my-aws-12345',
latest_findings_doc_count: 2,
posture_score: 50,
passed_findings_count: 1,
failed_findings_count: 1,
benchmark_name: 'CIS Amazon Web Services Foundations',
benchmark_id: 'cis_aws',
benchmark_version: 'v1.5.0',
kubernetes_version: null,
agents_count: 1,
nodes_count: 1,
pods_count: 0,
},
{
account_id: 'my-k8s-cluster-5555',
latest_findings_doc_count: 2,
posture_score: 100,
passed_findings_count: 2,
failed_findings_count: 0,
benchmark_name: 'CIS Kubernetes V1.23',
benchmark_id: 'cis_k8s',
benchmark_version: 'v1.0.0',
kubernetes_version: 'v1.23.0',
agents_count: 2,
nodes_count: 2,
pods_count: 0,
},
]);
expect(apiResponse.stack_stats.kibana.plugins.cloud_security_posture.resources_stats).to.eql([
{
account_id: 'my-aws-12345',
resource_type: 'identifyingType',
resource_type_doc_count: 2,
resource_sub_type: 'aws-password-policy',
resource_sub_type_doc_count: 2,
passed_findings_count: 1,
failed_findings_count: 1,
},
{
account_id: 'my-k8s-cluster-5555',
resource_type: 'k8s_object',
resource_type_doc_count: 1,
resource_sub_type: 'ServiceAccount',
resource_sub_type_doc_count: 1,
passed_findings_count: 1,
failed_findings_count: 0,
},
{
account_id: 'my-k8s-cluster-5555',
resource_type: 'process',
resource_type_doc_count: 1,
resource_sub_type: 'process',
resource_sub_type_doc_count: 1,
passed_findings_count: 1,
failed_findings_count: 0,
},
]);
});
});
}

View file

@ -13,5 +13,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./telemetry/telemetry_config'));
loadTestFile(require.resolve('./fleet/fleet'));
loadTestFile(require.resolve('./cases'));
loadTestFile(require.resolve('./cloud_security_posture'));
});
}

View file

@ -61,6 +61,7 @@
"@kbn/serverless-observability-settings",
"@kbn/serverless-search-settings",
"@kbn/serverless-security-settings",
"@kbn/cloud-security-posture-plugin",
"@kbn/reporting-plugin",
"@kbn/management-settings-ids",
]