Skip to main content
RunBook Academy

CephCI · Security HardeningSecurity Hardening

Running a repeatable hardening audit

Advanced⏱ ~18 mincephss

What you'll learn

  • Build a repeatable audit
  • Produce evidence rather than assertions
  • Interpret and triage the findings
  • Track remediation over time

Prerequisites

None — start here.

Verified against Ceph Tentacle 20.2.x · Ceph Squid 19.2.x (supported previous) · cephadm matches the verified Ceph release · podman 4.x · csi-rbd and csi-cephfs current · RBD / CephFS / RGW current (matches Ceph release) · Linux kernel 5.15+ (5.10 minimum) · Ubuntu 24.04 LTS (Ceph host baseline) · Debian 12 (Bookworm) (Ceph host baseline) · Rocky Linux / RHEL / AlmaLinux 9.x (Ceph host baseline) · Proxmox VE 9.x (cross-course integration) · Kubernetes 1.31+ (cross-course integration) · 2026-08-18

Not yet marked complete on this device.

Why this matters in production

An audit that produces a document is read once. An audit that produces comparable output every month is what shows whether posture is improving.

The audit

#!/bin/bash
# ceph-hardening-audit.sh — run from an admin host
set -u
echo "=== ceph hardening audit $(hostname -s) ==="

echo "--- cephx enforcement"
for k in auth_cluster_required auth_service_required auth_client_required; do
  printf '%-24s %s\n' "$k" "$(ceph config get global "$k" 2>/dev/null)"
done

echo "--- wire modes"
for k in ms_cluster_mode ms_service_mode ms_client_mode ms_bind_msgr1; do
  printf '%-24s %s\n' "$k" "$(ceph config get global "$k" 2>/dev/null)"
done

echo "--- monmap address families"
ceph mon dump 2>/dev/null | grep -oE 'v[12]:' | sort | uniq -c

echo "--- entities with unrestricted caps"
ceph auth ls --format json 2>/dev/null | python3 -c '
import sys,json
n = 0
for e in json.load(sys.stdin)["auth_dump"]:
    if any("allow *" in v for v in e.get("caps", {}).values()):
        print("  ", e["entity"]); n += 1
print("  total:", n)'

echo "--- networks"
printf '%-24s %s\n' public_network  "$(ceph config get global public_network)"
printf '%-24s %s\n' cluster_network "$(ceph config get global cluster_network)"

echo "--- encrypted OSDs"
ceph osd metadata --format json 2>/dev/null | python3 -c '
import sys,json
d = json.load(sys.stdin)
enc = sum(1 for o in d if o.get("osd_objectstore") and o.get("bluestore_bdev_type"))
crypt = sum(1 for o in d if str(o.get("devices","")).find("dm-") >= 0)
print("  osds:", len(d), " with dm mapping:", crypt)'

echo "--- dashboard exposure"
ceph mgr services --format json 2>/dev/null | python3 -c '
import sys,json
for k, v in json.load(sys.stdin).items(): print("  %-12s %s" % (k, v))'
bash ceph-hardening-audit.sh > "audit-$(date +%Y%m%d).txt"

Per-host checks

#!/bin/bash
# run on each Ceph host
echo "=== host $(hostname -s) ==="
stat -c '  %a %U:%G %n' /etc/ceph/*.keyring 2>/dev/null
grep -E '^(PermitRootLogin|PasswordAuthentication)' /etc/ssh/sshd_config \
  | sed 's/^/  /'
getenforce 2>/dev/null | sed 's/^/  selinux: /'
ss -ltn | awk 'NR>1 {print "  listening: " $4}' | sort -u
ls -l /run/podman/podman.sock 2>/dev/null | sed 's/^/  /'

Interpreting findings

FindingSeverityAction
auth_*_required not cephxcriticalfix immediately
Entities with allow * beyond adminhighnarrow
v1: in the monmapmediumplan msgr1 removal
Mode list includes crcmediumplan strict secure
Admin keyring readable beyond roothighfix permissions
No cluster networklowdesign decision, record it
Dashboard on a broad interfacehighrestrict
Severity should reflect what the finding enables, not how easy it is
to fix.

Tracking over time

diff "audit-$(date -d '1 month ago' +%Y%m).txt" "audit-$(date +%Y%m%d).txt"
# a single posture number, for trend
grep -c 'allow \*' "audit-$(date +%Y%m%d).txt"
The value is the diff. A finding that appears in twelve consecutive
audits is a decision that was never made, and naming it as such is more
useful than repeating the finding.

Quiz

Knowledge check · 4 questions

  1. Q1. Why should audit output be stored as comparable text rather than a written report?

  2. Q2. Audit findings should be ranked by how quickly they can be remediated.

  3. Q3. Build a hardening audit programme.

    A team has run a one-off hardening review producing a document. They want it to be ongoing.

  4. Q4. Which audit finding is critical severity, and why?

Passing score: 75%. Answers are checked in this browser.

Production discipline

Produce audit output as fixed-format dated text so each run is a diff — the diff is what answers whether posture is improving. Rank findings by what each enables rather than by remediation effort; ranking by effort leaves the real exposures permanently below the fold.

Cross-course references

  • Kubernetes: CIS benchmark runs are valuable as a trend, not a snapshot
  • Linux: audits ranked by effort systematically defer the expensive findings