Skip to main content

GCP Enable Linux Auditd Logging

More Info:

Deploy Linux auditd logging on Container-Optimized OS nodes so kernel-level audit events from nodes are captured and shipped to Cloud Logging. This provides host-level forensic visibility.

Risk Level

Medium

Address

Security

Compliance Standards

  • CIS GKE

Triage and Remediation

Remediation

Manual Steps
  1. Identify node OS and scope

    • On any machine with kubectl access, list nodes and their OS images to confirm which are Container-Optimized OS:
      kubectl get nodes -o wide
      kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, osImage: .status.nodeInfo.osImage}'
    • Decide whether you want auditd logging on all COS nodes or only on specific node pools (e.g., production).
  2. Check for existing auditd logging DaemonSet

    • On any machine with kubectl access, run:
      kubectl get daemonsets -A -o json \
      | jq '.items[] | select(.spec.template.spec.containers[].image | contains("gcr.io/stackdriver-agents/stackdriver-logging-agent")) \
      | {name: .metadata.name, annotations: .metadata.annotations."kubernetes.io/description", namespace: .metadata.namespace, status: .status}'
    • If a DaemonSet is present with a description indicating COS auditd logging to Cloud Logging and it is fully available on all target COS nodes, document that this control is covered and proceed to step 6 for periodic re-verification.
  3. Review/prepare deployment manifests (IaC or manual)

    • If no suitable DaemonSet exists, download the reference manifests on your IaC workstation or any machine with kubectl:
      curl https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-node-tools/master/os-audit/cos-auditd-logging.yaml \
      -o cos-auditd-logging.yaml
    • Open cos-auditd-logging.yaml and review: namespace, resource requests/limits, tolerations, and any labels/annotations to ensure they match your cluster standards and target only COS nodes you intend to monitor.
  4. Deploy or update the DaemonSet (change via console/CLI/IaC policy)

    • If you manage manifests via IaC (Terraform, Config Sync, etc.), add cos-auditd-logging.yaml to the appropriate repo/module and apply using your standard pipeline.
    • For direct CLI-based clusters, on a machine with kubectl access, you may deploy with:
      kubectl apply -f cos-auditd-logging.yaml
    • Ensure this change is reflected in your cloud provider configuration management (e.g., documenting in GKE cluster configuration or IaC) so it is reapplied if the cluster is recreated.
  5. Verify pod rollout and coverage

    • On any machine with kubectl access:
      kubectl get pods --namespace=cos-auditd -o wide
      kubectl get daemonset cos-auditd-logging --namespace=cos-auditd -o json \
      | jq '.status'
    • Confirm desired number of pods equals the number of target COS nodes and that pods are in Running state on those nodes.
  6. Validate logs in Cloud Logging and document decision

    • In the cloud console (Logging > Logs Explorer), filter for logs from the auditd logging agent (e.g., by namespace cos-auditd or the DaemonSet/pod name) and confirm kernel-level audit events from COS nodes are present.
    • Record in your security documentation whether COS auditd logging is: enabled for all COS nodes, enabled for specific node pools only (with rationale), or intentionally not enabled (with accepted risk and justification).
Using kubectl

kubectl cannot enable or configure Linux auditd logging on Container-Optimized OS nodes because this control is implemented via cloud provider / managed control plane configuration and supporting DaemonSets defined in manifests. To address this finding, follow the guidance in the Manual Steps section, using the cloud console and/or IaC to deploy and manage the required auditd logging resources.

Automation
#!/usr/bin/env bash
# Check for Linux auditd logging (CIS GKE 5.7.2) via cos-auditd-logging DaemonSet
# Run on any machine with kubectl access and cluster-wide RBAC.

set -euo pipefail

echo "== CIS GKE 5.7.2: Linux auditd logging status =="

# 1. Show all DaemonSets using the Stackdriver logging agent image (matches the audit command)
echo
echo "== DaemonSets using gcr.io/stackdriver-agents/stackdriver-logging-agent =="
kubectl get daemonsets -A -o json \
| jq -r '
.items[]
| select(.spec.template.spec.containers[].image
| contains("gcr.io/stackdriver-agents/stackdriver-logging-agent"))
| {
namespace: .metadata.namespace,
name: .metadata.name,
description: .metadata.annotations["kubernetes.io/description"],
desired: .status.desiredNumberScheduled,
ready: .status.numberReady,
nodes_misscheduled: .status.numberMisscheduled
}
' || echo "No matching DaemonSets found."

# 2. Specifically look for the reference implementation (cos-auditd-logging)
echo
echo "== cos-auditd-logging DaemonSets (reference manifests) =="
kubectl get daemonset -A \
| awk 'NR==1 || /cos-auditd-logging/'

# 3. For each matching DaemonSet, show node coverage and readiness
echo
echo "== Detailed readiness for matching DaemonSets =="
kubectl get daemonsets -A -o json \
| jq -r '
.items[]
| select(.spec.template.spec.containers[].image
| contains("gcr.io/stackdriver-agents/stackdriver-logging-agent"))
| [
.metadata.namespace,
.metadata.name,
.status.desiredNumberScheduled,
.status.currentNumberScheduled,
.status.numberReady,
.status.numberUnavailable,
.status.numberMisscheduled
]
| @tsv
' \
| awk 'BEGIN {
OFS="\t";
print "NAMESPACE","DAEMONSET","DESIRED","SCHEDULED","READY","UNAVAILABLE","MISSCHEDULED"
}
{ print }'

# 4. Optionally, show Pods for the typical namespace (cos-auditd), if present
if kubectl get ns cos-auditd >/dev/null 2>&1; then
echo
echo "== Pods in namespace cos-auditd =="
kubectl get pods -n cos-auditd -o wide
else
echo
echo "Namespace 'cos-auditd' not found; manifests may be using a different namespace."
fi

echo
echo "== Interpretation =="
cat <<'EOF'
Problem indicators you should investigate:
- No DaemonSets listed under "DaemonSets using gcr.io/stackdriver-agents/stackdriver-logging-agent":
likely means cluster-wide auditd logging is not deployed.
- DESIRED > 0 but READY < DESIRED for any DaemonSet:
auditd logging is not running on all targeted nodes.
- numberMisscheduled > 0:
Pods are scheduled onto nodes where they should not run (taints/labels mismatch).
- Namespace 'cos-auditd' missing AND no equivalent DaemonSet in another namespace:
reference auditd logging manifests have likely not been applied.

Because this control is MANUAL, you must decide whether:
- The existing DaemonSet(s) provide sufficient kernel-level audit logging coverage, or
- You need to deploy or adjust a DaemonSet (for example, using cos-auditd-logging.yaml)
so that all intended nodes run the auditd logging agent.
EOF