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

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Cloud Security] Render Setup Technology Selector based on deployment
mode (#194347)](https://github.com/elastic/kibana/pull/194347)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"seanrathier","email":"sean.rathier@gmail.com"},"sourceCommit":{"committedDate":"2024-10-09T12:52:03Z","message":"[Cloud
Security] Render Setup Technology Selector based on deployment mode
(#194347)","sha":"2609a533fa950b9e7974d704fa0c3f9986816dbe","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Fleet","v9.0.0","Team:Cloud
Security","backport:prev-minor","ci:cloud-deploy","8.16
candidate"],"title":"[Cloud Security] Render Setup Technology Selector
based on deployment
mode","number":194347,"url":"https://github.com/elastic/kibana/pull/194347","mergeCommit":{"message":"[Cloud
Security] Render Setup Technology Selector based on deployment mode
(#194347)","sha":"2609a533fa950b9e7974d704fa0c3f9986816dbe"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/194347","number":194347,"mergeCommit":{"message":"[Cloud
Security] Render Setup Technology Selector based on deployment mode
(#194347)","sha":"2609a533fa950b9e7974d704fa0c3f9986816dbe"}}]}]
BACKPORT-->

Co-authored-by: seanrathier <sean.rathier@gmail.com>
This commit is contained in:
Kibana Machine 2024-10-10 01:39:54 +11:00 committed by GitHub
parent 3f51455be8
commit 4de542f2c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 150 additions and 61 deletions

View file

@ -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';

View file

@ -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;
@ -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]);

View file

@ -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}

View file

@ -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) => {

View file

@ -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,
@ -374,7 +374,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
validationResults={validationResults}
isEditPage={false}
handleSetupTechnologyChange={handleSetupTechnologyChange}
isAgentlessEnabled={isAgentlessEnabled}
isAgentlessEnabled={isAgentlessIntegration(packageInfo)}
/>
</ExtensionWrapper>
)

View file

@ -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,
@ -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;

View file

@ -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'));
});
}

View file

@ -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);
});
});
}

View file

@ -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) {
@ -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')],
};
}

View file

@ -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
@ -505,6 +526,7 @@ export function AddCisIntegrationFormPageProvider({
cisAzure,
cisAws,
cisGcp,
navigateToAddIntegrationWithVersionPage,
navigateToAddIntegrationCspmPage,
navigateToAddIntegrationCspmWithVersionPage,
navigateToAddIntegrationCnvmPage,

View file

@ -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);
@ -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', () => {
@ -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.

View file

@ -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.
@ -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', () => {
@ -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', () => {