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

303 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`
```ini
# 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)
```bash
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:
```bash
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
```bash
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`
```ini
# 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`
```ini
# 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:
```bash
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:
```bash
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.