Skip to content

Commit

Permalink
[Cloud Security] Render Setup Technology Selector based on deployment…
Browse files Browse the repository at this point in the history
… mode (#194347)
  • Loading branch information
seanrathier authored Oct 9, 2024
1 parent d0fb004 commit 2609a53
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 61 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/cloud_security_posture/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,4 @@ export const SINGLE_ACCOUNT = 'single-account';

export const CLOUD_SECURITY_PLUGIN_VERSION = '1.9.0';
// Cloud Credentials Template url was implemented in 1.10.0-preview01. See PR - https://github.com/elastic/integrations/pull/9828
export const CLOUD_CREDENTIALS_PACKAGE_VERSION = '1.10.0-preview01';
export const CLOUD_CREDENTIALS_PACKAGE_VERSION = '1.11.0-preview10';
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ export const CspPolicyTemplateForm = memo<PackagePolicyReplaceDefineStepExtensio
const integration = SUPPORTED_POLICY_TEMPLATES.includes(integrationParam)
? integrationParam
: undefined;
const isParentSecurityPosture = !integration;
// Handling validation state
const [isValid, setIsValid] = useState(true);
const { cloud } = useKibana().services;
Expand Down Expand Up @@ -798,6 +799,12 @@ export const CspPolicyTemplateForm = memo<PackagePolicyReplaceDefineStepExtensio
// Required for mount only to ensure a single input type is selected
// This will remove errors in validationResults.vars
setEnabledPolicyInput(DEFAULT_INPUT_TYPE[input.policy_template]);

// When the integration is the parent Security Posture (!integration) we need to
// reset the setup technology when the integration option changes if it was set to agentless for CSPM
if (isParentSecurityPosture && input.policy_template !== 'cspm') {
updateSetupTechnology(SetupTechnology.AGENT_BASED);
}
refetch();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoading, input.policy_template, isEditPage]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ export const PolicyTemplateSelector = ({
</EuiText>
<EuiSpacer size="m" />
<RadioGroup
options={Array.from(policyTemplates, (v) => ({ id: v, label: getPolicyTemplateLabel(v) }))}
options={Array.from(policyTemplates, (v) => ({
id: v,
label: getPolicyTemplateLabel(v),
testId: `policy-template-radio-button-${v}`,
}))}
idSelected={selectedTemplate}
onChange={(id: CloudSecurityPolicyTemplate) => setPolicyTemplate(id)}
disabled={disabled}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export const useSetupTechnology = ({
const isAgentlessSupportedForCloudProvider = isCspmAws || isCspmGcp || isCspmAzure;
const isAgentlessAvailable = isAgentlessSupportedForCloudProvider && isAgentlessEnabled;
const defaultSetupTechnology =
isEditPage && isAgentlessEnabled ? SetupTechnology.AGENTLESS : SetupTechnology.AGENT_BASED;
isEditPage && isAgentlessAvailable ? SetupTechnology.AGENTLESS : SetupTechnology.AGENT_BASED;

const [setupTechnology, setSetupTechnology] = useState<SetupTechnology>(defaultSetupTechnology);

const updateSetupTechnology = (value: SetupTechnology) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
"'package-policy-create' and 'package-policy-replace-define-step' cannot both be registered as UI extensions"
);
}
const { isAgentlessEnabled, isAgentlessIntegration } = useAgentless();
const { isAgentlessIntegration } = useAgentless();
const { handleSetupTechnologyChange, selectedSetupTechnology } = useSetupTechnology({
newAgentPolicy,
setNewAgentPolicy,
Expand All @@ -374,7 +374,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
validationResults={validationResults}
isEditPage={false}
handleSetupTechnologyChange={handleSetupTechnologyChange}
isAgentlessEnabled={isAgentlessEnabled}
isAgentlessEnabled={isAgentlessIntegration(packageInfo)}
/>
</ExtensionWrapper>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const EditPackagePolicyForm = memo<{
} = useConfig();
const { getHref } = useLink();
const { canUseMultipleAgentPolicies } = useMultipleAgentPolicies();
const { isAgentlessAgentPolicy } = useAgentless();
const { isAgentlessAgentPolicy, isAgentlessIntegration } = useAgentless();
const {
// data
agentPolicies: existingAgentPolicies,
Expand All @@ -130,9 +130,10 @@ export const EditPackagePolicyForm = memo<{
const hasAgentlessAgentPolicy = useMemo(
() =>
existingAgentPolicies.length === 1
? existingAgentPolicies.some((policy) => isAgentlessAgentPolicy(policy))
? existingAgentPolicies.some((policy) => isAgentlessAgentPolicy(policy)) &&
isAgentlessIntegration(packageInfo)
: false,
[existingAgentPolicies, isAgentlessAgentPolicy]
[existingAgentPolicies, isAgentlessAgentPolicy, packageInfo, isAgentlessIntegration]
);

const canWriteIntegrationPolicies = useAuthz().integrations.writeIntegrationPolicies;
Expand Down
16 changes: 16 additions & 0 deletions x-pack/test/cloud_security_posture_functional/agentless/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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('./create_agent'));
loadTestFile(require.resolve('./security_posture'));
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 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 { CLOUD_CREDENTIALS_PACKAGE_VERSION } from '@kbn/cloud-security-posture-plugin/common/constants';
import expect from '@kbn/expect';
import type { FtrProviderContext } from '../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default function ({ getPageObjects, getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const pageObjects = getPageObjects([
'common',
'cspSecurity',
'security',
'header',
'cisAddIntegration',
]);

const KSPM_RADIO_OPTION = 'policy-template-radio-button-kspm';
const CSPM_RADIO_OPTION = 'policy-template-radio-button-cspm';
const CNVM_RADIO_OPTION = 'policy-template-radio-button-vuln_mgmt';

const POLICY_NAME_FIELD = 'createAgentPolicyNameField';
const SETUP_TECHNOLOGY_SELECTOR = 'setup-technology-selector-accordion';

describe('Agentless Security Posture Integration Options', function () {
let cisIntegration: typeof pageObjects.cisAddIntegration;

before(async () => {
cisIntegration = pageObjects.cisAddIntegration;
});

after(async () => {
await pageObjects.cspSecurity.logout();
});

it(`should show kspm without agentless option`, async () => {
await cisIntegration.navigateToAddIntegrationWithVersionPage(
CLOUD_CREDENTIALS_PACKAGE_VERSION
);

await cisIntegration.clickOptionButton(KSPM_RADIO_OPTION);
await pageObjects.header.waitUntilLoadingHasFinished();

const hasSetupTechnologySelector = await testSubjects.exists(SETUP_TECHNOLOGY_SELECTOR);
const hasAgentBased = await testSubjects.exists(POLICY_NAME_FIELD);

expect(hasSetupTechnologySelector).to.be(false);
expect(hasAgentBased).to.be(true);
});

it(`should show cnvm without agentless option`, async () => {
// const integrationPolicyName = `cloud_security_posture-${new Date().toISOString()}`;
await cisIntegration.navigateToAddIntegrationWithVersionPage(
CLOUD_CREDENTIALS_PACKAGE_VERSION
);

await cisIntegration.clickOptionButton(CNVM_RADIO_OPTION);
await pageObjects.header.waitUntilLoadingHasFinished();

const hasSetupTechnologySelector = await testSubjects.exists(SETUP_TECHNOLOGY_SELECTOR);
const hasAgentBased = await testSubjects.exists(POLICY_NAME_FIELD);

expect(hasSetupTechnologySelector).to.be(false);
expect(hasAgentBased).to.be(true);
});

it(`should show cspm with agentless option`, async () => {
// const integrationPolicyName = `cloud_security_posture-${new Date().toISOString()}`;
await cisIntegration.navigateToAddIntegrationWithVersionPage(
CLOUD_CREDENTIALS_PACKAGE_VERSION
);

await cisIntegration.clickOptionButton(CSPM_RADIO_OPTION);
await pageObjects.header.waitUntilLoadingHasFinished();

const hasSetupTechnologySelector = await testSubjects.exists(SETUP_TECHNOLOGY_SELECTOR);
const hasAgentBased = await testSubjects.exists(POLICY_NAME_FIELD);

expect(hasSetupTechnologySelector).to.be(true);
expect(hasAgentBased).to.be(true);
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import type { FtrConfigProviderContext } from '@kbn/test';
import { CA_CERT_PATH, KBN_CERT_PATH, KBN_KEY_PATH } from '@kbn/dev-utils';
import { CLOUD_CREDENTIALS_PACKAGE_VERSION } from '@kbn/cloud-security-posture-plugin/common/constants';
import { pageObjects } from './page_objects';

export default async function ({ readConfigFile }: FtrConfigProviderContext) {
Expand All @@ -30,9 +31,11 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
`--xpack.fleet.agentless.api.tls.key=${KBN_KEY_PATH}`,
`--xpack.fleet.agentless.api.tls.ca=${CA_CERT_PATH}`,
`--xpack.cloud.id=something-anything`,
`--xpack.fleet.packages.0.name=cloud_security_posture`,
`--xpack.fleet.packages.0.version=${CLOUD_CREDENTIALS_PACKAGE_VERSION}`,
],
},
// load tests in the index file
testFiles: [require.resolve('./agentless/create_agent.ts')],
testFiles: [require.resolve('./agentless')],
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,27 @@ export function AddCisIntegrationFormPageProvider({
await PageObjects.header.waitUntilLoadingHasFinished();
};

const navigateToAddIntegrationWithVersionPage = async (
packageVersion: string,
space?: string
) => {
const options = space
? {
basePath: `/s/${space}`,
shouldUseHashForSubUrl: false,
}
: {
shouldUseHashForSubUrl: false,
};

await PageObjects.common.navigateToUrl(
'fleet',
`integrations/cloud_security_posture-${packageVersion}/add-integration`,
options
);
await PageObjects.header.waitUntilLoadingHasFinished();
};

const navigateToAddIntegrationCspmWithVersionPage = async (
packageVersion: string,
space?: string
Expand Down Expand Up @@ -505,6 +526,7 @@ export function AddCisIntegrationFormPageProvider({
cisAzure,
cisAws,
cisGcp,
navigateToAddIntegrationWithVersionPage,
navigateToAddIntegrationCspmPage,
navigateToAddIntegrationCspmWithVersionPage,
navigateToAddIntegrationCnvmPage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
let cisIntegrationAws: typeof pageObjects.cisAddIntegration.cisAws;
let testSubjectIds: typeof pageObjects.cisAddIntegration.testSubjectIds;
let mockApiServer: http.Server;
const previousPackageVersion = '1.9.0';

before(async () => {
mockApiServer = mockAgentlessApiService.listen(8089);
Expand Down Expand Up @@ -66,20 +65,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
(await cisIntegrationAws.showLaunchCloudFormationAgentlessButton()) !== undefined
).to.be(true);
});

it(`should hide CIS_AWS Launch Cloud formation button when credentials selector is temporary keys and package version is less than ${previousPackageVersion}`, async () => {
await cisIntegration.navigateToAddIntegrationCspmWithVersionPage(previousPackageVersion);

await cisIntegration.clickOptionButton(testSubjectIds.CIS_AWS_OPTION_TEST_ID);
await cisIntegration.clickOptionButton(testSubjectIds.AWS_SINGLE_ACCOUNT_TEST_ID);
await cisIntegration.selectSetupTechnology('agentless');

await cisIntegration.selectAwsCredentials('temporary');

await pageObjects.header.waitUntilLoadingHasFinished();

expect(await cisIntegrationAws.showLaunchCloudFormationAgentlessButton()).to.be(false);
});
});

describe('Serverless - Agentless CIS_AWS ORG Account Launch Cloud formation', () => {
Expand All @@ -100,19 +85,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {

expect(await cisIntegrationAws.showLaunchCloudFormationAgentlessButton()).to.be(true);
});

it(`should hide CIS_AWS Launch Cloud formation button when credentials selector is temporary keys and package version is less than ${previousPackageVersion}`, async () => {
await cisIntegration.navigateToAddIntegrationCspmWithVersionPage(previousPackageVersion);

await cisIntegration.clickOptionButton(testSubjectIds.CIS_AWS_OPTION_TEST_ID);
await cisIntegration.selectSetupTechnology('agentless');

await cisIntegration.selectAwsCredentials('temporary');

await pageObjects.header.waitUntilLoadingHasFinished();

expect(await cisIntegrationAws.showLaunchCloudFormationAgentlessButton()).to.be(false);
});
});

// TODO: Migrate test after Serverless default agentless policy is deleted.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
const pageObjects = getPageObjects(['common', 'svlCommonPage', 'cisAddIntegration', 'header']);

const supertest = getService('supertest');
const previousPackageVersion = '1.9.0';

describe('Agentless CIS Integration Page', function () {
// TODO: we need to check if the tests are running on MKI. There is a suspicion that installing csp package via Kibana server args is not working on MKI.
Expand Down Expand Up @@ -60,18 +59,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {

expect(await cisIntegrationGcp.showLaunchCloudShellAgentlessButton()).to.be(true);
});

it(`should hide CIS_GCP Launch Cloud Shell button when package version is less than ${CLOUD_CREDENTIALS_PACKAGE_VERSION}`, async () => {
await cisIntegration.navigateToAddIntegrationCspmWithVersionPage(previousPackageVersion);

await cisIntegration.clickOptionButton(testSubjectIds.CIS_GCP_OPTION_TEST_ID);
await cisIntegration.clickOptionButton(testSubjectIds.GCP_SINGLE_ACCOUNT_TEST_ID);
await cisIntegration.selectSetupTechnology('agentless');

await pageObjects.header.waitUntilLoadingHasFinished();

expect(await cisIntegrationGcp.showLaunchCloudShellAgentlessButton()).to.be(false);
});
});

describe('Agentless CIS_GCP ORG Account Launch Cloud Shell', () => {
Expand All @@ -87,17 +74,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {

expect(await cisIntegrationGcp.showLaunchCloudShellAgentlessButton()).to.be(true);
});

it(`should hide CIS_GCP Launch Cloud shell button when package version is ${previousPackageVersion}`, async () => {
await cisIntegration.navigateToAddIntegrationCspmWithVersionPage(previousPackageVersion);

await cisIntegration.clickOptionButton(testSubjectIds.CIS_GCP_OPTION_TEST_ID);
await cisIntegration.selectSetupTechnology('agentless');

await pageObjects.header.waitUntilLoadingHasFinished();

expect(await cisIntegrationGcp.showLaunchCloudShellAgentlessButton()).to.be(false);
});
});

describe.skip('Serverless - Agentless CIS_GCP edit flow', () => {
Expand Down

0 comments on commit 2609a53

Please sign in to comment.