Skip to main content

Ensure That The Audit Policy Covers Key Security Concerns

More Info:

The audit policy should cover access to Secrets, modification of Pod and Deployment objects, and use of exec/portforward/proxy subresources. This ensures key security events are captured.

Risk Level

High

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. Locate and inspect the current audit policy

    • On every control plane node, display the policy file:
      sudo cat /etc/kubernetes/audit-policy.yaml
    • If the file is empty or missing, you must design and deploy an audit policy; capture that as a gap.
  2. Verify coverage of Secrets, ConfigMaps, and TokenReviews (metadata-only)

    • In the displayed YAML, look for rules with level: Metadata (or higher) that match at least these resources:
      • secrets
      • configmaps
      • tokenreviews (usually group: authentication.k8s.io)
    • Example patterns you should see in some rule(s):
      - level: Metadata
      resources:
      - group: ""
      resources: ["secrets", "configmaps"]
      - level: Metadata
      resources:
      - group: "authentication.k8s.io"
      resources: ["tokenreviews"]
    • If level is Request or RequestResponse for these resources, assess the risk of sensitive data being logged and consider reducing to Metadata where possible.
  3. Verify coverage of Pod and Deployment modifications

    • In the same file, confirm there are rules that log at least Metadata for modifications (e.g., verbs: ["create","update","patch","delete"]) on:
      • pods (group "")
      • deployments (group apps)
    • Example patterns you should see:
      - level: Metadata
      verbs: ["create", "update", "patch", "delete"]
      resources:
      - group: ""
      resources: ["pods"]
      - group: "apps"
      resources: ["deployments"]
    • If verbs are not restricted, ensure at minimum that modification verbs are covered; you may add or refine verbs as needed for your risk tolerance.
  4. Verify coverage of exec/portforward/proxy subresources

    • Still in /etc/kubernetes/audit-policy.yaml, ensure rules exist that log at least Metadata for these subresources:
      • pods/exec
      • pods/portforward
      • pods/proxy
      • services/proxy
    • Example patterns you should see:
      - level: Metadata
      resources:
      - group: ""
      resources:
      - "pods/exec"
      - "pods/portforward"
      - "pods/proxy"
      - "services/proxy"
    • If missing, plan to add such rules; if level is lower than desired, consider raising to Metadata or higher per your logging policy.
  5. Edit and apply changes, noting operational impact

    • On every control plane node, edit the policy file with your preferred editor, adding or adjusting rules as identified in steps 2–4:
      sudo vi /etc/kubernetes/audit-policy.yaml
    • Confirm the API server is actually using this file (and where it is referenced) by checking its manifest (static pod):
      sudo grep -n "audit-policy-file" /etc/kubernetes/manifests/kube-apiserver.yaml
    • If necessary, adjust the --audit-policy-file=/etc/kubernetes/audit-policy.yaml flag path to match your file location.
    • Any change to /etc/kubernetes/manifests/kube-apiserver.yaml or the audit policy file will cause the kube-apiserver static pod to restart on that control plane node.
  6. Verify the policy is active and producing expected logs

    • On every control plane node, confirm the kube-apiserver pod has restarted recently (after your changes):
      sudo crictl ps | grep kube-apiserver
    • Generate a test event (for example, reading a Secret and using kubectl exec) from any machine with kubectl access:
      kubectl get secret -n default --ignore-not-found
      kubectl run audit-test --image=busybox --restart=Never -- sleep 300
      kubectl exec audit-test -- echo "test"
    • On the control plane node where audit logs are written, inspect the audit log (path may vary; common example):
      sudo tail -n 200 /var/log/kubernetes/audit.log | grep -E 'secrets|configmaps|tokenreviews|pods/exec|pods/portforward|pods/proxy|services/proxy|\"deployments\"|\"pods\"'
    • Verify that the generated events appear at the expected log level (e.g., Metadata) and that sensitive Secret data is not logged in full. Adjust the policy and repeat as necessary.
Using kubectl

kubectl cannot modify the audit policy file /etc/kubernetes/audit-policy.yaml or any other host-level control plane configuration; these changes must be made directly on every control plane node. Refer to the Manual Steps section for guidance on reviewing and updating the audit policy on the nodes themselves.

Automation
#!/usr/bin/env bash
#
# check-audit-policy-key-events.sh
#
# Purpose:
# Summarize whether the API server audit policy covers key security concerns:
# - Access to Secrets / ConfigMaps / TokenReviews (metadata-only recommended)
# - Modification of Pods and Deployments
# - Use of pods/exec, pods/portforward, pods/proxy, services/proxy
#
# Run on:
# - ANY MACHINE WITH SSH ACCESS TO EVERY CONTROL PLANE NODE
#
# Requirements:
# - passwordless SSH access to each control plane node
# - audit policy located at: /etc/kubernetes/audit-policy.yaml

CONTROL_PLANE_NODES=(
"cp-node-1"
"cp-node-2"
"cp-node-3"
)

POLICY_PATH="/etc/kubernetes/audit-policy.yaml"

print_header() {
echo "======================================================================"
echo "$1"
echo "======================================================================"
}

check_node_policy() {
local node="$1"

echo
print_header "Node: ${node} | Policy: ${POLICY_PATH}"

# 1. Confirm the file exists
if ! ssh "${node}" "test -f ${POLICY_PATH}" 2>/dev/null; then
echo "[PROBLEM] Policy file not found at ${POLICY_PATH}"
return
fi

echo "[INFO] Found policy file."

# 2. Show all 'rules' sections once (for manual context)
echo
echo "[INFO] Showing top-level 'rules:' section (first 40 lines after 'rules:')"
ssh "${node}" "awk '/^rules:/ {flag=1; next} flag {print} NR>200{exit}' ${POLICY_PATH} | head -n 40"

# 3. Check for Secret/ConfigMap/TokenReview coverage
echo
echo "[CHECK] Coverage for Secrets / ConfigMaps / TokenReviews"

ssh "${node}" "grep -nE 'resources:.*(secrets|configmaps|tokenreviews)' -n ${POLICY_PATH} || echo '[PROBLEM] No rule mentioning secrets/configmaps/tokenreviews resources'"


echo
echo "[CHECK] Metadata-only logging for Secrets / ConfigMaps / TokenReviews (recommended)"
ssh "${node}" "awk '
/- ?level:/ {lvl=\$2}
/resources:/ {res_block=1}
res_block && /resources:/ {print_line=1}
print_line {
if (lvl ~ /(RequestBody|RequestResponse)/ && /secrets|configmaps|tokenreviews/) {
print \"[PROBLEM] Rule with level \" lvl \" applies to secrets/configmaps/tokenreviews:\"; print;
}
}
/^- ?level:/ {res_block=0; print_line=0}
' ${POLICY_PATH}"


# 4. Check for Pod/Deployment modification coverage
echo
echo "[CHECK] Coverage for Pod/Deployment modification (verbs: create, update, patch, delete)"

ssh "${node}" "awk '
/- ?level:/ {lvl=\$2; delete verbs; delete resources}
/verbs:/ {v=1; next}
v && /^ *- / {verbs[\$2]=1}
v && !/^ *- / {v=0}
/resources:/ {r=1; next}
r && /^ *- / {resources[\$2]=1}
r && !/^ *- / {r=0}
/^- ?level:/ {
if ((\"pods\" in resources || \"deployments\" in resources) &&
(\"create\" in verbs || \"update\" in verbs || \"patch\" in verbs || \"delete\" in verbs)) {
print \"[INFO] Pod/Deployment modification rule:\"; print \$0;
}
}
' ${POLICY_PATH}"

echo
echo "[HINT] If you see no '[INFO] Pod/Deployment modification rule:' lines above,"
echo "[PROBLEM] The policy may not explicitly log Pod/Deployment modifications."


# 5. Check exec/portforward/proxy coverage
echo
echo "[CHECK] Coverage for pods/exec, pods/portforward, pods/proxy, services/proxy subresources"

ssh "${node}" "grep -nE 'pods/exec|pods/portforward|pods/proxy|services/proxy' ${POLICY_PATH} || echo '[PROBLEM] No rule mentioning pods/exec|pods/portforward|pods/proxy|services/proxy'"


# 6. Summary indicators (simple greps)
echo
echo "[SUMMARY INDICATORS]"

ssh "${node}" "
missing=0

grep -qE 'resources:.*secrets' ${POLICY_PATH} || { echo '[PROBLEM] Missing any rule referencing secrets'; missing=1; }
grep -qE 'resources:.*configmaps' ${POLICY_PATH} || { echo '[WARN] No explicit rule for configmaps (recommended)'; }
grep -qE 'resources:.*tokenreviews' ${POLICY_PATH} || { echo '[WARN] No explicit rule for tokenreviews (recommended)'; }

grep -qE 'resources:.*pods' ${POLICY_PATH} || { echo '[PROBLEM] Missing any rule referencing pods'; missing=1; }
grep -qE 'resources:.*deployments' ${POLICY_PATH} || { echo '[WARN] No explicit rule for deployments (recommended)'; }

grep -qE 'pods/exec|pods/portforward|pods/proxy|services/proxy' ${POLICY_PATH} || { echo '[PROBLEM] Missing rules for exec/portforward/proxy subresources'; missing=1; }

if [ \$missing -eq 0 ]; then
echo '[INFO] Basic coverage for key resources/subresources appears present. Review levels and scoping manually.'
fi
"
}

for node in "${CONTROL_PLANE_NODES[@]}"; do
check_node_policy "${node}"
done

How to run

  1. Save the script as check-audit-policy-key-events.sh.
  2. Edit the CONTROL_PLANE_NODES array to list all your control plane node hostnames or IPs.
  3. Make it executable:
    chmod +x ./check-audit-policy-key-events.sh
  4. Run from any machine that can SSH to all control plane nodes:
    ./check-audit-policy-key-events.sh

Interpreting the output

Outputs that indicate a problem and require manual review/adjustment of /etc/kubernetes/audit-policy.yaml on the affected control plane node include:

  • [PROBLEM] Policy file not found at /etc/kubernetes/audit-policy.yaml
    → No audit policy configured at the expected path.

  • [PROBLEM] No rule mentioning secrets/configmaps/tokenreviews resources
    → Access to these sensitive resources may not be logged at all.

  • [PROBLEM] Rule with level RequestBody/RequestResponse applies to secrets/configmaps/tokenreviews
    → Audit may be logging sensitive data content instead of metadata only.

  • No lines starting with [INFO] Pod/Deployment modification rule:
    → Modifications to Pods/Deployments may not be distinctly logged.

  • [PROBLEM] No rule mentioning pods/exec|pods/portforward|pods/proxy|services/proxy
    → Use of these subresources may not be logged.

  • In the summary:

    • [PROBLEM] Missing any rule referencing secrets
    • [PROBLEM] Missing any rule referencing pods
    • [PROBLEM] Missing rules for exec/portforward/proxy subresources
      → Key security concerns are not covered and the policy should be revised manually.