Skip to content

Instantly share code, notes, and snippets.

@dmpe
Last active August 19, 2024 19:24
Show Gist options
  • Save dmpe/7c918efc0bcc079d5715aab35e5da711 to your computer and use it in GitHub Desktop.
Save dmpe/7c918efc0bcc079d5715aab35e5da711 to your computer and use it in GitHub Desktop.
RHEL9/Rocky9 Kickstart file with CIS hardening generated by gitlab.com/kickstart-my-heart/rocky8
#version=RHEL9
# Kickstart for HeadlessCISPodman
# Version 9.2.1
# License agreement
eula --agreed
# Use non-interactive install
# (this has to be `cmdline` on RHEL 7)
text --non-interactive
# Select a specific disk to use for safety
ignoredisk --only-use=/dev/sda
# Clear out partition tables on disks
zerombr
# Clear partitions and initialise with a label
clearpart --all --initlabel
# Create EFI System Partition and /boot partition (RHEL 8 default sizes)
part /boot/efi --fstype=vfat --fsoptions='defaults,umask=0027,fmask=0077,uid=0,gid=0' --size=600 --ondisk=/dev/sda # RHEL8 CIS 1.5.1
part /boot --fstype=xfs --fsoptions='nosuid,nodev' --size=1024 --ondisk=/dev/sda
# Create unencrypted partition for our LVM container
part pv.01 --size 1024 --grow --asprimary --ondisk=/dev/sda
# Create our LVM group
volgroup rhel_lvm pv.01
# Create a 16GB root partition (using LVM group we just created)
logvol / --fstype=xfs --size=16384 --name=root --vgname=rhel_lvm
# Create a 10GB /var partition (This increases to 50GB if we set 'workstation_deployment' to 'true', to make more room for Flatpaks)
logvol /var --fstype=xfs --size=10240 --fsoptions='nodev' --name=var --vgname=rhel_lvm # RHEL8 CIS 1.1.6
# Create our smaller volumes (totals 12GB)
logvol /opt --fstype=xfs --size=1024 --fsoptions='nodev' --name=opt --vgname=rhel_lvm
logvol /tmp --fstype=xfs --size=2048 --fsoptions='nodev,nosuid' --name=tmp --vgname=rhel_lvm # RHEL8 CIS 1.1.2, 1.1.3, 1.1.4
logvol /var/tmp --fstype=xfs --size=5120 --fsoptions='nodev,noexec,nosuid' --name=vartmp --vgname=rhel_lvm # RHEL8 CIS 1.1.7, 1.1.8, 1.1.9, 1.1.10
logvol /var/log --fstype=xfs --size=2048 --fsoptions='nodev,noexec,nosuid' --name=logs --vgname=rhel_lvm # RHEL8 CIS 1.1.11
logvol /var/log/audit --fstype=xfs --size=2048 --fsoptions='nodev,noexec,nosuid' --name=auditlogs --vgname=rhel_lvm # RHEL8 CIS 1.1.12
# Create an 8GB swap partition
logvol swap --fstype=swap --size=8192 --name=swap --vgname=rhel_lvm
# Create a 2GB /home volume
logvol /home --fstype=xfs --size=2048 --fsoptions='nodev,nosuid' --name=home --vgname=rhel_lvm # RHEL8 CIS 1.1.13, CIS 1.1.14
# EFI GRUB with password configured in playbook
# We don't need to specify 'rhgb' or 'quiet' here like some others
# do online, as these will get added automatically if the Plymouth
# package is installed. We don't include them here since we have
# some vars which explicitly do not install the Plymouth package.
#
# We enable cgroups v2 here via the systemd.unified_cgroup_hierarchy=1
# parameter, as RHEL 8 does not ship with this enabled by default.
bootloader --location=mbr --append="crashkernel=auto systemd.unified_cgroup_hierarchy=1" --iscrypted --password=grub.pbkdf2.sha512.10000.66122BFEE9BDAEF58D3F9872AA3CB9586414B15D6CB092ADA2732D28AE34233D139BFB51AA174550A4896A2DE7436FBDD85AC2A9AC02CFD3B90510A3064D681A.5CE12B6A5C8A4CF8C8947A25A8B9B1355A6FBDA5FDF04BC50891F825DCC2B8300E01849A30590C1A1435A0EC4DBABE1657D1FD213D90691CCD7C285F56F6A189
# Install using the booted DVD, or from a URL if we configured the 'install_url' variable in our Kickstart-generation playbook
# Please note when using "cdrom" as the installation source that Anaconda expects the installation
# source to actually look like a CD-ROM. This means mounting an ISO to a VM/BMC directly, or using
# an actual disk or a CD/DVD emulator like a Zalman ZM-VE300. The installation WILL FAIL without
# much clear feedback if the RHEL ISO is written to a USB stick, as anaconda considers that a
# "harddrive" instead.
cdrom
# Don't run the Setup Agent on first boot
firstboot --disable
# Locale
keyboard --xlayouts='gb'
lang en_GB.UTF-8
# Network information
# Because we're using Packer to build and may want to SSH into our host as part of the run,
# here we use just use DHCP and default to `--device=link` which will set up the network
# on the device with a link.
network --device=link --hostname=el9 --bootproto=dhcp --onboot=true
# Enable firewalld and allow incoming SSH
#
# Please note that this operates on the default firewalld zone of 'public'. CIS 3.4.2.4
# below involves setting our default zone to 'drop', so this command has no effect when
# CIS hardening is enabled. To account for this, please note the 'firewall-offline-cmd'
# command that we apply when we apply CIS 3.4.2.4, which specifically allows incoming
# SSH connections for the 'drop' zone.
#
# If we do not enable incoming SSH during install, a Packer run cannot complete so this
# is necessary.
#
firewall --enabled --ssh
# Make sure SELinux is enforcing
selinux --enforcing
# Timezone & NTP
timezone Etc/UTC --utc --ntpservers=time.cloudflare.com
# Lock the root account
rootpw --lock
# Create group for local users to be granted SSH access
# (See CIS 5.2.2 - Ensure SSH access is limited)
group --name=localssh --gid=770
# Create user accounts (imported from create_users.j2)
### START create_users.j2 INCLUDE FILE HERE ###
# Please do not forget to add corresponding entries to the 'configure_users.j2' file for each user included here
user --name=user --password="$6$cps9toc4dNxJFAGM$Ri/wKh/gyv.oWQSaEwsH5tGJF3YZsxMlld6n4gG5JXKQ0HdiIv8.R6uPWqYcmv0fU1aa5afybYezKtXQ7FRms0" --iscrypted --gecos="user" --groups=wheel,localssh --uid 9001
### END create_users.j2 INCLUDE FILE HERE ###
# Enable kdump
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
# Harden installation with CIS profile
# For more details and configuration options see
# https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html-single/performing_an_advanced_rhel_installation/index#addon-org_fedora_oscap_kickstart-commands-for-addons-supplied-with-the-rhel-installation-program
#
# We use the preinstall script section of the Kickstart to write our
# tailoring file to /tmp where this addon will look for it.
#
%addon com_redhat_oscap
content-type = scap-security-guide
profile = xccdf_org.ssgproject.content_profile_cis_tailored
tailoring-path = cis_tailoring.xml
%end
# Do not install a graphical environment
skipx
# Disable services (We can't use multiple invocations of the "services --disabled" line in an EL8 Kickstart it seems)
# - Avahi Daemon
# - Bluetooth
# - RHNSD
# - RHSM Certificate Daemon
services --disabled="avahi-daemon.service,bluetooth.service,rhnsd.service,rhsmcertd.service"
# Enable services (We can't use multiple invocations of the "services --enabled" line in an EL8 Kickstart it seems)
# Enable DNF Automatic Timer
services --enabled="dnf-automatic.timer"
# Configure packageset
#
# Please note below that we can specify additional packages to be included in this
# list by adding them to files/override/packages.j2
#
# To find out the correct names to use for package groups below, run the following
# command on an installed RHEL 9 system:
# sudo dnf grouplist -v
# and make sure to prepend the name of the desired package group with @ when referring
# to it in a Kickstart file. If the group is an 'Environment Group', it should be
# prepended with @^ instead. Only a single Environment can be specified in a Kickstart.
# Including minimal deployment environment
# - iwl*-firmware - Removed Intel Wireless NIC firmware that we aren't going to need on most headless systems.
# - plymouth - Removed from headless installs, as it adds graphical boot capabilities that we don't need and which obscure information during booting.
%packages
@^minimal-environment
-iwl*-firmware
-plymouth
%end
# Including CIS hardening packageset
# + aide - Filesystem integrity checker, required by CIS 1.4.1.
%packages
aide
%end
# Including default packageset
# - cockpit - Workstation installs bring in Cockpit as a soft dependency of the @^workstation-product-environment group, so I exclude it here.
# - firefox - Workstation installs carry this by default. I remove it from the base install as we have a preference for the (much more readily updated) Flatpak release.
# - setroubleshoot - For compliance with CIS 1.7.1.6, we remove this otherwise it just gets removed after being installed.
# - subscription-manager-cockpit - Workstation installs (on actual RHEL only) try and bring this package in, which causes a failure if we've excluded the Cockpit packages.
# - telnet - For compliance with CIS 2.3.2, we remove this otherwise it just gets removed after being installed.
# + conntrack-tools - Tools for interacting with the Conntrack layer in the Linux kernel. Useful for debugging.
# + dnf-automatic - Tools for scheduling patch and update installations via DNF.
# + kexec-tools - Required by the kdump service.
# + lsof - Displays information from /proc about which processes are interacting with files. Useful for debugging.
# + nano - Text editor. Useful for editing configurations and other text files.
# + perf - Provides the perf performance-monitoring tool.
# + policycoreutils-python-utils - Used by a number of utilities for SELinux purposes.
# + python3 - Provides Python 3.
# + python3-pexpect - Required to target this machine with Ansible's 'expect' module which can simulate interactive input.
# + rsync - Allows robust file synchronisation including checksum validation.
# + sos - Provides `sos report` functionality which can capture useful system info during an incident, or be used for filing support tickets with Red Hat.
# + strace - Provides an interface to debug and trace syscalls being run by programs on the system.
# + sysstat - Provides a number of useful system utilities such as 'iostat', 'mpstat' and 'sar'. Useful for debugging.
# + tar - Archival tool. Often pulled in as a dependency (notably by open-vm-tools) but we add it explicitly to make sure it is always available.
# + tcpdump - Allows running packet captures on the host via libpcap. Useful for debugging.
# + yum-utils - Provides a number of useful utilities for working with yum/dnf packages and repositories. Renamed to `dnf-utils` after RHEL 8.
%packages
-cockpit
-cockpit-*
-firefox
-setroubleshoot
-subscription-manager-cockpit
-telnet
conntrack-tools
dnf-automatic
kexec-tools
lsof
nano
perf
policycoreutils-python-utils
python3
python3-pexpect
rsync
sos
strace
sysstat
tar
tcpdump
yum-utils
%end
# Include packages from override file
%packages
%end
##################### START PREINSTALL SCRIPT #####################
%pre --logfile=/root/anaconda-pre.log --erroronfail
echo 'Hello, Kickstart!'
# Import our CIS tailoring file, if present.
#
# We generate these with SCAP Workbench by tailoring the scap-security-guide CIS
# profile, and saving the result with "Save Customization Only".
#
# It's largely undocumented behaviour, but during installation the oscap addon
# copies the tailoring file from /tmp/openscap_data to /root/openscap_data in
# the installed system's chroot.
#
# So here we use a heredoc to put it into /tmp before starting our installation.
# We have to do this here and not in the %post section because the content in
# the %post section runs after the oscap addon does.
#
# More info: https://github.com/OpenSCAP/oscap-anaconda-addon/pull/39
#
mkdir -p /tmp/openscap_data
cat <<"EOF" > /tmp/openscap_data/cis_tailoring.xml
<?xml version="1.0" encoding="UTF-8"?>
<xccdf:Tailoring xmlns:xccdf="http://checklists.nist.gov/xccdf/1.2" id="xccdf_scap-workbench_tailoring_default">
<xccdf:benchmark href="ssg-rhel9-ds.xml"/>
<xccdf:version time="1980-01-01T00:00:00">1</xccdf:version>
<xccdf:Profile id="xccdf_org.ssgproject.content_profile_cis_tailored" extends="xccdf_org.ssgproject.content_profile_cis">
<xccdf:title xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="en-US" override="true">CIS Red Hat Enterprise Linux 8 Benchmark [Tailored]</xccdf:title>
<xccdf:description xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="en-US" override="true">CIS Profile for RHEL 8 [Tailored]</xccdf:description>
<!---->
<!-- [EXCEPTION] CIS 1.1.5 Ensure noexec option set on /tmp partition -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_mount_option_tmp_noexec" selected="false"/>
<!-- [EXCEPTION] CIS 1.11 Ensure system-wide crypto policy is FUTURE or FIPS -->
<!-- Disabling this means we keep the default of DEFAULT, which is our preference -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_configure_crypto_policy" selected="false"/>
<!-- [TWEAKS] CIS 1.8.1.1 Ensure message of the day is configured properly -->
<!-- We don't want the default US Government text from these banners -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_banner_etc_motd" selected="false"/>
<!-- [TWEAKS] CIS 1.8.1.2 Ensure local login warning banner is configured properly -->
<!-- We don't want the default US Government text from these banners -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_banner_etc_issue" selected="false"/>
<!-- [TWEAKS] CIS 1.8.1.3 Ensure remote login warning banner is configured properly -->
<!-- CaC doesn't actually have a rule upstream for this yet but we will disable it when
it does. (See: https://github.com/ComplianceAsCode/content/issues/5225) -->
<!-- [TWEAKS] CIS 4.1.2.1 Ensure audit log storage size is configured -->
<xccdf:set-value idref="xccdf_org.ssgproject.content_value_var_auditd_max_log_file">10</xccdf:set-value>
<xccdf:set-value idref="xccdf_org.ssgproject.content_value_var_auditd_num_logs">100</xccdf:set-value>
<!-- [EXCEPTION] CIS 4.1.2.2 Ensure audit logs are not automatically deleted -->
<xccdf:set-value idref="xccdf_org.ssgproject.content_value_var_auditd_max_log_file_action">rotate</xccdf:set-value>
<!-- [EXCEPTION] CIS 4.1.2.3 Ensure system is disabled when audit logs are full -->
<xccdf:set-value idref="xccdf_org.ssgproject.content_value_var_auditd_space_left_action">syslog</xccdf:set-value>
<xccdf:set-value idref="xccdf_org.ssgproject.content_value_var_auditd_admin_space_left_action">syslog</xccdf:set-value>
<!-- [EXCEPTION] CIS 4.2.1.5 Ensure rsyslog is configured to send logs to a remote log host -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_rsyslog_remote_loghost" selected="false"/>
<!-- [EXCEPTION] CIS 4.2.3 Ensure permissions on all logfiles are configured -->
<!-- CaC doesn't actually have a rule upstream for this yet but we will disable it when
it does. (See: https://github.com/ComplianceAsCode/content/issues/5523) -->
<!-- [EXCEPTION] CIS 5.2.13 Ensure SSH Idle Timeout Interval is configured -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_sshd_set_idle_timeout" selected="false"/>
<!-- [EXCEPTION] CIS 5.5.3 Ensure default user shell timeout is 900 seconds or less -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_accounts_tmout" selected="false"/>
<!-- [ADDITION] Restrict access to kernel message buffer -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_sysctl_kernel_dmesg_restrict" selected="true"/>
<!-- [ADDITION] Harden the operation of the BPF just-in-time compiler -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_sysctl_net_core_bpf_jit_harden" selected="true"/>
<!-- [ADDITION] Disallow Magic SysRq Key -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_sysctl_kernel_sysrq" selected="true"/>
<!-- [ADDITION] Disable rhsmcertd service -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_service_rhsmcertd_disabled" selected="true"/>
<!-- [ADDITION] Disable Bluetooth service and kernel module -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_service_bluetooth_disabled" selected="true"/>
<xccdf:select idref="xccdf_org.ssgproject.content_rule_kernel_module_bluetooth_disabled" selected="true"/>
<!-- [ADDITION] Disable Access to Network bpf() Syscall From Unprivileged Processes -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_sysctl_kernel_unprivileged_bpf_disabled" selected="true"/>
<!-- [ADDITION] Restrict access to kernel pointers via /proc and other interfaces -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_sysctl_kernel_kptr_restrict" selected="true"/>
<!-- [ADDITION] Disable loading of kernel modules -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_sysctl_kernel_modules_disabled" selected="true"/>
<!-- [ADDITION] Disallow some ftrace and kernel profiling features for users without CAP_SYS_ADMIN -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_sysctl_kernel_perf_event_paranoid" selected="true"/>
<!-- [ADDITION] Restrict use of ptrace -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_sysctl_kernel_yama_ptrace_scope" selected="true"/>
<!-- [ADDITION] Ensure chrony is installed and enabled for timesync -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_service_chronyd_enabled" selected="true"/>
<xccdf:select idref="xccdf_org.ssgproject.content_rule_package_chrony_installed" selected="true"/>
<!-- [ADDITION] Stop chronyd listening on UDP 323 port for network management purposes -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_chronyd_no_chronyc_network" selected="true"/>
<!-- [ADDITION] Ensure chronyd is not allowed to act as a timeserver -->
<xccdf:select idref="xccdf_org.ssgproject.content_rule_chronyd_client_only" selected="true"/>
<!---->
</xccdf:Profile>
</xccdf:Tailoring>
EOF
%end
##################### END PREINSTALL SCRIPT #####################
##################### START POSTINSTALL SCRIPT #####################
%post --logfile=/root/anaconda-post.log --erroronfail
echo 'Hello, Kickstart!'
# Configure automatic updates to install security updates every 4 hours
# Relies on the 'services' module above, which enables dnf-automatic.timer if we asked for it
# in the config.yml
#
# NOTE: The actions below take place regardless of whether or not we actually requested the
# dnf-automatic.timer to be enabled. This is deliberate, as we want our systems to all have the
# same config for update methodology and schedule, even if we didn't initially install them
# with auto-updates enabled. This lets us enable it easily later, just by enabling the
# dnf-automatic.timer on the system.
#
# Configure dnf-automatic to install only security updates
sed -i 's/^upgrade_type.*/upgrade_type = security/g' /etc/dnf/automatic.conf
sed -i 's/^download_updates.*/download_updates = yes/g' /etc/dnf/automatic.conf
sed -i 's/^apply_updates.*/apply_updates = yes/g' /etc/dnf/automatic.conf
#
# Configure dnf-automatic.timer to run 15 minutes after boot, and then every 4 hours after that
mkdir -p /etc/systemd/system/dnf-automatic.timer.d
cat <<"EOF" > /etc/systemd/system/dnf-automatic.timer.d/99-override-timings.conf
[Timer]
OnCalendar=
RandomizedDelaySec=
OnBootSec=15min
OnUnitActiveSec=4h
EOF
chown -R root:root /etc/systemd/system/dnf-automatic.timer.d
chmod 0750 /etc/systemd/system/dnf-automatic.timer.d
chmod 0644 /etc/systemd/system/dnf-automatic.timer.d/99-override-timings.conf
# Here we implement CIS controls or tweaks which are still needed even
# though we're using the CIS OpenSCAP profile above via ComplianceAsCode.
#
# Corresponding CaC or CIS upstream bug(s) are linked for each control here.
#
# Last validated by me against: RHEL 8.5
# Which packages ComplianceAsCode version: 0.1.57 (with some backports from 0.1.58)
#
# RHEL Release Notes: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/8.4_release_notes/new-features#enhancement_security
# ComplianceAsCode Release Link: https://github.com/ComplianceAsCode/content/releases/tag/v0.1.54
#
# Key:
# [ADDITION] - Controls which do not belong to CIS but which are set anyway as they are generally desirable for security.
# [ADDITION-WS] - New controls configured as above, but specifically concerning Workstation systems.
# [CISBUG] - Controls which FAIL a CIS CAT Assessor validation due to bugs in Assessor or the logic it uses, but which are actually applied properly (based on a manual validation).
# [EXCEPTION] - Controls which FAIL a CIS CAT Assessor validation because we specifically do not want them to be applied.
# [EXCEPTION-WS] - Exceptions set as above, but which are only relevant when considering the CIS Workstation benchmarks.
# [POSTINST] - Controls which FAIL a CIS CAT Assessor validation without further remediation post-installation because we cannot remediate them from a Kickstart install.
# [SCAPBUG] - Controls which PASS a CIS CAT Assessor validation but not without the additional tweaks in this Kickstart (i.e. OpenSCAP profile does not apply them properly).
# [SCAPFIX] - Controls which PASS a CIS CAT Assessor validation with additional tweaks (as in SCAPBUG) but which have been fixed upstream and will therefore work without tweaks in future versions of scap-security-guide.
# [TODO] - Controls which FAIL a CIS CAT Assessor validation but which are a work in progress.
# [TWEAKS] - Controls which PASS a CIS CAT Assessor validation but which we tweak here to be specific to our environment.
#
# [EXCEPTION] CIS 1.1.1.2 Ensure mounting of vFAT filesystems is limited
# https://github.com/ComplianceAsCode/content/commit/eea787e1453b19aa949903c39189479538fbbab9
#
# This exception is pretty clear cut. Disabling vFAT means the FAT-formatted
# EFI ESP cannot be mounted and the whole boot process fails for RHEL systems
# deployed using UEFI. (Enters emergency mode if it can't mount /boot/efi
# during the boot process).
#
# This is actually disabled as of the version of CaC that ships with RHEL 8.4+
# as per the commit linked above, but we keep it included here as it's still
# a valid CIS control, and it should be disabled for deployment of RHEL < 8.4.
# [EXCEPTION] CIS 1.1.5 Ensure noexec option set on /tmp partition
#
# This rule breaks far too much software, including Red Hat Satellite (as a
# server) as well as (depending on modules used) many Ansible playbooks that
# would otherwise work when run against the client.
# [EXCEPTION] CIS 1.11 Ensure system-wide crypto policy is FUTURE or FIPS
# https://github.com/ComplianceAsCode/content/issues/5229
# https://workbench.cisecurity.org/community/14/tickets/12887
#
# This rule is far too overzealous so I personally do not consider this
# a failure, as long as CIS 1.10, which ensures that the crypto policy
# is *not* set to LEGACY, is satisfied. I consider DEFAULT to be acceptable.
#
# This rule goes against Red Hat's own advice, which suggests that the
# FUTURE policy is "not supposed to be used for general purpose systems".
# See: https://access.redhat.com/articles/3642912
#
# Using FUTURE also breaks connectivity to Red Hat Satellite, as FUTURE
# prevents the use of RSA keys shorter than 3072-bit, and Satellite generates
# 2048-bit RSA keys by default.
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1803027
#
# Amusingly, applying either FUTURE or FIPS also completely breaks validation
# using CIS CAT Assessor, since the SSH client code used by CIS CAT is based
# on JSch, which currently does not support the more modern algorithms. (On
# a FUTURE or FIPS system, CIS CAT Assessor won't connect via SSH at all).
# See: http://www.jcraft.com/jsch/
# [CISBUG] CIS 1.5.1 Ensure permissions on bootloader config are configured
# https://github.com/ComplianceAsCode/content/issues/5222
# https://workbench.cisecurity.org/community/14/tickets/4720
#
# This one is actually bugged in the CIS requirement itself as it
# has very specific ideas of where the GRUB config should reside,
# and these do not hold true when we install RHEL to an EFI system.
#
test -f /boot/efi/EFI/redhat/grub.cfg && chown root:root /boot/efi/EFI/redhat/grub.cfg
test -f /boot/efi/EFI/redhat/grub.cfg && chmod og-rwx /boot/efi/EFI/redhat/grub.cfg
test -f /boot/efi/EFI/redhat/grubenv && chown root:root /boot/efi/EFI/redhat/grubenv
test -f /boot/efi/EFI/redhat/grubenv && chmod og-rwx /boot/efi/EFI/redhat/grubenv
test -f /boot/grub2/grubenv && chown root:root /boot/grub2/grubenv
test -f /boot/grub2/grubenv && chmod og-rwx /boot/grub2/grubenv
# [TWEAKS] CIS 1.8.1.1 Ensure message of the day is configured properly
# [TWEAKS] CIS 1.8.1.4 Ensure permissions on /etc/motd are configured
#
# This one actually functions fine with the OpenSCAP profile from CaC
# but I include this as an example of how to set a custom MOTD because
# the text applied by CaC is very "US Government"-specific. The text
# I apply by default is based on the suggestion given by Tenable's CIS
# scanner and is much more generic.
#
# This include statement will include a file from 'files/override/motd.j2' if it exists,
# otherwise the default path of 'files/default/motd.j2' will be used.
#
cat <<"EOF" > /etc/motd
Authorized users only. All activity may be monitored and reported.
Deployed using EL8 Kickstart for HeadlessCISPodman
Version 9.2.1
EOF
chown root:root /etc/motd
chmod u-x,go-wx /etc/motd
# [TWEAKS] CIS 1.8.1.2 Ensure local login warning banner is configured properly
# [TWEAKS] CIS 1.8.1.5 Ensure permissions on /etc/issue are configured
#
# This one actually functions fine with the OpenSCAP profile from CaC
# but I include this as an example of how to set a custom MOTD because
# the text applied by CaC is very "US Government"-specific. The text
# I apply by default is based on the suggestion given by Tenable's CIS
# scanner and is much more generic.
#
# This include statement will include a file from 'files/override/issue.j2' if it exists,
# otherwise the default path of 'files/default/issue.j2' will be used.
#
cat <<"EOF" > /etc/issue
Authorized users only. All activity may be monitored and reported.
Deployed using EL8 Kickstart for HeadlessCISPodman
Version 9.2.1
EOF
chown root:root /etc/issue
chmod u-x,go-wx /etc/issue
# [TWEAKS] CIS 1.8.1.3 Ensure remote login warning banner is configured properly
# [TWEAKS] CIS 1.8.1.6 Ensure permissions on /etc/issue.net are configured
# https://github.com/ComplianceAsCode/content/issues/5225
#
# This one actually functions fine with the OpenSCAP profile from CaC
# but I include this as an example of how to set a custom MOTD because
# the text applied by CaC is very "US Government"-specific. The text
# I apply by default is based on the suggestion given by Tenable's CIS
# scanner and is much more generic.
#
# This include statement will include a file from 'files/override/issue.net.j2' if it exists,
# otherwise the default path of 'files/default/issue.net.j2' will be used.
#
cat <<"EOF" > /etc/issue.net
Authorized users only. All activity may be monitored and reported.
Deployed using EL8 Kickstart for HeadlessCISPodman
Version 9.2.1
EOF
chown root:root /etc/issue.net
chmod u-x,go-wx /etc/issue.net
# [TWEAKS] CIS 1.8.2 Ensure GDM login banner is configured
#
# This is handled in the default cis_tailoring_workstation.xml tailoring file.
# This is enabled by default in the CIS profile, but we use the tailoring
# file to configure the chosen text that will be displayed.
# [EXCEPTION-WS] CIS 2.2.2 Ensure X Window System is not installed
#
# Configured in Workstation tailoring file.
#
# If this control is not disabled then the default CaC policy will remove the
# X server from the system and configure the default.target to multi-user.target
# to make extra sure that a graphical session does not get loaded.
# [CISBUG] CIS 3.2.1 Ensure source routed packets are not accepted
# https://workbench.cisecurity.org/community/14/tickets/10371
# https://github.com/ComplianceAsCode/content/issues/7060
# Normally, the upstream CaC profile sets unset sysctls like these inside
# the /etc/sysctl.d/99-sysctl.conf file. But if CaC detects that a setting
# is already the default (i.e. it is set in /usr/lib/sysctl.d/50-default.conf)
# then it does not get set again inside the 99-sysctl.conf file.
#
# So 3 of the relevant sysctls for this control *are* getting explicitly set
# inside 99-sysctl.conf and can be detected by CIS CAT, while the remaining one:
# net.ipv4.conf.all.accept_source_route
# is already set in 50-default.conf with the required value of '0'. It is a failing
# of CIS CAT Assessor to not account for this, as CIS CAT checks that the setting
# is set explicitly on disk only within /etc/sysctl.conf and /etc/sysctl.d/*.conf.
#
# I have expanded a pre-existing upstream CIS ticket with more info around this
# specific issue, to suggest that the defaults are taken into account in future.
# [SCAPBUG] CIS 3.4.2.4 Ensure default zone is set
# https://github.com/ComplianceAsCode/content/blob/2b2152d288e05f0d64f26fff3f01b0e75311023d/linux_os/guide/system/network/network-firewalld/ruleset_modifications/set_firewalld_default_zone/rule.yml#L55-L59
#
# It seems like CIS CAT is actually not that opinionated about exactly *what*
# zone we set as the default for Firewalld, but CaC is adamant that the default
# should be 'drop'. CaC also doesn't remediate this one during install (see link)
# so we have to do it ourselves here:
sed -i 's/^DefaultZone=.*/DefaultZone=drop/g' /etc/firewalld/firewalld.conf
#
# Please note that since we are changing the default zone here, any 'firewall'
# commands used further up in this Kickstart file won't have any effect (they operate
# only on the 'public' zone). So we use 'firewall-offline-cmd' commands here to
# configure any firewall rules which we want to bake into the installation:
firewall-offline-cmd --zone=drop --add-service=ssh
# [POSTINST] / [EXCEPTION-WS] CIS 3.5 Ensure wireless interfaces are disabled
# NO UPSTREAM BUG
#
# Compliance is assessed by the following logic in Assessor v4.6.0:
# sudo nmcli radio all | grep -Eq "^\s*\S+\s+disabled\s+\S+\s+disabled\s*$" && passing=true
# We can satisfy the logic above by simply running:
# sudo nmcli radio all off
# on a booted system post-installation, but this doesn't appear to be something
# that we can configure from here within the Kickstart installation (I have tried).
#
# On Workstation installs, we disable this control as Wi-Fi is often a desirable feature.
# [TWEAKS] CIS 4.1.2.1 Ensure audit log storage size is configured
#
# In the tailoring file that accompanies this Kickstart, we configure this using
# one of CaC's configurable variables.
#
# We also configure the variable for the control which determines how many logfiles
# we're going to keep.
#
# Currently the settings chosen by the options in the tailoring file are:
# 10 x 100 MB = ~1GB audit logs in /var/log/audit
# [EXCEPTION] CIS 4.1.2.2 Ensure audit logs are not automatically deleted
# https://workbench.cisecurity.org/tickets/12888
#
# We specifically *want* this control to fail, as in conjunction with 4.1.2.3 being
# set, this control leads us to a situation where the system will eventually run
# out of disk space on /var/log/audit and halt without easily-diagnosed output.
#
# This control is disabled in the tailoring file that accompanies this Kickstart.
# [EXCEPTION] CIS 4.1.2.3 Ensure system is disabled when audit logs are full
#
# This is a high-risk control for very specific environments where it is preferable
# that a system halt completely rather than continue to run without generating
# audit logs. As this is unlikely to match many environments, I disable this control.
#
# This control is disabled in the tailoring file that accompanies this Kickstart.
# [CISBUG] CIS 4.1.3 Ensure changes to system administration scope (sudoers) is collected
# [CISBUG] CIS 4.1.4 Ensure login and logout events are collected
# [CISBUG] CIS 4.1.5 Ensure session initiation information is collected
# [CISBUG] CIS 4.1.6 Ensure events that modify date and time information are collected
# [CISBUG] CIS 4.1.7 Ensure events that modify the system's Mandatory Access Controls are collected
# [CISBUG] CIS 4.1.8 Ensure events that modify the system's network environment are collected
# [CISBUG] CIS 4.1.9 Ensure discretionary access control permission modification events are collected
# [CISBUG] CIS 4.1.10 Ensure unsuccessful unauthorized file access attempts are collected
# [CISBUG] CIS 4.1.11 Ensure events that modify user/group information are collected
# [CISBUG] CIS 4.1.12 Ensure successful file system mounts are collected
# [CISBUG] CIS 4.1.13 Ensure use of privileged commands is collected
# [CISBUG] CIS 4.1.14 Ensure file deletion events by users are collected
# [CISBUG] CIS 4.1.15 Ensure kernel module loading and unloading is collected
# [CISBUG] CIS 4.1.16 Ensure system administrator actions (sudolog) are collected
#
# All of the above controls appear to be applied correctly using the upstream OpenSCAP
# profile from CaC, but CIS CAT Assessor is very opinionated about the exact structure
# and order the ruleset should take when on disk, so reports failure even though the
# system in question does have all the correct rules loaded.
# [SCAPBUG] CIS 4.2.1.3 - Ensure rsyslog default file permissions configured
# https://github.com/ComplianceAsCode/content/issues/5518
#
echo '$FileCreateMode 0640' >> /etc/rsyslog.d/cis_file_create_mode.conf
# [EXCEPTION] CIS 4.2.1.5 Ensure rsyslog is configured to send logs to a remote log host
#
# This is set as an exception in my default tailoring file. By default, the OpenSCAP
# approach taken by CaC is to configure rsyslog to send logs to a remote host with
# the hostname of 'logcollector'. If you're lucky, that means you'll see this kind
# of thing in your journald logs for the rsyslog service:
#
# rsyslogd[2138]: cannot resolve hostname 'logcollector' [v8.1911.0-7.el8 try https://www.rsyslog.com/e/2027 ]
#
# If you're *unlucky*, then anyone on your subnet with a resolvable hostname of
# 'logcollector' can help themselves to a stream of your most sensitive system logs.
# (As can everyone else really, as they're streamed unencrypted on UDP 514 by default).
#
# A much more sensible approach here is to set up authenticated (and encrypted!) log
# shipping using something like Splunk.
# [SCAPBUG] CIS 4.2.2.1 Ensure journald is configured to send logs to rsyslog
# https://github.com/ComplianceAsCode/content/pull/7682
#
# Note: Fixed in 0.1.59 (see PR above)
#
#
sed -i 's/.*ForwardToSyslog.*/ForwardToSyslog=yes/g' /etc/systemd/journald.conf
# [SCAPBUG] CIS 4.2.2.2 Ensure journald is configured to compress large log files
# https://github.com/ComplianceAsCode/content/pull/7682
#
# Note: Fixed in 0.1.59 (see PR above)
#
#
sed -i 's/.*Compress.*/Compress=yes/g' /etc/systemd/journald.conf
# [SCAPBUG] CIS 4.2.2.3 Ensure journald is configured to write logfiles to persistent disk
# https://github.com/ComplianceAsCode/content/pull/7682
#
# Note: Fixed in 0.1.59 (see PR above)
#
#
sed -i 's/.*Storage.*/Storage=persistent/g' /etc/systemd/journald.conf
# [EXCEPTION] CIS 4.2.3 Ensure permissions on all logfiles are configured
# https://github.com/ComplianceAsCode/content/issues/5523
# https://workbench.cisecurity.org/community/14/tickets/13024
#
# This is a difficult control because the suggested remediation by CIS CAT Assessor
# is to run:
# find /var/log -type f -exec chmod g-wx,o-rwx "{}" + -o -type d -exec chmod g-w,o-rwx "{}" +
#
# The logic behind which is that it will set restrictive permissions on all logfiles
# and all subdirectories of /var/log.
#
# The problem with that approach is that the logic provided also matches /var/log itself and
# removing the world-executable bit from the top-level /var/log directory prevents any users
# who aren't root from traversing the directory path. This means that even if a service account
# owns its own logging subdirectory of /var/log and has permissions set accordingly, it won't
# be able to see its own logfile to write to, because it doesn't have the execute permissions
# it needs on /var/log to be able to traverse the directory path.
#
# This breaks too much software in my experience, so this control is set as an exception.
#
# Similarly, it's desirable not to set permissions too restrictively on some logfiles because
# it will break commands like 'last', and sshd's 'PrintLastLog' feature. The permissions also
# get reset on boot by systemd for a lot of logfiles.
# [SCAPBUG] CIS 5.1.8 Ensure at/cron is restricted to authorized users
# https://github.com/ComplianceAsCode/content/pull/7691
#
# Note: Fixed in 0.1.59 (see PR above)
#
test -f /etc/cron.deny && rm /etc/cron.deny
test -f /etc/at.deny && rm /etc/at.deny
touch /etc/cron.allow
touch /etc/at.allow
chmod og-rwx /etc/cron.allow
chmod og-rwx /etc/at.allow
chown root:root /etc/cron.allow
chown root:root /etc/at.allow
# [SCAPBUG] CIS 5.2.2 - Ensure SSH access is limited
# https://github.com/ComplianceAsCode/content/issues/7196
#
# Currently, this grants SSH access only to users in the 'localssh' group,
# which we add to our default 'user' user in the user creation step.
#
sed -i '/.*AllowGroups.*/d' /etc/ssh/sshd_config
echo '' >> /etc/ssh/sshd_config
echo '# CIS 5.2.2 - Ensure SSH access is limited' >> /etc/ssh/sshd_config
echo 'AllowGroups localssh' >> /etc/ssh/sshd_config
# [CISBUG] CIS 5.2.3 Ensure permissions on SSH private host key files are configured
# https://workbench.cisecurity.org/tickets/9978
# https://bugzilla.redhat.com/show_bug.cgi?id=1023945
# https://github.com/ComplianceAsCode/content/blob/986de004f480644aa33d379af0b66c13d3ec76fc/rhel8/profiles/cis.profile#L789
#
# Current profile sets some permissions on these, but it is not restrictive enough
# to pass the rule (uses 0640; keys owned by root:ssh-keys while CIS expects root:root).
#
# Remediating this inline in the Kickstart file does not stick and must be done post-install
# but it seems like deviating from Red Hat's default on RHEL 8 can cause issues with
# sshd (see discussion on CIS Workbench ticket above, and the Red Hat BZ for more details).
# [SCAPBUG] CIS 5.2.14 - Ensure SSH LoginGraceTime is set to one minute or less
# https://github.com/ComplianceAsCode/content/pull/7678
#
# Note: Fixed in 0.1.59 (see PR above)
#
sed -i '/.*LoginGraceTime.*/d' /etc/ssh/sshd_config
echo '' >> /etc/ssh/sshd_config
echo '# CIS 5.2.14 - Ensure SSH LoginGraceTime is set to one minute or less' >> /etc/ssh/sshd_config
echo 'LoginGraceTime 60' >> /etc/ssh/sshd_config
# [TODO] 5.3.1 Create custom authselect profile
# https://github.com/ComplianceAsCode/content/issues/5530
#
# These authselect controls need looking at.
# [TODO] 5.3.2 Select authselect profile
# https://github.com/ComplianceAsCode/content/issues/5531
#
# These authselect controls need looking at.
# [TODO] 5.3.3 Ensure authselect includes with-faillock
# https://github.com/ComplianceAsCode/content/issues/5532
#
# These authselect controls need looking at.
# [TWEAKS] CIS 5.5.1.1 Ensure password expiration is 365 days or less
# [TWEAKS] CIS 5.5.1.2 Ensure minimum days between password changes is 7 or more
# NO UPSTREAM BUG
#
# I have validated that the correct value is being set for PASS_MAX_DAYS
# in /etc/login.defs, but there is a second component to the check run by
# CIS CAT Assessor, which validates that all configured users must not have
# a password set to expire in more than 365 days (i.e. none have been
# grandfathered in by the default value of 99999 which they had before we
# applied the OpenSCAP profile to the system above.)
#
# I have validated that the correct value is being set for PASS_MIN_DAYS
# in /etc/login.defs, but there is a second component to the check run by
# CIS CAT Assessor, which validates that all configured users must not have
# a password minimum age of more than 7 days (i.e. none have been
# grandfathered in by the default value of 0 which they had before we
# applied the OpenSCAP profile to the system above.)
#
# So we need to run one chage command below for every new user (with a password)
# that we created as part of this Kickstart process.
#
# The --lastday flag is required to set the last date of password change for
# each account to the date of this Kickstart run. Without this, the user
# will be required to change their password at first login. With this tweak,
# the user has 365 days from the date of the Kickstart run before a password
# change will be enforced.
#
# Example:
# chage --lastday $(date --iso-8601) --mindays 7 --maxdays 365 user
#
# Instead of doing this here directly as before, I am now setting this inside
# the configure_users.j2 include file, which we import below. (We can't do it
# inside the 'create_users.j2' file as much as I'd like to, because that gets
# run outside the %post context, but we need to run these 'chage' commands in
# the chroot for the installed system).
### START configure_users.j2 INCLUDE FILE HERE ###
chage --lastday $(date --iso-8601) --mindays 7 --maxdays 365 user
### END configure_users.j2 INCLUDE FILE HERE ###
# [CISBUG] CIS 5.5.3 Ensure default user shell timeout is 900 seconds or less
# https://workbench.cisecurity.org/community/14/tickets/12980
#
# As per ticket above, CIS Assessor v4.6.0 wrongly reports this as failed
# but I have verified it manually as set correctly by the OpenSCAP profile.
# [SCAPBUG] CIS 5.7 Ensure access to the su command is restricted
#
# Note: CaC upstream considers this only "partially" automatable due to site policy:
# https://github.com/ComplianceAsCode/content/pull/8000
#
echo 'auth required pam_wheel.so use_uid' >> /etc/pam.d/su
# [CISBUG] CIS 6.1.1 Audit system file permissions
#
# This is an interesting one, because it is not validated or remediated by
# CIS CAT Assessor at all, although OpenSCAP has logic to do it and can generate
# an Ansible remediation playbook.
#
# The main thrust of this one is that files which have been delivered to the system
# as part of RPM packages should still be set to the same permissions as would be
# expected from the upstream RPM package.
#
# But this conflicts with a number of other CIS controls (for example, many of the
# files from the 'cron' package are ones which we explicitly change the permissions
# of, to satisfy other CIS controls).
#
# I do not exclude this from the CaC profile with the tailoring file since, although
# this control will always report a fail when validated with oscap (assuming all the
# other expected CIS controls are set correctly), it's useful to see the output as it
# might throw up some unexpected results if permissions have changed on files which
# we did not explicitly change them on.
#
# On a fresh-install of a system from this Kickstart, we expect oscap to report that
# the following files have failed validation under this control:
#
# /etc/cron.d (as a result of CIS 5.1.7)
# /etc/cron.daily (as a result of CIS 5.1.4)
# /etc/cron.hourly (as a result of CIS 5.1.3)
# /etc/cron.monthly (as a result of CIS 5.1.6)
# /etc/cron.weekly (as a result of CIS 5.1.5)
# /etc/crontab (as a result of CIS 5.1.2)
#
# Failures on files which lie outside the list defined above are not expected on a
# fresh install from this Kickstart and may indicate a problem.
# [ADDITION] Restrict access to kernel message buffer
#
# Configured in tailoring file.
#
# This control prevents regular system users from being able to read the output
# of the kernel message buffer via 'dmesg'. After setting this control, root
# privileges are required to read the kernel message buffer.
# [ADDITION] Harden the operation of the BPF just-in-time compiler
#
# Configured in tailoring file.
#
# The value set by this control (2) enables BPF JIT hardening for all users on
# the system. There is a performance/hardening tradeoff here but this control
# can help mitigate JIT spraying.
# [ADDITION] Disallow Magic SysRq Key
#
# Configured in tailoring file.
#
# It's often not configured on distributions these days, but the 'Magic SysRq
# Key' can perform a number of very low level operations on a system which are
# undesirable from a security perspective. This is especially relevant if it may
# be possible for an attacker to gain physical (or remote KVM/BMC) access to
# a machine.
# [ADDITION] Disable rhsmcertd service
#
# Configured in tailoring file and in the services config elsewhere in this Kickstart.
#
# This service is installed with RHEL and periodically checks with Red Hat (or
# a configured Satellite server) to verify the validity of current subscriptions
# and update for any changes. By default this is every 240 minutes (4 hours).
# This seems like excessive and unnecessary network activity considering these
# checks are already done before DNF transactions.
#
# This is related to the CIS control which disables rhnsd, which is a network
# daemon used by Red Hat with pre-6 versions of Satellite.
# [ADDITION] Disable Bluetooth service and kernel module
#
# Configured in tailoring file and in the services config elsewhere in this Kickstart.
# [ADDITION] Harden /proc with hidepid
echo '' >> /etc/fstab
echo '# Harden /proc by mounting with hidepid' >> /etc/fstab
echo 'proc /proc proc defaults,hidepid=2 0 0' >> /etc/fstab
# [ADDITION-WS] Apply various GNOME/GDM hardening controls
#
# This applies a few GNOME-specific controls in the tailoring file to Workstation
# systems. Currently this disables the geolocation feature of GNOME, and disables
# the automatic and guest login features of GDM.
# [ADDITION] Disable Access to Network bpf() Syscall From Unprivileged Processes -->
#
# By default, the bpf() syscall can be called from userspace by regular users. With
# BPF code running JIT-ed in the kernel, this represents an attack vector if there
# is a vulnerability in the BPF implementation in the kernel (there have been several
# so far).
#
# By disabling unprivileged BPF, we do not disable BPF (which can be very useful), but
# we ensure that a user executing BPF programs is already root on the system, which
# cuts out the possibility of an unprivileged user using a BPF vulnerability to elevate
# privileges.
# [ADDITION] Restrict access to kernel pointers via /proc and other interfaces -->
# https://lwn.net/Articles/420403/
#
# "The %pK format specifier is designed to hide exposed kernel pointers,
# specifically via /proc interfaces. Exposing these pointers provides an
# easy target for kernel write vulnerabilities, since they reveal the
# locations of writable structures containing easily triggerable function
# pointers."
# [ADDITION] Disable loading of kernel modules
#
# If we haven't selected to enable ZFS, we lock down the kernel by disabling the loading
# of kernel modules. The Kernel Lockdown feature does the same thing if we're booted in
# Secure Boot mode, but disabling it via sysctl adds another layer of protection which we
# might as well have.
# [ADDITION] Disallow some ftrace and kernel profiling features for users without CAP_SYS_ADMIN
#
# This addition controls the kernel.perf_event_paranoid sysctl, which denies access to
# certain perf tracepoints to unprivileged users. These can be a leak vector for information
# which could potentially be used to attack the system.
# [ADDITION] Restrict use of ptrace
#
# This applies a more restrictive setting to the use of ptrace on a system, ensuring that only
# a parent process can be debugged with ptrace.
# Configure the hostcritical.slice for critical service accounting and
# add the SSH daemon to the slice.
mkdir -p /etc/systemd/system/sshd.service.d
cat <<"EOF" > /etc/systemd/system/sshd.service.d/00-slice.conf
[Service]
Slice=hostcritical.slice
MemoryLow=192M
EOF
chown root:root /etc/systemd/system/sshd.service.d/00-slice.conf
chmod 0640 /etc/systemd/system/sshd.service.d/00-slice.conf
mkdir -p /etc/systemd/system.control/hostcritical.slice.d
cat <<"EOF" > /etc/systemd/system.control/hostcritical.slice.d/00-MemoryLow.conf
[Slice]
MemoryLow=192M
EOF
chown root:root /etc/systemd/system.control/hostcritical.slice.d/00-MemoryLow.conf
chmod 0640 /etc/systemd/system.control/hostcritical.slice.d/00-MemoryLow.conf
# Enable EPEL repository if we selected the 'enable_epel' var
# /etc/yum.repos.d/epel.repo
cat <<"EOF" > /etc/yum.repos.d/epel.repo
[epel]
name=Extra Packages for Enterprise Linux $releasever - $basearch
# It is much more secure to use the metalink, but if you wish to use a local mirror
# place it's address here.
#baseurl=https://download.example/pub/epel/$releasever/Everything/$basearch
metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-$releasever&arch=$basearch&infra=$infra&content=$contentdir
enabled=1
gpgcheck=1
countme=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8
EOF
chown root:root /etc/yum.repos.d/epel.repo
chmod 0644 /etc/yum.repos.d/epel.repo
# /etc/yum.repos.d/epel-modular.repo
cat <<"EOF" > /etc/yum.repos.d/epel-modular.repo
[epel-modular]
name=Extra Packages for Enterprise Linux Modular $releasever - $basearch
# It is much more secure to use the metalink, but if you wish to use a local mirror
# place it's address here.
#baseurl=https://download.example/pub/epel/$releasever/Modular/$basearch
metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-modular-$releasever&arch=$basearch&infra=$infra&content=$contentdir
enabled=1
gpgcheck=1
countme=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8
EOF
chown root:root /etc/yum.repos.d/epel-modular.repo
chmod 0644 /etc/yum.repos.d/epel-modular.repo
# /var/lib/systemd/system-preset/90-epel.preset
cat <<"EOF" > /var/lib/systemd/system-preset/90-epel.preset
# Also see:
# https://fedoraproject.org/wiki/Starting_services_by_default
#
# https://bugzilla.redhat.com/show_bug.cgi?id=1901721
enable x509watch.timer
EOF
mkdir -p /var/lib/systemd/system-preset
chown root:root /var/lib/systemd/system-preset/90-epel.preset
chmod 0644 /var/lib/systemd/system-preset/90-epel.preset
# /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8
cat <<"EOF" > /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFz3zvsBEADJOIIWllGudxnpvJnkxQz2CtoWI7godVnoclrdl83kVjqSQp+2
dgxuG5mUiADUfYHaRQzxKw8efuQnwxzU9kZ70ngCxtmbQWGmUmfSThiapOz00018
+eo5MFabd2vdiGo1y+51m2sRDpN8qdCaqXko65cyMuLXrojJHIuvRA/x7iqOrRfy
a8x3OxC4PEgl5pgDnP8pVK0lLYncDEQCN76D9ubhZQWhISF/zJI+e806V71hzfyL
/Mt3mQm/li+lRKU25Usk9dWaf4NH/wZHMIPAkVJ4uD4H/uS49wqWnyiTYGT7hUbi
ecF7crhLCmlRzvJR8mkRP6/4T/F3tNDPWZeDNEDVFUkTFHNU6/h2+O398MNY/fOh
yKaNK3nnE0g6QJ1dOH31lXHARlpFOtWt3VmZU0JnWLeYdvap4Eff9qTWZJhI7Cq0
Wm8DgLUpXgNlkmquvE7P2W5EAr2E5AqKQoDbfw/GiWdRvHWKeNGMRLnGI3QuoX3U
pAlXD7v13VdZxNydvpeypbf/AfRyrHRKhkUj3cU1pYkM3DNZE77C5JUe6/0nxbt4
ETUZBTgLgYJGP8c7PbkVnO6I/KgL1jw+7MW6Az8Ox+RXZLyGMVmbW/TMc8haJfKL
MoUo3TVk8nPiUhoOC0/kI7j9ilFrBxBU5dUtF4ITAWc8xnG6jJs/IsvRpQARAQAB
tChGZWRvcmEgRVBFTCAoOCkgPGVwZWxAZmVkb3JhcHJvamVjdC5vcmc+iQI4BBMB
AgAiBQJc9877AhsPBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAh6kWrL4bW
oWagD/4xnLWws34GByVDQkjprk0fX7Iyhpm/U7BsIHKspHLL+Y46vAAGY/9vMvdE
0fcr9Ek2Zp7zE1RWmSCzzzUgTG6BFoTG1H4Fho/7Z8BXK/jybowXSZfqXnTOfhSF
alwDdwlSJvfYNV9MbyvbxN8qZRU1z7PEWZrIzFDDToFRk0R71zHpnPTNIJ5/YXTw
NqU9OxII8hMQj4ufF11040AJQZ7br3rzerlyBOB+Jd1zSPVrAPpeMyJppWFHSDAI
WK6x+am13VIInXtqB/Cz4GBHLFK5d2/IYspVw47Solj8jiFEtnAq6+1Aq5WH3iB4
bE2e6z00DSF93frwOyWN7WmPIoc2QsNRJhgfJC+isGQAwwq8xAbHEBeuyMG8GZjz
xohg0H4bOSEujVLTjH1xbAG4DnhWO/1VXLX+LXELycO8ZQTcjj/4AQKuo4wvMPrv
9A169oETG+VwQlNd74VBPGCvhnzwGXNbTK/KH1+WRH0YSb+41flB3NKhMSU6dGI0
SGtIxDSHhVVNmx2/6XiT9U/znrZsG5Kw8nIbbFz+9MGUUWgJMsd1Zl9R8gz7V9fp
n7L7y5LhJ8HOCMsY/Z7/7HUs+t/A1MI4g7Q5g5UuSZdgi0zxukiWuCkLeAiAP4y7
zKK4OjJ644NDcWCHa36znwVmkz3ixL8Q0auR15Oqq2BjR/fyog==
=84m8
-----END PGP PUBLIC KEY BLOCK-----
EOF
chown root:root /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8
chmod 0644 /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-8
# Remove machine-id on pre generated images (Packer)
#
# See why we set the 'uninitialized' value here:
# https://www.freedesktop.org/software/systemd/man/machine-id.html
#
rm -fv /etc/machine-id
echo 'uninitialized' > /etc/machine-id
### START postinstall.j2 INCLUDE FILE HERE ###
# To include content here, place content in the override/postinstall.j2
# file in the main repo before running the Ansible Playbook to generate
# this Kickstart file.
### END postinstall.j2 INCLUDE FILE HERE ###
# Write out the version of the Kickstart that ran to /root/ks_ver_deployed
# so we can read it in later with Ansible etc and use it for remediation/updates
# of systems which we know were deployed with earlier versions of this Kickstart:
echo '9.2.1' > /root/ks_ver_deployed
%end
###################### END POSTINSTALL SCRIPT ######################
# Reboot if we want to carry out post-install actions
reboot --eject
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment