Enabling Audit Logging#
An audit log is an append-only, time-ordered, tamper-evident record of who did what, to which resource, when, from where, and with what result, across a system's control plane and the data plane where it touches controlled or regulated resources (credentials, secrets, regulated data).
k0rdent provides a consistent mechanism for managing cluster audit policy through
the ClusterAuditPolicy resource.
By separating audit policy from cluster templates and automating its propagation, k0rdent removes error-prone manual steps and provides a repeatable, auditable way to enforce audit policy across a fleet of clusters.
ClusterAuditPolicy Resource#
k0rdent supports configuring audit policy for child clusters through
the ClusterAuditPolicy custom resource. Each ClusterAuditPolicy resource can be referenced by one or
more ClusterDeployment objects.
The resource contains a Policy object from the audit.k8s.io/v1 API group with rules defining which events are
recorded and what data they include. For details, see the official Kubernetes
Auditing guide and
the Policy configuration reference
for supported Policy fields.
Examples#
You can use a minimal ClusterAuditPolicy to log all requests at the Metadata level:
apiVersion: k0rdent.mirantis.com/v1beta1
kind: ClusterAuditPolicy
metadata:
name: default
namespace: my-namespace
spec:
policy:
rules:
- level: Metadata
Audit Policy Example
If you are creating your own audit policy, you can use the following configuration as a starting point:apiVersion: k0rdent.mirantis.com/v1beta1
kind: ClusterAuditPolicy
metadata:
name: default
namespace: my-namespace
spec:
policy:
rules:
# The following requests were manually identified as high-volume and low-risk,
# so drop them.
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: "" # core
resources: ["endpoints", "services", "services/status"]
- level: None
userGroups: ["system:nodes"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["nodes", "nodes/status"]
- level: None
users:
- system:kube-controller-manager
- system:cloud-controller-manager
- system:kube-scheduler
- system:serviceaccount:kube-system:endpoint-controller
verbs: ["get", "update"]
namespaces: ["kube-system"]
resources:
- group: "" # core
resources: ["endpoints"]
- level: None
users: ["system:apiserver"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["namespaces", "namespaces/status", "namespaces/finalize"]
- level: None
users: ["cluster-autoscaler"]
verbs: ["get", "update"]
namespaces: ["kube-system"]
resources:
- group: "" # core
resources: ["configmaps", "endpoints"]
# Don't log leader election lease updates (high-volume from all controllers).
- level: None
verbs: ["get", "update"]
resources:
- group: "coordination.k8s.io"
resources: ["leases"]
# Don't log HPA fetching metrics.
- level: None
users:
- system:kube-controller-manager
- system:cloud-controller-manager
verbs: ["get", "list"]
resources:
- group: "metrics.k8s.io"
# Don't log these read-only URLs.
- level: None
nonResourceURLs:
- /healthz*
- /version
- /swagger*
# Don't log events requests because of performance impact.
- level: None
resources:
- group: "" # core
resources: ["events"]
# node and pod status calls from nodes are high-volume and can be large, don't log responses for expected updates from nodes
- level: Request
users: ["kubelet", "system:node-problem-detector", "system:serviceaccount:kube-system:node-problem-detector"]
verbs: ["update","patch"]
resources:
- group: "" # core
resources: ["nodes/status", "pods/status"]
omitStages:
- "RequestReceived"
- level: Request
userGroups: ["system:nodes"]
verbs: ["update","patch"]
resources:
- group: "" # core
resources: ["nodes/status", "pods/status"]
omitStages:
- "RequestReceived"
# deletecollection calls can be large, don't log responses for expected namespace deletions
- level: Request
users: ["system:serviceaccount:kube-system:namespace-controller"]
verbs: ["deletecollection"]
omitStages:
- "RequestReceived"
# Secrets, ConfigMaps, TokenRequest and TokenReviews can contain sensitive & binary data,
# so only log at the Metadata level.
- level: Metadata
resources:
- group: "" # core
resources: ["secrets", "configmaps", "serviceaccounts/token"]
- group: authentication.k8s.io
resources: ["tokenreviews"]
omitStages:
- "RequestReceived"
# Get responses can be large; skip them.
- level: Request
verbs: ["get", "list", "watch"]
resources:
- group: "admissionregistration.k8s.io"
- group: "apiextensions.k8s.io"
- group: "apiregistration.k8s.io"
- group: "apps"
- group: "authentication.k8s.io"
- group: "authorization.k8s.io"
- group: "autoscaling"
- group: "batch"
- group: "certificates.k8s.io"
- group: "coordination.k8s.io"
- group: "discovery.k8s.io"
- group: "extensions"
- group: "flowcontrol.apiserver.k8s.io"
- group: "metrics.k8s.io"
- group: "networking.k8s.io"
- group: "node.k8s.io"
- group: "policy"
- group: "rbac.authorization.k8s.io"
- group: "scheduling.k8s.io"
- group: "storage.k8s.io"
# k0s
- group: "k0s.k0sproject.io"
- group: "helm.k0sproject.io"
- group: "autopilot.k0sproject.io"
omitStages:
- "RequestReceived"
# Default level for known APIs
- level: RequestResponse
resources:
- group: "admissionregistration.k8s.io"
- group: "apiextensions.k8s.io"
- group: "apiregistration.k8s.io"
- group: "apps"
- group: "authentication.k8s.io"
- group: "authorization.k8s.io"
- group: "autoscaling"
- group: "batch"
- group: "certificates.k8s.io"
- group: "coordination.k8s.io"
- group: "discovery.k8s.io"
- group: "extensions"
- group: "flowcontrol.apiserver.k8s.io"
- group: "metrics.k8s.io"
- group: "networking.k8s.io"
- group: "node.k8s.io"
- group: "policy"
- group: "rbac.authorization.k8s.io"
- group: "scheduling.k8s.io"
- group: "storage.k8s.io"
# k0s
- group: "k0s.k0sproject.io"
- group: "helm.k0sproject.io"
- group: "autopilot.k0sproject.io"
omitStages:
- "RequestReceived"
# Default level for all other requests.
- level: Metadata
omitStages:
- "RequestReceived"
Key Fields#
spec.policy– Contains the fullaudit.k8s.io/v1Policyobject consumed by the Kubernetes API server. For all supported options, see the official Kubernetes documentation: Audit Policy.
Configuring Audit Policy for ClusterDeployments#
To enable audit policy for a cluster, set the spec.auditPolicy field to reference an existing ClusterAuditPolicy
object in the same namespace:
apiVersion: k0rdent.mirantis.com/v1beta1
kind: ClusterDeployment
metadata:
name: cluster-name
namespace: my-namespace
spec:
template: openstack-hosted-cp-1-0-12
credential: openstack-cluster-identity-cred
auditPolicy: default
Integration with ClusterTemplates#
When audit policy is enabled, k0rdent injects the audit policy configuration into the control plane and manages updates when the configuration changes.
What k0rdent Generates#
When spec.auditPolicy is configured and the referenced ClusterAuditPolicy exists, the KCM controller performs
the following actions:
- Generates a
ConfigMapnamed<cluster-deployment-name>-audit-policycontaining thePolicyconfiguration. - Passes audit policy values to the
HelmReleaseresponsible for deploying the cluster control plane:
audit:
policyRef:
name: cluster-name-audit-policy
key: policy
hash: g8d3f7b8
audit.policyRef.name– Name of theConfigMapcontaining the audit policy configuration.audit.policyRef.key– Key within theConfigMapwhere the audit policy is stored.audit.policyRef.hash– Hash of the configuration content; used to trigger control plane updates when the configuration changes.
What ClusterTemplates Must Consume#
The ClusterTemplate must consume these values to configure the API server correctly. Built-in templates already
reference this information.
If you are creating custom ClusterTemplates, you must explicitly reference these values. In particular,
the control plane resources (K0smotronControlPlane or K0sControlPlane) must:
- Mount the audit policy config map into control plane nodes or pods.
- Set the API server
--audit-policy-fileflag to the mounted configuration file.
Warning
Updating spec.auditPolicy changes the configuration hash and triggers a rolling recreation of control plane machines.
For clusters that were initially deployed with a single control plane node, this operation may cause the cluster to
lose etcd quorum during the rollout, potentially resulting in a cluster outage.
For mitigation steps and additional details, see Cluster Control Plane Rollout.
Additionally, you can configure the Kubernetes API server audit log backend using the following API server parameters:
audit-log-path, audit-log-maxage, audit-log-maxbackup, audit-log-maxsize.
When audit-log-path is set to "-", the API server writes audit logs to standard output instead of a file.
In this mode, log rotation and retention are managed externally, and the audit-log-max* settings do not apply.
For more information, see the Kubernetes documentation on the audit log backend.
Examples of how to consume these values in ClusterTemplates are available in the templates directory of the official {{ docsVersionInfo.k0rdentName }} repository.
Example: K0smotronControlPlane Audit Policy Configuration#
This example shows how a hosted control plane consumes the injected audit policy configuration.
spec:
k0sConfig:
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
name: k0s
spec:
mounts:
{{- if .Values.audit.policyRef.name }}
- path: {{ include "audit-policy.dir" . }}
configMap:
defaultMode: 420
items:
- key: {{ .Values.audit.policyRef.key | quote }}
path: policy-{{ .Values.audit.policyRef.hash }}.yaml
name: {{ .Values.audit.policyRef.name | quote }}
{{- end }}
...
api:
extraArgs:
{{- if .Values.audit.policyRef.name }}
audit-policy-file: /var/lib/k0s/audit/policy-{{ .Values.audit.policyRef.hash }}.yaml
audit-log-path: "-"
{{- end }}
...
Example: K0sControlPlane Audit Policy Configuration#
This example shows the configuration for standalone control plane clusters.
spec:
k0sConfigSpec:
{{- if .Values.audit.policyRef.name }}
files:
- contentFrom:
configMapRef:
name: {{ .Values.audit.policyRef.name | quote }}
key: {{ default "policy" .Values.audit.policyRef.key | quote }}
permissions: "0644"
path: /var/lib/k0s/audit/policy-{{ .Values.audit.policyRef.hash }}.yaml
{{- end }}
...
k0s:
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
name: k0s
spec:
api:
extraArgs:
{{- if .Values.audit.policyRef.name }}
audit-policy-file: /var/lib/k0s/audit/policy-{{ .Values.audit.policyRef.hash }}.yaml
{{- if .Values.audit.logPath }}
audit-log-path: {{ .Values.audit.logPath | quote }}
{{- end }}
{{- if and .Values.audit.logPath (ne .Values.audit.logPath "-") }}
{{- if .Values.audit.logMaxAge }}
audit-log-maxage: {{ .Values.audit.logMaxAge | quote }}
{{- end }}
{{- if .Values.audit.logMaxBackup }}
audit-log-maxbackup: {{ .Values.audit.logMaxBackup | quote }}
{{- end }}
{{- if .Values.audit.logMaxSize }}
audit-log-maxsize: {{ .Values.audit.logMaxSize | quote }}
{{- end }}
{{- end }}
{{- end }}
...