Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions rhel-stig/Dockerfile.rhel9
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init
FROM registry.access.redhat.com/ubi9-init:9.4-6

ARG USERNAME
ARG PASSWORD
ARG KAIROS_VERSION=v3.5.9

RUN dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm -y
# Subscription manager in redhat does not run directly in containers unless you run on a redhat host, hence we remove the rhsm-host, login to the redhat subscription and add the repos
RUN rm /etc/rhsm-host && subscription-manager register --username ${USERNAME} --password ${PASSWORD} \
# subscription-manager runs inside the UBI container (host OS does not need to be RHEL). Remove rhsm-host so it does not try to use host entitlements.
# Uses BuildKit secrets (--secret id=rhsm_username,src=... --secret id=rhsm_password,src=...) - credentials never stored in image
RUN --mount=type=secret,id=rhsm_username \
--mount=type=secret,id=rhsm_password \
sh -c 'rm /etc/rhsm-host && subscription-manager register --username "$(cat /run/secrets/rhsm_username)" --password "$(cat /run/secrets/rhsm_password)" \
&& yum repolist \
&& subscription-manager attach --auto \
&& subscription-manager repos --enable rhel-9-for-x86_64-appstream-rpms \
&& yum repolist
&& yum repolist'

# Let Kairos install packages first (provides network config, luet packages, etc.)
RUN --mount=type=bind,from=kairos-init,src=/kairos-init,dst=/kairos-init \
Expand Down
11 changes: 6 additions & 5 deletions rhel-stig/Dockerfile.rhel9-fips
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
FROM quay.io/kairos/kairos-init:v0.5.28 AS kairos-init
FROM registry.access.redhat.com/ubi9-init:9.4-6

ARG USERNAME
ARG PASSWORD
ARG KAIROS_VERSION=v3.5.9

# Don't get asked while running apt commands
ENV DEBIAN_FRONTEND=noninteractive

RUN dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm -y
# Subscription manager in redhat does not run directly in containers unless you run on a redhat host, hence we remove the rhsm-host, login to the redhat subscription and add the repos
RUN rm /etc/rhsm-host && subscription-manager register --username ${USERNAME} --password ${PASSWORD} \
# subscription-manager runs inside the UBI container (host OS does not need to be RHEL). Remove rhsm-host so it does not try to use host entitlements.
# Uses BuildKit secrets (--secret id=rhsm_username,src=... --secret id=rhsm_password,src=...) - credentials never stored in image
RUN --mount=type=secret,id=rhsm_username \
--mount=type=secret,id=rhsm_password \
sh -c 'rm /etc/rhsm-host && subscription-manager register --username "$(cat /run/secrets/rhsm_username)" --password "$(cat /run/secrets/rhsm_password)" \
&& yum repolist \
&& subscription-manager attach --auto \
&& subscription-manager repos --enable rhel-9-for-x86_64-appstream-rpms \
&& yum repolist
&& yum repolist'
RUN echo "install_weak_deps=False" >> /etc/dnf/dnf.conf

COPY overlay/rhel9/ /
Expand Down
8 changes: 6 additions & 2 deletions rhel-stig/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ RHEL 9 STIG (Security Technical Implementation Guide) compliance is required for
### Prerequisites

- Red Hat subscription credentials (username and password)
- Docker installed and running
- Docker installed and running (BuildKit enabled; the build script sets `DOCKER_BUILDKIT=1`)
- Access to Red Hat repositories (RHEL 9 packages required)

**Building on non-RHEL hosts (Ubuntu, etc.):** subscription-manager runs inside the UBI container, so the host OS does not need to be RHEL. The build works on any Docker host.

### Building Non-FIPS STIG Image

```bash
Expand All @@ -36,7 +38,7 @@ Example:
bash build.sh.rhel9 myuser@example.com mypassword rhel9-byoi-stig-fips true
```

**Note**: Red Hat subscription credentials are required to build these images as RHEL 9 STIG packages are only available through Red Hat repositories.
**Note**: Red Hat subscription credentials are required to build these images as RHEL 9 STIG packages are only available through Red Hat repositories. Credentials are passed via Docker BuildKit secrets (not build args) and are never stored in image layers. Requires Docker BuildKit (default in Docker 23+; set `DOCKER_BUILDKIT=1` for older versions).

## Using the Base Image

Expand Down Expand Up @@ -143,6 +145,8 @@ The build process automatically applies STIG remediation rules including:

STIG disables `net.ipv4.ip_forward` and `net.ipv4.conf.all.forwarding` for general servers. Kubernetes nodes require both `=1` for CNI pod networking (Calico, Flannel, etc.). The build overrides STIG via `/etc/sysctl.d/99-zzz-kubernetes-ip-forward.conf` and applies it during build.

STIG sets `rp_filter=1` (strict); overlay clusters (Calico, etc.) require `rp_filter=0`. The build overrides via `/etc/sysctl.d/99-zzz-kubernetes-rp-filter.conf`.

### Firewall Configuration

No firewall ports or zones are opened by default. Configure firewall rules via **user-data** or **cluster profile** as needed for your environment.
Expand Down
18 changes: 16 additions & 2 deletions rhel-stig/build.sh.rhel9
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
#!/bin/bash

# Run from rhel-stig/ so static/ and stig-remediate.sh are in build context
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

USERNAME=$1
PASSWORD=$2
BASE_IMAGE="${3:-rhel9-byoi-stig}"
FIPS_ENABLED="${4:-false}"

# BuildKit required for --secret (credentials never stored in image layers)
export DOCKER_BUILDKIT=1

# Use BuildKit secrets - credentials passed via temp files, never in image layers or build args
tmpdir=$(mktemp -d)
trap "rm -rf $tmpdir" EXIT
echo -n "$USERNAME" > "$tmpdir/rhsm_username"
echo -n "$PASSWORD" > "$tmpdir/rhsm_password"
chmod 600 "$tmpdir"/*

if [ "$FIPS_ENABLED" = "true" ]; then
echo "Building RHEL 9 STIG FIPS image..."
docker build --build-arg USERNAME="$USERNAME" --build-arg PASSWORD="$PASSWORD" -t "$BASE_IMAGE" -f Dockerfile.rhel9-fips .
docker build --secret id=rhsm_username,src="$tmpdir/rhsm_username" --secret id=rhsm_password,src="$tmpdir/rhsm_password" -t "$BASE_IMAGE" -f Dockerfile.rhel9-fips .
else
echo "Building RHEL 9 STIG image..."
docker build --no-cache --build-arg USERNAME="$USERNAME" --build-arg PASSWORD="$PASSWORD" -t "$BASE_IMAGE" -f Dockerfile.rhel9 .
docker build --secret id=rhsm_username,src="$tmpdir/rhsm_username" --secret id=rhsm_password,src="$tmpdir/rhsm_password" -t "$BASE_IMAGE" -f Dockerfile.rhel9 .
fi
27 changes: 27 additions & 0 deletions rhel-stig/stig-remediate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,33 @@ current=$(cat /proc/sys/net/ipv4/ip_forward 2>/dev/null || echo "MISSING")
current_all=$(cat /proc/sys/net/ipv4/conf/all/forwarding 2>/dev/null || echo "MISSING")
print_debug "Runtime after apply: net.ipv4.ip_forward=$current net.ipv4.conf.all.forwarding=$current_all"

# STIG sets rp_filter=1 (strict); overlay clusters/CNI require rp_filter=0 for pod networking
echo "Applying Kubernetes exception: net.ipv4.conf.all.rp_filter=0 and net.ipv4.conf.default.rp_filter=0 (required for overlay clusters)..."

shopt -s nullglob
for f in /etc/sysctl.conf /etc/sysctl.d/*.conf /run/sysctl.d/*.conf /usr/local/lib/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf; do
[ -f "$f" ] || continue
sed -i \
-e 's/^[[:space:]]*net\.ipv4\.conf\.all\.rp_filter[[:space:]]*=.*$/# STIG exception (Kubernetes overlay clusters require rp_filter=0): &/' \
-e 's/^[[:space:]]*net\.ipv4\.conf\.default\.rp_filter[[:space:]]*=.*$/# STIG exception (Kubernetes overlay clusters require rp_filter=0): &/' \
"$f" 2>/dev/null || true
done
shopt -u nullglob 2>/dev/null || true

cat > /etc/sysctl.d/99-zzz-kubernetes-rp-filter.conf <<'EOF'
# Kubernetes exception: STIG/Red Hat set rp_filter=1; overlay clusters (Calico, etc.) require rp_filter=0
# 50-redhat.conf uses net.ipv4.conf.*.rp_filter=1 per-interface; override with same wildcard (loads later)
net.ipv4.conf.*.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
EOF
chown root:root /etc/sysctl.d/99-zzz-kubernetes-rp-filter.conf
chmod 0644 /etc/sysctl.d/99-zzz-kubernetes-rp-filter.conf

/sbin/sysctl -w net.ipv4.conf.all.rp_filter=0 2>/dev/null || true
/sbin/sysctl -w net.ipv4.conf.default.rp_filter=0 2>/dev/null || true
/sbin/sysctl --system 2>/dev/null || true

# Ensure required drivers and modules are in dracut config (backup in case STIG removed them)
for conf_file in /etc/dracut.conf.d/*.conf; do
if [ -f "$conf_file" ]; then
Expand Down
Loading