mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Cloud Security][Bug] Fix for [Object object] issue on secret fields (#179237)
## Summary
This PR addresses the issue where secret fields value are rendered as
[Object object] when user tries to edit it
<img width="801" alt="Screenshot 2024-03-26 at 12 21 25 AM"
src="2b1995fb
-7a41-4223-9564-43e80a75720f">
---------
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Maxim Kholod <maxim.kholod@elastic.co>
This commit is contained in:
parent
fe507aa0b9
commit
3744a30b32
15 changed files with 496 additions and 157 deletions
|
@ -284,6 +284,7 @@ export const AwsCredentialsForm = ({
|
|||
<EuiSpacer size="l" />
|
||||
<AwsInputVarFields
|
||||
fields={fields}
|
||||
packageInfo={packageInfo}
|
||||
onChange={(key, value) => {
|
||||
updatePolicy(getPosturePolicy(newPolicy, input.type, { [key]: { value } }));
|
||||
}}
|
||||
|
|
|
@ -25,7 +25,12 @@ import {
|
|||
AwsCredentialTypeSelector,
|
||||
} from './aws_credentials_form';
|
||||
|
||||
export const AwsCredentialsFormAgentless = ({ input, newPolicy, updatePolicy }: AwsFormProps) => {
|
||||
export const AwsCredentialsFormAgentless = ({
|
||||
input,
|
||||
newPolicy,
|
||||
packageInfo,
|
||||
updatePolicy,
|
||||
}: AwsFormProps) => {
|
||||
const awsCredentialsType = getAwsCredentialsType(input) || DEFAULT_AGENTLESS_AWS_CREDENTIALS_TYPE;
|
||||
const options = getAwsCredentialsFormOptions();
|
||||
const group = options[awsCredentialsType];
|
||||
|
@ -74,6 +79,7 @@ export const AwsCredentialsFormAgentless = ({ input, newPolicy, updatePolicy }:
|
|||
<EuiSpacer size="l" />
|
||||
<AwsInputVarFields
|
||||
fields={fields}
|
||||
packageInfo={packageInfo}
|
||||
onChange={(key, value) => {
|
||||
updatePolicy(getPosturePolicy(newPolicy, input.type, { [key]: { value } }));
|
||||
}}
|
||||
|
|
|
@ -5,40 +5,80 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiFieldPassword, EuiFieldText, EuiFormRow } from '@elastic/eui';
|
||||
import React, { Suspense } from 'react';
|
||||
import { EuiFieldText, EuiFormRow, EuiSpacer, EuiLoadingSpinner } from '@elastic/eui';
|
||||
import { PackageInfo } from '@kbn/fleet-plugin/common';
|
||||
import { css } from '@emotion/react';
|
||||
import { LazyPackagePolicyInputVarField } from '@kbn/fleet-plugin/public';
|
||||
import { AwsOptions } from './get_aws_credentials_form_options';
|
||||
import { findVariableDef } from '../utils';
|
||||
|
||||
export const AwsInputVarFields = ({
|
||||
fields,
|
||||
onChange,
|
||||
packageInfo,
|
||||
}: {
|
||||
fields: Array<AwsOptions[keyof AwsOptions]['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}>
|
||||
packageInfo: PackageInfo;
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
{fields.map((field) => (
|
||||
<>
|
||||
{field.type === 'password' && (
|
||||
<EuiFieldPassword
|
||||
id={field.id}
|
||||
type="dual"
|
||||
fullWidth
|
||||
value={field.value || ''}
|
||||
onChange={(event) => onChange(field.id, event.target.value)}
|
||||
/>
|
||||
{field.type === 'password' && field.isSecret === true && (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
<div
|
||||
css={css`
|
||||
width: 100%;
|
||||
.euiFormControlLayout,
|
||||
.euiFormControlLayout__childrenWrapper,
|
||||
.euiFormRow,
|
||||
input {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
`}
|
||||
>
|
||||
<Suspense fallback={<EuiLoadingSpinner size="l" />}>
|
||||
<LazyPackagePolicyInputVarField
|
||||
varDef={{
|
||||
...findVariableDef(packageInfo, field.id)!,
|
||||
required: true,
|
||||
type: 'password',
|
||||
}}
|
||||
value={field.value || ''}
|
||||
onChange={(value) => {
|
||||
onChange(field.id, value);
|
||||
}}
|
||||
errors={[]}
|
||||
forceShowErrors={false}
|
||||
isEditPage={true}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
)}
|
||||
{field.type === 'text' && (
|
||||
<EuiFieldText
|
||||
id={field.id}
|
||||
<EuiFormRow
|
||||
key={field.id}
|
||||
label={field.label}
|
||||
fullWidth
|
||||
value={field.value || ''}
|
||||
onChange={(event) => onChange(field.id, event.target.value)}
|
||||
/>
|
||||
hasChildLabel={true}
|
||||
id={field.id}
|
||||
>
|
||||
<EuiFieldText
|
||||
id={field.id}
|
||||
fullWidth
|
||||
value={field.value || ''}
|
||||
onChange={(event) => onChange(field.id, event.target.value)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
)}
|
||||
</>
|
||||
</EuiFormRow>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -71,7 +71,10 @@ const AWS_FIELD_LABEL = {
|
|||
}),
|
||||
};
|
||||
|
||||
export type AwsCredentialsFields = Record<string, { label: string; type?: 'password' | 'text' }>;
|
||||
export type AwsCredentialsFields = Record<
|
||||
string,
|
||||
{ label: string; type?: 'password' | 'text'; isSecret?: boolean }
|
||||
>;
|
||||
|
||||
export interface AwsOptionValue {
|
||||
label: string;
|
||||
|
@ -89,6 +92,7 @@ export const getInputVarsFields = (input: NewPackagePolicyInput, fields: AwsCred
|
|||
label: field.label,
|
||||
type: field.type || 'text',
|
||||
value: inputVar.value,
|
||||
isSecret: field.isSecret,
|
||||
} as const;
|
||||
});
|
||||
|
||||
|
@ -147,7 +151,11 @@ export const getAwsCredentialsFormOptions = (): AwsOptions => ({
|
|||
info: DirectAccessKeysDescription,
|
||||
fields: {
|
||||
access_key_id: { label: AWS_FIELD_LABEL.access_key_id },
|
||||
secret_access_key: { label: AWS_FIELD_LABEL.secret_access_key, type: 'password' },
|
||||
secret_access_key: {
|
||||
label: AWS_FIELD_LABEL.secret_access_key,
|
||||
type: 'password',
|
||||
isSecret: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
[AWS_CREDENTIALS_TYPE.TEMPORARY_KEYS]: {
|
||||
|
@ -157,7 +165,11 @@ export const getAwsCredentialsFormOptions = (): AwsOptions => ({
|
|||
}),
|
||||
fields: {
|
||||
access_key_id: { label: AWS_FIELD_LABEL.access_key_id },
|
||||
secret_access_key: { label: AWS_FIELD_LABEL.secret_access_key, type: 'password' },
|
||||
secret_access_key: {
|
||||
label: AWS_FIELD_LABEL.secret_access_key,
|
||||
type: 'password',
|
||||
isSecret: true,
|
||||
},
|
||||
session_token: {
|
||||
label: i18n.translate('xpack.csp.awsIntegration.sessionTokenLabel', {
|
||||
defaultMessage: 'Session Token',
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { Suspense, useEffect } from 'react';
|
||||
import {
|
||||
EuiCallOut,
|
||||
EuiFieldPassword,
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
EuiHorizontalRule,
|
||||
|
@ -16,6 +15,7 @@ import {
|
|||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
EuiLoadingSpinner,
|
||||
} from '@elastic/eui';
|
||||
import type { NewPackagePolicy } from '@kbn/fleet-plugin/public';
|
||||
import { NewPackagePolicyInput, PackageInfo } from '@kbn/fleet-plugin/common';
|
||||
|
@ -25,13 +25,14 @@ import { i18n } from '@kbn/i18n';
|
|||
import semverValid from 'semver/functions/valid';
|
||||
import semverCoerce from 'semver/functions/coerce';
|
||||
import semverLt from 'semver/functions/lt';
|
||||
import { LazyPackagePolicyInputVarField } from '@kbn/fleet-plugin/public';
|
||||
import {
|
||||
AzureOptions,
|
||||
getAzureCredentialsFormManualOptions,
|
||||
} from './get_azure_credentials_form_options';
|
||||
import { AzureCredentialsType } from '../../../../common/types_old';
|
||||
import { useAzureCredentialsForm } from './hooks';
|
||||
import { getPosturePolicy, NewPackagePolicyPostureInput } from '../utils';
|
||||
import { findVariableDef, getPosturePolicy, NewPackagePolicyPostureInput } from '../utils';
|
||||
import { CspRadioOption, RadioGroup } from '../csp_boxed_radio_group';
|
||||
import { CIS_AZURE_SETUP_FORMAT_TEST_SUBJECTS } from '../../test_subjects';
|
||||
|
||||
|
@ -267,39 +268,73 @@ const AZURE_MANUAL_FIELDS_PACKAGE_VERSION = '1.7.0';
|
|||
|
||||
export const AzureInputVarFields = ({
|
||||
fields,
|
||||
packageInfo,
|
||||
onChange,
|
||||
}: {
|
||||
fields: Array<AzureOptions[keyof AzureOptions]['fields'][number] & { value: string; id: string }>;
|
||||
packageInfo: PackageInfo;
|
||||
onChange: (key: string, value: string) => void;
|
||||
}) => (
|
||||
<div>
|
||||
{fields.map((field) => (
|
||||
<EuiFormRow key={field.id} label={field.label} fullWidth hasChildLabel={true} id={field.id}>
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
{fields.map((field) => (
|
||||
<>
|
||||
{field.type === 'password' && (
|
||||
<EuiFieldPassword
|
||||
id={field.id}
|
||||
type="dual"
|
||||
fullWidth
|
||||
value={field.value || ''}
|
||||
onChange={(event) => onChange(field.id, event.target.value)}
|
||||
data-test-subj={field.testSubj}
|
||||
/>
|
||||
{field.type === 'password' && field.isSecret === true && (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
<div
|
||||
css={css`
|
||||
width: 100%;
|
||||
.euiFormControlLayout,
|
||||
.euiFormControlLayout__childrenWrapper,
|
||||
.euiFormRow,
|
||||
input {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
`}
|
||||
>
|
||||
<Suspense fallback={<EuiLoadingSpinner size="l" />}>
|
||||
<LazyPackagePolicyInputVarField
|
||||
varDef={{
|
||||
...findVariableDef(packageInfo, field.id)!,
|
||||
required: true,
|
||||
type: 'password',
|
||||
}}
|
||||
value={field.value || ''}
|
||||
onChange={(value) => {
|
||||
onChange(field.id, value);
|
||||
}}
|
||||
errors={[]}
|
||||
forceShowErrors={false}
|
||||
isEditPage={true}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{field.type === 'text' && (
|
||||
<EuiFieldText
|
||||
id={field.id}
|
||||
<EuiFormRow
|
||||
key={field.id}
|
||||
label={field.label}
|
||||
fullWidth
|
||||
value={field.value || ''}
|
||||
onChange={(event) => onChange(field.id, event.target.value)}
|
||||
data-test-subj={field.testSubj}
|
||||
/>
|
||||
hasChildLabel={true}
|
||||
id={field.id}
|
||||
>
|
||||
<EuiFieldText
|
||||
id={field.id}
|
||||
fullWidth
|
||||
value={field.value || ''}
|
||||
onChange={(event) => onChange(field.id, event.target.value)}
|
||||
data-test-subj={field.testSubj}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
)}
|
||||
</>
|
||||
</EuiFormRow>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const AzureCredentialsForm = ({
|
||||
input,
|
||||
|
@ -403,6 +438,7 @@ export const AzureCredentialsForm = ({
|
|||
<EuiSpacer size="m" />
|
||||
<AzureInputVarFields
|
||||
fields={fields}
|
||||
packageInfo={packageInfo}
|
||||
onChange={(key, value) => {
|
||||
updatePolicy(getPosturePolicy(newPolicy, input.type, { [key]: { value } }));
|
||||
}}
|
||||
|
@ -412,7 +448,7 @@ export const AzureCredentialsForm = ({
|
|||
<EuiSpacer size="m" />
|
||||
<EuiText color="subdued" size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.csp.azureIntegration.manualCredentialType.documentaion"
|
||||
id="xpack.csp.azureIntegration.manualCredentialType.documentation"
|
||||
defaultMessage="Read the {documentation} for more details"
|
||||
values={{
|
||||
documentation: (
|
||||
|
|
|
@ -29,6 +29,7 @@ export const AzureCredentialsFormAgentless = ({
|
|||
input,
|
||||
newPolicy,
|
||||
updatePolicy,
|
||||
packageInfo,
|
||||
}: AzureCredentialsFormProps) => {
|
||||
const integrationLink = cspIntegrationDocsNavigation.cspm.getStartedPath;
|
||||
const options = getAzureCredentialsFormOptions();
|
||||
|
@ -40,6 +41,7 @@ export const AzureCredentialsFormAgentless = ({
|
|||
<AzureSetupInfoContent integrationLink={integrationLink} />
|
||||
<EuiSpacer size="l" />
|
||||
<AzureInputVarFields
|
||||
packageInfo={packageInfo}
|
||||
fields={fields}
|
||||
onChange={(key, value) => {
|
||||
updatePolicy(getPosturePolicy(newPolicy, input.type, { [key]: { value } }));
|
||||
|
|
|
@ -16,7 +16,7 @@ import { AZURE_CREDENTIALS_TYPE } from './azure_credentials_form';
|
|||
|
||||
export type AzureCredentialsFields = Record<
|
||||
string,
|
||||
{ label: string; type?: 'password' | 'text'; testSubj?: string }
|
||||
{ label: string; type?: 'password' | 'text'; testSubj?: string; isSecret?: boolean }
|
||||
>;
|
||||
|
||||
export interface AzureOptionValue {
|
||||
|
@ -55,6 +55,7 @@ export const getInputVarsFields = (input: NewPackagePolicyInput, fields: AzureCr
|
|||
type: field.type || 'text',
|
||||
testSubj: field.testSubj,
|
||||
value: inputVar.value,
|
||||
isSecret: field?.isSecret,
|
||||
} as const;
|
||||
});
|
||||
|
||||
|
@ -107,6 +108,7 @@ export const getAzureCredentialsFormOptions = (): AzureOptions => ({
|
|||
},
|
||||
'azure.credentials.client_secret': {
|
||||
type: 'password',
|
||||
isSecret: true,
|
||||
label: i18n.translate('xpack.csp.azureIntegration.clientSecretLabel', {
|
||||
defaultMessage: 'Client Secret',
|
||||
}),
|
||||
|
@ -135,6 +137,7 @@ export const getAzureCredentialsFormOptions = (): AzureOptions => ({
|
|||
},
|
||||
'azure.credentials.client_certificate_password': {
|
||||
type: 'password',
|
||||
isSecret: true,
|
||||
label: i18n.translate('xpack.csp.azureIntegration.clientCertificatePasswordLabel', {
|
||||
defaultMessage: 'Client Certificate Password',
|
||||
}),
|
||||
|
@ -164,6 +167,7 @@ export const getAzureCredentialsFormOptions = (): AzureOptions => ({
|
|||
},
|
||||
'azure.credentials.client_password': {
|
||||
type: 'password',
|
||||
isSecret: true,
|
||||
label: i18n.translate('xpack.csp.azureIntegration.clientPasswordLabel', {
|
||||
defaultMessage: 'Client Password',
|
||||
}),
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import React from 'react';
|
||||
import { EuiLink, EuiSpacer, EuiText, EuiTitle, EuiHorizontalRule } from '@elastic/eui';
|
||||
import type { NewPackagePolicy } from '@kbn/fleet-plugin/public';
|
||||
import { NewPackagePolicyInput } from '@kbn/fleet-plugin/common';
|
||||
import { NewPackagePolicyInput, PackageInfo } from '@kbn/fleet-plugin/common';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { RadioGroup } from './csp_boxed_radio_group';
|
||||
|
@ -119,7 +119,7 @@ type AwsOptions = Record<
|
|||
{
|
||||
label: string;
|
||||
info: React.ReactNode;
|
||||
fields: Record<string, { label: string; type?: 'password' | 'text' }>;
|
||||
fields: Record<string, { label: string; type?: 'password' | 'text'; isSecret?: boolean }>;
|
||||
testId: string;
|
||||
}
|
||||
>;
|
||||
|
@ -146,7 +146,11 @@ const options: AwsOptions = {
|
|||
info: DirectAccessKeysDescription,
|
||||
fields: {
|
||||
access_key_id: { label: AWS_FIELD_LABEL.access_key_id },
|
||||
secret_access_key: { label: AWS_FIELD_LABEL.secret_access_key, type: 'password' },
|
||||
secret_access_key: {
|
||||
label: AWS_FIELD_LABEL.secret_access_key,
|
||||
type: 'password',
|
||||
isSecret: true,
|
||||
},
|
||||
},
|
||||
testId: 'directAccessKeyTestId',
|
||||
},
|
||||
|
@ -157,7 +161,11 @@ const options: AwsOptions = {
|
|||
}),
|
||||
fields: {
|
||||
access_key_id: { label: AWS_FIELD_LABEL.access_key_id },
|
||||
secret_access_key: { label: AWS_FIELD_LABEL.secret_access_key, type: 'password' },
|
||||
secret_access_key: {
|
||||
label: AWS_FIELD_LABEL.secret_access_key,
|
||||
type: 'password',
|
||||
isSecret: true,
|
||||
},
|
||||
session_token: {
|
||||
label: i18n.translate('xpack.csp.eksIntegration.sessionTokenLabel', {
|
||||
defaultMessage: 'Session Token',
|
||||
|
@ -197,6 +205,7 @@ const AWS_CREDENTIALS_OPTIONS = Object.keys(options).map((value) => ({
|
|||
|
||||
interface Props {
|
||||
newPolicy: NewPackagePolicy;
|
||||
packageInfo: PackageInfo;
|
||||
input: Extract<NewPackagePolicyPostureInput, { type: 'cloudbeat/cis_aws' | 'cloudbeat/cis_eks' }>;
|
||||
updatePolicy(updatedPolicy: NewPackagePolicy): void;
|
||||
}
|
||||
|
@ -214,13 +223,14 @@ const getInputVarsFields = (
|
|||
label: field.label,
|
||||
type: field.type || 'text',
|
||||
value: inputVar.value,
|
||||
isSecret: field?.isSecret,
|
||||
} as const;
|
||||
});
|
||||
|
||||
const getAwsCredentialsType = (input: Props['input']): AwsCredentialsType | undefined =>
|
||||
input.streams[0].vars?.['aws.credentials.type'].value;
|
||||
|
||||
export const EksCredentialsForm = ({ input, newPolicy, updatePolicy }: Props) => {
|
||||
export const EksCredentialsForm = ({ input, newPolicy, packageInfo, updatePolicy }: Props) => {
|
||||
// We only have a value for 'aws.credentials.type' once the form has mounted.
|
||||
// On initial render we don't have that value so we default to the first option.
|
||||
const awsCredentialsType = getAwsCredentialsType(input) || AWS_CREDENTIALS_OPTIONS[0].id;
|
||||
|
@ -248,6 +258,7 @@ export const EksCredentialsForm = ({ input, newPolicy, updatePolicy }: Props) =>
|
|||
<EuiSpacer />
|
||||
<AwsInputVarFields
|
||||
fields={fields}
|
||||
packageInfo={packageInfo}
|
||||
onChange={(key, value) =>
|
||||
updatePolicy(getPosturePolicy(newPolicy, input.type, { [key]: { value } }))
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import type { NewPackagePolicy } from '@kbn/fleet-plugin/public';
|
||||
import type { PackageInfo, PackagePolicyConfigRecord } from '@kbn/fleet-plugin/common';
|
||||
import { createNewPackagePolicyMock, createAgentPolicyMock } from '@kbn/fleet-plugin/common/mocks';
|
||||
import { RegistryRelease, RegistryVarType } from '@kbn/fleet-plugin/common/types';
|
||||
import {
|
||||
CLOUDBEAT_GCP,
|
||||
CLOUDBEAT_AZURE,
|
||||
|
@ -31,6 +32,7 @@ export const getMockPolicyVulnMgmtAWS = () =>
|
|||
export const getMockAgentlessAgentPolicy = () => {
|
||||
return createAgentPolicyMock({ id: 'agentless' });
|
||||
};
|
||||
export const getMockPackageInfo = () => getPackageInfoMock();
|
||||
|
||||
export const getMockPackageInfoVulnMgmtAWS = () => {
|
||||
return {
|
||||
|
@ -142,7 +144,7 @@ const getPolicyMock = (
|
|||
|
||||
const awsVarsMock = {
|
||||
access_key_id: { type: 'text' },
|
||||
secret_access_key: { type: 'text' },
|
||||
secret_access_key: { type: 'password', isSecret: true },
|
||||
session_token: { type: 'text' },
|
||||
shared_credential_file: { type: 'text' },
|
||||
credential_profile_name: { type: 'text' },
|
||||
|
@ -152,7 +154,7 @@ const getPolicyMock = (
|
|||
|
||||
const eksVarsMock = {
|
||||
access_key_id: { type: 'text' },
|
||||
secret_access_key: { type: 'text' },
|
||||
secret_access_key: { type: 'password', isSecret: true },
|
||||
session_token: { type: 'text' },
|
||||
shared_credential_file: { type: 'text' },
|
||||
credential_profile_name: { type: 'text' },
|
||||
|
@ -262,3 +264,95 @@ const getPolicyMock = (
|
|||
],
|
||||
};
|
||||
};
|
||||
|
||||
export const getPackageInfoMock = () => {
|
||||
return {
|
||||
data_streams: [
|
||||
{
|
||||
dataset: 'cloud_security_posture.findings',
|
||||
type: 'logs',
|
||||
|
||||
package: 'cloud_security_posture',
|
||||
path: 'findings',
|
||||
release: 'ga' as RegistryRelease,
|
||||
|
||||
title: 'Cloud Security Posture Findings',
|
||||
streams: [
|
||||
{
|
||||
input: 'cloudbeat/cis_aws',
|
||||
template_path: 'aws.yml.hbs',
|
||||
title: 'CIS AWS Benchmark',
|
||||
vars: [
|
||||
{
|
||||
name: 'secret_access_key',
|
||||
title: 'Secret Access Key',
|
||||
secret: true,
|
||||
type: 'text' as RegistryVarType,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
input: 'cloudbeat/cis_eks',
|
||||
template_path: 'eks.yml.hbs',
|
||||
title: 'Amazon EKS Benchmark',
|
||||
vars: [
|
||||
{
|
||||
name: 'secret_access_key',
|
||||
title: 'Secret Access Key',
|
||||
secret: true,
|
||||
type: 'text' as RegistryVarType,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
input: 'cloudbeat/cis_azure',
|
||||
template_path: 'azure.yml.hbs',
|
||||
title: 'CIS Azure Benchmark',
|
||||
vars: [
|
||||
{
|
||||
multi: false,
|
||||
name: 'azure.credentials.client_secret',
|
||||
required: false,
|
||||
secret: true,
|
||||
show_user: true,
|
||||
title: 'Client Secret',
|
||||
type: 'text' as RegistryVarType,
|
||||
},
|
||||
{
|
||||
multi: false,
|
||||
name: 'azure.credentials.client_password',
|
||||
required: false,
|
||||
secret: true,
|
||||
show_user: true,
|
||||
title: 'Client Password',
|
||||
type: 'text' as RegistryVarType,
|
||||
},
|
||||
{
|
||||
multi: false,
|
||||
name: 'azure.credentials.client_certificate_password',
|
||||
required: false,
|
||||
secret: true,
|
||||
show_user: true,
|
||||
title: 'Client Certificate Password',
|
||||
type: 'text' as RegistryVarType,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
format_version: '3.0.0',
|
||||
version: '1.9.0-preview109',
|
||||
name: 'cloud_security_posture',
|
||||
description: 'Identify & remediate configuration risks in your Cloud infrastructure',
|
||||
owner: {
|
||||
github: 'elastic/cloud-security-posture',
|
||||
type: 'elastic' as 'elastic' | 'partner' | 'community' | undefined,
|
||||
},
|
||||
title: 'Security Posture Management',
|
||||
latestVersion: '1.9.0',
|
||||
assets: {
|
||||
kibana: {},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
import { TestProvider } from '../../test/test_provider';
|
||||
import {
|
||||
getMockAgentlessAgentPolicy,
|
||||
getMockPackageInfo,
|
||||
getMockPackageInfoCspmAWS,
|
||||
getMockPackageInfoCspmAzure,
|
||||
getMockPackageInfoCspmGCP,
|
||||
|
@ -27,6 +28,7 @@ import {
|
|||
getMockPolicyGCP,
|
||||
getMockPolicyK8s,
|
||||
getMockPolicyVulnMgmtAWS,
|
||||
getPackageInfoMock,
|
||||
} from './mocks';
|
||||
import type {
|
||||
AgentPolicy,
|
||||
|
@ -58,6 +60,8 @@ import {
|
|||
SETUP_TECHNOLOGY_SELECTOR_ACCORDION_TEST_SUBJ,
|
||||
SETUP_TECHNOLOGY_SELECTOR_TEST_SUBJ,
|
||||
} from '../test_subjects';
|
||||
import { ExperimentalFeaturesService } from '@kbn/fleet-plugin/public/services';
|
||||
import { ThemeProvider } from '@emotion/react';
|
||||
|
||||
// mock useParams
|
||||
jest.mock('react-router-dom', () => ({
|
||||
|
@ -68,8 +72,10 @@ jest.mock('react-router-dom', () => ({
|
|||
}));
|
||||
jest.mock('../../common/api/use_setup_status_api');
|
||||
jest.mock('../../common/api/use_package_policy_list');
|
||||
jest.mock('@kbn/fleet-plugin/public/services/experimental_features');
|
||||
|
||||
const onChange = jest.fn();
|
||||
const mockedExperimentalFeaturesService = jest.mocked(ExperimentalFeaturesService);
|
||||
|
||||
const createReactQueryResponseWithRefetch = (
|
||||
data: Parameters<typeof createReactQueryResponse>[0]
|
||||
|
@ -85,6 +91,9 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
(useParams as jest.Mock).mockReturnValue({
|
||||
integration: undefined,
|
||||
});
|
||||
mockedExperimentalFeaturesService.get.mockReturnValue({
|
||||
secretsStorage: true,
|
||||
} as any);
|
||||
(usePackagePolicyList as jest.Mock).mockImplementation((packageName) =>
|
||||
createReactQueryResponseWithRefetch({
|
||||
status: 'success',
|
||||
|
@ -116,29 +125,31 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
onChange?: jest.Mock<void, [NewPackagePolicy]>;
|
||||
agentlessPolicy?: AgentPolicy;
|
||||
}) => (
|
||||
<TestProvider>
|
||||
{edit && (
|
||||
<CspPolicyTemplateForm
|
||||
policy={newPolicy as PackagePolicy}
|
||||
newPolicy={newPolicy}
|
||||
onChange={onChange}
|
||||
packageInfo={packageInfo}
|
||||
isEditPage={true}
|
||||
agentPolicy={agentPolicy}
|
||||
agentlessPolicy={agentlessPolicy}
|
||||
/>
|
||||
)}
|
||||
{!edit && (
|
||||
<CspPolicyTemplateForm
|
||||
newPolicy={newPolicy}
|
||||
onChange={onChange}
|
||||
packageInfo={packageInfo}
|
||||
isEditPage={false}
|
||||
agentPolicy={agentPolicy}
|
||||
agentlessPolicy={agentlessPolicy}
|
||||
/>
|
||||
)}
|
||||
</TestProvider>
|
||||
<ThemeProvider theme={() => ({ eui: { euiSizeXS: '4px' } })}>
|
||||
<TestProvider>
|
||||
{edit && (
|
||||
<CspPolicyTemplateForm
|
||||
policy={newPolicy as PackagePolicy}
|
||||
newPolicy={newPolicy}
|
||||
onChange={onChange}
|
||||
packageInfo={packageInfo}
|
||||
isEditPage={true}
|
||||
agentPolicy={agentPolicy}
|
||||
agentlessPolicy={agentlessPolicy}
|
||||
/>
|
||||
)}
|
||||
{!edit && (
|
||||
<CspPolicyTemplateForm
|
||||
newPolicy={newPolicy}
|
||||
onChange={onChange}
|
||||
packageInfo={packageInfo}
|
||||
isEditPage={false}
|
||||
agentPolicy={agentPolicy}
|
||||
agentlessPolicy={agentlessPolicy}
|
||||
/>
|
||||
)}
|
||||
</TestProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
it('updates package policy namespace to default when it changes', () => {
|
||||
|
@ -625,29 +636,32 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it(`renders ${CLOUDBEAT_EKS} Direct Access Keys fields`, () => {
|
||||
let policy: NewPackagePolicy = getMockPolicyEKS();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, {
|
||||
'aws.credentials.type': { value: 'direct_access_keys' },
|
||||
'aws.setup.format': { value: 'manual' },
|
||||
});
|
||||
|
||||
const { getByLabelText } = render(<WrappedComponent newPolicy={policy} />);
|
||||
|
||||
const option = getByLabelText('Direct access keys');
|
||||
expect(option).toBeChecked();
|
||||
|
||||
expect(getByLabelText('Access Key ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Secret Access Key')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it(`updates ${CLOUDBEAT_EKS} Direct Access Keys fields`, () => {
|
||||
it(`renders ${CLOUDBEAT_EKS} Direct Access Keys fields`, async () => {
|
||||
let policy = getMockPolicyEKS();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, {
|
||||
'aws.credentials.type': { value: 'direct_access_keys' },
|
||||
'aws.setup.format': { value: 'manual' },
|
||||
});
|
||||
const { getByLabelText, rerender } = render(<WrappedComponent newPolicy={policy} />);
|
||||
const { getByLabelText } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
const option = getByLabelText('Direct access keys');
|
||||
expect(option).toBeChecked();
|
||||
|
||||
expect(getByLabelText('Access Key ID')).toBeInTheDocument();
|
||||
await waitFor(() => expect(getByLabelText('Secret Access Key')).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it(`updates ${CLOUDBEAT_EKS} Direct Access Keys fields`, async () => {
|
||||
let policy = getMockPolicyEKS();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, {
|
||||
'aws.credentials.type': { value: 'direct_access_keys' },
|
||||
'aws.setup.format': { value: 'manual' },
|
||||
});
|
||||
const { getByLabelText, rerender, getByTestId } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Access Key ID'), 'a');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, { access_key_id: { value: 'a' } });
|
||||
|
@ -658,10 +672,12 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(<WrappedComponent newPolicy={policy} />);
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Secret Access Key'), 'b');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, { secret_access_key: { value: 'b' } });
|
||||
await waitFor(() => userEvent.type(getByTestId('passwordInput-secret-access-key'), 'c'));
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, { secret_access_key: { value: 'c' } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
|
@ -669,30 +685,34 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it(`renders ${CLOUDBEAT_EKS} Temporary Keys fields`, () => {
|
||||
it(`renders ${CLOUDBEAT_EKS} Temporary Keys fields`, async () => {
|
||||
let policy: NewPackagePolicy = getMockPolicyEKS();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, {
|
||||
'aws.credentials.type': { value: 'temporary_keys' },
|
||||
'aws.setup.format': { value: 'manual' },
|
||||
});
|
||||
|
||||
const { getByLabelText } = render(<WrappedComponent newPolicy={policy} />);
|
||||
const { getByLabelText } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
const option = getByLabelText('Temporary keys');
|
||||
expect(option).toBeChecked();
|
||||
|
||||
expect(getByLabelText('Access Key ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Secret Access Key')).toBeInTheDocument();
|
||||
await waitFor(() => expect(getByLabelText('Secret Access Key')).toBeInTheDocument());
|
||||
expect(getByLabelText('Session Token')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it(`updates ${CLOUDBEAT_EKS} Temporary Keys fields`, () => {
|
||||
it(`updates ${CLOUDBEAT_EKS} Temporary Keys fields`, async () => {
|
||||
let policy = getMockPolicyEKS();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, {
|
||||
'aws.credentials.type': { value: 'temporary_keys' },
|
||||
'aws.setup.format': { value: 'manual' },
|
||||
});
|
||||
const { getByLabelText, rerender } = render(<WrappedComponent newPolicy={policy} />);
|
||||
const { getByLabelText, rerender, getByTestId } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Access Key ID'), 'a');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, { access_key_id: { value: 'a' } });
|
||||
|
@ -702,17 +722,21 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(<WrappedComponent newPolicy={policy} />);
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Secret Access Key'), 'b');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, { secret_access_key: { value: 'b' } });
|
||||
await waitFor(() => userEvent.type(getByTestId('passwordInput-secret-access-key'), 'c'));
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, { secret_access_key: { value: 'c' } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(<WrappedComponent newPolicy={policy} />);
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Session Token'), 'a');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_EKS, { session_token: { value: 'a' } });
|
||||
|
@ -907,30 +931,34 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it(`renders ${CLOUDBEAT_AWS} Direct Access Keys fields`, () => {
|
||||
it(`renders ${CLOUDBEAT_AWS} Direct Access Keys fields`, async () => {
|
||||
let policy: NewPackagePolicy = getMockPolicyAWS();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AWS, {
|
||||
'aws.credentials.type': { value: 'direct_access_keys' },
|
||||
'aws.setup.format': { value: 'manual' },
|
||||
});
|
||||
|
||||
const { getByLabelText, getByRole } = render(<WrappedComponent newPolicy={policy} />);
|
||||
const { getByLabelText, getByRole } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
expect(
|
||||
getByRole('option', { name: 'Direct access keys', selected: true })
|
||||
).toBeInTheDocument();
|
||||
|
||||
expect(getByLabelText('Access Key ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Secret Access Key')).toBeInTheDocument();
|
||||
await waitFor(() => expect(getByLabelText('Secret Access Key')).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it(`updates ${CLOUDBEAT_AWS} Direct Access Keys fields`, () => {
|
||||
it(`updates ${CLOUDBEAT_AWS} Direct Access Keys fields`, async () => {
|
||||
let policy = getMockPolicyAWS();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AWS, {
|
||||
'aws.credentials.type': { value: 'direct_access_keys' },
|
||||
'aws.setup.format': { value: 'manual' },
|
||||
});
|
||||
const { getByLabelText, rerender } = render(<WrappedComponent newPolicy={policy} />);
|
||||
const { getByLabelText, rerender, getByTestId } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Access Key ID'), 'a');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AWS, { access_key_id: { value: 'a' } });
|
||||
|
@ -941,9 +969,11 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(<WrappedComponent newPolicy={policy} />);
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Secret Access Key'), 'b');
|
||||
await waitFor(() => userEvent.type(getByTestId('passwordInput-secret-access-key'), 'b'));
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AWS, { secret_access_key: { value: 'b' } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
|
@ -952,28 +982,32 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it(`renders ${CLOUDBEAT_AWS} Temporary Keys fields`, () => {
|
||||
it(`renders ${CLOUDBEAT_AWS} Temporary Keys fields`, async () => {
|
||||
let policy: NewPackagePolicy = getMockPolicyAWS();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AWS, {
|
||||
'aws.credentials.type': { value: 'temporary_keys' },
|
||||
'aws.setup.format': { value: 'manual' },
|
||||
});
|
||||
|
||||
const { getByLabelText, getByRole } = render(<WrappedComponent newPolicy={policy} />);
|
||||
const { getByLabelText, getByRole } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
expect(getByRole('option', { name: 'Temporary keys', selected: true })).toBeInTheDocument();
|
||||
|
||||
expect(getByLabelText('Access Key ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Secret Access Key')).toBeInTheDocument();
|
||||
await waitFor(() => expect(getByLabelText('Secret Access Key')).toBeInTheDocument());
|
||||
expect(getByLabelText('Session Token')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it(`updates ${CLOUDBEAT_AWS} Temporary Keys fields`, () => {
|
||||
it(`updates ${CLOUDBEAT_AWS} Temporary Keys fields`, async () => {
|
||||
let policy = getMockPolicyAWS();
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AWS, {
|
||||
'aws.credentials.type': { value: 'temporary_keys' },
|
||||
'aws.setup.format': { value: 'manual' },
|
||||
});
|
||||
const { getByLabelText, rerender } = render(<WrappedComponent newPolicy={policy} />);
|
||||
const { getByLabelText, rerender, getByTestId } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Access Key ID'), 'a');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AWS, { access_key_id: { value: 'a' } });
|
||||
|
@ -983,9 +1017,16 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(<WrappedComponent newPolicy={policy} />);
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
userEvent.type(getByLabelText('Secret Access Key'), 'b');
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
await waitFor(() => userEvent.type(getByTestId('passwordInput-secret-access-key'), 'b'));
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AWS, { secret_access_key: { value: 'b' } });
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
|
@ -993,7 +1034,9 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
updatedPolicy: policy,
|
||||
});
|
||||
|
||||
rerender(<WrappedComponent newPolicy={policy} />);
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfo() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Session Token'), 'a');
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AWS, { session_token: { value: 'a' } });
|
||||
|
@ -1384,14 +1427,14 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it(`renders ${CLOUDBEAT_AZURE} Service Principal with Client Secret fields`, () => {
|
||||
it(`renders ${CLOUDBEAT_AZURE} Service Principal with Client Secret fields`, async () => {
|
||||
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')} />
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getPackageInfoMock() as PackageInfo} />
|
||||
);
|
||||
|
||||
expect(
|
||||
|
@ -1399,17 +1442,17 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
).toBeInTheDocument();
|
||||
expect(getByLabelText('Tenant ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client Secret')).toBeInTheDocument();
|
||||
await waitFor(() => expect(getByLabelText('Client Secret')).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it(`updates ${CLOUDBEAT_AZURE} Service Principal with Client Secret fields`, () => {
|
||||
it(`updates ${CLOUDBEAT_AZURE} Service Principal with Client Secret fields`, async () => {
|
||||
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')} />
|
||||
const { rerender, getByLabelText, getByTestId } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getPackageInfoMock() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Tenant ID'), 'a');
|
||||
|
@ -1424,7 +1467,7 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getPackageInfoMock() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client ID'), 'b');
|
||||
|
@ -1438,10 +1481,10 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getPackageInfoMock() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client Secret'), 'c');
|
||||
await waitFor(() => userEvent.type(getByTestId('passwordInput-client-secret'), 'c'));
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_secret': { value: 'c' },
|
||||
});
|
||||
|
@ -1600,7 +1643,7 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
<WrappedComponent
|
||||
newPolicy={newPackagePolicy}
|
||||
agentlessPolicy={agentlessPolicy}
|
||||
packageInfo={{ version: '1.8.0' } as PackageInfo}
|
||||
packageInfo={getPackageInfoMock() as PackageInfo}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -1649,7 +1692,7 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
<WrappedComponent
|
||||
newPolicy={newPackagePolicy}
|
||||
agentlessPolicy={agentlessPolicy}
|
||||
packageInfo={{ version: '1.8.0' } as PackageInfo}
|
||||
packageInfo={getPackageInfoMock() as PackageInfo}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -1709,14 +1752,14 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it(`renders Service principal with Client Certificate fields`, () => {
|
||||
it(`renders Service principal with Client Certificate fields`, async () => {
|
||||
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')} />
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getPackageInfoMock() as PackageInfo} />
|
||||
);
|
||||
|
||||
expect(
|
||||
|
@ -1725,17 +1768,17 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
expect(getByLabelText('Tenant ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client ID')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client Certificate Path')).toBeInTheDocument();
|
||||
expect(getByLabelText('Client Certificate Password')).toBeInTheDocument();
|
||||
await waitFor(() => expect(getByLabelText('Client Certificate Password')).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it(`updates Service principal with Client Certificate fields`, () => {
|
||||
it(`updates Service principal with Client Certificate fields`, async () => {
|
||||
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')} />
|
||||
const { rerender, getByLabelText, getByTestId } = render(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getPackageInfoMock() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Tenant ID'), 'a');
|
||||
|
@ -1750,7 +1793,7 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getPackageInfoMock() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client ID'), 'b');
|
||||
|
@ -1764,7 +1807,7 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getPackageInfoMock() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client Certificate Path'), 'c');
|
||||
|
@ -1778,10 +1821,12 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
|
||||
rerender(
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getMockPackageInfoCspmAzure('1.7.0')} />
|
||||
<WrappedComponent newPolicy={policy} packageInfo={getPackageInfoMock() as PackageInfo} />
|
||||
);
|
||||
|
||||
userEvent.type(getByLabelText('Client Certificate Password'), 'd');
|
||||
await waitFor(() =>
|
||||
userEvent.type(getByTestId('passwordInput-client-certificate-password'), 'd')
|
||||
);
|
||||
policy = getPosturePolicy(policy, CLOUDBEAT_AZURE, {
|
||||
'azure.credentials.client_certificate_password': { value: 'd' },
|
||||
});
|
||||
|
|
|
@ -16,8 +16,9 @@ import {
|
|||
getDefaultAwsCredentialsType,
|
||||
getDefaultAzureCredentialsType,
|
||||
getDefaultGcpHiddenVars,
|
||||
findVariableDef,
|
||||
} from './utils';
|
||||
import { getMockPolicyAWS, getMockPolicyK8s, getMockPolicyEKS } from './mocks';
|
||||
import { getMockPolicyAWS, getMockPolicyK8s, getMockPolicyEKS, getPackageInfoMock } from './mocks';
|
||||
|
||||
describe('getPosturePolicy', () => {
|
||||
for (const [name, getPolicy, expectedVars] of [
|
||||
|
@ -486,3 +487,65 @@ describe('getDefaultGcpHiddenVars', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('findVariableDef', () => {
|
||||
it('Should return var item when key exist', () => {
|
||||
const packageInfo = getPackageInfoMock() as PackageInfo;
|
||||
const key = 'secret_access_key';
|
||||
const result = findVariableDef(packageInfo, key);
|
||||
|
||||
expect(result).toMatchObject({
|
||||
name: 'secret_access_key',
|
||||
secret: true,
|
||||
title: 'Secret Access Key',
|
||||
});
|
||||
});
|
||||
|
||||
it('Should return undefined when key is invalid', () => {
|
||||
const packageInfo = getPackageInfoMock() as PackageInfo;
|
||||
const key = 'invalid_access_key';
|
||||
const result = findVariableDef(packageInfo, key);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should return undefined when datastream is undefined', () => {
|
||||
const packageInfo = {
|
||||
data_streams: [{}],
|
||||
} as PackageInfo;
|
||||
const key = 'secret_access_key';
|
||||
const result = findVariableDef(packageInfo, key);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should return undefined when stream is undefined', () => {
|
||||
const packageInfo = {
|
||||
data_streams: [
|
||||
{
|
||||
title: 'Cloud Security Posture Findings',
|
||||
streams: [{}],
|
||||
},
|
||||
],
|
||||
} as PackageInfo;
|
||||
const key = 'secret_access_key';
|
||||
const result = findVariableDef(packageInfo, key);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('Should return undefined when stream.var is invalid', () => {
|
||||
const packageInfo = {
|
||||
data_streams: [
|
||||
{
|
||||
title: 'Cloud Security Posture Findings',
|
||||
streams: [{ vars: {} }],
|
||||
},
|
||||
],
|
||||
} as PackageInfo;
|
||||
const key = 'secret_access_key';
|
||||
const result = findVariableDef(packageInfo, key);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -378,3 +378,20 @@ export const isBelowMinVersion = (version: string, minVersion: string) => {
|
|||
const versionNumberOnly = semverCoerce(semanticVersion) || '';
|
||||
return semverLt(versionNumberOnly, minVersion);
|
||||
};
|
||||
|
||||
/**
|
||||
* Searches for a variable definition in a given packageInfo object based on a specified key.
|
||||
* It navigates through nested arrays within the packageInfo object to locate the variable definition associated with the provided key.
|
||||
* If found, it returns the variable definition object; otherwise, it returns undefined.
|
||||
*/
|
||||
export const findVariableDef = (packageInfo: PackageInfo, key: string) => {
|
||||
return packageInfo?.data_streams
|
||||
?.filter((datastreams) => datastreams !== undefined)
|
||||
.map((ds) => ds.streams)
|
||||
.filter((streams) => streams !== undefined)
|
||||
.flat()
|
||||
.filter((streams) => streams?.vars !== undefined)
|
||||
.map((cis) => cis?.vars)
|
||||
.flat()
|
||||
.find((vars) => vars?.name === key);
|
||||
};
|
||||
|
|
|
@ -66,7 +66,7 @@ export const SETUP_TECHNOLOGY_SELECTOR_TEST_SUBJ = 'setup-technology-selector';
|
|||
export const CIS_AZURE_INPUT_FIELDS_TEST_SUBJECTS = {
|
||||
TENANT_ID: 'cisAzureTenantId',
|
||||
CLIENT_ID: 'cisAzureClientId',
|
||||
CLIENT_SECRET: 'cisAzureClientSecret',
|
||||
CLIENT_SECRET: 'passwordInput-client-secret',
|
||||
CLIENT_CERTIFICATE_PATH: 'cisAzureClientCertificatePath',
|
||||
CLIENT_CERTIFICATE_PASSWORD: 'cisAzureClientCertificatePassword',
|
||||
CLIENT_USERNAME: 'cisAzureClientUsername',
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState, memo, useMemo, useRef } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -51,11 +50,11 @@ const FormRow = styled(EuiFormRow)`
|
|||
}
|
||||
|
||||
.euiFormRow__fieldWrapper > .euiPanel {
|
||||
padding: ${(props) => props.theme.eui.euiSizeXS};
|
||||
padding: ${(props) => props.theme.eui?.euiSizeXS};
|
||||
}
|
||||
`;
|
||||
|
||||
interface InputFieldProps {
|
||||
export interface InputFieldProps {
|
||||
varDef: RegistryVarsEntry;
|
||||
value: any;
|
||||
onChange: (newValue: any) => void;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
import type { PluginInitializerContext } from '@kbn/core/public';
|
||||
|
||||
import { lazy } from 'react';
|
||||
|
||||
import { FleetPlugin } from './plugin';
|
||||
|
||||
export type { FleetSetup, FleetStart, FleetStartServices } from './plugin';
|
||||
|
@ -62,9 +64,16 @@ export { PackagePolicyEditorDatastreamPipelines } from './applications/fleet/sec
|
|||
export type { PackagePolicyEditorDatastreamPipelinesProps } from './applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_pipelines';
|
||||
export { PackagePolicyEditorDatastreamMappings } from './applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_mappings';
|
||||
export type { PackagePolicyEditorDatastreamMappingsProps } from './applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_mappings';
|
||||
|
||||
export type { DynamicPagePathValues } from './constants';
|
||||
|
||||
// This Type export is added to prevent error TS4023
|
||||
export type { InputFieldProps } from './applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_var_field';
|
||||
|
||||
export const LazyPackagePolicyInputVarField = lazy(() =>
|
||||
import(
|
||||
'./applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_var_field'
|
||||
).then((module) => ({ default: module.PackagePolicyInputVarField }))
|
||||
);
|
||||
export type { PackageListGridProps } from './applications/integrations/sections/epm/components/package_list_grid';
|
||||
export type { AvailablePackagesHookType } from './applications/integrations/sections/epm/screens/home/hooks/use_available_packages';
|
||||
export type { IntegrationCardItem } from './applications/integrations/sections/epm/screens/home';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue