Previously, when a user selected a compliance policy with tailored rules,
the review page always showed the default profile customizations instead
of the policy-specific customizations.
Root cause: OscapProfileInformation component was only using the profile
endpoint (/oscap/{distribution}/{profile}/customizations) which returns
base profile rules, not the policy endpoint
(/oscap/{policy}/{distribution}/policy_customizations) which returns
customized rules.
Changes:
- Add useGetOscapCustomizationsForPolicyQuery export to backendApi
- Implement dual data fetching in OscapProfileInformation:
* Profile endpoint: for description and reference ID
* Policy endpoint: for customized packages, services, kernel args
Fixes the compliance policy customization display bug where edited
policy rules were not reflected in the image build summary.
Add unit tests for compliance policy customizations
Fix profile description title
361 lines
11 KiB
TypeScript
361 lines
11 KiB
TypeScript
import { screen, waitFor, within } from '@testing-library/react';
|
|
import { userEvent } from '@testing-library/user-event';
|
|
|
|
import { CREATE_BLUEPRINT, EDIT_BLUEPRINT } from '../../../../../constants';
|
|
import { CreateBlueprintRequest } from '../../../../../store/imageBuilderApi';
|
|
import { mockBlueprintIds } from '../../../../fixtures/blueprints';
|
|
import {
|
|
baseCreateBlueprintRequest,
|
|
expectedFilesystemCisL2,
|
|
expectedKernelCisL2,
|
|
expectedOpenscapCisL2,
|
|
expectedPackagesCisL2,
|
|
expectedServicesCisL2,
|
|
oscapCreateBlueprintRequest,
|
|
} from '../../../../fixtures/editMode';
|
|
import {
|
|
clickNext,
|
|
clickReviewAndFinish,
|
|
goToOscapStep,
|
|
goToReview,
|
|
interceptBlueprintRequest,
|
|
interceptEditBlueprintRequest,
|
|
openAndDismissSaveAndBuildModal,
|
|
renderCreateMode,
|
|
renderEditMode,
|
|
selectGuestImageTarget,
|
|
selectRhel9,
|
|
} from '../../wizardTestUtils';
|
|
|
|
const selectRhel8 = async () => {
|
|
const user = userEvent.setup();
|
|
await waitFor(async () => user.click(screen.getByTestId('release_select')));
|
|
const rhel8 = await screen.findByRole('option', {
|
|
name: /red hat enterprise linux \(rhel\) 8/i,
|
|
});
|
|
await waitFor(async () => user.click(rhel8));
|
|
};
|
|
|
|
const selectImageInstallerTarget = async () => {
|
|
const user = userEvent.setup();
|
|
const imageInstallerCheckbox = await screen.findByRole('checkbox', {
|
|
name: /Bare metal installer/i,
|
|
});
|
|
await waitFor(() => user.click(imageInstallerCheckbox));
|
|
};
|
|
|
|
const selectWslTarget = async () => {
|
|
const user = userEvent.setup();
|
|
const wslCheckBox = await screen.findByRole('checkbox', {
|
|
name: /windows subsystem for linux/i,
|
|
});
|
|
await waitFor(() => user.click(wslCheckBox));
|
|
};
|
|
|
|
const selectProfile = async () => {
|
|
const user = userEvent.setup();
|
|
const selectProfileDropdown = await screen.findByPlaceholderText(/none/i);
|
|
await waitFor(() => user.click(selectProfileDropdown));
|
|
|
|
const cis1Profile = await screen.findByText(
|
|
/cis red hat enterprise linux 8 benchmark for level 1 - workstation/i,
|
|
);
|
|
await waitFor(() => user.click(cis1Profile));
|
|
};
|
|
|
|
const selectDifferentProfile = async () => {
|
|
const user = userEvent.setup();
|
|
const selectProfileDropdown = await screen.findByPlaceholderText(/none/i);
|
|
await waitFor(() => user.click(selectProfileDropdown));
|
|
|
|
const cis2Profile = await screen.findByText(
|
|
/cis red hat enterprise linux 8 benchmark for level 2 - workstation/i,
|
|
);
|
|
await waitFor(() => user.click(cis2Profile));
|
|
};
|
|
|
|
const selectNone = async () => {
|
|
const user = userEvent.setup();
|
|
const selectProfileDropdown = await screen.findByPlaceholderText(/none/i);
|
|
await waitFor(() => user.click(selectProfileDropdown));
|
|
|
|
await waitFor(async () => user.click(await screen.findByText(/none/i)));
|
|
};
|
|
|
|
const clickRevisitButton = async () => {
|
|
const user = userEvent.setup();
|
|
const expandable = await screen.findByTestId('oscap-detail-expandable');
|
|
const revisitButton =
|
|
await within(expandable).findByTestId('revisit-openscap');
|
|
await waitFor(() => user.click(revisitButton));
|
|
};
|
|
|
|
describe('Step OpenSCAP', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
const user = userEvent.setup();
|
|
|
|
test('create an image with None OpenSCAP profile', async () => {
|
|
await renderCreateMode();
|
|
await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet
|
|
await selectGuestImageTarget();
|
|
await goToOscapStep();
|
|
await selectNone();
|
|
|
|
// check that the FSC does not contain a /tmp partition
|
|
await clickNext();
|
|
await screen.findByRole('heading', { name: /File system configuration/i });
|
|
expect(
|
|
screen.queryByRole('cell', {
|
|
name: /tmp/i,
|
|
}),
|
|
).not.toBeInTheDocument();
|
|
|
|
await clickNext(); // skip Snapshots
|
|
await clickNext(); // skip Repositories
|
|
|
|
// check that there are no Packages contained when selecting the "None" profile option
|
|
await clickNext();
|
|
await screen.findByRole('heading', {
|
|
name: /Additional packages/i,
|
|
});
|
|
await screen.findByText(
|
|
/Search above to add additionalpackages to your image/,
|
|
);
|
|
});
|
|
|
|
test('create an image with an OpenSCAP profile', async () => {
|
|
await renderCreateMode();
|
|
await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet
|
|
await selectGuestImageTarget();
|
|
await goToOscapStep();
|
|
await selectProfile();
|
|
|
|
await screen.findByText(/Packages/);
|
|
await screen.findByText(/aide, neovim/i);
|
|
await screen.findByText(/Kernel arguments/);
|
|
await screen.findByText(/audit_backlog_limit=8192 audit=1/i);
|
|
await screen.findByText(/Enabled services/);
|
|
await screen.findByText(/crond/i);
|
|
await screen.findByText(/Disabled services/);
|
|
await screen.findByText(
|
|
/rpcbind autofs nftables nfs-server emacs-service/i,
|
|
);
|
|
|
|
// check that the FSC contains a /tmp partition
|
|
await clickNext();
|
|
await screen.findByRole('heading', { name: /File system configuration/i });
|
|
await screen.findByText(/tmp/i);
|
|
|
|
await clickNext(); // skip Snapshots
|
|
await clickNext(); // skip Repositories
|
|
|
|
// check that the Packages contains correct packages
|
|
await clickNext();
|
|
await screen.findByRole('heading', {
|
|
name: /Additional packages/i,
|
|
});
|
|
const selected = await screen.findByText(/Selected/);
|
|
user.click(selected);
|
|
await screen.findByText(/aide/i);
|
|
await screen.findByText(/neovim/i);
|
|
});
|
|
|
|
test('dropdown is disabled for WSL targets only', async () => {
|
|
await renderCreateMode();
|
|
await selectRhel8();
|
|
await selectWslTarget();
|
|
await goToOscapStep();
|
|
await screen.findByText(
|
|
/OpenSCAP profiles are not compatible with WSL images/i,
|
|
);
|
|
expect(await screen.findByTestId('profileSelect')).toHaveClass(
|
|
'pf-m-disabled',
|
|
);
|
|
});
|
|
|
|
test('alert displayed and OpenSCAP dropdown enabled when targets include WSL', async () => {
|
|
await renderCreateMode();
|
|
await selectRhel8();
|
|
await selectImageInstallerTarget();
|
|
await selectWslTarget();
|
|
await goToOscapStep();
|
|
await screen.findByText(
|
|
/OpenSCAP profiles are not compatible with WSL images/i,
|
|
);
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText(/none/i)).toBeEnabled();
|
|
});
|
|
});
|
|
|
|
test('clicking Review and finish leads to Review', async () => {
|
|
await renderCreateMode();
|
|
await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet
|
|
await selectGuestImageTarget();
|
|
await goToOscapStep();
|
|
await clickReviewAndFinish();
|
|
await screen.findByRole('heading', {
|
|
name: /Review/i,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('OpenSCAP request generated correctly', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
test('add a profile', async () => {
|
|
await renderCreateMode();
|
|
await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet
|
|
await selectGuestImageTarget();
|
|
await goToOscapStep();
|
|
await selectProfile();
|
|
await goToReview('Oscap test');
|
|
// informational modal pops up in the first test only as it's tied
|
|
// to a 'imageBuilder.saveAndBuildModalSeen' variable in localStorage
|
|
await openAndDismissSaveAndBuildModal();
|
|
|
|
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
|
|
|
const expectedRequest: CreateBlueprintRequest = {
|
|
...oscapCreateBlueprintRequest,
|
|
name: 'Oscap test',
|
|
};
|
|
await waitFor(() => {
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
});
|
|
|
|
test('remove a profile', { timeout: 20000 }, async () => {
|
|
await renderCreateMode();
|
|
await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet
|
|
await selectGuestImageTarget();
|
|
await goToOscapStep();
|
|
await selectProfile();
|
|
await selectNone();
|
|
await goToReview('Oscap test');
|
|
|
|
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
|
|
|
const expectedRequest: CreateBlueprintRequest = {
|
|
...baseCreateBlueprintRequest,
|
|
name: 'Oscap test',
|
|
};
|
|
await waitFor(() => {
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
});
|
|
|
|
test('change profile', { timeout: 20000 }, async () => {
|
|
await renderCreateMode();
|
|
await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet
|
|
await selectGuestImageTarget();
|
|
await goToOscapStep();
|
|
await selectProfile();
|
|
await selectDifferentProfile();
|
|
await goToReview('Oscap test');
|
|
|
|
const receivedRequest = await interceptBlueprintRequest(CREATE_BLUEPRINT);
|
|
|
|
const expectedRequest: CreateBlueprintRequest = {
|
|
...baseCreateBlueprintRequest,
|
|
customizations: {
|
|
packages: expectedPackagesCisL2,
|
|
openscap: expectedOpenscapCisL2,
|
|
services: expectedServicesCisL2,
|
|
kernel: expectedKernelCisL2,
|
|
filesystem: expectedFilesystemCisL2,
|
|
},
|
|
name: 'Oscap test',
|
|
};
|
|
|
|
await waitFor(() => {
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
});
|
|
|
|
test('revisit step button on Review works', async () => {
|
|
await renderCreateMode();
|
|
await selectRhel9(); // OpenSCAP is not available for RHEL 10 yet
|
|
await selectGuestImageTarget();
|
|
await goToOscapStep();
|
|
await selectProfile();
|
|
await goToReview('Oscap test');
|
|
await clickRevisitButton();
|
|
await screen.findByRole('heading', { name: /OpenSCAP/ });
|
|
});
|
|
});
|
|
|
|
describe('OpenSCAP edit mode', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
const user = userEvent.setup();
|
|
test('edit mode works', async () => {
|
|
const id = mockBlueprintIds['oscap'];
|
|
await renderEditMode(id);
|
|
|
|
// starts on review step
|
|
const receivedRequest = await interceptEditBlueprintRequest(
|
|
`${EDIT_BLUEPRINT}/${id}`,
|
|
);
|
|
const expectedRequest = oscapCreateBlueprintRequest;
|
|
expect(receivedRequest).toEqual(expectedRequest);
|
|
});
|
|
|
|
test('fsc and packages get populated on edit', async () => {
|
|
const id = mockBlueprintIds['oscap'];
|
|
await renderEditMode(id);
|
|
|
|
// check that the FSC contains a /tmp partition
|
|
const fscBtns = await screen.findAllByRole('button', {
|
|
name: /file system configuration/i,
|
|
});
|
|
user.click(fscBtns[0]);
|
|
await screen.findByRole('heading', { name: /file system configuration/i });
|
|
await screen.findByText('/tmp');
|
|
// check that the Packages contain neovim package
|
|
const packagesNavBtn = await screen.findByRole('button', {
|
|
name: /additional packages/i,
|
|
});
|
|
user.click(packagesNavBtn);
|
|
await screen.findByRole('heading', {
|
|
name: /Additional packages/i,
|
|
});
|
|
const selectedBtn = await screen.findByRole('button', {
|
|
name: /Selected/i,
|
|
});
|
|
user.click(selectedBtn);
|
|
await screen.findByText('neovim');
|
|
});
|
|
|
|
test('customized policy shows only non-removed rules', async () => {
|
|
const { oscapCustomizations, oscapCustomizationsPolicy } = await import(
|
|
'../../../../fixtures/oscap'
|
|
);
|
|
|
|
const profileId = 'xccdf_org.ssgproject.content_profile_cis_workstation_l1';
|
|
const normalProfile = oscapCustomizations(profileId);
|
|
expect(normalProfile.packages).toEqual(['aide', 'neovim']);
|
|
const customPolicy = oscapCustomizationsPolicy('custom-policy-123');
|
|
expect(customPolicy.packages).toEqual(['neovim']);
|
|
await renderCreateMode();
|
|
await selectRhel9();
|
|
await selectGuestImageTarget();
|
|
await goToOscapStep();
|
|
await selectProfile();
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText(/aide, neovim/i)).toBeInTheDocument();
|
|
});
|
|
|
|
expect(customPolicy.packages).not.toContain('aide');
|
|
expect(customPolicy.packages).toContain('neovim');
|
|
expect(normalProfile.packages).toContain('aide');
|
|
expect(normalProfile.packages).toContain('neovim');
|
|
});
|
|
});
|