Skip to content

Commit

Permalink
[Cloud Security][FTR] FTR for GCP Orgs (elastic#168314)
Browse files Browse the repository at this point in the history
## Summary

This PR adds FTRs for GCP Organization option

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
animehart and kibanamachine authored Oct 12, 2023
1 parent 79e5c1e commit eefc275
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export interface CloudPostureIntegrationProps {
icon?: string;
tooltip?: string;
isBeta?: boolean;
testId?: string;
}>;
}

Expand All @@ -85,6 +86,7 @@ export const cloudPostureIntegrations: CloudPostureIntegrations = {
defaultMessage: 'CIS AWS',
}),
icon: 'logoAWS',
testId: 'cisAwsTestId',
},
{
type: CLOUDBEAT_GCP,
Expand All @@ -95,6 +97,7 @@ export const cloudPostureIntegrations: CloudPostureIntegrations = {
defaultMessage: 'CIS GCP',
}),
icon: googleCloudLogo,
testId: 'cisGcpTestId',
},
// needs to be a function that disables/enabled based on integration version
{
Expand All @@ -108,6 +111,7 @@ export const cloudPostureIntegrations: CloudPostureIntegrations = {
disabled: false,
isBeta: true,
icon: 'logoAzure',
testId: 'cisAzureTestId',
},
],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface CspRadioOption {
icon?: string;
tooltip?: string;
isBeta?: boolean;
testId?: string;
}

export const RadioGroup = ({
Expand All @@ -34,7 +35,6 @@ export const RadioGroup = ({
onChange,
}: CspRadioGroupProps) => {
const { euiTheme } = useEuiTheme();

return (
<div
css={css`
Expand Down Expand Up @@ -101,6 +101,7 @@ export const RadioGroup = ({
`}
>
<EuiRadio
data-test-subj={option.testId}
label={option.label}
id={option.id}
checked={isChecked}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,20 +233,23 @@ const getSetupFormatOptions = (): Array<{
id: SetupFormatGCP;
label: string;
disabled: boolean;
testId: string;
}> => [
{
id: SETUP_ACCESS_CLOUD_SHELL,
label: i18n.translate('xpack.csp.gcpIntegration.setupFormatOptions.googleCloudShell', {
defaultMessage: 'Google Cloud Shell',
}),
disabled: false,
testId: 'gcpGoogleCloudShellOptionTestId',
},
{
id: SETUP_ACCESS_MANUAL,
label: i18n.translate('xpack.csp.gcpIntegration.setupFormatOptions.manual', {
defaultMessage: 'Manual',
}),
disabled: false,
testId: 'gcpManualOptionTestId',
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,14 @@ const getGcpAccountTypeOptions = (isGcpOrgDisabled: boolean): CspRadioGroupProps
defaultMessage: 'Supported from integration version 1.6.0 and above',
})
: undefined,
testId: 'gcpOrganizationAccountTestId',
},
{
id: GCP_SINGLE_ACCOUNT,
label: i18n.translate('xpack.csp.fleetIntegration.gcpAccountType.gcpSingleAccountLabel', {
defaultMessage: 'Single Account',
}),
testId: 'gcpSingleAccountTestId',
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ export const getPolicyTemplateInputOptions = (policyTemplate: CloudSecurityPolic
icon: o.icon,
disabled: o.disabled,
isBeta: o.isBeta,
testId: o.testId,
}));

export const getMaxPackageName = (
Expand Down
2 changes: 1 addition & 1 deletion x-pack/test/cloud_security_posture_functional/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
* 2. merge the updated version number change to kibana
*/
`--xpack.fleet.packages.0.name=cloud_security_posture`,
`--xpack.fleet.packages.0.version=1.5.0`,
`--xpack.fleet.packages.0.version=1.6.0`,
// `--xpack.fleet.registryUrl=https://localhost:8080`,
],
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* 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 type { FtrProviderContext } from '../ftr_provider_context';

export function AddCisIntegrationFormPageProvider({
getService,
getPageObjects,
}: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['common', 'header']);

const cisGcp = {
getIntegrationFormEntirePage: () => testSubjects.find('dataCollectionSetupStep'),

getIntegrationPolicyTable: () => testSubjects.find('integrationPolicyTable'),

getIntegrationFormEditPage: () => testSubjects.find('editPackagePolicy_page'),

findOptionInPage: async (text: string) => {
await PageObjects.header.waitUntilLoadingHasFinished();
const optionToBeClicked = await testSubjects.find(text);
return await optionToBeClicked;
},

clickOptionButton: async (text: string) => {
const optionToBeClicked = await cisGcp.findOptionInPage(text);
await optionToBeClicked.click();
},

clickSaveButton: async () => {
const optionToBeClicked = await cisGcp.findOptionInPage('createPackagePolicySaveButton');
await optionToBeClicked.click();
},

getPostInstallModal: async () => {
return await testSubjects.find('confirmModalTitleText');
},

isPostInstallGoogleCloudShellModal: async (isOrg: boolean, orgID?: string, prjID?: string) => {
const googleCloudShellModal = await testSubjects.find('postInstallGoogleCloudShellModal');
const googleCloudShellModalVisibleText = await googleCloudShellModal.getVisibleText();
const stringProjectId = prjID ? prjID : '<PROJECT_ID>';
const stringOrganizationId = orgID ? `ORG_ID=${orgID}` : 'ORG_ID=<ORGANIZATION_ID>';
const orgIdExist = googleCloudShellModalVisibleText.includes(stringOrganizationId);
const prjIdExist = googleCloudShellModalVisibleText.includes(stringProjectId);

if (isOrg) {
return orgIdExist === true && prjIdExist === true;
} else {
return orgIdExist === false && prjIdExist === true;
}
},

checkGcpFieldExist: async (text: string) => {
const field = await testSubjects.findAll(text);
return field.length;
},

fillInTextField: async (selector: string, text: string) => {
const test = await testSubjects.find(selector);
await test.type(text);
},
};

const navigateToAddIntegrationCspmPage = async () => {
await PageObjects.common.navigateToUrl(
'fleet', // Defined in Security Solution plugin
'integrations/cloud_security_posture/add-integration/cspm',
{ shouldUseHashForSubUrl: false }
);
};

return {
cisGcp,
navigateToAddIntegrationCspmPage,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import { pageObjects as xpackFunctionalPageObjects } from '../../functional/page_objects';
import { FindingsPageProvider } from './findings_page';
import { CspDashboardPageProvider } from './csp_dashboard_page';
import { AddCisIntegrationFormPageProvider } from './add_cis_integration_form_page';
import { VulnerabilityDashboardPageProvider } from './vulnerability_dashboard_page_object';

export const cloudSecurityPosturePageObjects = {
findings: FindingsPageProvider,
cloudPostureDashboard: CspDashboardPageProvider,
cisAddIntegration: AddCisIntegrationFormPageProvider,
vulnerabilityDashboard: VulnerabilityDashboardPageProvider,
};
export const pageObjects = {
Expand Down
107 changes: 107 additions & 0 deletions x-pack/test/cloud_security_posture_functional/pages/cis_integration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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 { FtrProviderContext } from '../ftr_provider_context';

const CIS_GCP_OPTION_TEST_ID = 'cisGcpTestId';
const GCP_ORGANIZATION_TEST_ID = 'gcpOrganizationAccountTestId';
const GCP_SINGLE_ACCOUNT_TEST_ID = 'gcpSingleAccountTestId';
const GCP_CLOUD_SHELL_TEST_ID = 'gcpGoogleCloudShellOptionTestId';
const GCP_MANUAL_TEST_ID = 'gcpManualOptionTestId';
const PRJ_ID_TEST_ID = 'project_id_test_id';
const ORG_ID_TEST_ID = 'organization_id_test_id';
const CREDENTIALS_TYPE_TEST_ID = 'credentials_type_test_id';

// eslint-disable-next-line import/no-default-export
export default function (providerContext: FtrProviderContext) {
const { getPageObjects, getService } = providerContext;
const pageObjects = getPageObjects(['cloudPostureDashboard', 'cisAddIntegration', 'header']);
const kibanaServer = getService('kibanaServer');

describe('Test adding Cloud Security Posture Integrations', function () {
this.tags(['cloud_security_posture_cis_integration']);
let cisIntegrationGcp: typeof pageObjects.cisAddIntegration.cisGcp;
let cisIntegration: typeof pageObjects.cisAddIntegration;

beforeEach(async () => {
cisIntegration = pageObjects.cisAddIntegration;
cisIntegrationGcp = pageObjects.cisAddIntegration.cisGcp;

await cisIntegration.navigateToAddIntegrationCspmPage();
});

after(async () => {
await kibanaServer.savedObjects.cleanStandardList();
});

describe('CIS_GCP Organization', () => {
it('Switch between Manual and Google cloud shell', async () => {
await cisIntegrationGcp.clickOptionButton(CIS_GCP_OPTION_TEST_ID);
await cisIntegrationGcp.clickOptionButton(GCP_ORGANIZATION_TEST_ID);
await cisIntegrationGcp.clickOptionButton(GCP_MANUAL_TEST_ID);
/* Check for existing fields. In Manual, Credential field should be visible */
expect((await cisIntegrationGcp.checkGcpFieldExist(PRJ_ID_TEST_ID)) === 1).to.be(true);
expect((await cisIntegrationGcp.checkGcpFieldExist(ORG_ID_TEST_ID)) === 1).to.be(true);
expect((await cisIntegrationGcp.checkGcpFieldExist(CREDENTIALS_TYPE_TEST_ID)) === 1).to.be(
true
);

await cisIntegrationGcp.clickOptionButton(GCP_CLOUD_SHELL_TEST_ID);
/* Check for existing fields. In Google Cloud Shell, Credential field should NOT be visible */
expect((await cisIntegrationGcp.checkGcpFieldExist(PRJ_ID_TEST_ID)) === 1).to.be(true);
expect((await cisIntegrationGcp.checkGcpFieldExist(ORG_ID_TEST_ID)) === 1).to.be(true);
expect((await cisIntegrationGcp.checkGcpFieldExist(CREDENTIALS_TYPE_TEST_ID)) === 0).to.be(
true
);
});

it('Post Installation Google Cloud Shell modal pops up after user clicks on Save button when adding integration, when there are no Project ID or Organization ID provided, it should use default value', async () => {
await cisIntegrationGcp.clickOptionButton(CIS_GCP_OPTION_TEST_ID);
await cisIntegrationGcp.clickOptionButton(GCP_ORGANIZATION_TEST_ID);
await cisIntegrationGcp.clickOptionButton(GCP_CLOUD_SHELL_TEST_ID);
await cisIntegrationGcp.clickSaveButton();
pageObjects.header.waitUntilLoadingHasFinished();
expect((await cisIntegrationGcp.isPostInstallGoogleCloudShellModal(true)) === true).to.be(
true
);
});

it('Post Installation Google Cloud Shell modal pops up after user clicks on Save button when adding integration, when there are Project ID or Organization ID provided, it should use that value', async () => {
const projectName = 'PRJ_NAME_TEST';
const organizationName = 'ORG_NAME_TEST';
await cisIntegrationGcp.clickOptionButton(CIS_GCP_OPTION_TEST_ID);
await cisIntegrationGcp.clickOptionButton(GCP_ORGANIZATION_TEST_ID);
await cisIntegrationGcp.clickOptionButton(GCP_CLOUD_SHELL_TEST_ID);
await cisIntegrationGcp.fillInTextField('project_id_test_id', projectName);
await cisIntegrationGcp.fillInTextField('organization_id_test_id', organizationName);

await cisIntegrationGcp.clickSaveButton();
pageObjects.header.waitUntilLoadingHasFinished();
expect(
(await cisIntegrationGcp.isPostInstallGoogleCloudShellModal(
true,
organizationName,
projectName
)) === true
).to.be(true);
});

it('Organization ID field on cloud shell command should only be shown if user chose Google Cloud Shell, if user chose Single Account it shouldn not show up', async () => {
await cisIntegrationGcp.clickOptionButton(CIS_GCP_OPTION_TEST_ID);
await cisIntegrationGcp.clickOptionButton(GCP_SINGLE_ACCOUNT_TEST_ID);
await cisIntegrationGcp.clickOptionButton(GCP_CLOUD_SHELL_TEST_ID);

await cisIntegrationGcp.clickSaveButton();
pageObjects.header.waitUntilLoadingHasFinished();
expect((await cisIntegrationGcp.isPostInstallGoogleCloudShellModal(false)) === true).to.be(
true
);
});
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./findings_alerts'));
loadTestFile(require.resolve('./compliance_dashboard'));
loadTestFile(require.resolve('./vulnerability_dashboard'));
loadTestFile(require.resolve('./cis_integration'));
});
}

0 comments on commit eefc275

Please sign in to comment.