Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.x] [Cloud Security] Render Setup Technology Selector based on deployment mode (#194347) #195591

Merged
merged 1 commit into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading