WIKI
AKS Azure Kubernetes Service

03 · Identités et sécurité d'AKS

30 min de lecture Mis à jour le 21 octobre 2026
Sur cette page

Version : 1.0 · Date : 2026-10-21 · Parcours AKS, niveau architecte (entretiens)

En une phrase : un cluster AKS manipule quatre identités qu'il ne faut jamais confondre (qui parle à l'API server, le cluster lui-même, le kubelet, les pods) ; tout le reste de la sécurité consiste à ne laisser entrer que des requêtes authentifiées, autorisées et conformes, des images de confiance, et à garder les secrets hors du cluster.

Les quatre identités d'un cluster AKS

Chapitre du parcours Sujet
01-architecture Kubernetes pour un architecte, ce qu'AKS gère, anatomie d'un cluster, topologies de référence
02-reseau CNI (Overlay, Cilium), Services, entrée, sortie, cluster privé, DNS
03-identite-securite (ce fichier) Entra ID, RBAC, Workload ID, secrets, admission, images, Defender, multilocation
04-stockage-scalabilite-fiabilite Volumes, mise à l'échelle, zones, mises à niveau
05-exploitation-gitops Supervision, GitOps, Fleet Manager, coûts
06-ia-llm GPU, KAITO, inférence de LLM, intégration Foundry
07-conteneurs-azure-et-entretiens AKS ou Container Apps, App Service, ACI ; questions d'entretien

Ce chapitre explique le fonctionnement et les choix d'architecture. Microsoft Entra ID, Azure RBAC, Azure Key Vault et les managed identities sont supposés connus (cours SC-500, chapitre 01 et 02) ; la même sécurité AKS vue « examen » est dans SC-500, chapitre 09, section 3.

Les noms de services, fonctionnalités, objets et rôles restent en anglais, comme dans le portail et la documentation.


1. Les quatre identités, et une cinquième question#

Microsoft Learn découpe l'identité AKS en cinq scénarios. Les scénarios A, B, D et E correspondent à des identités distinctes ; le C est une simple permission Azure sur la ressource AKS, souvent oubliée.

Scénario Question Mécanisme Où ça se règle
A. Control plane authentication Qui appelle l'API Kubernetes ? Microsoft Entra ID (recommandé), local accounts, external identity provider OIDC (préversion) Intégration Entra du cluster
B. Control plane authorization Que peut-il faire une fois authentifié ? Kubernetes RBAC et/ou Microsoft Entra ID authorization (Azure RBAC) Role assignments Azure ou objets Role/RoleBinding
C. AKS resource authorization Qui peut récupérer le kubeconfig, modifier le cluster ? Azure RBAC classique sur Microsoft.ContainerService Access control (IAM) du cluster
D. Cluster identity (cluster → Azure) Comment le cluster agit-il sur Azure ? Managed identities du control plane, du kubelet, des add-ons Profil d'identité du cluster
E. Workload identity (pod → Azure) Comment un pod accède-t-il à Key Vault, au Storage ? Microsoft Entra Workload ID ServiceAccount Kubernetes + federated credential

1.1 Les managed identities du cluster#

Identité Nom par défaut Sert à Droits par défaut Apporter la sienne
Control plane identity nom du cluster Créer Load Balancer et public IP, attacher les disques, cluster autoscaler, pilotes CSI Contributor sur le node resource group (MC_…) Oui (user-assigned)
Kubelet identity <cluster>-agentpool Tirer les images depuis Azure Container Registry Aucun : il faut AcrPull (ou Container Registry Repository Reader pour un registre en mode ABAC) Oui
Add-on identities selon l'add-on (azurekeyvaultsecretsprovider-…, application routing, AGIC…) L'add-on seulement Selon l'add-on En général non

Points d'architecture :

  • La control plane identity est system-assigned par défaut. Pour un VNet, une static IP, une route table ou une kubelet identity hors du node resource group, il faut des role assignments que la CLI crée mais pas ARM ni Terraform ; avec une system-assigned identity, elles ne peuvent se faire qu'après la création : préférer une user-assigned managed identity.
  • Une kubelet identity apportée hors du node resource group exige Managed Identity Operator pour la control plane identity.
  • Changer de type d'identité prend plusieurs heures (l'ancienne sert jusqu'à l'expiration de son jeton). Un service principal reste possible, mais Microsoft recommande la managed identity.

Phrase d'entretien : « Le kubelet tire les images, la cluster identity gère l'infrastructure Azure, et les pods n'utilisent ni l'une ni l'autre : ils ont leur propre identité, fédérée par Workload ID. Donner un data role à la kubelet identity pour qu'une application lise un coffre, c'est donner ce coffre à tous les pods du node pool. »


2. Accéder à l'API server#

Authentification puis autorisation sur l'API server

2.1 S'authentifier#

Méthode Ce qu'il faut savoir
Microsoft Entra ID (recommandé) L'API server valide le jeton Entra ; un changement de groupe ou un départ est pris en compte sans toucher au cluster ; Conditional Access, MFA et Privileged Identity Management (PIM) s'appliquent. Le tenant Entra doit être celui de la subscription du cluster
kubelogin Plugin d'identification client-go qui implémente les flux Entra. Les clusters 1.24 et plus utilisent d'office le format exec ; kubelogin convert-kubeconfig choisit la méthode (navigateur interactif, device code, Azure CLI, managed identity…). Le device code ne fonctionne pas si une Conditional Access policy s'applique : prendre le navigateur interactif
Local accounts Certificat d'administrateur intégré qui contourne Entra ID : pas d'audit centralisé, pas de Conditional Access, pas de PIM. Activés par défaut à la création. À désactiver en production
External identity provider (préversion) GitHub, Okta, Google… via la structured authentication de l'API server, seulement si l'identité doit rester hors d'Entra

Désactiver les local accounts, et le faire respecter sur toute la flotte avec la built-in policy « Azure Kubernetes Service Clusters should have local authentication methods disabled » (Audit ou Deny) :

az aks update --resource-group rg-aks-prd --name aks-prd --disable-local-accounts
# Vérification : la récupération d'un kubeconfig administrateur doit échouer
az aks get-credentials --resource-group rg-aks-prd --name aks-prd --admin
# → "Getting static credential isn't allowed because this cluster is set to disable local accounts."

Piège : sur un cluster existant où des gens ont pu utiliser le certificat administrateur, désactiver les local accounts ne suffit pas : il faut faire tourner les certificats du cluster (certificate rotation) pour révoquer ceux déjà distribués. Les membres du groupe passé dans --aad-admin-group-object-ids gardent, eux, un accès administrateur par Entra.

2.2 Récupérer le kubeconfig : une permission Azure, pas Kubernetes#

Rôle Azure sur la ressource AKS Action Effet avec Entra ID Effet sans Entra ID
Azure Kubernetes Service Cluster User Role listClusterUserCredential kubeconfig « vide » qui déclenche la connexion Entra ; les droits viennent ensuite du RBAC Identique à l'administrateur
Azure Kubernetes Service Cluster Admin Role listClusterAdminCredential kubeconfig administrateur (certificat), si les local accounts sont actifs Administrateur

Pour un pipeline de déploiement : workload identity federation côté pipeline (pas de secret), Cluster User Role pour récupérer le kubeconfig, puis Azure Kubernetes Service RBAC Writer limité au namespace visé. Jamais les identifiants administrateur. Avec un API server privé, l'agent doit être dans un réseau qui l'atteint (self-hosted agent ou Managed DevOps Pools) : les Microsoft-hosted agents d'Azure DevOps ne sont pas pris en charge pour un cluster privé (voir 02-reseau).

2.3 Autoriser : Kubernetes RBAC ou Microsoft Entra ID authorization#

Les deux modèles peuvent cohabiter sur le même cluster. Microsoft recommande Microsoft Entra ID authorization (aussi appelée Azure RBAC for Kubernetes Authorization) par défaut et le Kubernetes RBAC pour le fin à l'intérieur d'un cluster.

Kubernetes RBAC Microsoft Entra ID authorization (Azure RBAC)
Où vivent les droits Objets Role, ClusterRole, RoleBinding, ClusterRoleBinding dans le cluster Role assignments Azure ; un authorization webhook AKS interroge l'API checkaccess d'Entra
Portée d'une attribution Un cluster Ressource, resource group, subscription, management group : une role assignment régit tous les clusters de la portée, présents et futurs
Conditional Access, PIM Non Hérités d'Entra ID
Audit des changements de droits Kubernetes audit log Azure Activity Log
Custom resources (CRD) Role sur le groupe d'API Conditions ABAC sur customResources:group et :kind (préversion)
Idéal pour Service accounts internes, droits versionnés en GitOps avec l'application Humains et pipelines, gouvernance multi-clusters
Activation Toujours présent --enable-azure-rbac (préconfiguré sur AKS Automatic)

Les quatre built-in roles de Microsoft Entra ID authorization, et leur subtilité :

Rôle Portée habituelle À savoir
Azure Kubernetes Service RBAC Reader Namespace Lecture ; ne voit ni les rôles ni les Secrets (lire un Secret donnerait les jetons des service accounts : escalade)
Azure Kubernetes Service RBAC Writer Namespace Lecture/écriture, sans rôles ; mais lit les Secrets et peut lancer un pod sous n'importe quel ServiceAccount du namespace : il en obtient donc les droits
Azure Kubernetes Service RBAC Admin Namespace Peut créer rôles et bindings dans le namespace ; pas d'écriture sur les ResourceQuota ni sur le namespace lui-même
Azure Kubernetes Service RBAC Cluster Admin Cluster Super-utilisateur, tous les namespaces
AKS_ID=$(az aks show -g rg-aks-prd -n aks-prd --query id -o tsv)
# Lecture seule sur un seul namespace (propagation jusqu'à 5 minutes)
az role assignment create --role "Azure Kubernetes Service RBAC Reader" \
  --assignee <objectId-du-groupe-Entra> --scope "$AKS_ID/namespaces/equipe-a"

Un custom role cible les data actions Microsoft.ContainerService/managedClusters/<groupe>/<ressource>/<verbe>, par exemple Microsoft.ContainerService/managedClusters/apps/deployments/read.

Côté Kubernetes RBAC, on lie toujours un groupe Entra (par son object ID, pas son nom), jamais des utilisateurs un par un :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: { name: lecteur-pods, namespace: equipe-a }
rules: [{ apiGroups: [""], resources: ["pods", "pods/log"], verbs: ["get", "list", "watch"] }]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: { name: lecteur-pods-equipe-a, namespace: equipe-a }
subjects: [{ kind: Group, apiGroup: rbac.authorization.k8s.io, name: "<objectId-du-groupe-Entra>" }]
roleRef: { kind: Role, name: lecteur-pods, apiGroup: rbac.authorization.k8s.io }
flowchart TD
    A["Qui a besoin d'un droit sur l'API ?"] --> B{"Un humain ou un pipeline ?"}
    B -- Oui --> C{"Même règle sur plusieurs clusters ?"}
    C -- Oui --> D["Microsoft Entra ID authorization<br/>AKS RBAC role à la portée resource group ou subscription"]
    C -- Non --> E["Microsoft Entra ID authorization<br/>portée cluster ou namespace"]
    B -- Non --> F{"Un composant dans le cluster<br/>(operator, controller) ?"}
    F -- Oui --> G["Kubernetes RBAC<br/>ServiceAccount + Role, versionné en GitOps"]
    D --> H["Accès élevé : PIM for Groups<br/>Conditional Access sur l'application AKS"]
    E --> H

2.4 Conditional Access, PIM et accès aux nodes#

  • Conditional Access (accès conditionnel) : cibler l'application « Azure Kubernetes Service Microsoft Entra Server » (par exemple : Require device to be marked as compliant pour le groupe administrateur).
  • PIM for Groups : le groupe admin porte Azure Kubernetes Service RBAC Admin, ses membres y sont eligible et activent juste-à-temps, avec Require approval to activate. Sans cette case, l'activation est libre. L'approbateur doit être member du groupe approbateur (owner ne suffit pas). Licence Microsoft Entra ID P2 ou ID Governance.
  • SSH vers les nodes, trois modes par node pool : Disabled SSH (préversion, recommandé en production ; kubectl debug node continue de fonctionner), Microsoft Entra ID based SSH (préversion : rôles Virtual Machine User Login ou Virtual Machine Administrator Login, Conditional Access sur « Azure Linux Virtual Machine Sign-In », pas sur Windows ni Azure Container Linux), Local user SSH (clés SSH à faire tourner). Le changement de mode s'applique après une réimage du node pool (az aks nodepool upgrade --node-image-only).

3. Microsoft Entra Workload ID : l'identité des pods#

Workload ID : un pod obtient un jeton Azure sans secret

3.1 Le mécanisme#

  1. Le cluster devient OIDC issuer : il publie {IssuerURL}/.well-known/openid-configuration et {IssuerURL}/openid/v1/jwks (ses clés publiques).
  2. On crée une user-assigned managed identity (ou une App registration) avec un federated credential : issuer = URL de l'OIDC issuer du cluster, subject = system:serviceaccount:<namespace>:<serviceaccount>, audience api://AzureADTokenExchange.
  3. Le ServiceAccount Kubernetes porte l'annotation azure.workload.identity/client-id.
  4. Le pod porte le label azure.workload.identity/use: "true" : seuls ces pods sont modifiés par le mutating admission webhook, qui injecte AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_FEDERATED_TOKEN_FILE et le volume du projected service account token (renouvelé par Kubernetes avant expiration).
  5. Le SDK (DefaultAzureCredential ou WorkloadIdentityCredential d'Azure Identity, ou MSAL) échange ce jeton contre un jeton Entra au token endpoint v2 ; Entra vérifie la signature avec les clés publiques de l'issuer.
sequenceDiagram
    participant K as kubelet
    participant P as Pod (SDK Azure Identity)
    participant E as Microsoft Entra ID
    participant O as OIDC issuer du cluster
    participant KV as Key Vault
    K->>P: Projected service account token (fichier)
    P->>E: Échange : jeton SA + client-id (portée https://vault.azure.net/.default)
    E->>O: Lit la configuration OIDC et les clés publiques (JWKS)
    E->>E: Vérifie issuer, subject, audience du federated credential
    E-->>P: Jeton d'accès Entra
    P->>KV: Lit le secret avec le jeton (rôle Key Vault Secrets User)

3.2 Les détails qui font la différence#

Point Détail
Activation AKS Standard : --enable-oidc-issuer --enable-workload-identity ; AKS Automatic : préconfiguré
Label du pod Obligatoire (comportement « fail close ») : sans lui, rien n'est injecté et le pod échoue après redémarrage
Correspondance Exacte : un nom de namespace ou de ServiceAccount différent dans le subject = erreur AADSTS… à l'échange
Limites 20 federated credentials par managed identity ; quelques secondes de propagation après création ; virtual nodes non pris en charge
Durées Projected token : 3 600 s par défaut, réglable de 3 600 à 86 400 s (annotation) ; jeton Entra : expire dans les 24 heures
Portée demandée Format v2 <ressource>/.default (une URI brute peut échouer)
Chemin du jeton Toujours lire AZURE_FEDERATED_TOKEN_FILE, ne jamais coder le chemin en dur
Correspondances Un-à-un, plusieurs-à-un (plusieurs ServiceAccounts → une identité), un-à-plusieurs ; changer l'annotation impose de redémarrer le pod
Grande échelle Les identity bindings partagent une identité entre de nombreux clusters avec un seul federated credential (contourne la limite de 20) ; documentés sans mention de préversion au 21/10/2026, pris en charge par le Key Vault provider du Secrets Store CSI Driver
Ancien modèle La Microsoft Entra pod-managed identity est dépréciée depuis le 24/10/2022 ; un migration sidecar existe, comme solution transitoire

Les commandes complètes (activation, federated credential, ServiceAccount, label du pod) sont dans le lab.

3.3 Fermer la porte de l'IMDS#

Par défaut, tout pod peut joindre l'Instance Metadata Service (IMDS, 169.254.169.254) et donc obtenir un jeton des managed identities du node. L'IMDS restriction (préversion, --enable-imds-restriction, puis réimage) bloque les pods non hostNetwork et oblige à passer par Workload ID. Elle est incompatible avec plusieurs add-ons qui ont besoin de l'IMDS (Azure Policy, Container Insights, AGIC, Flux, application routing…) et avec les node pools Windows ; l'Azure Key Vault provider du Secrets Store CSI Driver, lui, fonctionne en mode Workload ID. À défaut, une NetworkPolicy de sortie qui exclut 169.254.169.254/32 dans chaque namespace applicatif est la recommandation historique.

Phrase d'entretien : « Workload ID, c'est la workload identity federation de GitHub Actions appliquée aux pods : le cluster signe un jeton, Entra fait confiance à cet issuer pour ce ServiceAccount précis, et aucun secret n'existe nulle part. »


4. Les secrets#

4.1 Le Secret Kubernetes, sans illusion#

  • Un manifeste Secret contient les valeurs en base64 : c'est un encodage, pas un chiffrement. Ne jamais le versionner.
  • Le Secret est stocké dans etcd ; il n'est livré qu'aux nodes qui exécutent un pod qui en a besoin, dans un tmpfs (jamais écrit sur disque), et supprimé du node avec le dernier pod qui l'utilise. Il est limité à son namespace.
  • Quiconque peut lire les Secrets d'un namespace ou lancer un pod qui les monte les obtient : c'est pourquoi RBAC Reader ne les voit pas, et pourquoi RBAC Writer est plus puissant qu'il n'en a l'air.

4.2 Chiffrer etcd avec KMS#

Azure Storage chiffre toujours les données au repos (AES 256). Le KMS provider ajoute une couche : les Secrets sont chiffrés avant d'être écrits dans etcd, par chiffrement d'enveloppe (une clé de données DEK chiffre le Secret, elle-même chiffrée par une clé KEK dans Key Vault).

KMS data encryption (nouvelle expérience) KMS etcd encryption (legacy)
Version Kubernetes 1.33 et plus, managed identity obligatoire Clusters plus anciens
Clés Platform-managed keys (rotation automatique) ou customer-managed keys avec rotation automatique Customer-managed key ; rotation = changer l'ID de clé, puis réécrire tous les Secrets
Coffre privé Exception de pare-feu trusted services (Private Endpoint pas encore pris en charge) Exige l'API Server VNet Integration
Retour arrière Impossible de désactiver une fois activé Désactivable (puis réécrire les Secrets)

Piège mortel : supprimer (purger) la clé ou le coffre rend les Secrets irrécupérables et peut imposer de recréer le cluster. Purge protection activée, et jamais d'expiration de clé « pour voir ».

4.3 Le Secrets Store CSI Driver et l'Azure Key Vault provider#

Secrets Store CSI Driver et Azure Key Vault provider

L'add-on azure-keyvault-secrets-provider installe le Secrets Store CSI Driver et l'Azure Key Vault provider (DaemonSets). Un pod monte un volume CSI qui pointe vers une SecretProviderClass ; secrets, clés et certificats arrivent en fichiers. L'add-on crée une identité azurekeyvaultsecretsprovider-… dans le node resource group (impossible d'empêcher sa création) ; mieux vaut s'authentifier avec Workload ID (usePodIdentity: "false" et clientID de l'identité dans la SecretProviderClass, voir le lab), qui donne une identité par application au lieu d'une identité partagée par tout le node pool.

Besoin Réglage À savoir
Autorotation az aks addon update … --addon azure-keyvault-secrets-provider --enable-secret-rotation --rotation-poll-interval 5m Sondage toutes les 2 minutes par défaut ; un montage en subPath ne reçoit pas la rotation ; une variable d'environnement exige un redémarrage du pod
Copie en Kubernetes Secret Champ secretObjects de la SecretProviderClass La copie n'existe que tant qu'au moins un pod monte le volume, et disparaît avec le dernier
Certificat objectType: secret Renvoie la clé privée et le certificat (chaîne complète) ; cert ne renvoie que le certificat, key la clé publique
Rôles Key Vault Secrets User (secrets), Key Vault Certificate User (clés et certificats) Sur le coffre, jamais plus large
Réseau Private Endpoint du coffre ; FQDN à autoriser si la sortie passe par Azure Firewall ; ports 9808 et 8095 si l'entrée est filtrée

Quoi choisir ?

Situation Choix Pourquoi
Application qu'on développe, SDK Azure disponible Workload ID + SDK directement vers Key Vault Pas de copie du secret, rotation lue à la source
Application qui attend un fichier (certificat TLS, fichier de configuration) Secrets Store CSI Driver en Workload ID Pas de modification du code
Application qui n'accepte qu'une variable d'environnement CSI + secretObjects, en connaissance de cause Le secret redevient un Kubernetes Secret ; prévoir un redémarrage à la rotation
Le service cible accepte l'authentification Entra Aucun secret : Workload ID vers le service Le meilleur secret est celui qui n'existe pas

5. Les images : une chaîne d'approvisionnement de confiance#

Chaîne de confiance d'une image

Étape Contrôle Détail
Construire Image de base minimale, analyse en CI, tri par risque (pas de blocage aveugle sur toute vulnérabilité) ACR Tasks peut reconstruire automatiquement les images quand leur image de base change
Prouver l'origine Signature Notation (Notary v2), clé dans Key Vault ou certificats éphémères d'Artifact Signing (avec horodatage) Une image signée et non modifiée vient d'une source de confiance
Stocker ACR privé, admin user désactivé, kubelet identity en AcrPull az aks update --attach-acr <id> ; registre en mode ABAC : attribuer à la main Container Registry Repository Reader, --attach-acr n'est pas pris en charge ; diagnostic : az aks check-acr
Analyser en continu Defender for Containers : analyse au push et périodique, dans le registre et à l'exécution Une vulnérabilité découverte après la construction remonte sans nouvelle build
Admettre Ratify + Azure Policy (Gatekeeper) refuse les images non signées ; Image Integrity d'AKS (préversion) Image Integrity : effet Audit uniquement, Notation seul vérificateur, 200 signatures au plus, pas pour la production ; Ratify open source avec effet Deny pour bloquer
Nettoyer Image Cleaner supprime des nodes les images inutilisées vulnérables Activé par défaut sur AKS Automatic

Piège : attribuer AcrPull à un groupe Entra dont la kubelet identity est membre peut prendre du temps à s'appliquer ; en automatisation, préférer une kubelet identity apportée, ajoutée au groupe avant la création du cluster.


6. L'admission : ce qui a le droit d'entrer dans le cluster#

Le chemin d'une requête dans l'API server

Chaque requête passe par authentification → autorisation → mutating admission → validating admission → écriture dans etcd. Les contrôles de sécurité des charges de travail se branchent sur l'admission.

6.1 Pod Security Admission (PSA)#

Natif Kubernetes, activé par défaut dans AKS, piloté par des labels de namespace, avec trois niveaux des Pod Security Standards : privileged (aucune restriction), baseline (bloque les escalades connues : hostNetwork, hostPID, conteneur privilégié, hostPath, ports hôte…), restricted (en plus : non-root, allowPrivilegeEscalation: false, abandon de toutes les capabilities sauf NET_BIND_SERVICE, seccomp RuntimeDefault ou Localhost, types de volumes limités).

kubectl label --overwrite ns commandes \
  pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/warn=restricted
kubectl label --overwrite ns --all pod-security.kubernetes.io/warn=baseline   # avertir partout d'abord

6.2 Azure Policy for AKS, Deployment Safeguards#

PSA Azure Policy for AKS Deployment Safeguards
Moteur Natif Add-on qui étend Gatekeeper v3 (OPA), admission webhook Initiative Azure Policy gérée par AKS (exige l'add-on Azure Policy)
Portée Un namespace Subscription, management group : toute la flotte, rapport de conformité central Un cluster, namespaces exclus possibles
Modes enforce, audit, warn Audit, Deny (et définitions personnalisées) Warn ou Enforce (tout ou rien) ; en Enforce, mute aussi
Exemples Interdire privileged Local accounts désactivés, registres autorisés, pas de latest Probes obligatoires, requests CPU/mémoire (mises par défaut à 500m et 2Gi si absentes), anti-affinité, pas de tag latest, pilotes CSI
Par défaut Niveau privileged sur AKS Standard Non installé sur AKS Standard AKS Automatic : Enforce + PSS Baseline, non débrayable en Warn ; AKS Standard : optionnel
az aks enable-addons --addons azure-policy -g rg-aks-prd -n aks-prd
az aks safeguards create -g rg-aks-prd -n aks-prd --level Warn            # d'abord avertir
az aks safeguards update -g rg-aks-prd -n aks-prd --level Enforce --pss-level Restricted --excluded-ns outils

Piège d'architecte : Gatekeeper fonctionne en « fail-open » : s'il ne répond pas, la validation est ignorée pour ne pas bloquer les déploiements. C'est un garde-fou de conformité, pas une frontière de sécurité absolue : il se complète par PSA, par le RBAC et par Defender.

6.3 Le securityContext d'un conteneur bien élevé#

spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile: { type: RuntimeDefault }
  containers:
  - name: api
    image: acrprd.azurecr.io/commandes/api:1.4.2   # tag explicite, jamais latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true                 # bonne pratique, hors exigences PSS
      capabilities: { drop: ["ALL"] }

Pour aller plus loin sur l'hôte : AppArmor, seccomp et les user namespaces limitent les mouvements latéraux en cas d'évasion de conteneur.


7. Durcir les nodes#

Sujet À retenir
Système Ubuntu ou Azure Linux optimisés ; Azure Container Linux (immuable, dérivé de Flatcar) en disponibilité générale depuis AKS 1.34. Azure Linux 2.0 : plus de correctifs depuis le 30/11/2025, images supprimées le 31/10/2026 (plus de mise à l'échelle) : migrer vers Azure Linux 3
Mises à jour Nodes créés avec les derniers correctifs ; le maintien à jour (node OS upgrade channel, images de nodes) est traité dans 05-exploitation-gitops
Réseau Nodes dans un subnet privé sans public IP ; ne pas modifier le Network Security Group de NIC géré par AKS, ajouter des NSG de subnet sans casser le trafic de gestion
Accès SSH désactivé ou par Entra ID (section 2.4) ; Node authorization active par défaut depuis 1.24 (le kubelet ne lit que ce qui concerne ses pods)
Démarrage Trusted Launch (Secure Boot, vTPM) sur les VM de génération 2
Isolement renforcé Isolated VM sizes (matériel dédié), Confidential Containers (préversion, mémoire chiffrée SEV-SNP), Pod Sandboxing (préversion, frontière entre conteneur et noyau partagé)
Disques Managed Disks chiffrés au repos par la plateforme

8. Defender for Containers#

Composant Ce qu'il fait Agent dans le cluster ?
Defender sensor DaemonSet eBPF (microsoft-defender-collector-ds, publisher-ds, sortie HTTPS 443) : télémétrie processus, réseau, événements pour la runtime threat detection Oui
Azure Policy for Kubernetes Évaluation de la posture, recommandations, application de règles Oui (add-on)
ACR integration Analyse des vulnérabilités au push et périodique Non
Agentless discovery for Kubernetes Inventaire et configuration des clusters par l'API, via le rôle Kubernetes Agentless Operator et un binding Trusted Access Non
Agentless scanning for machines Snapshots des disques des nodes pour les vulnérabilités et secrets Non
Microsoft Defender XDR integration Enquête et réponse unifiées Non

Options du sensor : Defender Security Gating (contrôle d'admission qui évalue les déploiements avant exécution) et Defender Runtime Anti Malware (détection, blocage possible). Exemples d'alertes : tableau de bord Kubernetes exposé, Service LoadBalancer exposant une charge sur Internet, création de rôles très privilégiés, montages sensibles. Les alertes ne portent que sur ce qui se passe après l'activation du plan. Le détail examen est dans SC-500, chapitre 09, section 2.


9. Isoler des équipes ou des clients#

Trois modèles d'isolation

Le choix entre namespace, node pool et cluster par locataire (coût, exploitation, cas d'usage) est comparé au chapitre 01, section 5.1. Côté sécurité, la boîte à outils d'un cluster partagé : namespaces, ResourceQuota et LimitRange (contre le voisin bruyant), NetworkPolicy (par défaut, tout pod parle à tout pod ; activer le network policy engine à la création, l'ajouter ensuite peut réimager les node pools), RBAC par namespace, PSA restricted, node pools dédiés :

az aks nodepool add -g rg-aks-prd --cluster-name aks-prd --name tenanta \
  --node-taints tenant=tenant-a:NoSchedule --labels tenant=tenant-a

Règle à citer : Kubernetes n'est pas sûr pour un multilocataire hostile. La frontière de sécurité est le cluster, pas le node ; seul un hyperviseur est digne de confiance. Des locataires qui ne se font pas confiance = des clusters séparés.


10. Erreurs fréquentes#

Erreur Conséquence Correction
Laisser les local accounts actifs Accès administrateur sans audit ni MFA --disable-local-accounts + built-in policy, certificate rotation
Donner Cluster Admin Role au pipeline Certificat administrateur dans la CI Cluster User Role + RBAC Writer sur le namespace
Croire que RBAC Writer ne lit pas les Secrets Escalade vers les droits des ServiceAccounts RBAC Reader pour la lecture seule, Kubernetes RBAC fin sinon
Data role sur la kubelet identity Tous les pods du node pool accèdent à la ressource Workload ID, une identité par application
Oublier le label azure.workload.identity/use Variables non injectées, pod en échec Label dans le modèle de pod
subject du federated credential faux Échec de l'échange de jeton system:serviceaccount:<namespace>:<serviceaccount> exact
Tout synchroniser en Kubernetes Secrets + variables d'environnement Secrets copiés partout, rotation sans effet Fichiers CSI ou SDK direct
Purger la clé KMS Secrets irrécupérables Purge protection, pas d'expiration de clé
--attach-acr sur un registre ABAC 401 Unauthorized au pull Container Registry Repository Reader attribué à la main
Modifier le NSG de NIC géré par AKS Trafic du cluster cassé NSG de subnet
Compter sur Gatekeeper comme barrière absolue Requêtes admises s'il ne répond pas Défense en profondeur

11. Lab : une application lit un secret Key Vault avec Workload ID (30 minutes)#

À faire dans une subscription de test (jamais en production) ; supprimer le resource group à la fin.

RG=rg-lab-aks-securite; LOC=francecentral; AKS=aks-lab; KV=kv-lab-$RANDOM; UAMI=id-lab-app
az group create -n $RG -l $LOC
# 1. Cluster : Entra ID + Entra ID authorization, local accounts coupés, OIDC issuer, Workload ID, Secrets Store CSI Driver
az aks create -g $RG -n $AKS --enable-aad --enable-azure-rbac --disable-local-accounts \
  --enable-oidc-issuer --enable-workload-identity --enable-addons azure-keyvault-secrets-provider --generate-ssh-keys
az role assignment create --role "Azure Kubernetes Service RBAC Cluster Admin" \
  --assignee $(az ad signed-in-user show --query id -o tsv) --scope $(az aks show -g $RG -n $AKS --query id -o tsv)
az aks get-credentials -g $RG -n $AKS
# 2. Coffre (modèle Azure RBAC par défaut) et secret
az keyvault create -n $KV -g $RG -l $LOC
az role assignment create --role "Key Vault Secrets Officer" --assignee $(az ad signed-in-user show --query id -o tsv) \
  --scope $(az keyvault show -n $KV --query id -o tsv)
az keyvault secret set --vault-name $KV --name message --value "bonjour depuis Key Vault"
# 3. Identité de l'application, droit de lecture, federated credential
az identity create -g $RG -n $UAMI
CLIENT_ID=$(az identity show -g $RG -n $UAMI --query clientId -o tsv)
az role assignment create --role "Key Vault Secrets User" --assignee $CLIENT_ID --scope $(az keyvault show -n $KV --query id -o tsv)
ISSUER=$(az aks show -g $RG -n $AKS --query "oidcIssuerProfile.issuerUrl" -o tsv)
az identity federated-credential create --name fic-lab --identity-name $UAMI -g $RG \
  --issuer "$ISSUER" --subject system:serviceaccount:lab:sa-lab
kubectl create namespace lab
kubectl label ns lab pod-security.kubernetes.io/enforce=baseline
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata: { name: sa-lab, namespace: lab, annotations: { azure.workload.identity/client-id: "$CLIENT_ID" } }
---
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata: { name: kv-lab, namespace: lab }
spec:
  provider: azure
  parameters:
    usePodIdentity: "false"
    clientID: "$CLIENT_ID"
    keyvaultName: $KV
    tenantId: "$(az account show --query tenantId -o tsv)"
    objects: |
      array:
        - |
          objectName: message
          objectType: secret
---
apiVersion: v1
kind: Pod
metadata: { name: lecteur, namespace: lab, labels: { azure.workload.identity/use: "true" } }
spec:
  serviceAccountName: sa-lab
  containers:
  - name: busybox
    image: registry.k8s.io/e2e-test-images/busybox:1.29-4
    command: ["/bin/sleep", "10000"]
    volumeMounts: [{ name: secrets, mountPath: /mnt/secrets-store, readOnly: true }]
  volumes:
  - name: secrets
    csi: { driver: secrets-store.csi.k8s.io, readOnly: true, volumeAttributes: { secretProviderClass: kv-lab } }
EOF
kubectl exec -n lab lecteur -- cat /mnt/secrets-store/message      # → bonjour depuis Key Vault
kubectl exec -n lab lecteur -- env | grep AZURE_                    # variables injectées par le webhook
az group delete -n $RG --yes --no-wait                              # nettoyage

Variantes à tester : retirer le label du pod (échec du montage), changer le nom du ServiceAccount (échec de l'échange), passer le namespace en restricted (le pod busybox est refusé : lire le message et corriger le securityContext).

Le même socle en Terraform (azurerm_kubernetes_cluster, provider 5.x, arguments vérifiés dans le registre) : local_account_disabled = true (exige l'intégration Entra ID), oidc_issuer_enabled (vrai par défaut), workload_identity_enabled = true, bloc azure_active_directory_role_based_access_control { azure_rbac_enabled = true }, azure_policy_enabled, image_cleaner_enabled, bloc key_vault_secrets_provider { secret_rotation_enabled = true }, et bloc identity { type = "UserAssigned" } pour apporter la control plane identity.


12. Questions d'entretien#

1. Quelles identités un cluster AKS utilise-t-il, et pourquoi les séparer ?

Quatre : les utilisateurs et pipelines qui appellent l'API (Entra ID), la control plane identity qui gère Load Balancer, public IP et disques (Contributor sur le node resource group), la kubelet identity qui tire les images (AcrPull), et une identité Workload ID par application. Les séparer, c'est le moindre privilège : un rôle donné au kubelet profite à tous les pods du node pool, un rôle donné à une identité Workload ID ne profite qu'aux pods de ce ServiceAccount.

2. Pourquoi désactiver les local accounts, et quel est le piège ?

Le certificat administrateur contourne Entra ID : pas de MFA, pas de Conditional Access, pas de PIM, pas d'audit nominatif. Le piège : sur un cluster existant, il faut aussi faire une certificate rotation, sinon les certificats déjà téléchargés restent valides. Et s'assurer d'abord qu'un groupe Entra a bien un accès administrateur, pour ne pas se fermer la porte.

3. Azure RBAC for Kubernetes ou Kubernetes RBAC ?

Les deux. Azure RBAC pour les humains et les pipelines : une role assignment au niveau d'un resource group régit tous les clusters, avec PIM et l'Azure Activity Log. Kubernetes RBAC pour les ServiceAccounts et les droits fins versionnés en GitOps. Attention à RBAC Writer : il lit les Secrets et peut lancer un pod sous n'importe quel ServiceAccount du namespace.

4. Explique comment un pod lit un secret Key Vault sans aucun secret.

Le cluster est OIDC issuer. Une user-assigned managed identity porte un federated credential qui fait confiance à cet issuer pour system:serviceaccount:<namespace>:<serviceaccount>. Le mutating webhook injecte dans les pods labellisés le projected token et les variables ; le SDK échange ce jeton contre un jeton Entra, qui porte les rôles de l'identité (Key Vault Secrets User).

5. Les Secrets Kubernetes sont-ils chiffrés ?

En base64 dans les manifestes, ce n'est pas du chiffrement. Au repos, Azure Storage chiffre toujours ; KMS ajoute un chiffrement d'enveloppe avant l'écriture dans etcd, avec une platform-managed key ou une customer-managed key. Mais le vrai sujet est de ne pas avoir de Secret : Workload ID vers le service, ou Key Vault monté par le Secrets Store CSI Driver.

6. Secrets Store CSI Driver ou SDK avec Workload ID ?

SDK direct quand on maîtrise le code : pas de copie, la rotation est lue à la source. CSI quand l'application attend un fichier (certificat TLS) ou qu'on ne peut pas la modifier. Éviter la synchronisation en Secret + variable d'environnement, qui recopie le secret et impose un redémarrage à chaque rotation.

7. Comment garantir que seules des images de confiance tournent ?

ACR privé avec AcrPull pour le kubelet, policy « allowed registries », signature Notation en CI avec la clé dans Key Vault, vérification à l'admission par Ratify et Azure Policy (Image Integrity est en préversion et seulement en Audit), analyse continue de Defender for Containers dans le registre et à l'exécution, et Image Cleaner pour retirer les images vulnérables des nodes.

8. PSA, Azure Policy, Deployment Safeguards : à quoi sert chacun ?

PSA : natif, par namespace, trois niveaux. Azure Policy for AKS : Gatekeeper piloté par Azure, la même règle sur toute la flotte avec un rapport de conformité. Deployment Safeguards : un paquet de bonnes pratiques géré par AKS, qui avertit ou impose et mute (requests par défaut, anti-affinité). Et rappeler que Gatekeeper est fail-open.

9. Un namespace par client suffit-il ?

Pour des équipes internes de confiance, oui, avec ResourceQuota, NetworkPolicy, RBAC et PSA. Pour des clients qui ne se font pas confiance, non : Microsoft le dit, Kubernetes n'est pas sûr pour un multilocataire hostile, la frontière est le cluster. Entre les deux, un node pool par locataire isole le calcul mais partage le control plane.

10. Comment donnes-tu le minimum de droits à un pipeline de déploiement ?

Workload identity federation côté pipeline (pas de secret), Cluster User Role pour le kubeconfig, RBAC Writer sur le seul namespace cible, jamais d'identifiants administrateur. Réseau : si l'API server est privé, un self-hosted agent ou Managed DevOps Pools dans un réseau qui l'atteint ; s'il est public, API server authorized IP ranges limitées à la sortie de l'agent.


13. Fiche à retenir#

  • Cinq scénarios : authentication, authorization, permission sur la ressource AKS, cluster identity, workload identity.
  • Control plane identity : Contributor sur le node resource group par défaut ; kubelet identity : aucun droit, AcrPull à donner ; user-assigned si réseau apporté.
  • Entra ID + local accounts désactivés (+ certificate rotation sur un cluster existant) ; built-in policy pour la flotte.
  • Cluster User Role (kubeconfig) ≠ Cluster Admin Role (certificat administrateur).
  • Microsoft Entra ID authorization par défaut (une role assignment, plusieurs clusters, PIM) ; Kubernetes RBAC pour le fin ; RBAC Writer lit les Secrets.
  • Conditional Access sur « Azure Kubernetes Service Microsoft Entra Server » ; kubelogin, pas de device code avec Conditional Access.
  • Workload ID : OIDC issuer, federated credential system:serviceaccount:ns:sa, annotation client-id, label use: "true", 20 federated credentials par identité.
  • Pod-managed identity dépréciée depuis 2022 ; IMDS restriction (préversion) pour couper l'accès aux jetons du node.
  • Secret Kubernetes = base64 ; KMS = enveloppe DEK/KEK (KMS data encryption 1.33+, non désactivable) ; purger la clé = tout perdre.
  • Secrets Store CSI Driver : fichiers, autorotation 2 min par défaut, pas de rotation en subPath, secretObjects vit avec les pods.
  • Images : ACR privé, Notation, Ratify, Image Integrity en préversion (Audit), analyse continue Defender for Containers, Image Cleaner.
  • Admission : authentifier → autoriser → mutating → validating → etcd ; PSA (namespace), Azure Policy (flotte), Safeguards (cluster) ; Gatekeeper fail-open.
  • Nodes : sans public IP, SSH désactivé ou Entra ID, Azure Linux 2.0 fini (images retirées le 31/10/2026), Trusted Launch.
  • Defender for Containers : Defender sensor eBPF + Azure Policy dans le cluster, le reste agentless.
  • Multilocataire hostile = clusters séparés.

Références#

Toutes lues le 21/10/2026 sur Microsoft Learn :

Sur cette page
Échap

Tape au moins 2 lettres. Plusieurs mots : tous doivent apparaître.