From 16f7fc62073c317dec51b8456e29cb6a0168a0ef Mon Sep 17 00:00:00 2001 From: Dmitry Gurevich <99176494+gurevichdmitry@users.noreply.github.com> Date: Sun, 19 May 2024 17:41:46 +0300 Subject: [PATCH 1/7] poc - adding basic ui sanity --- .../config.ts | 64 ++++++++--------- .../page_objects/csp_dashboard_page.ts | 25 +++++++ .../pages/basic_ui_sanity.ts | 71 +++++++++++++++++++ .../pages/index.ts | 37 +++++----- 4 files changed, 149 insertions(+), 48 deletions(-) create mode 100644 x-pack/test/cloud_security_posture_functional/pages/basic_ui_sanity.ts diff --git a/x-pack/test/cloud_security_posture_functional/config.ts b/x-pack/test/cloud_security_posture_functional/config.ts index bd2f1eb9d594dc..6127447d3c7cee 100644 --- a/x-pack/test/cloud_security_posture_functional/config.ts +++ b/x-pack/test/cloud_security_posture_functional/config.ts @@ -13,36 +13,36 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xpackFunctionalConfig = await readConfigFile( require.resolve('../functional/config.base.js') ); - - return { - ...xpackFunctionalConfig.getAll(), - pageObjects, - testFiles: [resolve(__dirname, './pages')], - junit: { - reportName: 'X-Pack Cloud Security Posture Functional Tests', - }, - kbnTestServer: { - ...xpackFunctionalConfig.get('kbnTestServer'), - serverArgs: [ - ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), - /** - * Package version is fixed (not latest) so FTR won't suddenly break when package is changed. - * - * test a new package: - * 1. build the package and start the registry with elastic-package and uncomment the 'registryUrl' flag below - * 2. locally checkout the kibana version that matches the new package - * 3. update the package version below to use the new package version - * 4. run tests with NODE_EXTRA_CA_CERTS pointing to the elastic-package certificate - * 5. when test pass: - * 1. release a new package to EPR - * 2. merge the updated version number change to kibana - */ - `--xpack.fleet.packages.0.name=cloud_security_posture`, - `--xpack.fleet.packages.0.version=1.7.4`, - // `--xpack.fleet.registryUrl=https://localhost:8080`, - `--xpack.fleet.agents.fleet_server.hosts=["https://ftr.kibana:8220"]`, - `--xpack.fleet.internal.fleetServerStandalone=true`, - ], - }, - }; + // If TEST_CLOUD environment varible is defined, return the configuration for cloud testing + if (process.env.TEST_CLOUD !== '1') { + return { + ...xpackFunctionalConfig.getAll(), + pageObjects, + testFiles: [resolve(__dirname, './pages')], + junit: { + reportName: 'X-Pack Cloud Security Posture Functional Tests', + }, + kbnTestServer: { + ...xpackFunctionalConfig.get('kbnTestServer'), + serverArgs: [ + ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), + `--xpack.fleet.packages.0.name=cloud_security_posture`, + `--xpack.fleet.packages.0.version=1.7.4`, + // `--xpack.fleet.registryUrl=https://localhost:8080`, + `--xpack.fleet.agents.fleet_server.hosts=["https://ftr.kibana:8220"]`, + `--xpack.fleet.internal.fleetServerStandalone=true`, + ], + }, + }; + } else { + // FTR configuration for cloud testing + return { + ...xpackFunctionalConfig.getAll(), + pageObjects, + testFiles: [resolve(__dirname, './pages')], + junit: { + reportName: 'X-Pack Cloud Security Posture Sanity Tests', + }, + }; + } } diff --git a/x-pack/test/cloud_security_posture_functional/page_objects/csp_dashboard_page.ts b/x-pack/test/cloud_security_posture_functional/page_objects/csp_dashboard_page.ts index 24a89549fb025b..4343662e32efdb 100644 --- a/x-pack/test/cloud_security_posture_functional/page_objects/csp_dashboard_page.ts +++ b/x-pack/test/cloud_security_posture_functional/page_objects/csp_dashboard_page.ts @@ -96,11 +96,26 @@ export function CspDashboardPageProvider({ getService, getPageObjects }: FtrProv return await testSubjects.find('dashboard-summary-section'); }, + getAllCloudComplianceScores: async () => { + await dashboard.getCloudDashboard(); + return await testSubjects.findAll('dashboard-summary-section-compliance-score'); + }, + getCloudComplianceScore: async () => { await dashboard.getCloudSummarySection(); return await testSubjects.find('dashboard-summary-section-compliance-score'); }, + getCloudResourcesEvaluatedCard: async () => { + await dashboard.getCloudDashboard(); + return await testSubjects.find('dashboard-counter-card-resources-evaluated'); + }, + + getCloudResourcesEvaluated: async () => { + const resourcesEvaluatedCard = await dashboard.getCloudResourcesEvaluatedCard(); + return await resourcesEvaluatedCard.findByXpath('//div/p/span'); + }, + // Kubernetes Dashboard getKubernetesDashboard: async () => { @@ -121,6 +136,16 @@ export function CspDashboardPageProvider({ getService, getPageObjects }: FtrProv return await testSubjects.find('dashboard-summary-section-compliance-score'); }, + + getKubernetesResourcesEvaluatedCard: async () => { + await dashboard.getKubernetesDashboard(); + return await testSubjects.find('dashboard-counter-card-resources-evaluated'); + }, + + getKubernetesResourcesEvaluated: async () => { + const resourcesEvaluatedCard = await dashboard.getKubernetesResourcesEvaluatedCard(); + return await resourcesEvaluatedCard.findByXpath('//div/p/span'); + }, }; const navigateToComplianceDashboardPage = async () => { diff --git a/x-pack/test/cloud_security_posture_functional/pages/basic_ui_sanity.ts b/x-pack/test/cloud_security_posture_functional/pages/basic_ui_sanity.ts new file mode 100644 index 00000000000000..29378530745598 --- /dev/null +++ b/x-pack/test/cloud_security_posture_functional/pages/basic_ui_sanity.ts @@ -0,0 +1,71 @@ +/* + * 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 { FtrProviderContext } from '../ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const retry = getService('retry'); + const pageObjects = getPageObjects(['common', 'cloudPostureDashboard', 'header']); + + describe('Cloud Posture Dashboard Page', function () { + this.tags(['cloud_security_posture_ui_sanity']); + let cspDashboard: typeof pageObjects.cloudPostureDashboard; + let dashboard: typeof pageObjects.cloudPostureDashboard.dashboard; + + before(async () => { + cspDashboard = pageObjects.cloudPostureDashboard; + dashboard = pageObjects.cloudPostureDashboard.dashboard; + await cspDashboard.waitForPluginInitialized(); + await cspDashboard.navigateToComplianceDashboardPage(); + await retry.waitFor( + 'Cloud posture integration dashboard to be displayed', + async () => !!dashboard.getIntegrationDashboardContainer() + ); + }); + + describe('Cloud Dashboard', () => { + it('displays accurate summary compliance score', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + const scoreElement = await dashboard.getCloudComplianceScore(); + expect((await scoreElement.getVisibleText()) === '41%').to.be(true); + }); + + it('displays accurate all complience scores', async () => { + const scoresElements = await dashboard.getAllCloudComplianceScores(); + const scores: string[] = []; + for (const scoreElement of scoresElements) { + scores.push(await scoreElement.getVisibleText()); + } + // 3 scores for each cloud provider + 1 summary score + expect(scores.length).to.be(4); + const expectedScores = ['41%', '14%', '55%', '59%']; + scores.forEach((score) => { + expect(expectedScores).contain(score); + }); + }); + + it('displays correct number of resources evaluated', async () => { + const resourcesEvaluated = await dashboard.getCloudResourcesEvaluated(); + expect((await resourcesEvaluated.getVisibleText()) === '3,342').to.be(true); + }); + }); + + describe('Kubernetes Dashboard', () => { + it('displays accurate summary compliance score', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + const scoreElement = await dashboard.getKubernetesComplianceScore(); + expect((await scoreElement.getVisibleText()) === '83%').to.be(true); + }); + + it('displays correct number of resources evaluated', async () => { + const resourcesEvaluated = await dashboard.getKubernetesResourcesEvaluated(); + expect((await resourcesEvaluated.getVisibleText()) === '199').to.be(true); + }); + }); + }); +}; diff --git a/x-pack/test/cloud_security_posture_functional/pages/index.ts b/x-pack/test/cloud_security_posture_functional/pages/index.ts index a1f9177f05c086..a59140c04d0e78 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/index.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/index.ts @@ -10,21 +10,26 @@ import { FtrProviderContext } from '../ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ loadTestFile }: FtrProviderContext) { describe('Cloud Security Posture', function () { - loadTestFile(require.resolve('./rules')); - loadTestFile(require.resolve('./findings_onboarding')); - loadTestFile(require.resolve('./findings')); - loadTestFile(require.resolve('./findings_grouping')); - loadTestFile(require.resolve('./findings_alerts')); - loadTestFile(require.resolve('./compliance_dashboard')); - loadTestFile(require.resolve('./vulnerability_dashboard')); - loadTestFile(require.resolve('./cis_integrations/cnvm/cis_integration_cnvm')); - loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_aws')); - loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_gcp')); - loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_azure')); - loadTestFile(require.resolve('./cis_integrations/kspm/cis_integration_k8s')); - loadTestFile(require.resolve('./cis_integrations/kspm/cis_integration_eks')); - loadTestFile(require.resolve('./findings_old_data')); - loadTestFile(require.resolve('./vulnerabilities')); - loadTestFile(require.resolve('./vulnerabilities_grouping')); + if (process.env.TEST_CLOUD === '1') { + // Run basic UI sanity tests only in cloud testing + loadTestFile(require.resolve('./basic_ui_sanity')); + } else { + loadTestFile(require.resolve('./rules')); + loadTestFile(require.resolve('./findings_onboarding')); + loadTestFile(require.resolve('./findings')); + loadTestFile(require.resolve('./findings_grouping')); + loadTestFile(require.resolve('./findings_alerts')); + loadTestFile(require.resolve('./compliance_dashboard')); + loadTestFile(require.resolve('./vulnerability_dashboard')); + loadTestFile(require.resolve('./cis_integrations/cnvm/cis_integration_cnvm')); + loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_aws')); + loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_gcp')); + loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_azure')); + loadTestFile(require.resolve('./cis_integrations/kspm/cis_integration_k8s')); + loadTestFile(require.resolve('./cis_integrations/kspm/cis_integration_eks')); + loadTestFile(require.resolve('./findings_old_data')); + loadTestFile(require.resolve('./vulnerabilities')); + loadTestFile(require.resolve('./vulnerabilities_grouping')); + } }); } From f4e644e8e5f3e31ecb2e2cb14d0f4ed1991b71cc Mon Sep 17 00:00:00 2001 From: Dmitry Gurevich <99176494+gurevichdmitry@users.noreply.github.com> Date: Mon, 20 May 2024 09:56:36 +0300 Subject: [PATCH 2/7] review comments fix --- .buildkite/ftr_configs.yml | 1 + .../cloud_tests/basic_ui_sanity.ts | 71 +++++++++++++++++++ .../cloud_tests/index.ts | 15 ++++ .../config.cloud.ts | 25 +++++++ .../config.ts | 51 +++++-------- 5 files changed, 131 insertions(+), 32 deletions(-) create mode 100644 x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts create mode 100644 x-pack/test/cloud_security_posture_functional/cloud_tests/index.ts create mode 100644 x-pack/test/cloud_security_posture_functional/config.cloud.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 5b1734613c0f60..c0f60dc43ca48b 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -24,6 +24,7 @@ disabled: - x-pack/test/upgrade/config.ts - test/functional/config.edge.js - x-pack/test/functional/config.edge.js + - x-pack/test/cloud_security_posture_functional/config.cloud.ts # Cypress configs, for now these are still run manually - x-pack/test/fleet_cypress/cli_config.ts diff --git a/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts b/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts new file mode 100644 index 00000000000000..df3bc0ce2563a6 --- /dev/null +++ b/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts @@ -0,0 +1,71 @@ +/* + * 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 { FtrProviderContext } from '../ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const retry = getService('retry'); + const pageObjects = getPageObjects(['common', 'cloudPostureDashboard', 'header']); + + describe('Cloud Posture Dashboard Page', function () { + this.tags(['cloud_security_posture_ui_sanity']); + let cspDashboard: typeof pageObjects.cloudPostureDashboard; + let dashboard: typeof pageObjects.cloudPostureDashboard.dashboard; + + before(async () => { + cspDashboard = pageObjects.cloudPostureDashboard; + dashboard = pageObjects.cloudPostureDashboard.dashboard; + await cspDashboard.waitForPluginInitialized(); + await cspDashboard.navigateToComplianceDashboardPage(); + await retry.waitFor( + 'Cloud posture integration dashboard to be displayed', + async () => !!dashboard.getIntegrationDashboardContainer() + ); + }); + + describe('Cloud Dashboard', () => { + it('displays accurate summary compliance score', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + const scoreElement = await dashboard.getCloudComplianceScore(); + expect((await scoreElement.getVisibleText()) === '41%').to.be(true); + }); + + it('displays accurate all complience scores', async () => { + const scoresElements = await dashboard.getAllCloudComplianceScores(); + const scores: string[] = []; + for (const scoreElement of scoresElements) { + scores.push(await scoreElement.getVisibleText()); + } + // 3 scores for each cloud provider + 1 summary score + expect(scores.length).to.be(4); + const expectedScores = ['41%', '14%', '55%', '59%']; + scores.forEach((score) => { + expect(expectedScores).contain(score); + }); + }); + + it('displays correct number of resources evaluated', async () => { + const resourcesEvaluated = await dashboard.getCloudResourcesEvaluated(); + expect((await resourcesEvaluated.getVisibleText()) === '3,339').to.be(true); + }); + }); + + describe('Kubernetes Dashboard', () => { + it('displays accurate summary compliance score', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + const scoreElement = await dashboard.getKubernetesComplianceScore(); + expect((await scoreElement.getVisibleText()) === '83%').to.be(true); + }); + + it('displays correct number of resources evaluated', async () => { + const resourcesEvaluated = await dashboard.getKubernetesResourcesEvaluated(); + expect((await resourcesEvaluated.getVisibleText()) === '199').to.be(true); + }); + }); + }); +}; diff --git a/x-pack/test/cloud_security_posture_functional/cloud_tests/index.ts b/x-pack/test/cloud_security_posture_functional/cloud_tests/index.ts new file mode 100644 index 00000000000000..b08970ccaed13f --- /dev/null +++ b/x-pack/test/cloud_security_posture_functional/cloud_tests/index.ts @@ -0,0 +1,15 @@ +/* + * 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'; + +// eslint-disable-next-line import/no-default-export +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Cloud Security Posture', function () { + loadTestFile(require.resolve('./basic_ui_sanity')); + }); +} diff --git a/x-pack/test/cloud_security_posture_functional/config.cloud.ts b/x-pack/test/cloud_security_posture_functional/config.cloud.ts new file mode 100644 index 00000000000000..1fc18baeba7434 --- /dev/null +++ b/x-pack/test/cloud_security_posture_functional/config.cloud.ts @@ -0,0 +1,25 @@ +/* + * 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 { resolve } from 'path'; +import type { FtrConfigProviderContext } from '@kbn/test'; +import { pageObjects } from './page_objects'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); + // FTR configuration for cloud testing + return { + ...xpackFunctionalConfig.getAll(), + pageObjects, + testFiles: [resolve(__dirname, './cloud_tests')], + junit: { + reportName: 'X-Pack Cloud Security Posture Sanity Tests', + }, + }; +} diff --git a/x-pack/test/cloud_security_posture_functional/config.ts b/x-pack/test/cloud_security_posture_functional/config.ts index 6127447d3c7cee..730c46e6e78049 100644 --- a/x-pack/test/cloud_security_posture_functional/config.ts +++ b/x-pack/test/cloud_security_posture_functional/config.ts @@ -13,36 +13,23 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xpackFunctionalConfig = await readConfigFile( require.resolve('../functional/config.base.js') ); - // If TEST_CLOUD environment varible is defined, return the configuration for cloud testing - if (process.env.TEST_CLOUD !== '1') { - return { - ...xpackFunctionalConfig.getAll(), - pageObjects, - testFiles: [resolve(__dirname, './pages')], - junit: { - reportName: 'X-Pack Cloud Security Posture Functional Tests', - }, - kbnTestServer: { - ...xpackFunctionalConfig.get('kbnTestServer'), - serverArgs: [ - ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), - `--xpack.fleet.packages.0.name=cloud_security_posture`, - `--xpack.fleet.packages.0.version=1.7.4`, - // `--xpack.fleet.registryUrl=https://localhost:8080`, - `--xpack.fleet.agents.fleet_server.hosts=["https://ftr.kibana:8220"]`, - `--xpack.fleet.internal.fleetServerStandalone=true`, - ], - }, - }; - } else { - // FTR configuration for cloud testing - return { - ...xpackFunctionalConfig.getAll(), - pageObjects, - testFiles: [resolve(__dirname, './pages')], - junit: { - reportName: 'X-Pack Cloud Security Posture Sanity Tests', - }, - }; - } + return { + ...xpackFunctionalConfig.getAll(), + pageObjects, + testFiles: [resolve(__dirname, './pages')], + junit: { + reportName: 'X-Pack Cloud Security Posture Functional Tests', + }, + kbnTestServer: { + ...xpackFunctionalConfig.get('kbnTestServer'), + serverArgs: [ + ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), + `--xpack.fleet.packages.0.name=cloud_security_posture`, + `--xpack.fleet.packages.0.version=1.7.4`, + // `--xpack.fleet.registryUrl=https://localhost:8080`, + `--xpack.fleet.agents.fleet_server.hosts=["https://ftr.kibana:8220"]`, + `--xpack.fleet.internal.fleetServerStandalone=true`, + ], + }, + }; } From 993189d0c2effebbd2c81477461ded105fe7b5e3 Mon Sep 17 00:00:00 2001 From: Dmitry Gurevich <99176494+gurevichdmitry@users.noreply.github.com> Date: Mon, 20 May 2024 10:05:35 +0300 Subject: [PATCH 3/7] fix review comments --- .../config.ts | 13 ++++ .../pages/basic_ui_sanity.ts | 71 ------------------- .../pages/index.ts | 37 +++++----- 3 files changed, 29 insertions(+), 92 deletions(-) delete mode 100644 x-pack/test/cloud_security_posture_functional/pages/basic_ui_sanity.ts diff --git a/x-pack/test/cloud_security_posture_functional/config.ts b/x-pack/test/cloud_security_posture_functional/config.ts index 730c46e6e78049..4ba1fd6ca64be6 100644 --- a/x-pack/test/cloud_security_posture_functional/config.ts +++ b/x-pack/test/cloud_security_posture_functional/config.ts @@ -13,6 +13,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xpackFunctionalConfig = await readConfigFile( require.resolve('../functional/config.base.js') ); + return { ...xpackFunctionalConfig.getAll(), pageObjects, @@ -22,6 +23,18 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { }, kbnTestServer: { ...xpackFunctionalConfig.get('kbnTestServer'), + /** + * Package version is fixed (not latest) so FTR won't suddenly break when package is changed. + * + * test a new package: + * 1. build the package and start the registry with elastic-package and uncomment the 'registryUrl' flag below + * 2. locally checkout the kibana version that matches the new package + * 3. update the package version below to use the new package version + * 4. run tests with NODE_EXTRA_CA_CERTS pointing to the elastic-package certificate + * 5. when test pass: + * 1. release a new package to EPR + * 2. merge the updated version number change to kibana + */ serverArgs: [ ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), `--xpack.fleet.packages.0.name=cloud_security_posture`, diff --git a/x-pack/test/cloud_security_posture_functional/pages/basic_ui_sanity.ts b/x-pack/test/cloud_security_posture_functional/pages/basic_ui_sanity.ts deleted file mode 100644 index 29378530745598..00000000000000 --- a/x-pack/test/cloud_security_posture_functional/pages/basic_ui_sanity.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 { FtrProviderContext } from '../ftr_provider_context'; - -// eslint-disable-next-line import/no-default-export -export default ({ getPageObjects, getService }: FtrProviderContext) => { - const retry = getService('retry'); - const pageObjects = getPageObjects(['common', 'cloudPostureDashboard', 'header']); - - describe('Cloud Posture Dashboard Page', function () { - this.tags(['cloud_security_posture_ui_sanity']); - let cspDashboard: typeof pageObjects.cloudPostureDashboard; - let dashboard: typeof pageObjects.cloudPostureDashboard.dashboard; - - before(async () => { - cspDashboard = pageObjects.cloudPostureDashboard; - dashboard = pageObjects.cloudPostureDashboard.dashboard; - await cspDashboard.waitForPluginInitialized(); - await cspDashboard.navigateToComplianceDashboardPage(); - await retry.waitFor( - 'Cloud posture integration dashboard to be displayed', - async () => !!dashboard.getIntegrationDashboardContainer() - ); - }); - - describe('Cloud Dashboard', () => { - it('displays accurate summary compliance score', async () => { - await pageObjects.header.waitUntilLoadingHasFinished(); - const scoreElement = await dashboard.getCloudComplianceScore(); - expect((await scoreElement.getVisibleText()) === '41%').to.be(true); - }); - - it('displays accurate all complience scores', async () => { - const scoresElements = await dashboard.getAllCloudComplianceScores(); - const scores: string[] = []; - for (const scoreElement of scoresElements) { - scores.push(await scoreElement.getVisibleText()); - } - // 3 scores for each cloud provider + 1 summary score - expect(scores.length).to.be(4); - const expectedScores = ['41%', '14%', '55%', '59%']; - scores.forEach((score) => { - expect(expectedScores).contain(score); - }); - }); - - it('displays correct number of resources evaluated', async () => { - const resourcesEvaluated = await dashboard.getCloudResourcesEvaluated(); - expect((await resourcesEvaluated.getVisibleText()) === '3,342').to.be(true); - }); - }); - - describe('Kubernetes Dashboard', () => { - it('displays accurate summary compliance score', async () => { - await pageObjects.header.waitUntilLoadingHasFinished(); - const scoreElement = await dashboard.getKubernetesComplianceScore(); - expect((await scoreElement.getVisibleText()) === '83%').to.be(true); - }); - - it('displays correct number of resources evaluated', async () => { - const resourcesEvaluated = await dashboard.getKubernetesResourcesEvaluated(); - expect((await resourcesEvaluated.getVisibleText()) === '199').to.be(true); - }); - }); - }); -}; diff --git a/x-pack/test/cloud_security_posture_functional/pages/index.ts b/x-pack/test/cloud_security_posture_functional/pages/index.ts index a59140c04d0e78..a1f9177f05c086 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/index.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/index.ts @@ -10,26 +10,21 @@ import { FtrProviderContext } from '../ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ loadTestFile }: FtrProviderContext) { describe('Cloud Security Posture', function () { - if (process.env.TEST_CLOUD === '1') { - // Run basic UI sanity tests only in cloud testing - loadTestFile(require.resolve('./basic_ui_sanity')); - } else { - loadTestFile(require.resolve('./rules')); - loadTestFile(require.resolve('./findings_onboarding')); - loadTestFile(require.resolve('./findings')); - loadTestFile(require.resolve('./findings_grouping')); - loadTestFile(require.resolve('./findings_alerts')); - loadTestFile(require.resolve('./compliance_dashboard')); - loadTestFile(require.resolve('./vulnerability_dashboard')); - loadTestFile(require.resolve('./cis_integrations/cnvm/cis_integration_cnvm')); - loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_aws')); - loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_gcp')); - loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_azure')); - loadTestFile(require.resolve('./cis_integrations/kspm/cis_integration_k8s')); - loadTestFile(require.resolve('./cis_integrations/kspm/cis_integration_eks')); - loadTestFile(require.resolve('./findings_old_data')); - loadTestFile(require.resolve('./vulnerabilities')); - loadTestFile(require.resolve('./vulnerabilities_grouping')); - } + loadTestFile(require.resolve('./rules')); + loadTestFile(require.resolve('./findings_onboarding')); + loadTestFile(require.resolve('./findings')); + loadTestFile(require.resolve('./findings_grouping')); + loadTestFile(require.resolve('./findings_alerts')); + loadTestFile(require.resolve('./compliance_dashboard')); + loadTestFile(require.resolve('./vulnerability_dashboard')); + loadTestFile(require.resolve('./cis_integrations/cnvm/cis_integration_cnvm')); + loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_aws')); + loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_gcp')); + loadTestFile(require.resolve('./cis_integrations/cspm/cis_integration_azure')); + loadTestFile(require.resolve('./cis_integrations/kspm/cis_integration_k8s')); + loadTestFile(require.resolve('./cis_integrations/kspm/cis_integration_eks')); + loadTestFile(require.resolve('./findings_old_data')); + loadTestFile(require.resolve('./vulnerabilities')); + loadTestFile(require.resolve('./vulnerabilities_grouping')); }); } From b72489091e2b4be30f9324fd6eee4e14bab30ada Mon Sep 17 00:00:00 2001 From: Dmitry Gurevich <99176494+gurevichdmitry@users.noreply.github.com> Date: Mon, 20 May 2024 10:12:08 +0300 Subject: [PATCH 4/7] revert config file --- .../config.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/x-pack/test/cloud_security_posture_functional/config.ts b/x-pack/test/cloud_security_posture_functional/config.ts index 4ba1fd6ca64be6..bd2f1eb9d594dc 100644 --- a/x-pack/test/cloud_security_posture_functional/config.ts +++ b/x-pack/test/cloud_security_posture_functional/config.ts @@ -23,20 +23,20 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { }, kbnTestServer: { ...xpackFunctionalConfig.get('kbnTestServer'), - /** - * Package version is fixed (not latest) so FTR won't suddenly break when package is changed. - * - * test a new package: - * 1. build the package and start the registry with elastic-package and uncomment the 'registryUrl' flag below - * 2. locally checkout the kibana version that matches the new package - * 3. update the package version below to use the new package version - * 4. run tests with NODE_EXTRA_CA_CERTS pointing to the elastic-package certificate - * 5. when test pass: - * 1. release a new package to EPR - * 2. merge the updated version number change to kibana - */ serverArgs: [ ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), + /** + * Package version is fixed (not latest) so FTR won't suddenly break when package is changed. + * + * test a new package: + * 1. build the package and start the registry with elastic-package and uncomment the 'registryUrl' flag below + * 2. locally checkout the kibana version that matches the new package + * 3. update the package version below to use the new package version + * 4. run tests with NODE_EXTRA_CA_CERTS pointing to the elastic-package certificate + * 5. when test pass: + * 1. release a new package to EPR + * 2. merge the updated version number change to kibana + */ `--xpack.fleet.packages.0.name=cloud_security_posture`, `--xpack.fleet.packages.0.version=1.7.4`, // `--xpack.fleet.registryUrl=https://localhost:8080`, From 116e4efc3badfd2be685854a97942e4fa4b29ca5 Mon Sep 17 00:00:00 2001 From: Dmitry Gurevich <99176494+gurevichdmitry@users.noreply.github.com> Date: Mon, 20 May 2024 16:09:33 +0300 Subject: [PATCH 5/7] update test cases --- .../cloud_tests/basic_ui_sanity.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts b/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts index df3bc0ce2563a6..edc5d6f6f5136a 100644 --- a/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts +++ b/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts @@ -35,7 +35,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect((await scoreElement.getVisibleText()) === '41%').to.be(true); }); - it('displays accurate all complience scores', async () => { + it('displays all compliance scores', async () => { const scoresElements = await dashboard.getAllCloudComplianceScores(); const scores: string[] = []; for (const scoreElement of scoresElements) { @@ -43,15 +43,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { } // 3 scores for each cloud provider + 1 summary score expect(scores.length).to.be(4); - const expectedScores = ['41%', '14%', '55%', '59%']; - scores.forEach((score) => { - expect(expectedScores).contain(score); - }); }); - it('displays correct number of resources evaluated', async () => { + it('displays a number of resources evaluated', async () => { const resourcesEvaluated = await dashboard.getCloudResourcesEvaluated(); - expect((await resourcesEvaluated.getVisibleText()) === '3,339').to.be(true); + const visibleText = await resourcesEvaluated.getVisibleText(); + const resourcesEvaluatedCount = parseInt(visibleText.replace(/,/g, ''), 10); + expect(resourcesEvaluatedCount).greaterThan(3000); }); }); From f9be95355d0600d5f9b8792c768804cebb4ff797 Mon Sep 17 00:00:00 2001 From: Dmitry Gurevich <99176494+gurevichdmitry@users.noreply.github.com> Date: Thu, 23 May 2024 08:42:23 +0300 Subject: [PATCH 6/7] add readme file --- .../cloud_tests/README.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 x-pack/test/cloud_security_posture_functional/cloud_tests/README.md diff --git a/x-pack/test/cloud_security_posture_functional/cloud_tests/README.md b/x-pack/test/cloud_security_posture_functional/cloud_tests/README.md new file mode 100644 index 00000000000000..ce67cefa1022aa --- /dev/null +++ b/x-pack/test/cloud_security_posture_functional/cloud_tests/README.md @@ -0,0 +1,24 @@ +## Tests Development Process + +**Preparation** + +- **Environment Deployment** - Initially, to start tests development, deploy the environment using the [Create Environment](https://github.com/elastic/cloudbeat/blob/main/dev-docs/Cloud-Env-Testing.md) workflow. + +- **Configuration & Run** - After provisioning the environment, configure the FTR environment variables accordingly. At a minimum, configure the following variables: TEST_KIBANA_URL, TEST_ES_URL, TEST_CLOUD, ES_SECURITY_ENABLED. More information can be found in the [FTR documentation](https://www.elastic.co/guide/en/kibana/current/development-tests.html#development-functional-tests). Note that URLs should contain the user and password. + +``` bash +export TEST_KIBANA_URL=https://elastic:password@my-kbn-cluster.elastic-cloud.com:443 +export TEST_ES_URL=https://elastic:password@my-es-cluster.elastic-cloud.com:443 + +export TEST_CLOUD=1 +export ES_SECURITY_ENABLED=1 + +node scripts/functional_test_runner [--config ] [--es-version ] +``` + +- **Suite Config** - The config file is located here: `x-pack/test/cloud_security_posture_functional/config.cloud.ts`. + + +**Final Testing on Demand** + +After finishing the implementation and ensuring that the whole suite is working locally, proceed to execution in the Create Environment workflow. [This PR](https://github.com/elastic/cloudbeat/pull/2219) adds the feature to run UI tests. To do this, open a PR in Kibana, then find the PR commit and apply it in the Create Environment workflow for the final end-to-end process. This process takes time, so proceed only after a few local runs to ensure test stability. \ No newline at end of file From b968f695d54867ef54d56964fc10946542ac295f Mon Sep 17 00:00:00 2001 From: Dmitry Gurevich <99176494+gurevichdmitry@users.noreply.github.com> Date: Sun, 2 Jun 2024 14:22:39 +0300 Subject: [PATCH 7/7] update tests --- .../cloud_tests/basic_ui_sanity.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts b/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts index edc5d6f6f5136a..495105017e5c22 100644 --- a/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts +++ b/x-pack/test/cloud_security_posture_functional/cloud_tests/basic_ui_sanity.ts @@ -29,10 +29,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); describe('Cloud Dashboard', () => { - it('displays accurate summary compliance score', async () => { + it('displays compliance score greater than 40', async () => { await pageObjects.header.waitUntilLoadingHasFinished(); const scoreElement = await dashboard.getCloudComplianceScore(); - expect((await scoreElement.getVisibleText()) === '41%').to.be(true); + const score = parseInt((await scoreElement.getVisibleText()).replace('%', ''), 10); + expect(score).to.be.greaterThan(40); }); it('displays all compliance scores', async () => { @@ -45,7 +46,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(scores.length).to.be(4); }); - it('displays a number of resources evaluated', async () => { + it('displays a number of resources evaluated greater than 3000', async () => { const resourcesEvaluated = await dashboard.getCloudResourcesEvaluated(); const visibleText = await resourcesEvaluated.getVisibleText(); const resourcesEvaluatedCount = parseInt(visibleText.replace(/,/g, ''), 10); @@ -54,15 +55,20 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); describe('Kubernetes Dashboard', () => { - it('displays accurate summary compliance score', async () => { + it('displays compliance score greater than 80', async () => { await pageObjects.header.waitUntilLoadingHasFinished(); const scoreElement = await dashboard.getKubernetesComplianceScore(); - expect((await scoreElement.getVisibleText()) === '83%').to.be(true); + const score = parseInt((await scoreElement.getVisibleText()).replace('%', ''), 10); + expect(score).to.be.greaterThan(80); }); - it('displays correct number of resources evaluated', async () => { + it('displays a number of resources evaluated greater than 150', async () => { const resourcesEvaluated = await dashboard.getKubernetesResourcesEvaluated(); - expect((await resourcesEvaluated.getVisibleText()) === '199').to.be(true); + const resourcesEvaluatedCount = parseInt( + (await resourcesEvaluated.getVisibleText()).replace(/,/g, ''), + 10 + ); + expect(resourcesEvaluatedCount).greaterThan(150); }); }); });