Les logs d’audit Kubernetes enregistrent chaque requête à l’API Server pour la traçabilité et l’investigation de sécurité. Ils répondent aux questions “qui a fait quoi, quand, et via quelle méthode”. Ce guide vous montre comment configurer une politique d’audit, activer les logs sur l’API Server, et analyser les événements pour détecter les comportements suspects ou reconstituer un incident.
Prérequis
Section intitulée « Prérequis »- Accès à la configuration de l’API Server (fichiers manifests ou flags)
- Pour les clusters managés (EKS/GKE/AKS) : accès à la console cloud
- Compréhension des ressources Kubernetes (pods, secrets, configmaps)
Comment fonctionne l’audit Kubernetes ?
Section intitulée « Comment fonctionne l’audit Kubernetes ? »L’audit se compose de trois éléments :
- Audit Policy : définit quels événements capturer et à quel niveau de détail
- API Server : applique la politique et génère les événements
- Backend : stocke les logs (fichier local ou webhook vers système externe)
Les quatre niveaux d’audit
Section intitulée « Les quatre niveaux d’audit »Chaque règle de la politique spécifie un niveau qui détermine la quantité d’information enregistrée :
| Niveau | Ce qui est enregistré | Usage |
|---|---|---|
None | Rien | Exclure des ressources du logging (éviter le bruit) |
Metadata | Metadata de la requête (user, timestamp, resource, verb) mais pas le body | Audit de base, faible volume |
Request | Metadata + body de la requête | Voir ce qui a été envoyé |
RequestResponse | Metadata + requête + réponse | Debug complet, volume élevé |
Les quatre stages d’un événement
Section intitulée « Les quatre stages d’un événement »Un événement peut être enregistré à différentes étapes de son traitement :
| Stage | Moment | Usage |
|---|---|---|
RequestReceived | Dès réception, avant traitement | Logging exhaustif |
ResponseStarted | Headers de réponse envoyés (watch/long-running) | Requêtes longues |
ResponseComplete | Réponse terminée | Standard, le plus utilisé |
Panic | Si l’API Server panic | Debugging uniquement |
Créer une politique d’audit
Section intitulée « Créer une politique d’audit »Structure de base
Section intitulée « Structure de base »apiVersion: audit.k8s.io/v1kind: Policy# Règle par défaut si aucune autre ne matchomitStages: - "RequestReceived" # Évite les doublonsrules: # Les règles sont évaluées dans l'ordre, première qui match gagne
# 1. Ne pas logger les health checks (bruit) - level: None users: ["system:kube-probe", "system:serviceaccount:kube-system:kube-proxy"] resources: - group: "" resources: ["endpoints", "services"]
# 2. Secrets/ConfigMaps/TokenRequests : Metadata uniquement (jamais le contenu) # IMPORTANT : RequestResponse exposerait les valeurs sensibles dans les logs ! - level: Metadata resources: - group: "" resources: ["secrets", "configmaps", "serviceaccounts/token"] - group: authentication.k8s.io resources: ["tokenreviews"] omitStages: - "RequestReceived"
# 4. Logger les modifications RBAC - level: RequestResponse resources: - group: "rbac.authorization.k8s.io" resources: ["roles", "rolebindings", "clusterroles", "clusterrolebindings"]
# 5. Logger les actions sur pods au niveau Metadata - level: Metadata resources: - group: "" resources: ["pods", "pods/exec", "pods/portforward"]
# 6. Règle par défaut : Metadata pour tout le reste - level: MetadataPolitique minimale pour CKS
Section intitulée « Politique minimale pour CKS »Pour l’examen CKS, voici une politique simple mais fonctionnelle :
apiVersion: audit.k8s.io/v1kind: PolicyomitStages: - "RequestReceived"rules: # Ignorer les endpoints health - level: None nonResourceURLs: - "/healthz*" - "/readyz*" - "/livez*"
# Secrets, ConfigMaps, tokens : Metadata uniquement (pas le contenu) - level: Metadata resources: - group: "" resources: ["secrets", "configmaps", "serviceaccounts/token"] - group: authentication.k8s.io resources: ["tokenreviews"]
# RBAC : RequestResponse pour traçabilité complète - level: RequestResponse resources: - group: "rbac.authorization.k8s.io"
# Metadata pour tout le reste - level: MetadataFiltres disponibles
Section intitulée « Filtres disponibles »rules: - level: Metadata # Filtrer par utilisateur users: ["admin", "system:serviceaccount:default:myapp"] userGroups: ["system:authenticated"]
# Filtrer par verbe verbs: ["create", "update", "delete"]
# Filtrer par ressource resources: - group: "" # core API group resources: ["pods", "services"] - group: "apps" resources: ["deployments"]
# Filtrer par namespace namespaces: ["production", "finance"]
# URLs non-ressources (healthz, metrics) nonResourceURLs: ["/api*", "/version"]
# Stages à omettre pour cette règle omitStages: ["RequestReceived"]Configurer l’API Server
Section intitulée « Configurer l’API Server »Clusters kubeadm / self-managed
Section intitulée « Clusters kubeadm / self-managed »-
Créer le fichier de politique
Fenêtre de terminal sudo mkdir -p /etc/kubernetes/auditsudo vim /etc/kubernetes/audit/audit-policy.yamlColler la politique YAML.
-
Modifier le manifest de l’API Server
Fenêtre de terminal sudo vim /etc/kubernetes/manifests/kube-apiserver.yamlAjouter les flags :
spec:containers:- command:- kube-apiserver# ... autres flags existants ...- --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml- --audit-log-path=/var/log/kubernetes/audit/audit.log- --audit-log-maxage=30 # Rétention en jours- --audit-log-maxbackup=10 # Nombre de fichiers à conserver- --audit-log-maxsize=100 # Taille max en Mo avant rotation -
Ajouter les volumes et volumeMounts
spec:containers:- volumeMounts:# ... mounts existants ...- mountPath: /etc/kubernetes/auditname: audit-policyreadOnly: true- mountPath: /var/log/kubernetes/auditname: audit-logsvolumes:# ... volumes existants ...- name: audit-policyhostPath:path: /etc/kubernetes/audittype: DirectoryOrCreate- name: audit-logshostPath:path: /var/log/kubernetes/audittype: DirectoryOrCreate -
Créer le répertoire de logs
Fenêtre de terminal sudo mkdir -p /var/log/kubernetes/audit -
Vérifier le redémarrage de l’API Server
Fenêtre de terminal # L'API Server redémarre automatiquement (kubelet surveille /etc/kubernetes/manifests)kubectl get pods -n kube-system | grep api# Vérifier les logssudo tail -f /var/log/kubernetes/audit/audit.log | jq .
Exemple de manifest complet
Section intitulée « Exemple de manifest complet »apiVersion: v1kind: Podmetadata: name: kube-apiserver namespace: kube-systemspec: containers: - name: kube-apiserver command: - kube-apiserver - --advertise-address=10.0.0.10 - --allow-privileged=true - --authorization-mode=Node,RBAC # ... autres flags ... - --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml - --audit-log-path=/var/log/kubernetes/audit/audit.log - --audit-log-maxage=7 - --audit-log-maxbackup=5 - --audit-log-maxsize=100 volumeMounts: - mountPath: /etc/kubernetes/audit name: audit-policy readOnly: true - mountPath: /var/log/kubernetes/audit name: audit-logs volumes: - hostPath: path: /etc/kubernetes/audit type: DirectoryOrCreate name: audit-policy - hostPath: path: /var/log/kubernetes/audit type: DirectoryOrCreate name: audit-logsWebhook backend (optionnel)
Section intitulée « Webhook backend (optionnel) »Pour envoyer les événements vers un système externe (SIEM, Elasticsearch) :
apiVersion: v1kind: Configclusters: - name: audit-webhook cluster: server: https://siem.example.com/k8s-audit certificate-authority: /etc/kubernetes/pki/ca.crtcontexts: - name: audit-webhook context: cluster: audit-webhookcurrent-context: audit-webhookFlags API Server pour webhook :
--audit-webhook-config-file=/etc/kubernetes/audit/audit-webhook-config.yaml--audit-webhook-initial-backoff=5s--audit-webhook-batch-max-size=1000Analyser les logs d’audit
Section intitulée « Analyser les logs d’audit »Structure d’un événement
Section intitulée « Structure d’un événement »{ "kind": "Event", "apiVersion": "audit.k8s.io/v1", "level": "RequestResponse", "auditID": "abc123", "stage": "ResponseComplete", "requestURI": "/api/v1/namespaces/default/secrets", "verb": "create", "user": { "username": "admin", "groups": ["system:masters", "system:authenticated"] }, "sourceIPs": ["10.0.0.50"], "userAgent": "kubectl/v1.30.0", "objectRef": { "resource": "secrets", "namespace": "default", "name": "my-secret", "apiVersion": "v1" }, "responseStatus": { "code": 201 }, "requestObject": { "kind": "Secret", "data": { "password": "***" } }, "stageTimestamp": "2025-06-19T10:30:00Z"}Requêtes d’investigation courantes
Section intitulée « Requêtes d’investigation courantes »# Toutes les créations de secretscat audit.log | jq 'select(.verb=="create" and .objectRef.resource=="secrets")'
# Actions d'un utilisateur spécifiquecat audit.log | jq 'select(.user.username=="suspicious-user")'
# Accès refusés (403)cat audit.log | jq 'select(.responseStatus.code==403)'
# Toutes les actions sur un namespacecat audit.log | jq 'select(.objectRef.namespace=="production")'
# Exec dans des podscat audit.log | jq 'select(.objectRef.subresource=="exec")'
# Top 10 des utilisateurs les plus actifscat audit.log | jq -r '.user.username' | sort | uniq -c | sort -rn | head -10
# Actions des 5 dernières minutescat audit.log | jq --arg d "$(date -u -d '5 minutes ago' +%Y-%m-%dT%H:%M:%SZ)" \ 'select(.stageTimestamp > $d)'Reconstituer une timeline d’incident
Section intitulée « Reconstituer une timeline d’incident »# Exemple : qui a modifié le RBAC hier ?cat audit.log | jq --arg start "2025-06-18T00:00:00Z" --arg end "2025-06-19T00:00:00Z" \ 'select( .objectRef.apiGroup=="rbac.authorization.k8s.io" and .verb!="get" and .verb!="list" and .verb!="watch" and .stageTimestamp > $start and .stageTimestamp < $end ) | {time: .stageTimestamp, user: .user.username, verb, resource: .objectRef.resource, name: .objectRef.name}'Intégration avec Falco
Section intitulée « Intégration avec Falco »Falco peut analyser les audit logs Kubernetes pour des détections avancées. Voir le guide Falco pour la configuration du plugin K8s Audit.
Clusters managés
Section intitulée « Clusters managés »Sur les clusters managés, les audit logs sont gérés par le fournisseur cloud. Vous ne pouvez généralement pas personnaliser la politique d’audit, mais les logs sont automatiquement centralisés et consultables via les outils natifs.
AWS EKS envoie les audit logs vers CloudWatch Logs. Par défaut, seuls les logs API Server et Authenticator sont activés.
# Activer les audit logs (control plane logging)eksctl utils update-cluster-logging \ --cluster my-cluster \ --enable-types audit,api,authenticator \ --region eu-west-1Ou via AWS CLI :
aws eks update-cluster-config \ --name my-cluster \ --logging '{"clusterLogging":[{"types":["audit","api","authenticator"],"enabled":true}]}'Consulter les logs :
# Les logs sont dans le groupe /aws/eks/<cluster>/clusteraws logs filter-log-events \ --log-group-name /aws/eks/my-cluster/cluster \ --log-stream-name-prefix kube-apiserver-audit \ --filter-pattern '{ $.verb = "create" && $.objectRef.resource = "secrets" }'GKE utilise Cloud Audit Logs, activé par défaut. Deux types de logs :
- Admin Activity : créations, modifications, suppressions (toujours activé, gratuit)
- Data Access : lectures (désactivé par défaut, payant)
# Vérifier la configuration du clustergcloud container clusters describe my-cluster \ --format="yaml(loggingConfig)"
# Activer Data Access logs (optionnel, génère du volume)gcloud projects get-iam-policy PROJECT_ID \ --format=yaml > policy.yaml# Éditer pour ajouter auditConfigs pour GKEConsulter les logs dans Cloud Logging :
resource.type="k8s_cluster"protoPayload.methodName:"secrets"protoPayload.authenticationInfo.principalEmail:"user@example.com"AKS expose les audit logs via Azure Monitor et Diagnostic Settings. Plusieurs catégories disponibles :
kube-audit: audit complet (volume élevé)kube-audit-admin: uniquement les opérations d’écriture (recommandé)
# Créer un Log Analytics workspace si nécessaireaz monitor log-analytics workspace create \ --resource-group myRG \ --workspace-name myWorkspace
# Activer les diagnostic settingsCLUSTER_ID=$(az aks show -g myRG -n my-cluster --query id -o tsv)WORKSPACE_ID=$(az monitor log-analytics workspace show \ -g myRG -n myWorkspace --query id -o tsv)
az monitor diagnostic-settings create \ --name aks-audit \ --resource "$CLUSTER_ID" \ --workspace "$WORKSPACE_ID" \ --logs '[{"category":"kube-audit-admin","enabled":true}]'Requête KQL dans Log Analytics :
AzureDiagnostics| where Category == "kube-audit-admin"| extend auditLog = parse_json(log_s)| where auditLog.objectRef.resource == "secrets"| project TimeGenerated, User=auditLog.user.username, Verb=auditLog.verb, Resource=auditLog.objectRef.name| order by TimeGenerated descDépannage
Section intitulée « Dépannage »L’API Server ne redémarre pas
Section intitulée « L’API Server ne redémarre pas »# Vérifier les erreurssudo journalctl -u kubelet | grep -i apiserver | tail -50
# Erreurs YAML courantessudo cat /etc/kubernetes/manifests/kube-apiserver.yaml | yq .Causes fréquentes :
| Symptôme | Cause | Solution |
|---|---|---|
| ”audit policy file not found” | Chemin incorrect ou fichier absent | Vérifier le path et les permissions |
| ”invalid audit policy” | YAML invalide | Valider le YAML avec yq . policy.yaml ou un linter |
| CrashLoopBackOff API Server | Volume mount incorrect | Vérifier hostPath et mountPath |
Pas de logs générés
Section intitulée « Pas de logs générés »# Vérifier que l'audit est actifps aux | grep kube-apiserver | grep audit
# Les flags doivent apparaître# --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml# --audit-log-path=/var/log/kubernetes/audit/audit.log
# Vérifier les permissions du répertoirels -la /var/log/kubernetes/audit/
# Générer une action pour créer des logskubectl create secret generic test-audit --from-literal=key=valuekubectl delete secret test-auditBonnes pratiques
Section intitulée « Bonnes pratiques »Exclure le bruit
Utiliser level: None pour les health checks, metrics, et reads fréquents.
RequestResponse avec parcimonie
Réserver ce niveau aux secrets, RBAC, et pods/exec.
Rotation des logs
Configurer maxage, maxbackup, maxsize pour éviter de remplir le disque.
Centraliser les logs
Utiliser un webhook vers SIEM/Elasticsearch pour la rétention longue.
À retenir
Section intitulée « À retenir »| Concept | Description |
|---|---|
| Audit Policy | Fichier YAML définissant quoi logger et à quel niveau |
| Niveaux | None < Metadata < Request < RequestResponse |
| Stages | RequestReceived, ResponseStarted, ResponseComplete, Panic |
| Backend fichier | --audit-log-path pour logs locaux |
| Backend webhook | Pour envoyer vers systèmes externes (SIEM) |
| Rotation | --audit-log-maxage/maxbackup/maxsize |
Prochaines étapes
Section intitulée « Prochaines étapes »Falco Runtime Security
Détecter les comportements suspects en temps réel. Configurer Falco
CIS Benchmark
Valider la configuration sécurisée du cluster. CIS Benchmark
RBAC
Contrôler les accès audités. RBAC Kubernetes
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications