Skip to content

Commit

Permalink
add /hardening/container/bootc-image-builder
Browse files Browse the repository at this point in the history
Signed-off-by: Jiri Jaburek <comps@nomail.dom>
  • Loading branch information
comps committed Nov 15, 2024
1 parent ef82d01 commit 7d1573d
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 0 deletions.
108 changes: 108 additions & 0 deletions hardening/container/bootc-image-builder/main.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
summary: Runs bootc-image-builder remediation and scan inside VMs
test: python3 -m lib.runtest ./test.py
result: custom
environment+:
PYTHONPATH: ../../..
duration: 1h
require+:
# virt library dependencies
- libvirt-daemon
- libvirt-daemon-driver-qemu
- libvirt-daemon-driver-storage-core
- libvirt-daemon-driver-network
- firewalld
- qemu-kvm
- libvirt-client
- virt-install
- rpm-build
- createrepo
# podman library dependencies
- podman
extra-hardware: |
keyvalue = HVM=1
hostrequire = memory>=3720
adjust:
- when: arch != x86_64
enabled: false
because: we want to run virtualization on x86_64 only
- when: distro < rhel-9.6
enabled: false
because: Image Mode not supported for older RHELs
- when: distro == rhel
enabled: false
because: TODO - no freely accessible RHEL bootc image, CentOS Stream only

/anssi_bp28_high:

/anssi_bp28_enhanced:
tag+:
- subset-profile

/anssi_bp28_intermediary:
tag+:
- subset-profile

/anssi_bp28_minimal:
tag+:
- subset-profile

/cis:

/cis_server_l1:
tag+:
- subset-profile

/cis_workstation_l2:

/cis_workstation_l1:
tag+:
- subset-profile

/cui:
adjust+:
- when: distro >= rhel-10
enabled: false
because: there is no CUI profile on RHEL-10+

/e8:

/hipaa:

/ism_o:

/ospp:
adjust+:
- when: distro >= rhel-10
enabled: false
because: there is no OSPP profile on RHEL-10+

/pci-dss:

/stig:

/stig_gui:
adjust+:
- enabled: false
because: not supported without GUI, use stig instead

/ccn_advanced:
adjust+:
- when: distro == rhel-8 or distro == rhel-10
enabled: false
because: CCN profiles are not present on RHEL-8 and on RHEL-10

/ccn_intermediate:
tag+:
- subset-profile
adjust+:
- when: distro == rhel-8 or distro == rhel-10
enabled: false
because: CCN profiles are not present on RHEL-8 and on RHEL-10

/ccn_basic:
tag+:
- subset-profile
adjust+:
- when: distro == rhel-8 or distro == rhel-10
enabled: false
because: CCN profiles are not present on RHEL-8 and on RHEL-10
94 changes: 94 additions & 0 deletions hardening/container/bootc-image-builder/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/python3

import shutil
from pathlib import Path

from lib import results, oscap, versions, virt, podman, util
from conf import remediation


virt.Host.setup()

_, variant, profile = util.get_test_name().rsplit('/', 2)

oscap.unselect_rules(util.get_datastream(), 'remediation-ds.xml', remediation.excludes())

# note that the .wipe() is necessary here, as we are not calling any .install()
# function that would normally perform it
guest = virt.Guest()
guest.wipe()
guest.generate_ssh_keypair()

# CentOS Stream image only, for now
src_image = f'quay.io/centos-bootc/centos-bootc:stream{versions.rhel.major}'

# RHEL-9 and older use 'maint-1.3' openscap git repo branch, newer use 'main'
if versions.rhel <= 9:
copr = 'packit/OpenSCAP-openscap-maint-1.3'
else:
copr = 'packit/OpenSCAP-openscap-main'

# prepare a Container file for making a hardened image
cfile = podman.Containerfile()
cfile += util.dedent(fr'''
FROM {src_image}
RUN dnf -y install dnf-plugins-core
RUN dnf -y copr enable {copr} centos-stream-{versions.rhel.major}-x86_64
RUN dnf -y install openscap-utils
COPY remediation-ds.xml /root/.
RUN oscap-bootc --profile '{profile}' /root/remediation-ds.xml
# hack sshd cmdline to allow root login
RUN echo "OPTIONS=-oPermitRootLogin=yes" >> /etc/sysconfig/sshd
''')
cfile.add_ssh_pubkey(guest.ssh_pubkey)
cfile.write_to('Containerfile')

podman.podman('image', 'build', '--tag', 'contest-hardened', '.')

# pre-create a directory (inside GUEST_IMG_DIR) for storing the
# hardened image, built by bootc-image-builder
bootc_output_dir = Path(virt.GUEST_IMG_DIR) / 'bootc-image-builder-output'
if bootc_output_dir.exists():
shutil.rmtree(bootc_output_dir)
bootc_output_dir.mkdir(parents=True)

# build the hardened image using a containerized builder,
podman.podman(
'container', 'run',
'--rm',
'--privileged',
'--security-opt', 'label=type:unconfined_t',
'--volume', f'{bootc_output_dir}:/output',
'--volume', '/var/lib/containers/storage:/var/lib/containers/storage',
'quay.io/centos-bootc/bootc-image-builder',
# arguments for the builder itself
'build',
'--type', 'qcow2',
'--local',
# 'localhost/' prefix tells the builder to just use local image storage
'localhost/contest-hardened',
)

# path inside the output dir seems to be hardcoded in bootc-image-builder
qcow2_path = bootc_output_dir / 'qcow2' / 'disk.qcow2'
guest.import_image(qcow2_path, 'qcow2')

# boot up and scan the VM
with guest.booted():
# copy the original DS to the guest
guest.copy_to(util.get_datastream(), 'scan-ds.xml')
# scan the remediated system
proc, lines = guest.ssh_stream(
f'oscap xccdf eval --profile {profile} --progress --report report.html'
f' --results-arf results-arf.xml scan-ds.xml'
)
oscap.report_from_verbose(lines)
if proc.returncode not in [0,2]:
raise RuntimeError("post-reboot oscap failed unexpectedly")

guest.copy_from('report.html')
guest.copy_from('results-arf.xml')

util.subprocess_run(['gzip', '-9', 'results-arf.xml'], check=True)

results.report_and_exit(logs=['report.html', 'results-arf.xml.gz'])

0 comments on commit 7d1573d

Please sign in to comment.