Last active
August 19, 2024 19:24
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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