This page explains how to enable verbose operating system audit logs on Google Kubernetes Engine nodes running Container-Optimized OS. This page also explains how to configure a fluent-bit logging agent to send logs to Cloud Logging. Enabling verbose logs can provide valuable information about the state of your cluster and workloads, such as error messages, login attempts, and binary executions. You can use this information to debug problems or investigate security incidents.
Enabling Linux auditd logging is not supported in GKE Autopilot clusters, because Google manages the nodes and underlying virtual machines (VMs).
This page is for Security specialists who review and analyze security logs. Use this information to understand the requirements and limitations of verbose OS logs and guide your implementation when enabling them on your GKE nodes. To learn more about common roles and example tasks that we reference in Google Cloud content, see Common GKE user roles and tasks.
Before reading this page, ensure that you're familiar with Linux operating system audit logs.
Operating system audit logging is distinct from Cloud Audit Logs and Kubernetes Audit Logs.
Overview
To collect logs from each node in a cluster, use a
DaemonSet
which runs exactly one Pod on each cluster node where the DaemonSet is eligible
to be scheduled. This Pod configures the auditd logging daemon on the host and
configures the logging agent to send the logs to Logging or any
other log-ingestion service.
By definition, auditing occurs after an event and is a retrospective security measure. auditd logs alone are probably not sufficient for conducting forensics on your cluster. Consider how to best use auditd logging as part of your overall security strategy.
Limitations
The logging mechanisms described on this page work only on nodes running Container-Optimized OS in GKE Standard clusters.
How the logging DaemonSet works
This section describes how the example logging DaemonSet works so that you can configure it to suit your needs. The next section explains how to deploy the DaemonSet.
The example manifest defines a DaemonSet, a ConfigMap, and a Namespace to contain them.
The DaemonSet deploys a Pod to each node in the cluster. The Pod contains two
containers. The first is an init
container
that starts the cloud-audit-setup systemd service available on
Container-Optimized OS nodes.
The second container,
cos-auditd-fluent-bit, contains an instance of
fluent-bit which is configured
to collect the Linux audit logs from the node journal and export them to
Cloud Logging.
The example logging DaemonSet logs the following events:
auditdsystem configuration modifications- AppArmor permission checks
execve(),socket(),setsockopt(), andmmap()executions- network connections
- user logins
- SSH session and all other TTYs (including
kubectl exec -tsessions)
Configure the logging DaemonSet
You configure the logging DaemonSet using a ConfigMap,
cos-auditd-fluent-bit-config. The example provided sends audit logs to
Logging, but you can configure it to send logs to
other destinations.
The volume of logs produced by auditd can be very large and may incur
additional costs because it consumes system resources and sends more logs than
the default logging configuration. You can set up filters to manage the logging
volume:
- You can set up filters in the
cos-auditd-fluent-bit-configConfigMap so that certain data isn't logged. Refer to the fluent-bit documentation for the Grep, Modify, Record Modifier, and other filters. - You can also configure Logging to filter incoming logs. For more details, see Configure and manage sinks.
Deploy the logging DaemonSet
You can use an existing cluster or create a new one.
Download the example manifests:
curl https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-node-tools/master/troubleshooting/os-audit/cos-auditd-logging.yaml > cos-auditd-logging.yamlEdit the example manifests to suit your needs. Refer to the previous section for details about how the DaemonSet works. Note that the
fluent-bitimage used in this sample manifest is for demonstration purposes only. As a best practice, replace the image with an image from a controlled source with SHA-256 digest.Initialize common variables:
export CLUSTER_NAME=CLUSTER_NAME export CLUSTER_LOCATION=COMPUTE_REGIONReplace the following:
CLUSTER_NAME: the name of your cluster.COMPUTE_REGION: the Compute Engine region for your cluster. For zonal clusters, use the zone instead.
Deploy the logging Namespace, DaemonSet, and ConfigMap:
envsubst '$CLUSTER_NAME,$CLUSTER_LOCATION' < cos-auditd-logging.yaml \ | kubectl apply -f -Verify that the logging Pods have started. If you defined a different Namespace in your manifests, replace cos-auditd with the name of the namespace you're using.
kubectl get pods --namespace=cos-auditdIf the Pods are running, the output looks like this:
NAME READY STATUS RESTARTS AGE cos-auditd-logging-g5sbq 1/1 Running 0 27s cos-auditd-logging-l5p8m 1/1 Running 0 27s cos-auditd-logging-tgwz6 1/1 Running 0 27sOne Pod is deployed on each node in the cluster, in this case the cluster has three nodes.
You can now access the audit logs in Logging. In the Logs Explorer, filter the results using the following query:
LOG_ID("linux-auditd") resource.labels.cluster_name = "CLUSTER_NAME" resource.labels.location = "COMPUTE_REGION"Alternatively, you can use gcloud CLI (use
--limitbecause the result set can be very large):gcloud logging read --limit=100 "LOG_ID("linux-auditd") AND resource.labels.cluster_name = "${CLUSTER_NAME}" AND resource.labels.location = "${CLUSTER_LOCATION}""
Export logs
To learn how to route your logs to supported destinations, see Configure and manage sinks.
Disable logs
To disable auditd logging on your nodes, delete the logging DaemonSet, and
then deploy the
cos-auditd-logging-disable
DaemonSet to revert the systemd service changes on each node. After you deploy
this DaemonSet, you can't enable auditd logging unless the nodes are re-created.
Delete the original logging DaemonSet and its related resources:
kubectl delete daemonset cos-auditd-logging -n cos-auditd kubectl delete configmap fluent-bit-config -n cos-auditd # The namespace will be deleted by the cleanup daemonset's namespace definitionApply the cos-auditd-logging-disable cleanup DaemonSet:
kubectl apply -f 'https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-node-tools/master/troubleshooting/os-audit/cos-auditd-logging-disable.yaml'Verify that the
cleanup-auditdPods are running on all of your nodes:kubectl get pods -n cos-auditd -l name=cleanup-auditd -wWait until all Pods show
Running.After the cleanup Pods are running, confirm that new
linux-auditdlogs aren't generated by running the queries from the Deploying the logging DaemonSet section. For example, you can use the following gcloud CLI command:gcloud logging read --limit=10 --freshness="5m" \ "LOG_ID(\"linux-auditd\") AND \ resource.labels.cluster_name = \"${CLUSTER_NAME}\" AND \ resource.labels.location = \"${CLUSTER_LOCATION}\""This command checks for logs in the last five minutes. If the cleanup was successful, the output is empty.
Similarly, when using the Cloud Explorer with the same filter, you should see no new log entries appearing after the cleanup time.
Delete the cleanup DaemonSet and namespace:
kubectl delete -f cleanup-auditd-daemonset.yamlThis command will delete both the DaemonSet and the
cos-auditdnamespace.
What's next
- Watch Cloud Forensics 101 to get started with cloud forensics.
- Learn about Kubernetes Audit Logging and audit policy.
- Read the Kubernetes Engine Security Overview.
- Learn about Cloud Audit Logs.