oscap: add the compliance step to the wizard
This commit adds the Compliance step to the wizard. In this step the user can select a policy from the list of available policies. Their image is going to be updated with the necessary changes on the later steps. IB and The compliance endpoint are both returning the list of policies a user has access to. The oscap step computes the intersection of the policies accessible before showing the select list to the user. HMS-2077
This commit is contained in:
parent
1587ead4d9
commit
02a642df19
6 changed files with 209 additions and 1 deletions
|
|
@ -19,6 +19,7 @@ import {
|
|||
registration,
|
||||
repositories,
|
||||
review,
|
||||
oscap,
|
||||
} from './steps';
|
||||
import {
|
||||
fileSystemConfigurationValidator,
|
||||
|
|
@ -95,6 +96,12 @@ const onSave = (values) => {
|
|||
}
|
||||
}
|
||||
|
||||
if (values['oscap-policy']) {
|
||||
customizations.openscap = {
|
||||
profile_id: values['oscap-policy'],
|
||||
};
|
||||
}
|
||||
|
||||
const requests = [];
|
||||
if (values['target-environment']?.aws) {
|
||||
const options =
|
||||
|
|
@ -470,6 +477,10 @@ const requestToState = (composeRequest, distroInfo, isBeta, isProd) => {
|
|||
formState['register-system'] = 'register-later';
|
||||
}
|
||||
|
||||
// oscap policy
|
||||
formState['oscap-policy'] =
|
||||
composeRequest?.customizations?.openscap?.profile_id;
|
||||
|
||||
return formState;
|
||||
} else {
|
||||
return;
|
||||
|
|
@ -495,6 +506,8 @@ const formStepHistory = (composeRequest, contentSourcesEnabled) => {
|
|||
steps.push('registration');
|
||||
}
|
||||
|
||||
steps.push('Compliance');
|
||||
|
||||
if (contentSourcesEnabled) {
|
||||
steps.push('File system configuration', 'packages', 'repositories');
|
||||
|
||||
|
|
@ -654,6 +667,7 @@ const CreateImageWizard = () => {
|
|||
fileSystemConfiguration,
|
||||
imageName,
|
||||
review,
|
||||
oscap,
|
||||
],
|
||||
initialState: {
|
||||
activeStep: initialStep || 'image-output', // name of the active step
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import CentOSAcknowledgement from './formComponents/CentOSAcknowledgement';
|
|||
import FileSystemConfiguration from './formComponents/FileSystemConfiguration';
|
||||
import GalleryLayout from './formComponents/GalleryLayout';
|
||||
import ImageOutputReleaseSelect from './formComponents/ImageOutputReleaseSelect';
|
||||
import { Oscap } from './formComponents/Oscap';
|
||||
import {
|
||||
ContentSourcesPackages,
|
||||
RedHatPackages,
|
||||
|
|
@ -72,6 +73,7 @@ const ImageCreator = ({
|
|||
'azure-sources-select': AzureSourcesSelect,
|
||||
'azure-resource-groups': AzureResourceGroups,
|
||||
'gallery-layout': GalleryLayout,
|
||||
'oscap-profile-selector': Oscap,
|
||||
registration: Registration,
|
||||
...customComponentMapper,
|
||||
}}
|
||||
|
|
|
|||
155
src/Components/CreateImageWizard/formComponents/Oscap.js
Normal file
155
src/Components/CreateImageWizard/formComponents/Oscap.js
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
import React, { useState } from 'react';
|
||||
|
||||
import useFieldApi from '@data-driven-forms/react-form-renderer/use-field-api';
|
||||
import useFormApi from '@data-driven-forms/react-form-renderer/use-form-api';
|
||||
import {
|
||||
Alert,
|
||||
Radio,
|
||||
FormGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
Spinner,
|
||||
} from '@patternfly/react-core';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useGetOscapProfilesQuery } from '../../../store/imageBuilderApi';
|
||||
|
||||
/**
|
||||
* Component for the user to select the policy to apply to their image.
|
||||
* The selected policy will be stored in the `oscap-policy` form state variable.
|
||||
* The Component is shown or not depending on the ShowSelector variable.
|
||||
*/
|
||||
const PolicySelector = ({ input, showSelector }) => {
|
||||
const { change, getState } = useFormApi();
|
||||
const [policy, selectPolicy] = useState(getState()?.values?.['oscap-policy']);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const { data, isFetching, isSuccess, isError, refetch } =
|
||||
useGetOscapProfilesQuery(
|
||||
{
|
||||
distribution: getState()?.values?.['release'],
|
||||
},
|
||||
{
|
||||
skip: !showSelector,
|
||||
}
|
||||
);
|
||||
|
||||
if (!showSelector) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const handleToggle = () => {
|
||||
if (!isOpen) {
|
||||
refetch();
|
||||
}
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
const handleClear = () => {
|
||||
selectPolicy(undefined);
|
||||
change(input.name, undefined);
|
||||
};
|
||||
|
||||
const setPolicy = (_, selection) => {
|
||||
selectPolicy(selection);
|
||||
setIsOpen(false);
|
||||
change(input.name, selection);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
isRequired={true}
|
||||
label={'Policy to use for this image'}
|
||||
data-testid="policies-form-group"
|
||||
>
|
||||
<Select
|
||||
ouiaId="policySelect"
|
||||
variant={SelectVariant.typeahead}
|
||||
onToggle={handleToggle}
|
||||
onSelect={setPolicy}
|
||||
onClear={handleClear}
|
||||
selections={policy}
|
||||
isOpen={isOpen}
|
||||
placeholderText="Select a policy"
|
||||
typeAheadAriaLabel="Select a policy"
|
||||
isDisabled={!isSuccess}
|
||||
>
|
||||
{isSuccess &&
|
||||
data.map((key, index) => <SelectOption key={index} value={key} />)}
|
||||
{isFetching && (
|
||||
<SelectOption isNoResultsOption={true} data-testid="policies-loading">
|
||||
<Spinner isSVG size="md" />
|
||||
</SelectOption>
|
||||
)}
|
||||
</Select>
|
||||
{isError && (
|
||||
<Alert
|
||||
title="Error fetching the policies"
|
||||
variant="danger"
|
||||
isPlain
|
||||
isInline
|
||||
>
|
||||
Cannot get the list of policies
|
||||
</Alert>
|
||||
)}
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
|
||||
PolicySelector.propTypes = {
|
||||
input: PropTypes.any,
|
||||
showSelector: PropTypes.bool,
|
||||
};
|
||||
|
||||
/**
|
||||
* Component to prompt the use with two choices:
|
||||
* - to add a policy, in which case the PolicySelector will allow the user to
|
||||
* pick a policy to be stored in the `oscap-policy` variable.
|
||||
* - to not add a policy, in which case the `oscap-policy` form state goes
|
||||
* undefined.
|
||||
*/
|
||||
const AddPolicy = ({ input }) => {
|
||||
const { change, getState } = useFormApi();
|
||||
const oscapPolicy = getState()?.values?.['oscap-policy'];
|
||||
const [wantsPolicy, setWantsPolicy] = useState(oscapPolicy !== undefined);
|
||||
return (
|
||||
<>
|
||||
<FormGroup label="Compliance policy">
|
||||
<Radio
|
||||
name="add-a-policy"
|
||||
className="pf-u-mt-md"
|
||||
data-testid="add-a-policy-radio"
|
||||
id="add-a-policy"
|
||||
label="Add a policy"
|
||||
isChecked={wantsPolicy}
|
||||
onChange={() => {
|
||||
setWantsPolicy(true);
|
||||
}}
|
||||
/>
|
||||
<Radio
|
||||
name="dont-add-a-policy"
|
||||
className="pf-u-mt-md"
|
||||
data-testid="dont-add-a-policy-radio"
|
||||
id="dont-add-a-policy"
|
||||
label="Do not add a policy"
|
||||
isChecked={!wantsPolicy}
|
||||
onChange={() => {
|
||||
setWantsPolicy(false);
|
||||
change(input.name, undefined);
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
<PolicySelector input={input} showSelector={wantsPolicy} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
AddPolicy.propTypes = {
|
||||
input: PropTypes.object,
|
||||
};
|
||||
|
||||
export const Oscap = ({ ...props }) => {
|
||||
const { input } = useFieldApi(props);
|
||||
return <AddPolicy input={input} />;
|
||||
};
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
export { default as awsTarget } from './aws';
|
||||
export { default as googleCloudTarget } from './googleCloud';
|
||||
export { default as msAzureTarget } from './msAzure';
|
||||
export { default as oscap } from './oscap';
|
||||
export { default as packages } from './packages';
|
||||
export { default as packagesContentSources } from './packagesContentSources';
|
||||
export { default as registration } from './registration';
|
||||
|
|
|
|||
36
src/Components/CreateImageWizard/steps/oscap.js
Normal file
36
src/Components/CreateImageWizard/steps/oscap.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import React from 'react';
|
||||
|
||||
import componentTypes from '@data-driven-forms/react-form-renderer/component-types';
|
||||
import { Text } from '@patternfly/react-core';
|
||||
|
||||
import StepTemplate from './stepTemplate';
|
||||
|
||||
import CustomButtons from '../formComponents/CustomButtons';
|
||||
|
||||
const oscapStep = {
|
||||
StepTemplate,
|
||||
id: 'wizard-systemconfiguration-oscap',
|
||||
title: 'OpenSCAP Compliance',
|
||||
name: 'Compliance',
|
||||
nextStep: 'File system configuration',
|
||||
buttons: CustomButtons,
|
||||
fields: [
|
||||
{
|
||||
component: componentTypes.PLAIN_TEXT,
|
||||
name: 'oscap-text-component',
|
||||
label: (
|
||||
<Text>
|
||||
Monitor regulatory compliance policies of registered RHEL systems you
|
||||
must adhere to via OpenSCAP.
|
||||
</Text>
|
||||
),
|
||||
},
|
||||
{
|
||||
component: 'oscap-profile-selector',
|
||||
name: 'oscap-policy',
|
||||
label: 'Available profiles for the distribution',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default oscapStep;
|
||||
|
|
@ -69,7 +69,7 @@ const registrationStep = {
|
|||
</Title>
|
||||
),
|
||||
name: 'registration',
|
||||
nextStep: 'File system configuration',
|
||||
nextStep: 'Compliance',
|
||||
buttons: CustomButtons,
|
||||
fields: [
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue