Wizard: edit compliance according to updated mockups
Changes the compliance step based on most recent mockups
This commit is contained in:
parent
ad6b38a115
commit
cfa437a34b
5 changed files with 103 additions and 179 deletions
|
|
@ -1,33 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { Popover, TextContent, Text, Button } from '@patternfly/react-core';
|
|
||||||
import { HelpIcon } from '@patternfly/react-icons';
|
|
||||||
|
|
||||||
const OpenSCAPFGLabel = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
OpenSCAP profile
|
|
||||||
<Popover
|
|
||||||
maxWidth="30rem"
|
|
||||||
bodyContent={
|
|
||||||
<TextContent>
|
|
||||||
<Text>
|
|
||||||
To run a manual compliance scan in OpenSCAP, download this image.
|
|
||||||
</Text>
|
|
||||||
</TextContent>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
variant="plain"
|
|
||||||
aria-label="About OpenSCAP"
|
|
||||||
isInline
|
|
||||||
className="pf-v5-u-pl-sm pf-v5-u-pt-0 pf-v5-u-pb-0 pf-v5-u-pr-0"
|
|
||||||
>
|
|
||||||
<HelpIcon />
|
|
||||||
</Button>
|
|
||||||
</Popover>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default OpenSCAPFGLabel;
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CodeBlock,
|
|
||||||
CodeBlockCode,
|
|
||||||
Spinner,
|
Spinner,
|
||||||
TextContent,
|
TextContent,
|
||||||
TextList,
|
TextList,
|
||||||
|
|
@ -11,7 +9,6 @@ import {
|
||||||
TextListVariants,
|
TextListVariants,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
import { RELEASES } from '../../../../../constants';
|
|
||||||
import { useGetOscapCustomizationsQuery } from '../../../../../store/backendApi';
|
import { useGetOscapCustomizationsQuery } from '../../../../../store/backendApi';
|
||||||
import { PolicyRead, usePolicyQuery } from '../../../../../store/complianceApi';
|
import { PolicyRead, usePolicyQuery } from '../../../../../store/complianceApi';
|
||||||
import { useAppDispatch, useAppSelector } from '../../../../../store/hooks';
|
import { useAppDispatch, useAppSelector } from '../../../../../store/hooks';
|
||||||
|
|
@ -22,7 +19,6 @@ import {
|
||||||
selectComplianceProfileID,
|
selectComplianceProfileID,
|
||||||
selectDistribution,
|
selectDistribution,
|
||||||
} from '../../../../../store/wizardSlice';
|
} from '../../../../../store/wizardSlice';
|
||||||
import { useFlag } from '../../../../../Utilities/useGetEnvironment';
|
|
||||||
|
|
||||||
type OscapProfileInformationOptionPropType = {
|
type OscapProfileInformationOptionPropType = {
|
||||||
allowChangingCompliancePolicy?: boolean;
|
allowChangingCompliancePolicy?: boolean;
|
||||||
|
|
@ -36,9 +32,6 @@ export const OscapProfileInformation = ({
|
||||||
const compliancePolicyID = useAppSelector(selectCompliancePolicyID);
|
const compliancePolicyID = useAppSelector(selectCompliancePolicyID);
|
||||||
const complianceProfileID = useAppSelector(selectComplianceProfileID);
|
const complianceProfileID = useAppSelector(selectComplianceProfileID);
|
||||||
|
|
||||||
const isKernelEnabled = useFlag('image-builder.kernel.enabled');
|
|
||||||
const isServicesStepEnabled = useFlag('image-builder.services.enabled');
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: oscapProfileInfo,
|
data: oscapProfileInfo,
|
||||||
isFetching: isFetchingOscapProfileInfo,
|
isFetching: isFetchingOscapProfileInfo,
|
||||||
|
|
@ -82,15 +75,6 @@ export const OscapProfileInformation = ({
|
||||||
);
|
);
|
||||||
}, [isSuccessPolicyInfo]);
|
}, [isSuccessPolicyInfo]);
|
||||||
|
|
||||||
const enabledServicesDisplayString =
|
|
||||||
oscapProfileInfo?.services?.enabled?.join(' ');
|
|
||||||
const disabledAndMaskedServices = [
|
|
||||||
...(oscapProfileInfo?.services?.disabled ?? []),
|
|
||||||
...(oscapProfileInfo?.services?.masked ?? []),
|
|
||||||
];
|
|
||||||
const disabledAndMaskedServicesDisplayString =
|
|
||||||
disabledAndMaskedServices.join(' ');
|
|
||||||
|
|
||||||
const oscapProfile = oscapProfileInfo?.openscap as OpenScapProfile;
|
const oscapProfile = oscapProfileInfo?.openscap as OpenScapProfile;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -111,15 +95,6 @@ export const OscapProfileInformation = ({
|
||||||
<TextListItem component={TextListItemVariants.dd}>
|
<TextListItem component={TextListItemVariants.dd}>
|
||||||
{oscapProfile?.profile_description}
|
{oscapProfile?.profile_description}
|
||||||
</TextListItem>
|
</TextListItem>
|
||||||
<TextListItem
|
|
||||||
component={TextListItemVariants.dt}
|
|
||||||
className="pf-v5-u-min-width"
|
|
||||||
>
|
|
||||||
Operating system:
|
|
||||||
</TextListItem>
|
|
||||||
<TextListItem component={TextListItemVariants.dd}>
|
|
||||||
{RELEASES.get(release)}
|
|
||||||
</TextListItem>
|
|
||||||
<TextListItem
|
<TextListItem
|
||||||
component={TextListItemVariants.dt}
|
component={TextListItemVariants.dt}
|
||||||
className="pf-v5-u-min-width"
|
className="pf-v5-u-min-width"
|
||||||
|
|
@ -132,53 +107,50 @@ export const OscapProfileInformation = ({
|
||||||
>
|
>
|
||||||
{oscapProfile?.profile_id}
|
{oscapProfile?.profile_id}
|
||||||
</TextListItem>
|
</TextListItem>
|
||||||
{!isKernelEnabled && (
|
</TextList>
|
||||||
<>
|
</TextContent>
|
||||||
<TextListItem
|
</>
|
||||||
component={TextListItemVariants.dt}
|
)}
|
||||||
className="pf-v5-u-min-width"
|
{isSuccessPolicyInfo && (
|
||||||
>
|
<>
|
||||||
Kernel arguments:
|
<TextContent>
|
||||||
</TextListItem>
|
<TextList component={TextListVariants.dl}>
|
||||||
<TextListItem component={TextListItemVariants.dd}>
|
<TextListItem
|
||||||
<CodeBlock>
|
component={TextListItemVariants.dt}
|
||||||
<CodeBlockCode>
|
className="pf-v5-u-min-width"
|
||||||
{oscapProfileInfo?.kernel?.append}
|
>
|
||||||
</CodeBlockCode>
|
Policy description:
|
||||||
</CodeBlock>
|
</TextListItem>
|
||||||
</TextListItem>
|
<TextListItem component={TextListItemVariants.dd}>
|
||||||
</>
|
{policyInfo?.data?.schema?.description}
|
||||||
)}
|
</TextListItem>
|
||||||
{!isServicesStepEnabled && (
|
<TextListItem
|
||||||
<>
|
component={TextListItemVariants.dt}
|
||||||
<TextListItem
|
className="pf-v5-u-min-width"
|
||||||
component={TextListItemVariants.dt}
|
>
|
||||||
className="pf-v5-u-min-width"
|
Business objective:
|
||||||
>
|
</TextListItem>
|
||||||
Disabled services:
|
<TextListItem component={TextListItemVariants.dd}>
|
||||||
</TextListItem>
|
{policyInfo?.data?.schema?.business_objective}
|
||||||
<TextListItem component={TextListItemVariants.dd}>
|
</TextListItem>
|
||||||
<CodeBlock>
|
<TextListItem
|
||||||
<CodeBlockCode>
|
component={TextListItemVariants.dt}
|
||||||
{disabledAndMaskedServicesDisplayString}
|
className="pf-v5-u-min-width"
|
||||||
</CodeBlockCode>
|
>
|
||||||
</CodeBlock>
|
Policy type:
|
||||||
</TextListItem>
|
</TextListItem>
|
||||||
<TextListItem
|
<TextListItem component={TextListItemVariants.dd}>
|
||||||
component={TextListItemVariants.dt}
|
{policyInfo?.data?.schema?.type}
|
||||||
className="pf-v5-u-min-width"
|
</TextListItem>
|
||||||
>
|
<TextListItem
|
||||||
Enabled services:
|
component={TextListItemVariants.dt}
|
||||||
</TextListItem>
|
className="pf-v5-u-min-width"
|
||||||
<TextListItem component={TextListItemVariants.dd}>
|
>
|
||||||
<CodeBlock>
|
Reference ID:
|
||||||
<CodeBlockCode>
|
</TextListItem>
|
||||||
{enabledServicesDisplayString}
|
<TextListItem component={TextListItemVariants.dd}>
|
||||||
</CodeBlockCode>
|
{policyInfo?.data?.schema?.id}
|
||||||
</CodeBlock>
|
</TextListItem>
|
||||||
</TextListItem>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</TextList>
|
</TextList>
|
||||||
</TextContent>
|
</TextContent>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@ import {
|
||||||
import { TimesIcon } from '@patternfly/react-icons';
|
import { TimesIcon } from '@patternfly/react-icons';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import OpenSCAPFGLabel from './OpenSCAPFGLabel';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useGetOscapProfilesQuery,
|
useGetOscapProfilesQuery,
|
||||||
useGetOscapCustomizationsQuery,
|
useGetOscapCustomizationsQuery,
|
||||||
|
|
@ -323,6 +321,11 @@ const ProfileSelector = () => {
|
||||||
onClick={() => setIsOpen(!isOpen)}
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
isExpanded={isOpen}
|
isExpanded={isOpen}
|
||||||
isDisabled={!isSuccess || hasWslTargetOnly}
|
isDisabled={!isSuccess || hasWslTargetOnly}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
width: '100%',
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<TextInputGroup isPlain>
|
<TextInputGroup isPlain>
|
||||||
<TextInputGroupMain
|
<TextInputGroupMain
|
||||||
|
|
@ -350,7 +353,7 @@ const ProfileSelector = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormGroup data-testid="profiles-form-group" label={<OpenSCAPFGLabel />}>
|
<FormGroup data-testid="profiles-form-group" label="Profile">
|
||||||
<Select
|
<Select
|
||||||
isScrollable
|
isScrollable
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Alert,
|
||||||
|
AlertActionLink,
|
||||||
Form,
|
Form,
|
||||||
FormGroup,
|
|
||||||
Radio,
|
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title,
|
||||||
|
ToggleGroup,
|
||||||
|
ToggleGroupItem,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { ExternalLinkAltIcon } from '@patternfly/react-icons';
|
|
||||||
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
|
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
|
||||||
|
|
||||||
import OscapOnPremSpinner from './components/OnPremSpinner';
|
import OscapOnPremSpinner from './components/OnPremSpinner';
|
||||||
|
|
@ -16,14 +16,12 @@ import OscapOnPremWarning from './components/OnPremWarning';
|
||||||
import Oscap from './Oscap';
|
import Oscap from './Oscap';
|
||||||
import { removeBetaFromRelease } from './removeBetaFromRelease';
|
import { removeBetaFromRelease } from './removeBetaFromRelease';
|
||||||
|
|
||||||
import {
|
import { COMPLIANCE_URL } from '../../../../constants';
|
||||||
COMPLIANCE_AND_VULN_SCANNING_URL,
|
|
||||||
COMPLIANCE_URL,
|
|
||||||
} from '../../../../constants';
|
|
||||||
import {
|
import {
|
||||||
useBackendPrefetch,
|
useBackendPrefetch,
|
||||||
useGetOscapCustomizationsQuery,
|
useGetOscapCustomizationsQuery,
|
||||||
} from '../../../../store/backendApi';
|
} from '../../../../store/backendApi';
|
||||||
|
import { usePoliciesQuery } from '../../../../store/complianceApi';
|
||||||
import { useAppDispatch, useAppSelector } from '../../../../store/hooks';
|
import { useAppDispatch, useAppSelector } from '../../../../store/hooks';
|
||||||
import {
|
import {
|
||||||
ComplianceType,
|
ComplianceType,
|
||||||
|
|
@ -54,6 +52,7 @@ const OscapContent = () => {
|
||||||
const profileID = useAppSelector(selectComplianceProfileID);
|
const profileID = useAppSelector(selectComplianceProfileID);
|
||||||
const prefetchOscapProfile = useBackendPrefetch('getOscapProfiles', {});
|
const prefetchOscapProfile = useBackendPrefetch('getOscapProfiles', {});
|
||||||
const release = removeBetaFromRelease(useAppSelector(selectDistribution));
|
const release = removeBetaFromRelease(useAppSelector(selectDistribution));
|
||||||
|
const majorVersion = release.split('-')[1];
|
||||||
|
|
||||||
const { data: currentProfileData } = useGetOscapCustomizationsQuery(
|
const { data: currentProfileData } = useGetOscapCustomizationsQuery(
|
||||||
{
|
{
|
||||||
|
|
@ -101,78 +100,59 @@ const OscapContent = () => {
|
||||||
analytics.screen('ib-createimagewizard-step-security-openscap');
|
analytics.screen('ib-createimagewizard-step-security-openscap');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const { data: policies } = usePoliciesQuery(
|
||||||
|
{
|
||||||
|
filter: `os_major_version=${majorVersion}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: complianceType === 'openscap',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
<Title headingLevel="h1" size="xl">
|
<Title headingLevel="h1" size="xl">
|
||||||
{complianceEnabled ? 'Compliance' : 'OpenSCAP profile'}
|
{complianceEnabled ? 'Compliance' : 'OpenSCAP profile'}
|
||||||
</Title>
|
</Title>
|
||||||
|
<Text>
|
||||||
|
Below you can select which Insights compliance policy or OpenSCAP
|
||||||
|
profile your image will be compliant to. Insights compliance allows the
|
||||||
|
use of tailored policies, whereas OpenSCAP gives you the default
|
||||||
|
versions. This will automatically help monitor the adherence of your
|
||||||
|
registered RHEL systems to a selected policy or profile.
|
||||||
|
</Text>
|
||||||
{complianceEnabled && (
|
{complianceEnabled && (
|
||||||
<FormGroup>
|
<ToggleGroup aria-label="Default with single selectable">
|
||||||
<Radio
|
<ToggleGroupItem
|
||||||
id="openscap radio openscap type"
|
text="Compliance policies"
|
||||||
label="OpenSCAP"
|
buttonId="toggle-group-compliance"
|
||||||
name="oscap-radio-openscap"
|
isSelected={complianceType === 'compliance'}
|
||||||
isChecked={complianceType === 'openscap'}
|
|
||||||
onChange={() => handleTypeChange('openscap')}
|
|
||||||
/>
|
|
||||||
<Radio
|
|
||||||
id="openscap radio compliance type"
|
|
||||||
label="Insights compliance"
|
|
||||||
name="oscap-radio-compliance"
|
|
||||||
isChecked={complianceType === 'compliance'}
|
|
||||||
onChange={() => handleTypeChange('compliance')}
|
onChange={() => handleTypeChange('compliance')}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
<ToggleGroupItem
|
||||||
)}
|
text="OpenSCAP profiles"
|
||||||
{(!complianceEnabled || complianceType === 'openscap') && (
|
buttonId="toggle-group-openscap"
|
||||||
<Text>
|
isSelected={complianceType === 'openscap'}
|
||||||
OpenSCAP enables you to automatically monitor the adherence of your
|
onChange={() => handleTypeChange('openscap')}
|
||||||
registered RHEL systems to a selected regulatory compliance profile.
|
/>
|
||||||
<br />
|
</ToggleGroup>
|
||||||
<Button
|
|
||||||
component="a"
|
|
||||||
target="_blank"
|
|
||||||
variant="link"
|
|
||||||
icon={<ExternalLinkAltIcon />}
|
|
||||||
iconPosition="right"
|
|
||||||
isInline
|
|
||||||
href={COMPLIANCE_AND_VULN_SCANNING_URL}
|
|
||||||
>
|
|
||||||
Documentation
|
|
||||||
</Button>
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
{complianceType === 'compliance' && (
|
|
||||||
<Text>
|
|
||||||
Insights compliance enables you to monitor the adherence of your
|
|
||||||
registered RHEL systems to a selected compliance policy.
|
|
||||||
<br />
|
|
||||||
<Button
|
|
||||||
component="a"
|
|
||||||
target="_blank"
|
|
||||||
variant="link"
|
|
||||||
icon={<ExternalLinkAltIcon />}
|
|
||||||
iconPosition="right"
|
|
||||||
isInline
|
|
||||||
href={COMPLIANCE_URL}
|
|
||||||
>
|
|
||||||
Define new policies in Insights Compliance
|
|
||||||
</Button>
|
|
||||||
<br />
|
|
||||||
<Button
|
|
||||||
component="a"
|
|
||||||
target="_blank"
|
|
||||||
variant="link"
|
|
||||||
icon={<ExternalLinkAltIcon />}
|
|
||||||
iconPosition="right"
|
|
||||||
isInline
|
|
||||||
href={COMPLIANCE_AND_VULN_SCANNING_URL}
|
|
||||||
>
|
|
||||||
Documentation
|
|
||||||
</Button>
|
|
||||||
</Text>
|
|
||||||
)}
|
)}
|
||||||
|
{Array.isArray(policies?.data) &&
|
||||||
|
policies.data.length === 0 &&
|
||||||
|
complianceType === 'compliance' && (
|
||||||
|
<Alert variant="info" isInline title="No compliance policies created">
|
||||||
|
<p>
|
||||||
|
Currently there are no compliance policies in your environment. To
|
||||||
|
help you get started, select one of the default policies below and
|
||||||
|
we will create the policy for you. However, in order to modify the
|
||||||
|
policy or to create a new one, you must go through Insights
|
||||||
|
Compliance.
|
||||||
|
</p>
|
||||||
|
<AlertActionLink component="a" href={COMPLIANCE_URL}>
|
||||||
|
Save blueprint and navigate to Insights Compliance
|
||||||
|
</AlertActionLink>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
<Oscap />
|
<Oscap />
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,9 @@ const goToComplianceStep = async () => {
|
||||||
await clickRegisterLater();
|
await clickRegisterLater();
|
||||||
await clickNext(); // Compliance
|
await clickNext(); // Compliance
|
||||||
await screen.findByRole('heading', { name: /Compliance/ });
|
await screen.findByRole('heading', { name: /Compliance/ });
|
||||||
const button = await screen.findByLabelText('Insights compliance');
|
const button = await screen.findByRole('button', {
|
||||||
|
name: /Compliance policies/,
|
||||||
|
});
|
||||||
await waitFor(() => user.click(button));
|
await waitFor(() => user.click(button));
|
||||||
// wait until all policies are loaded
|
// wait until all policies are loaded
|
||||||
await screen.findByText('Select a policy');
|
await screen.findByText('Select a policy');
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue