diff --git a/src/Components/CreateImageWizardV2/steps/Oscap/Oscap.tsx b/src/Components/CreateImageWizardV2/steps/Oscap/Oscap.tsx index d688541e..57f7ad61 100644 --- a/src/Components/CreateImageWizardV2/steps/Oscap/Oscap.tsx +++ b/src/Components/CreateImageWizardV2/steps/Oscap/Oscap.tsx @@ -26,12 +26,23 @@ import { } from '../../../../store/imageBuilderApi'; import { changeOscapProfile, + changeKernel, selectDistribution, selectProfile, + selectKernel, + selectDisabledServices, + selectEnabledServices, + changeDisabledServices, + changeEnabledServices, } from '../../../../store/wizardSlice'; const ProfileSelector = () => { const oscapProfile = useAppSelector((state) => selectProfile(state)); + let kernel = useAppSelector((state) => selectKernel(state)); + let disabledServices = useAppSelector((state) => + selectDisabledServices(state) + ); + let enabledServices = useAppSelector((state) => selectEnabledServices(state)); const release = useAppSelector((state) => selectDistribution(state)); const dispatch = useAppDispatch(); const [profileName, setProfileName] = useState('None'); @@ -56,6 +67,26 @@ const ProfileSelector = () => { skip: !oscapProfile, } ); + kernel = data?.kernel?.append; + disabledServices = data?.services?.disabled; + enabledServices = data?.services?.enabled; + + useEffect(() => { + if (isFetching || !isSuccess) return; + dispatch(changeKernel(kernel)); + dispatch(changeDisabledServices(disabledServices)); + dispatch(changeEnabledServices(enabledServices)); + }, [ + isFetching, + isSuccess, + dispatch, + data?.kernel?.append, + data?.services?.disabled, + data?.services?.enabled, + disabledServices, + enabledServices, + kernel, + ]); useEffect(() => { if ( @@ -76,6 +107,9 @@ const ProfileSelector = () => { const handleClear = () => { dispatch(changeOscapProfile(undefined)); + dispatch(changeKernel(undefined)); + dispatch(changeDisabledServices(undefined)); + dispatch(changeEnabledServices(undefined)); setProfileName(undefined); }; @@ -84,6 +118,9 @@ const ProfileSelector = () => { selection: DistributionProfileItem ) => { dispatch(changeOscapProfile(selection)); + dispatch(changeKernel(kernel)); + dispatch(changeDisabledServices(disabledServices)); + dispatch(changeEnabledServices(enabledServices)); setIsOpen(false); }; diff --git a/src/Components/CreateImageWizardV2/steps/Oscap/OscapProfileInformation.tsx b/src/Components/CreateImageWizardV2/steps/Oscap/OscapProfileInformation.tsx index 643e0905..6d9f44a2 100644 --- a/src/Components/CreateImageWizardV2/steps/Oscap/OscapProfileInformation.tsx +++ b/src/Components/CreateImageWizardV2/steps/Oscap/OscapProfileInformation.tsx @@ -1,6 +1,9 @@ import React from 'react'; import { + Alert, + CodeBlock, + CodeBlockCode, Spinner, TextContent, TextList, @@ -17,7 +20,7 @@ import { selectProfile, } from '../../../../store/wizardSlice'; -const OscapProfileInformation = (): JSX.Element => { +export const OscapProfileInformation = (): JSX.Element => { const release = useAppSelector((state) => selectDistribution(state)); const oscapProfile = useAppSelector((state) => selectProfile(state)); @@ -36,46 +39,97 @@ const OscapProfileInformation = (): JSX.Element => { } ); + const enabledServicesDisplayString = + oscapProfileInfo?.services?.enabled?.join(' '); + const disableServicesDisplayString = + oscapProfileInfo?.services?.disabled?.join(' '); + return ( <> {isFetchingOscapProfileInfo && } {isSuccessOscapProfileInfo && ( - -
- - - Profile description: - - - {oscapProfileInfo.openscap?.profile_description} - - - - - Operating system: - - - {RELEASES.get(release)} - - - - - Reference ID: - - - {oscapProfileInfo.openscap?.profile_id} - - -
+ <> + +
+ + + Profile description: + + + {oscapProfileInfo.openscap?.profile_description} + + component={TextListVariants.dl} + + Operating system: + + + {RELEASES.get(release)} + + component={TextListVariants.dl} + + Reference ID: + + + {oscapProfileInfo.openscap?.profile_id} + + + Kernel arguments: + + + + + {oscapProfileInfo?.kernel?.append} + + + + + Disabled services: + + + + {disableServicesDisplayString} + + + + Enabled services: + + + + {enabledServicesDisplayString} + + + +
+ + + Selecting an OpenSCAP profile will cause the appropriate packages, + file system configuration, kernel arguments, and services to be + added to your image. + + )} ); diff --git a/src/Components/CreateImageWizardV2/steps/Review/ReviewStepTextLists.tsx b/src/Components/CreateImageWizardV2/steps/Review/ReviewStepTextLists.tsx index e3792ef5..7065ec9f 100644 --- a/src/Components/CreateImageWizardV2/steps/Review/ReviewStepTextLists.tsx +++ b/src/Components/CreateImageWizardV2/steps/Review/ReviewStepTextLists.tsx @@ -30,7 +30,6 @@ import { } from '../../../../constants'; import { extractProvisioningList } from '../../../../store/helpers'; import { useAppSelector } from '../../../../store/hooks'; -import { useGetOscapCustomizationsQuery } from '../../../../store/imageBuilderApi'; import { useGetSourceListQuery } from '../../../../store/provisioningApi'; import { useShowActivationKeyQuery } from '../../../../store/rhsmApi'; import { @@ -45,12 +44,12 @@ import { selectGcpAccountType, selectGcpEmail, selectGcpShareMethod, - selectProfile, selectRegistrationType, } from '../../../../store/wizardSlice'; import { toMonthAndYear } from '../../../../Utilities/time'; import { useGetEnvironment } from '../../../../Utilities/useGetEnvironment'; import { MajorReleasesLifecyclesChart } from '../../../CreateImageWizard/formComponents/ReleaseLifecycle'; +import OscapProfileInformation from '../Oscap/OscapProfileInformation'; const ExpirationWarning = () => { return ( @@ -501,54 +500,5 @@ export const ImageDetailsList = () => { }; export const OscapList = () => { - const oscapProfile = useAppSelector((state) => selectProfile(state)); - const release = useAppSelector((state) => selectDistribution(state)); - const { data } = useGetOscapCustomizationsQuery( - { - distribution: release, - // @ts-ignore if oscapProfile is undefined the query is going to get skipped, so it's safe here to ignore the linter here - profile: oscapProfile, - }, - { - skip: !oscapProfile, - } - ); - return ( - - - - Profile name: - - - {data?.openscap?.profile_name} - - - - - Profile description: - - - {data?.openscap?.profile_description} - - - - - Reference ID: - - - {oscapProfile} - - -
-
- ); + return ; }; diff --git a/src/store/wizardSlice.ts b/src/store/wizardSlice.ts index f227be78..ead8d0c5 100644 --- a/src/store/wizardSlice.ts +++ b/src/store/wizardSlice.ts @@ -45,7 +45,15 @@ type wizardState = { }; openScap: { profile: DistributionProfileItem | undefined; + kernel: { + kernelAppend: string | undefined; + }; + services: { + disabled: string[] | undefined; + enabled: string[] | undefined; + }; }; + repositories: { customRepositories: CustomRepository[]; }; @@ -79,6 +87,13 @@ const initialState: wizardState = { }, openScap: { profile: undefined, + kernel: { + kernelAppend: '', + }, + services: { + disabled: [], + enabled: [], + }, }, repositories: { customRepositories: [], @@ -147,6 +162,18 @@ export const selectProfile = (state: RootState) => { return state.wizard.openScap.profile; }; +export const selectKernel = (state: RootState) => { + return state.wizard.openScap.kernel.kernelAppend; +}; + +export const selectDisabledServices = (state: RootState) => { + return state.wizard.openScap.services.disabled; +}; + +export const selectEnabledServices = (state: RootState) => { + return state.wizard.openScap.services.enabled; +}; + export const selectCustomRepositories = (state: RootState) => { return state.wizard.repositories.customRepositories; }; @@ -238,6 +265,22 @@ export const wizardSlice = createSlice({ ) => { state.openScap.profile = action.payload; }, + + changeKernel: (state, action: PayloadAction) => { + state.openScap.kernel.kernelAppend = action.payload; + }, + changeDisabledServices: ( + state, + action: PayloadAction + ) => { + state.openScap.services.disabled = action.payload; + }, + changeEnabledServices: ( + state, + action: PayloadAction + ) => { + state.openScap.services.enabled = action.payload; + }, changeCustomRepositories: ( state, action: PayloadAction @@ -271,6 +314,9 @@ export const { changeRegistrationType, changeActivationKey, changeOscapProfile, + changeKernel, + changeDisabledServices, + changeEnabledServices, changeCustomRepositories, changeBlueprintName, changeBlueprintDescription, diff --git a/src/test/Components/CreateImageWizardV2/CreateImageWizard.compliance.test.tsx b/src/test/Components/CreateImageWizardV2/CreateImageWizard.compliance.test.tsx index 9048911b..fca954c4 100644 --- a/src/test/Components/CreateImageWizardV2/CreateImageWizard.compliance.test.tsx +++ b/src/test/Components/CreateImageWizardV2/CreateImageWizard.compliance.test.tsx @@ -154,6 +154,13 @@ describe('Step Compliance', () => { /cis red hat enterprise linux 8 benchmark for level 1 - workstation/i ) ); + await screen.findByText(/kernel arguments:/i); + await screen.findByText(/audit_backlog_limit=8192 audit=1/i); + await screen.findByText(/disabled services:/i); + await screen.findByText(/nfs-server/i); + await screen.findByText(/enabled services:/i); + await screen.findByText(/crond/i); + // check that the FSC contains a /tmp partition await clickNext(); // await screen.findByRole('heading', { name: /File system configuration/i }); diff --git a/src/test/fixtures/oscap.ts b/src/test/fixtures/oscap.ts index 29c0b93a..65f4efb9 100644 --- a/src/test/fixtures/oscap.ts +++ b/src/test/fixtures/oscap.ts @@ -32,6 +32,13 @@ export const oscapCustomizations = ( 'nftables', 'libselinux', ], + kernel: { + append: 'audit_backlog_limit=8192 audit=1', + }, + services: { + disabled: ['nfs-server'], + enabled: ['crond'], + }, }; } if (profile === 'xccdf_org.ssgproject.content_profile_cis_workstation_l2') { @@ -52,6 +59,13 @@ export const oscapCustomizations = ( 'nftables', 'libselinux', ], + kernel: { + append: 'audit_backlog_limit=8192 audit=1', + }, + services: { + disabled: ['nfs-server', 'nftables'], + enabled: ['crond', 'firewalld'], + }, }; } return { @@ -70,5 +84,12 @@ export const oscapCustomizations = ( 'nftables', 'libselinux', ], + kernel: { + append: 'audit_backlog_limit=8192 audit=1', + }, + services: { + disabled: ['nfs-server', 'rpcbind', 'autofs', 'nftables'], + enabled: ['crond', 'firewalld', 'systemd-journald', 'rsyslog', 'auditd'], + }, }; };