Files
pxe_boot_alma/homelab/docs/alma10-cis-hardening.md
T
andersenandClaude Fable 5 6d398b826a refactor: move tree under homelab/, add alma10 hardening and kickstart docs
- restructure boot/kickstarts/scripts/docs into homelab/
- docs: alma9->10 breaking changes, CIS hardening, kickstart changes
- add find_cron_entries.sh helper and codex running memory notes

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-06 22:35:07 -04:00

11 KiB
Raw Blame History

AlmaLinux 10 — CIS Level 1 Hardening Decisions

Created: 2026-03-27 Updated: 2026-03-28 Reference: CIS AlmaLinux OS 10 Benchmark (tracks RHEL 10) Script: work/KickStart/cfg/AlmaLinux-10.1-x86_64/ks.d/S940A-cis-hardening


Summary of Decisions

CIS Control Description Decision
1.1.1 Disable unused filesystem modules Applied
1.1.2 /tmp as separate partition or tmpfs Deferred — pending dev review
1.6 Disable core dumps Applied
3.3.1 Disable IP forwarding Applied (probes/servers are not routers)
3.3.2 Disable packet redirect sending Applied
3.3.3 Refuse source-routed packets Applied
3.3.4 Refuse ICMP redirects Applied
3.3.5 Refuse secure ICMP redirects Applied
3.3.6 Log martian packets Applied
3.3.7 Ignore broadcast ICMP echo requests Applied
3.3.8 Ignore bogus ICMP error responses Applied
3.3.9 Enable TCP SYN cookies Applied
3.3.10 Disable IPv6 router advertisements Applied
4.1.2 auditd enabled at boot Applied
4.1.3 Audit processes prior to auditd start Applied (audit=1 audit_backlog_limit=8192 kernel args)
4.1.4 Date/time change events Applied
4.1.5 User/group identity changes Applied
4.1.6 Network environment changes Applied
4.1.7 MAC policy changes (SELinux) Applied
4.1.8 Login/logout events Applied
4.1.9 Session initiation Applied
4.1.10 Permission modification events Applied
4.1.11 Unauthorized file access attempts Applied
4.1.12 Privileged command usage Applied (generated dynamically via find)
4.1.13 File system mounts Applied
4.1.14 File deletion by users Applied
4.1.15 sudoers scope changes Applied
4.1.16 sudo log monitoring Applied
4.1.17 Kernel module load/unload Applied
4.1.18 Audit rules immutable (-e 2) Applied
5.3.2 sudo: require pty Applied
5.3.3 sudo: log all usage Applied
5.4.1 Password quality (pwquality) Applied
5.4.2 Password aging Excluded — no expiration policy in this environment
5.4.3 Account lockout (pam_faillock) Applied (pre-configured; active after authselect enable-feature with-faillock post-IPA)
squashfs module blacklist CIS recommends disabling Excluded — containers (Docker/Podman) require squashfs
udf module blacklist CIS recommends disabling Excluded — not prohibited in this environment
AIDE cron CIS recommends local AIDE cron Excluded — managed centrally, not locally
authselect profile change Required to activate faillock in PAM Excluded from kickstart — IPA owns the authselect profile

Applied Controls

1.1.1 — Disable Unused Filesystem Modules

File: /etc/modprobe.d/cis-fs-blacklist.conf

install cramfs   /bin/true
install freevxfs /bin/true
install hfs      /bin/true
install hfsplus  /bin/true
install jffs2    /bin/true
blacklist cramfs
blacklist freevxfs
blacklist hfs
blacklist hfsplus
blacklist jffs2

Both install (prevents modprobe load) and blacklist (prevents udev autoload) directives are used for belt-and-suspenders.

Excluded from this list:

  • squashfs — Docker/Podman containers require it. Re-evaluate if container usage changes.
  • udf — Not prohibited in this environment. Re-evaluate if needed.

1.6 — Core Dump Restrictions

Three layers applied:

/etc/security/limits.d/cis-coredump.conf (PAM limits):

*  hard  core  0

/etc/sysctl.d/20-cis-coredump.conf (kernel — disables setuid core dumps):

fs.suid_dumpable = 0

/etc/systemd/coredump.conf.d/cis.conf (systemd coredump handler):

[Coredump]
Storage=none
ProcessSizeMax=0

3.3 — Network Sysctl Hardening

File: /etc/sysctl.d/30-cis-network.conf

# 3.3.1 — disable IP forwarding
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0

# 3.3.2 — disable packet redirect sending
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# 3.3.3 — refuse source-routed packets
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0

# 3.3.4 — refuse ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0

# 3.3.5 — refuse secure ICMP redirects
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0

# 3.3.6 — log martian packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# 3.3.7 — ignore broadcast ICMP echo requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# 3.3.8 — ignore bogus ICMP error responses
net.ipv4.icmp_ignore_bogus_error_responses = 1

# 3.3.9 — enable TCP SYN cookies
net.ipv4.tcp_syncookies = 1

# 3.3.10 — disable IPv6 router advertisements
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0

# Kernel ASLR
kernel.randomize_va_space = 2

Note on net.ipv4.ip_forward: The default is already 0 on RHEL 10 for non-router systems. This is explicitly set for audit compliance. If Docker/Podman networking requires it, Docker daemon config ("ip-forward": true) re-enables it automatically — but explicitly setting 0 here means Docker/Podman will need to override it at startup. Verify if container networking is affected.

4.x — Auditd Configuration

Added 2026-03-28.

Kernel boot flag (4.1.3)

grubby --update-kernel=ALL --args="audit=1 audit_backlog_limit=8192"

Ensures processes that start before auditd is running are still audited. audit_backlog_limit=8192 prevents kernel audit buffer overflow during boot.

Rules file: /etc/audit/rules.d/cis.rules

Controls 4.1.4–4.1.17 are written as a static heredoc, with 4.1.12 (privileged commands) appended dynamically:

find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null \
   | awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged"}' \
   >> /etc/audit/rules.d/cis.rules

-e 2 (immutable flag, 4.1.18) is appended last so it takes effect after all rules including the dynamic privileged-command list.

Network environment path note (4.1.6)

CIS references /etc/sysconfig/network-scripts/ which does not exist in RHEL 10. Replaced with /etc/NetworkManager/ which is the canonical location for NM keyfiles.

auditd service

systemctl enable auditd

audit package is a dependency of audit-libs which is pulled in transitively. No explicit KS_Packages.cfg entry required.


5.3 — sudo Hardening

File: /etc/sudoers.d/cis-sudo (mode 0440)

# 5.3.2 — require pty (prevents background sudo abuse)
Defaults  use_pty
# 5.3.3 — log all sudo usage
Defaults  logfile=/var/log/sudo.log
# credential caching limit
Defaults  timestamp_timeout=5

5.4.1 — Password Quality (pwquality)

File: /etc/security/pwquality.conf.d/cis.conf

# CIS 5.4.1 — password complexity requirements
minlen = 14
minclass = 4
dcredit = -1
ucredit = -1
ocredit = -1
lcredit = -1
maxrepeat = 3
maxsequence = 3

Applies to all interactive password changes. Does not affect pre-hashed passwords set in kickstart.

5.4.3 — Account Lockout (pam_faillock)

File: /etc/security/faillock.conf

# 5.4.3 — lock after 5 failures in a 15-minute window
deny = 5
fail_interval = 900
unlock_time = 900
even_deny_root
root_unlock_time = 60

Important: This configuration is pre-staged but not active until PAM is wired to use it. ipa-client-install owns the authselect profile. After IPA enrolment, enable faillock:

authselect enable-feature with-faillock

Do not run this in kickstart — IPA resets the authselect profile during enrolment.


Deferred Controls

1.1.2 — /tmp as Separate Partition or tmpfs

Status: Deferred pending dev review.

Reason: /var/tmp may need exec permissions for some application stack components. Current kickstart uses autopart --type=lvm which places /tmp on the root LVM volume. Mounting /tmp as tmpfs or a separate partition requires validating that:

  1. No application code writes large temporary files to /tmp that would exhaust a size-limited tmpfs
  2. /var/tmp exec requirements are understood — CIS also recommends noexec on /var/tmp, which may conflict with application use

Action: Revisit with dev team. If approved, add to kickstart:

%pre
# ... partition layout
%end

or post-install:

echo "tmpfs /tmp tmpfs defaults,nodev,nosuid,noexec,size=2G 0 0" >> /etc/fstab

Excluded Controls

5.4.2 — Password Aging

No password expiration policy for any accounts in this environment. PASS_MAX_DAYS, PASS_MIN_DAYS, PASS_WARN_AGE are left at system defaults. Service accounts and probe accounts do not rotate passwords on a schedule.

squashfs Module Blacklist

CIS recommends blacklisting squashfs. Excluded because Docker and Podman use squashfs for container image layers. If container usage is removed from these hosts, re-evaluate.

udf Module Blacklist

CIS recommends blacklisting udf (Universal Disk Format). Not prohibited in this environment and excluded from scope.

AIDE Cron

AIDE is installed (aide package in KS_Packages.cfg) but cron-based integrity scanning is managed centrally by a dedicated machine — not configured locally on each probe/server. Local AIDE cron is not added.

authselect Profile Change

ipa-client-install owns and resets the authselect profile. Any pre-kickstart authselect change would be overwritten during IPA enrolment. faillock.conf is pre-staged; authselect enable-feature with-faillock is a manual post-enrolment step.


Kernel ASLR Note

kernel.randomize_va_space = 2 (full ASLR) is set in 30-cis-network.conf. This is the RHEL 10 default but is explicitly set for audit compliance. No known application compatibility issues with this value.


Future Review Items

  • SELinux verification: audit2allow outputs CIL format by default in RHEL 10 (changed from .te). Any local SELinux policy management scripts need to be updated. Verify in test VM.
  • Docker/container network compatibility with ip_forward=0: If containers use bridged networking, Docker daemon re-enables ip_forward at startup. Confirm no conflict with the sysctl set above.