mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Cloud Security] Azure integration manual fields (#171069)
This commit is contained in:
parent
d3e9ab7cea
commit
3437e6d878
8 changed files with 574 additions and 28 deletions
|
@ -10,7 +10,6 @@ import {
|
|||
VulnSeverity,
|
||||
AwsCredentialsTypeFieldMap,
|
||||
GcpCredentialsTypeFieldMap,
|
||||
AzureCredentialsTypeFieldMap,
|
||||
} from './types';
|
||||
|
||||
export const STATUS_ROUTE_PATH = '/internal/cloud_security_posture/status';
|
||||
|
@ -161,7 +160,25 @@ export const GCP_CREDENTIALS_TYPE_TO_FIELDS_MAP: GcpCredentialsTypeFieldMap = {
|
|||
'credentials-json': ['gcp.credentials.json'],
|
||||
};
|
||||
|
||||
export const AZURE_CREDENTIALS_TYPE_TO_FIELDS_MAP: AzureCredentialsTypeFieldMap = {
|
||||
manual: [],
|
||||
export const AZURE_CREDENTIALS_TYPE_TO_FIELDS_MAP = {
|
||||
arm_template: [],
|
||||
service_principal_with_client_secret: [
|
||||
'azure.credentials.tenant_id',
|
||||
'azure.credentials.client_id',
|
||||
'azure.credentials.client_secret',
|
||||
],
|
||||
service_principal_with_client_certificate: [
|
||||
'azure.credentials.tenant_id',
|
||||
'azure.credentials.client_id',
|
||||
'azure.credentials.client_certificate_path',
|
||||
'azure.credentials.client_certificate_password',
|
||||
],
|
||||
service_principal_with_client_username_and_password: [
|
||||
'azure.credentials.tenant_id',
|
||||
'azure.credentials.client_id',
|
||||
'azure.credentials.client_username',
|
||||
'azure.credentials.client_password',
|
||||
],
|
||||
managed_identity: [],
|
||||
manual: [],
|
||||
};
|
||||
|
|
|
@ -30,7 +30,13 @@ export type GcpCredentialsTypeFieldMap = {
|
|||
[key in GcpCredentialsType]: string[];
|
||||
};
|
||||
|
||||
export type AzureCredentialsType = 'arm_template' | 'manual';
|
||||
export type AzureCredentialsType =
|
||||
| 'arm_template'
|
||||
| 'service_principal_with_client_secret'
|
||||
| 'service_principal_with_client_certificate'
|
||||
| 'service_principal_with_client_username_and_password'
|
||||
| 'managed_identity'
|
||||
| 'manual';
|
||||
|
||||
export type AzureCredentialsTypeFieldMap = {
|
||||
[key in AzureCredentialsType]: string[];
|
||||
|
|
|
@ -124,7 +124,7 @@ export const cleanupCredentials = (packagePolicy: NewPackagePolicy | UpdatePacka
|
|||
const azureCredentialType: AzureCredentialsType | undefined =
|
||||
enabledInput?.streams?.[0].vars?.['azure.credentials.type']?.value;
|
||||
|
||||
if (awsCredentialType || gcpCredentialType) {
|
||||
if (awsCredentialType || gcpCredentialType || azureCredentialType) {
|
||||
let credsToKeep: string[] = [' '];
|
||||
let credFields: string[] = [' '];
|
||||
if (awsCredentialType) {
|
||||
|
|
|
@ -5,7 +5,18 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import React, { useEffect } from 'react';
|
||||
import { EuiLink, EuiSpacer, EuiText, EuiTitle, EuiCallOut, EuiHorizontalRule } from '@elastic/eui';
|
||||
import {
|
||||
EuiLink,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
EuiCallOut,
|
||||
EuiHorizontalRule,
|
||||
EuiFormRow,
|
||||
EuiSelect,
|
||||
EuiFieldPassword,
|
||||
EuiFieldText,
|
||||
} from '@elastic/eui';
|
||||
import type { NewPackagePolicy } from '@kbn/fleet-plugin/public';
|
||||
import { NewPackagePolicyInput, PackageInfo } from '@kbn/fleet-plugin/common';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
@ -14,8 +25,13 @@ import { i18n } from '@kbn/i18n';
|
|||
import semverValid from 'semver/functions/valid';
|
||||
import semverCoerce from 'semver/functions/coerce';
|
||||
import semverLt from 'semver/functions/lt';
|
||||
import {
|
||||
AzureOptions,
|
||||
getAzureCredentialsFormManualOptions,
|
||||
} from './get_azure_credentials_form_options';
|
||||
import { AzureCredentialsType } from '../../../../common/types';
|
||||
import { SetupFormat, useAzureCredentialsForm } from './hooks';
|
||||
import { NewPackagePolicyPostureInput } from '../utils';
|
||||
import { getPosturePolicy, NewPackagePolicyPostureInput } from '../utils';
|
||||
import { CspRadioOption, RadioGroup } from '../csp_boxed_radio_group';
|
||||
|
||||
interface AzureSetupInfoContentProps {
|
||||
|
@ -161,7 +177,31 @@ const ArmTemplateSetup = ({
|
|||
);
|
||||
};
|
||||
|
||||
const ManualSetup = ({ integrationLink }: { integrationLink: string }) => {
|
||||
const AzureCredentialTypeSelector = ({
|
||||
type,
|
||||
onChange,
|
||||
}: {
|
||||
onChange(type: AzureCredentialsType): void;
|
||||
type: AzureCredentialsType;
|
||||
}) => (
|
||||
<EuiFormRow
|
||||
fullWidth
|
||||
label={i18n.translate('xpack.csp.azureIntegration.azureCredentialTypeSelectorLabel', {
|
||||
defaultMessage: 'Preferred manual method',
|
||||
})}
|
||||
>
|
||||
<EuiSelect
|
||||
fullWidth
|
||||
options={getAzureCredentialsFormManualOptions()}
|
||||
value={type}
|
||||
onChange={(optionElem) => {
|
||||
onChange(optionElem.target.value as AzureCredentialsType);
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
|
||||
const TemporaryManualSetup = ({ integrationLink }: { integrationLink: string }) => {
|
||||
return (
|
||||
<>
|
||||
<EuiText color="subdued" size="s">
|
||||
|
@ -206,6 +246,53 @@ const ManualSetup = ({ integrationLink }: { integrationLink: string }) => {
|
|||
};
|
||||
|
||||
const AZURE_MINIMUM_PACKAGE_VERSION = '1.6.0';
|
||||
const AZURE_MANUAL_FIELDS_PACKAGE_VERSION = '1.7.0';
|
||||
|
||||
export const getDefaultAzureManualCredentialType = (packageInfo: PackageInfo) => {
|
||||
const packageSemanticVersion = semverValid(packageInfo.version);
|
||||
const cleanPackageVersion = semverCoerce(packageSemanticVersion) || '';
|
||||
|
||||
const isPackageVersionValidForManualFields = !semverLt(
|
||||
cleanPackageVersion,
|
||||
AZURE_MANUAL_FIELDS_PACKAGE_VERSION
|
||||
);
|
||||
|
||||
return isPackageVersionValidForManualFields ? 'managed_identity' : 'manual';
|
||||
};
|
||||
|
||||
const AzureInputVarFields = ({
|
||||
fields,
|
||||
onChange,
|
||||
}: {
|
||||
fields: Array<AzureOptions[keyof AzureOptions]['fields'][number] & { value: string; id: string }>;
|
||||
onChange: (key: string, value: string) => void;
|
||||
}) => (
|
||||
<div>
|
||||
{fields.map((field) => (
|
||||
<EuiFormRow key={field.id} label={field.label} fullWidth hasChildLabel={true} id={field.id}>
|
||||
<>
|
||||
{field.type === 'password' && (
|
||||
<EuiFieldPassword
|
||||
id={field.id}
|
||||
type="dual"
|
||||
fullWidth
|
||||
value={field.value || ''}
|
||||
onChange={(event) => onChange(field.id, event.target.value)}
|
||||
/>
|
||||
)}
|
||||
{field.type === 'text' && (
|
||||
<EuiFieldText
|
||||
id={field.id}
|
||||
fullWidth
|
||||
value={field.value || ''}
|
||||
onChange={(event) => onChange(field.id, event.target.value)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</EuiFormRow>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const AzureCredentialsForm = ({
|
||||
input,
|
||||
|
@ -216,15 +303,22 @@ export const AzureCredentialsForm = ({
|
|||
setIsValid,
|
||||
disabled,
|
||||
}: Props) => {
|
||||
const { setupFormat, onSetupFormatChange, integrationLink, hasArmTemplateUrl } =
|
||||
useAzureCredentialsForm({
|
||||
newPolicy,
|
||||
input,
|
||||
packageInfo,
|
||||
onChange,
|
||||
setIsValid,
|
||||
updatePolicy,
|
||||
});
|
||||
const {
|
||||
group,
|
||||
fields,
|
||||
azureCredentialsType,
|
||||
setupFormat,
|
||||
onSetupFormatChange,
|
||||
integrationLink,
|
||||
hasArmTemplateUrl,
|
||||
} = useAzureCredentialsForm({
|
||||
newPolicy,
|
||||
input,
|
||||
packageInfo,
|
||||
onChange,
|
||||
setIsValid,
|
||||
updatePolicy,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!setupFormat) {
|
||||
|
@ -238,6 +332,10 @@ export const AzureCredentialsForm = ({
|
|||
cleanPackageVersion,
|
||||
AZURE_MINIMUM_PACKAGE_VERSION
|
||||
);
|
||||
const isPackageVersionValidForManualFields = !semverLt(
|
||||
cleanPackageVersion,
|
||||
AZURE_MANUAL_FIELDS_PACKAGE_VERSION
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setIsValid(isPackageVersionValidForAzure);
|
||||
|
@ -280,8 +378,52 @@ export const AzureCredentialsForm = ({
|
|||
{setupFormat === AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE && (
|
||||
<ArmTemplateSetup hasArmTemplateUrl={hasArmTemplateUrl} input={input} />
|
||||
)}
|
||||
{setupFormat === AZURE_MANUAL_CREDENTIAL_TYPE && (
|
||||
<ManualSetup integrationLink={integrationLink} />
|
||||
{setupFormat === AZURE_MANUAL_CREDENTIAL_TYPE && !isPackageVersionValidForManualFields && (
|
||||
<TemporaryManualSetup integrationLink={integrationLink} />
|
||||
)}
|
||||
{setupFormat === AZURE_MANUAL_CREDENTIAL_TYPE && isPackageVersionValidForManualFields && (
|
||||
<>
|
||||
<AzureCredentialTypeSelector
|
||||
type={azureCredentialsType}
|
||||
onChange={(optionId) => {
|
||||
updatePolicy(
|
||||
getPosturePolicy(newPolicy, input.type, {
|
||||
'azure.credentials.type': { value: optionId },
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
<AzureInputVarFields
|
||||
fields={fields}
|
||||
onChange={(key, value) => {
|
||||
updatePolicy(getPosturePolicy(newPolicy, input.type, { [key]: { value } }));
|
||||
}}
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
{group.info}
|
||||
<EuiSpacer size="m" />
|
||||
<EuiText color="subdued" size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.csp.azureIntegration.manualCredentialType.documentaion"
|
||||
defaultMessage="Read the {documentation} for more details"
|
||||
values={{
|
||||
documentation: (
|
||||
<EuiLink
|
||||
href={ARM_TEMPLATE_EXTERNAL_DOC_URL}
|
||||
target="_blank"
|
||||
rel="noopener nofollow noreferrer"
|
||||
data-test-subj="externalLink"
|
||||
>
|
||||
{i18n.translate('xpack.csp.azureIntegration.documentationLinkText', {
|
||||
defaultMessage: 'documentation',
|
||||
})}
|
||||
</EuiLink>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</EuiText>
|
||||
</>
|
||||
)}
|
||||
<EuiSpacer />
|
||||
</>
|
||||
|
|
|
@ -8,18 +8,32 @@
|
|||
import { NewPackagePolicyInput } from '@kbn/fleet-plugin/common';
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiText } from '@elastic/eui';
|
||||
import { AzureCredentialsType } from '../../../../common/types';
|
||||
|
||||
export type AzureCredentialsFields = Record<string, { label: string; type?: 'password' | 'text' }>;
|
||||
|
||||
export interface AzureOptionValue {
|
||||
label: string;
|
||||
info: React.ReactNode;
|
||||
info?: React.ReactNode;
|
||||
fields: AzureCredentialsFields;
|
||||
}
|
||||
|
||||
export type AzureOptions = Record<AzureCredentialsType, AzureOptionValue>;
|
||||
|
||||
export const getAzureCredentialsFormManualOptions = (): Array<{
|
||||
value: AzureCredentialsType;
|
||||
text: string;
|
||||
}> => {
|
||||
return Object.entries(getAzureCredentialsFormOptions())
|
||||
.map(([key, value]) => ({
|
||||
value: key as AzureCredentialsType,
|
||||
text: value.label,
|
||||
}))
|
||||
.filter(({ value }) => value !== 'arm_template');
|
||||
};
|
||||
|
||||
export const getInputVarsFields = (input: NewPackagePolicyInput, fields: AzureCredentialsFields) =>
|
||||
Object.entries(input.streams[0].vars || {})
|
||||
.filter(([id]) => id in fields)
|
||||
|
@ -33,19 +47,102 @@ export const getInputVarsFields = (input: NewPackagePolicyInput, fields: AzureCr
|
|||
} as const;
|
||||
});
|
||||
|
||||
export const DEFAULT_AZURE_MANUAL_CREDENTIALS_TYPE = 'manual';
|
||||
const I18N_TENANT_ID = i18n.translate('xpack.csp.azureIntegration.tenantIdLabel', {
|
||||
defaultMessage: 'Tenant ID',
|
||||
});
|
||||
|
||||
const I18N_CLIENT_ID = i18n.translate('xpack.csp.azureIntegration.clientIdLabel', {
|
||||
defaultMessage: 'Client ID',
|
||||
});
|
||||
|
||||
export const getAzureCredentialsFormOptions = (): AzureOptions => ({
|
||||
managed_identity: {
|
||||
label: i18n.translate('xpack.csp.azureIntegration.credentialType.managedIdentityLabel', {
|
||||
defaultMessage: 'Managed Identity',
|
||||
}),
|
||||
info: (
|
||||
<EuiText color="subdued" size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.csp.azureIntegration.credentialType.managedIdentityInfo"
|
||||
defaultMessage="Ensure the agent is deployed on a resource that supports managed identities (e.g., Azure Virtual Machines). No explicit credentials need to be provided; Azure handles the authentication."
|
||||
/>
|
||||
</EuiText>
|
||||
),
|
||||
fields: {},
|
||||
},
|
||||
arm_template: {
|
||||
label: 'ARM Template',
|
||||
info: [],
|
||||
fields: {},
|
||||
},
|
||||
service_principal_with_client_secret: {
|
||||
label: i18n.translate('xpack.csp.azureIntegration.servicePrincipalWithClientSecretLabel', {
|
||||
defaultMessage: 'Service principal with Client Secret',
|
||||
}),
|
||||
fields: {
|
||||
'azure.credentials.tenant_id': { label: I18N_TENANT_ID },
|
||||
'azure.credentials.client_id': { label: I18N_CLIENT_ID },
|
||||
'azure.credentials.client_secret': {
|
||||
type: 'password',
|
||||
label: i18n.translate('xpack.csp.azureIntegration.clientSecretLabel', {
|
||||
defaultMessage: 'Client Secret',
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
service_principal_with_client_certificate: {
|
||||
label: i18n.translate('xpack.csp.azureIntegration.servicePrincipalWithClientCertificateLabel', {
|
||||
defaultMessage: 'Service principal with Client Certificate',
|
||||
}),
|
||||
fields: {
|
||||
'azure.credentials.tenant_id': { label: I18N_TENANT_ID },
|
||||
'azure.credentials.client_id': { label: I18N_CLIENT_ID },
|
||||
'azure.credentials.client_certificate_path': {
|
||||
label: i18n.translate('xpack.csp.azureIntegration.clientCertificatePathLabel', {
|
||||
defaultMessage: 'Client Certificate Path',
|
||||
}),
|
||||
},
|
||||
'azure.credentials.client_certificate_password': {
|
||||
type: 'password',
|
||||
label: i18n.translate('xpack.csp.azureIntegration.clientCertificatePasswordLabel', {
|
||||
defaultMessage: 'Client Certificate Password',
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
service_principal_with_client_username_and_password: {
|
||||
label: i18n.translate(
|
||||
'xpack.csp.azureIntegration.servicePrincipalWithClientUsernameAndPasswordLabel',
|
||||
{ defaultMessage: 'Service principal with Client Username and Password' }
|
||||
),
|
||||
fields: {
|
||||
'azure.credentials.tenant_id': { label: I18N_TENANT_ID },
|
||||
'azure.credentials.client_id': { label: I18N_CLIENT_ID },
|
||||
'azure.credentials.client_username': {
|
||||
label: i18n.translate('xpack.csp.azureIntegration.clientUsernameLabel', {
|
||||
defaultMessage: 'Client Username',
|
||||
}),
|
||||
},
|
||||
'azure.credentials.client_password': {
|
||||
type: 'password',
|
||||
label: i18n.translate('xpack.csp.azureIntegration.clientPasswordLabel', {
|
||||
defaultMessage: 'Client Password',
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
manual: {
|
||||
label: i18n.translate('xpack.csp.azureIntegration.credentialType.manualLabel', {
|
||||
defaultMessage: 'Manual',
|
||||
}),
|
||||
info: [],
|
||||
info: (
|
||||
<EuiText color="subdued" size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.csp.azureIntegration.credentialType.manualInfo"
|
||||
defaultMessage="Ensure the agent is deployed on a resource that supports managed identities (e.g., Azure Virtual Machines). No explicit credentials need to be provided; Azure handles the authentication."
|
||||
/>
|
||||
</EuiText>
|
||||
),
|
||||
fields: {},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { NewPackagePolicy, PackageInfo } from '@kbn/fleet-plugin/common';
|
||||
import { AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE } from './azure_credentials_form';
|
||||
import {
|
||||
AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE,
|
||||
getDefaultAzureManualCredentialType,
|
||||
} from './azure_credentials_form';
|
||||
import { cspIntegrationDocsNavigation } from '../../../common/navigation/constants';
|
||||
import {
|
||||
getArmTemplateUrlFromCspmPackage,
|
||||
|
@ -15,14 +18,28 @@ import {
|
|||
NewPackagePolicyPostureInput,
|
||||
} from '../utils';
|
||||
import {
|
||||
DEFAULT_AZURE_MANUAL_CREDENTIALS_TYPE,
|
||||
getAzureCredentialsFormOptions,
|
||||
getInputVarsFields,
|
||||
} from './get_azure_credentials_form_options';
|
||||
import { CLOUDBEAT_AZURE } from '../../../../common/constants';
|
||||
import { AzureCredentialsType } from '../../../../common/types';
|
||||
|
||||
export type SetupFormat = AzureCredentialsType;
|
||||
export type SetupFormat = 'arm_template' | 'manual';
|
||||
|
||||
const getSetupFormatFromInput = (
|
||||
input: Extract<NewPackagePolicyPostureInput, { type: 'cloudbeat/cis_azure' }>,
|
||||
hasArmTemplateUrl: boolean
|
||||
): SetupFormat => {
|
||||
const credentialsType = getAzureCredentialsType(input);
|
||||
if (!credentialsType && hasArmTemplateUrl) {
|
||||
return 'arm_template';
|
||||
}
|
||||
if (credentialsType !== 'arm_template') {
|
||||
return 'manual';
|
||||
}
|
||||
|
||||
return 'arm_template';
|
||||
};
|
||||
|
||||
const getAzureCredentialsType = (
|
||||
input: Extract<NewPackagePolicyPostureInput, { type: 'cloudbeat/cis_azure' }>
|
||||
|
@ -107,7 +124,7 @@ export const useAzureCredentialsForm = ({
|
|||
|
||||
const hasArmTemplateUrl = !!getArmTemplateUrlFromCspmPackage(packageInfo);
|
||||
|
||||
const setupFormat = azureCredentialsType;
|
||||
const setupFormat = getSetupFormatFromInput(input, hasArmTemplateUrl);
|
||||
|
||||
const group = options[azureCredentialsType];
|
||||
const fields = getInputVarsFields(input, group.fields);
|
||||
|
@ -134,6 +151,8 @@ export const useAzureCredentialsForm = ({
|
|||
setupFormat,
|
||||
});
|
||||
|
||||
const defaultAzureManualCredentialType = getDefaultAzureManualCredentialType(packageInfo);
|
||||
|
||||
const onSetupFormatChange = (newSetupFormat: SetupFormat) => {
|
||||
if (newSetupFormat === AZURE_ARM_TEMPLATE_CREDENTIAL_TYPE) {
|
||||
fieldsSnapshot.current = Object.fromEntries(
|
||||
|
@ -155,7 +174,7 @@ export const useAzureCredentialsForm = ({
|
|||
updatePolicy(
|
||||
getPosturePolicy(newPolicy, input.type, {
|
||||
'azure.credentials.type': {
|
||||
value: lastManualCredentialsType.current || DEFAULT_AZURE_MANUAL_CREDENTIALS_TYPE,
|
||||
value: lastManualCredentialsType.current || defaultAzureManualCredentialType,
|
||||
type: 'text',
|
||||
},
|
||||
...fieldsSnapshot.current,
|
||||
|
|
|
@ -162,8 +162,15 @@ const getPolicyMock = (
|
|||
};
|
||||
|
||||
const azureVarsMock = {
|
||||
'azure.credentials.type': { value: 'arm_template', type: 'text' },
|
||||
'azure.account_type': { type: 'text' },
|
||||
'azure.credentials.type': { type: 'text' },
|
||||
'azure.credentials.tenant_id': { type: 'text' },
|
||||
'azure.credentials.client_id': { type: 'text' },
|
||||
'azure.credentials.client_secret': { type: 'text' },
|
||||
'azure.credentials.client_certificate_path': { type: 'text' },
|
||||
'azure.credentials.client_certificate_password': { type: 'text' },
|
||||
'azure.credentials.client_username': { type: 'text' },
|
||||
'azure.credentials.client_password': { type: 'text' },
|
||||
};
|
||||
|
||||
const dataStream = { type: 'logs', dataset: 'cloud_security_posture.findings' };
|
||||
|
|
|
@ -1330,6 +1330,27 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it(`doesnt render ${CLOUDBEAT_AZURE} Manual fields when version is not at least version 1.7.0`, () => {
|
||||
let policy = getMockPolicyAzure();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.type': { value: 'manual' },
|
||||
'azure.account_type': { value: 'single-account' },
|
||||
});
|
||||
|
||||
const { queryByRole } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.6.0')} />
|
||||
);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
expect(
|
||||
queryByRole('option', { name: 'Service principal with Client Secret', selected: true })
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it(`selects default ${CLOUDBEAT_AZURE} fields`, () => {
|
||||
let policy = getMockPolicyAzure();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
|
@ -1344,5 +1365,242 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
updatedPolicy: policy,
|
||||
});
|
||||
});
|
||||
|
||||
it(`renders ${CLOUDBEAT_AZURE} Service Principal with Client Secret fields`, () => {
|
||||
let policy = getMockPolicyAzure();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.type': { value: 'service_principal_with_client_secret' },
|
||||
});
|
||||
|
||||
const { getByLabelText, getByRole } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
expect(
|
||||
getByRole('option', { name: 'Service principal with Client Secret', selected: true })
|
||||
).toBeInTheDocument();
|
||||
expect(getByLabelText('Tenant ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client Secret')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it(`updates ${CLOUDBEAT_AZURE} Service Principal with Client Secret fields`, () => {
|
||||
let policy = getMockPolicyAzure();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.type': { value: 'service_principal_with_client_secret' },
|
||||
});
|
||||
|
||||
const { rerender, getByLabelText } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Tenant ID'), 'a');
|
||||
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.tenant_id': { value: 'a' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client ID'), 'b');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_id': { value: 'b' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client Secret'), 'c');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_secret': { value: 'c' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it(`renders Service principal with Client Certificate fields`, () => {
|
||||
let policy = getMockPolicyAzure();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.type': { value: 'service_principal_with_client_certificate' },
|
||||
});
|
||||
|
||||
const { getByLabelText, getByRole } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
expect(
|
||||
getByRole('option', { name: 'Service principal with Client Certificate', selected: true })
|
||||
).toBeInTheDocument();
|
||||
expect(getByLabelText('Tenant ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client Certificate Path')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client Certificate Password')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it(`updates Service principal with Client Certificate fields`, () => {
|
||||
let policy = getMockPolicyAzure();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.type': { value: 'service_principal_with_client_certificate' },
|
||||
});
|
||||
|
||||
const { rerender, getByLabelText } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Tenant ID'), 'a');
|
||||
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.tenant_id': { value: 'a' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client ID'), 'b');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_id': { value: 'b' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client Certificate Path'), 'c');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_certificate_path': { value: 'c' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client Certificate Password'), 'd');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_certificate_password': { value: 'd' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
});
|
||||
|
||||
it(`renders Service principal with Client Username and Password fields`, () => {
|
||||
let policy = getMockPolicyAzure();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.type': { value: 'service_principal_with_client_username_and_password' },
|
||||
});
|
||||
|
||||
const { getByLabelText, getByRole } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
expect(
|
||||
getByRole('option', {
|
||||
name: 'Service principal with Client Username and Password',
|
||||
selected: true,
|
||||
})
|
||||
).toBeInTheDocument();
|
||||
expect(getByLabelText('Tenant ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client Username')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client Password')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it(`updates Service principal with Client Username and Password fields`, () => {
|
||||
let policy = getMockPolicyAzure();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.type': { value: 'service_principal_with_client_username_and_password' },
|
||||
});
|
||||
|
||||
const { rerender, getByLabelText } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Tenant ID'), 'a');
|
||||
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.tenant_id': { value: 'a' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client ID'), 'b');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_id': { value: 'b' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client Username'), 'c');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_username': { value: 'c' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client Password'), 'd');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_password': { value: 'd' },
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue