Meaningful Compliance – Tailoring a Profile

Duration: ~25 minutes

Overview

Re-scan CIS (ocp4-cis) after 201-06 so audit logging and log forwarding go green, then tailor the same profile for lab-only noise. Do not disable the controls you just fixed, and do not switch to rhcos4-moderate for this story.

Why it matters

101-10 showed the usual CIS gap: path PASS, forwarding FAIL. 201-06 shipped kube-apiserver audit to Splunk with a ClusterLogForwarder. Auditors still want a new ocp4-cis result, not a screenshot of Splunk. Tailoring is how you document exceptions that are not those logging controls.

What does it solve

  • “We forwarded logs” with no CIS evidence that 1.2.21 / 3.2.1 passed

  • Alert fatigue from irrelevant CIS findings (while hiding a real FAIL)

  • “Waived forever” exceptions with no ownership

  • Mixing RHCOS node profiles with OpenShift CIS platform audit rules

Your Mission

Keep Splunk and the forwarder from 201-06. Re-scan ocp4-cis, prove audit logging and forwarding PASS, then tailor other FAILs. Do not disable audit-log-forwarding-enabled or audit-logging-enabled.

Prerequisites

  • 201-06 completed without tearing down Splunk (lab cleanup for 201-06 only removes the sleeper project)

  • Compliance Operator installed (openshift-compliance)

  • Cluster-admin (or equivalent) to create scans and TailoredProfiles

CIS OpenShift 1.7 rows this pair of labs is aiming to PASS (automated, ocp4-cis platform profile):

CIS OCP Rule (name contains) What 201-06 contributed

1.2.20

api-server-audit-log-path

Already on stock OpenShift; 101-09 listed the file

1.2.21

audit-log-forwarding-enabled

ClusterLogForwarder with inputRefs: [audit] → Splunk HEC

1.2.22 / 1.2.23

audit-log-maxbackup / audit-log-maxsize

Platform defaults; do not set unsupportedConfigOverrides

3.2.1 (Logging)

audit-logging-enabled

API server audit profile is not None (OpenShift default)

3.2.2 (Logging, Level 2)

audit-profile-set

Often FAIL on Default vs WriteRequestBodies — tailor or leave; do not confuse with 3.2.1

OpenShift CIS 1.7 has no separate “Prometheus is installed” automated row. Platform monitoring (openshift-monitoring) is the metrics half of 201-06 correlation; you verify it is running, you do not score it as CIS 1.2.21.

audit_log_forwarding_uses_tls and audit_error_alert_exists are STIG/NIST-oriented. Stay on ocp4-cis for this lab.

Click each step only if you need a hint.

Part A: Prove 201-06 against CIS

Confirm the forwarder still matches CIS 1.2.21

Same OCIL Compliance Operator uses: at least one pipeline lists audit. Logging 5 looks at ClusterLogForwarder/instance; Logging 6 looks at any CLF in openshift-logging.

echo "=== observability.openshift.io ==="
oc get clusterlogforwarders.observability.openshift.io -n openshift-logging -o json 2>/dev/null \
  | jq -r '[.items[]?.spec.pipelines[]?.inputRefs[]?] | index("audit") != null' \
  || echo "n/a"
echo "=== logging.openshift.io instance ==="
oc get clusterlogforwarder.logging.openshift.io instance -n openshift-logging -o json 2>/dev/null \
  | jq -r '[.spec.pipelines[]?.inputRefs[]?] | index("audit") != null' \
  || echo "n/a"
oc get clusterlogforwarder -n openshift-logging 2>/dev/null || true
At least one of the jq lines should print true. If both are n/a or false, go back to 201-06 configure-openshift-audit.sh before you scan.
Confirm platform monitoring is up (201-06 “cluster measured Y”)

Not a CIS 1.2.21 check. Confirms the monitoring side of the 201-06 story is still there.

oc get pods -n openshift-monitoring | head -20
cluster-monitoring-operator and Prometheus/Alertmanager pods Running. Empty namespace means escalate to the platform owner; do not disable CIS logging rules because metrics are missing.
Rescan ocp4-cis

Reuse the 101-10 (or instructor) CIS platform scan. Annotating rescan records a new result after the forwarder exists. If no ocp4-cis scan exists, bind the profile like 101-10.

SCAN=$(oc get compliancescans -n openshift-compliance -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
  | grep -E 'ocp4-cis$' | head -1)
if [ -n "$SCAN" ]; then
  echo "Rescanning $SCAN"
  oc annotate compliancescan "$SCAN" compliance.openshift.io/rescan= --overwrite -n openshift-compliance
else
  oc apply -f - <<'EOF'
apiVersion: compliance.openshift.io/v1alpha1
kind: ScanSettingBinding
metadata:
  name: 201-07-cis
  namespace: openshift-compliance
profiles:
- name: ocp4-cis
  kind: Profile
  apiGroup: compliance.openshift.io/v1alpha1
settingsRef:
  name: default
  kind: ScanSetting
  apiGroup: compliance.openshift.io/v1alpha1
EOF
fi
oc get compliancescans -n openshift-compliance
Phase DONE before you read results. A full CIS platform scan can take several minutes (RUNNING → wait).
Show audit logging and forwarding results

Filter to the CIS logging/audit rows. After 201-06 you want PASS on forwarding and on 3.2.1 (audit-logging-enabled).

oc get compliancecheckresults -n openshift-compliance --no-headers \
  | grep -iE 'audit-log|audit-logging|log-forward' \
  || echo 'No audit-log results yet -- wait for DONE, then re-run.'
…-audit-log-forwarding-enabled should be PASS (CIS 1.2.21). …-audit-logging-enabled should be PASS (CIS 3.2.1). …-audit-profile-set may still FAIL — that is Level 2 (3.2.2), not forwarding.
List remaining non-PASS audit/logging rules

Anything still red here is not solved by Splunk. Do not tailor 1.2.21 away to fake a clean report.

oc get compliancecheckresults -n openshift-compliance --no-headers \
  | awk 'tolower($0) ~ /audit-log|audit-logging|log-forward|audit-profile/ && toupper($2) != "PASS" {print $1, $2, $3}'
Empty (or only audit-profile-set FAIL) is the expected roadshow picture. If forwarding is still FAIL, the CLF is missing audit in inputRefs or the scan finished before the CR existed—fix 201-06, then rescan.

Part B: Tailor CIS noise — not the logging controls

Pick a FAIL that is not audit/forwarding

Typical lab noise: kubeadmin-removed (attendees still log in as kubeadmin). Copy the Rule name (ocp4-…), not the long Scan-prefixed ComplianceCheckResult name.

oc get compliancecheckresults -n openshift-compliance -o json \
  | jq -r '
    .items[]
    | select.status|tostring|ascii_upcase|contains("FAIL")
    | select(.metadata.name | test("audit-log|audit-logging|log-forward";"i") | not)
    | "\(.metadata.name)\t\(.metadata.annotations["compliance.openshift.io/rule"] // "no-rule-annotation")"
  ' | head -15
Use the annotation value with the ocp4- prefix as the TailoredProfile disableRules[].name (for example kubeadmin-removedocp4-kubeadmin-removed). Confirm with oc get rules.compliance.openshift.io -n openshift-compliance | grep kubeadmin.
Apply TailoredProfile ocp4-cis-lab

Replace ocp4-kubeadmin-removed if your FAIL was a different rule. The rationale is the audit trail for why the exception exists. Never list ocp4-audit-log-forwarding-enabled or ocp4-audit-logging-enabled here.

oc apply -f - <<'EOF'
apiVersion: compliance.openshift.io/v1alpha1
kind: TailoredProfile
metadata:
  name: ocp4-cis-lab
  namespace: openshift-compliance
spec:
  title: ocp4-cis-lab
  description: Roadshow CIS — keep audit logging and forwarding; disable lab-only kubeadmin.
  extends: ocp4-cis
  disableRules:
    - name: ocp4-kubeadmin-removed
      rationale: Lab clusters keep kubeadmin for attendee login. Production must remove kubeadmin after an identity provider is configured.
EOF
tailoredprofile.compliance.openshift.io/ocp4-cis-lab created. If the API rejects the rule name, use the exact ocp4-… Rule from the previous step.
Bind and scan the tailored CIS profile

Same ScanSetting as the stock profile, different profile object.

oc apply -f - <<'EOF'
apiVersion: compliance.openshift.io/v1alpha1
kind: ScanSettingBinding
metadata:
  name: 201-07-cis-lab
  namespace: openshift-compliance
profiles:
- name: ocp4-cis-lab
  kind: TailoredProfile
  apiGroup: compliance.openshift.io/v1alpha1
settingsRef:
  name: default
  kind: ScanSetting
  apiGroup: compliance.openshift.io/v1alpha1
EOF
oc get compliancescans -n openshift-compliance
Wait until the new scan is DONE. Compare FAIL counts: kubeadmin (or your exception) should disappear; forwarding must still be present and PASS.
Compare stock CIS vs tailored — forwarding still scored
echo "=== stock ocp4-cis (audit/logging) ==="
oc get compliancecheckresults -n openshift-compliance --no-headers \
  | grep -iE 'ocp4-cis-.*audit-log|ocp4-cis-.*audit-logging|ocp4-cis-.*log-forward' \
  | grep -v cis-lab || true
echo "=== tailored ocp4-cis-lab (audit/logging) ==="
oc get compliancecheckresults -n openshift-compliance --no-headers \
  | grep -iE 'cis-lab.*audit-log|cis-lab.*audit-logging|cis-lab.*log-forward' \
  || true
Tailored results still include forwarding and 3.2.1. If those rows vanished, you disabled the wrong rule—edit the TailoredProfile and rescan.
Auto-apply of ComplianceRemediations is for non-prod iterative hardening only. Do not apply remediations that patch kube-apiserver unsupportedConfigOverrides to silence maxsize/maxbackup. Prefer a change ticket and a rescan.

Debrief

201-06 implemented CIS 1.2.21 (forward audit off-cluster) and left 3.2.1 (audit enabled) intact. 201-07 is the Compliance Operator receipt: rescan ocp4-cis, then tailor only documented lab exceptions.

What breaks without this:

  • Untailored profiles → alert fatigue and ignored findings

  • Tailoring away forwarding → a green report that lies about 201-06

  • Scanning rhcos4-moderate here → you never re-score OpenShift CIS logging

tailored profiles, scan comparison, never disable audit-log-forwarding-enabled / audit-logging-enabled to pass the demo.
document why a check is disabled; re-scan after 201-06 and after tailoring. Splunk teardown runs with this module’s cleanup.
giphy

Cleanup

Before moving to the next module, run the lab cleanup script. It removes the 201-07 TailoredProfile/scans and the Splunk stack left from 201-06.

cd ~/ocp5-rhacs-showroom
bash setup/lab-cleanup.sh --module 201-07