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
Remediation
Manual Steps
-
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.
- On every control plane node, display the policy file:
-
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:secretsconfigmapstokenreviews(usuallygroup: authentication.k8s.io)
- Example patterns you should see in some rule(s):
- level: Metadataresources:- group: ""resources: ["secrets", "configmaps"]- level: Metadataresources:- group: "authentication.k8s.io"resources: ["tokenreviews"]
- If
levelisRequestorRequestResponsefor these resources, assess the risk of sensitive data being logged and consider reducing toMetadatawhere possible.
- In the displayed YAML, look for rules with
-
Verify coverage of Pod and Deployment modifications
- In the same file, confirm there are rules that log at least
Metadatafor modifications (e.g.,verbs: ["create","update","patch","delete"]) on:pods(group"")deployments(groupapps)
- Example patterns you should see:
- level: Metadataverbs: ["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
verbsas needed for your risk tolerance.
- In the same file, confirm there are rules that log at least
-
Verify coverage of exec/portforward/proxy subresources
- Still in
/etc/kubernetes/audit-policy.yaml, ensure rules exist that log at leastMetadatafor these subresources:pods/execpods/portforwardpods/proxyservices/proxy
- Example patterns you should see:
- level: Metadataresources:- group: ""resources:- "pods/exec"- "pods/portforward"- "pods/proxy"- "services/proxy"
- If missing, plan to add such rules; if
levelis lower than desired, consider raising toMetadataor higher per your logging policy.
- Still in
-
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.yamlflag path to match your file location. - Any change to
/etc/kubernetes/manifests/kube-apiserver.yamlor the audit policy file will cause the kube-apiserver static pod to restart on that control plane node.
- On every control plane node, edit the policy file with your preferred editor, adding or adjusting rules as identified in steps 2–4:
-
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-foundkubectl run audit-test --image=busybox --restart=Never -- sleep 300kubectl 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.
- On every control plane node, confirm the kube-apiserver pod has restarted recently (after your changes):
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
- Save the script as
check-audit-policy-key-events.sh. - Edit the
CONTROL_PLANE_NODESarray to list all your control plane node hostnames or IPs. - Make it executable:
chmod +x ./check-audit-policy-key-events.sh
- 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.