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.

| 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#

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-idsgardent, 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 nodecontinue de fonctionner), Microsoft Entra ID based SSH (préversion : rôlesVirtual Machine User LoginouVirtual 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#

3.1 Le mécanisme#
- Le cluster devient OIDC issuer : il publie
{IssuerURL}/.well-known/openid-configurationet{IssuerURL}/openid/v1/jwks(ses clés publiques). - 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>, audienceapi://AzureADTokenExchange. - Le ServiceAccount Kubernetes porte l'annotation
azure.workload.identity/client-id. - Le pod porte le label
azure.workload.identity/use: "true": seuls ces pods sont modifiés par le mutating admission webhook, qui injecteAZURE_CLIENT_ID,AZURE_TENANT_ID,AZURE_FEDERATED_TOKEN_FILEet le volume du projected service account token (renouvelé par Kubernetes avant expiration). - Le SDK (
DefaultAzureCredentialouWorkloadIdentityCredentiald'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
Secretcontient 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 Readerne les voit pas, et pourquoiRBAC Writerest 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#

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#

| É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#

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#

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
AcrPullpour 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 Writersur 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 Writerlit 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, annotationclient-id, labeluse: "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,secretObjectsvit 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 :
- Options d'accès et d'identité pour AKS
- Vue d'ensemble des managed identities dans AKS
- Concepts d'authentification de cluster
- Concepts d'autorisation de cluster
- Microsoft Entra ID authorization pour l'API Kubernetes
- Gérer les local accounts
- Contrôler l'accès au fichier kubeconfig
- Conditional Access pour le cluster et les nœuds
- PIM pour l'accès aux clusters et aux nœuds AKS
- kubelogin dans AKS
- Gérer l'accès SSH aux nœuds
- Utiliser Microsoft Entra Workload ID avec AKS
- IMDS restriction (préversion)
- Concepts de chiffrement des données au repos (KMS)
- KMS etcd encryption (legacy)
- Azure Key Vault provider for Secrets Store CSI Driver
- Identité d'accès de l'Azure Key Vault provider
- Options de configuration du Secrets Store CSI Driver (rotation, synchronisation)
- S'authentifier auprès d'ACR depuis AKS
- Image Integrity (préversion)
- Vérifier les signatures d'images avec Ratify et Azure Policy
- Utiliser Pod Security Admission
- Deployment Safeguards
- Concepts de sécurité pour les applications et les clusters
- Bonnes pratiques de sécurité et de mise à niveau du cluster
- Sécuriser l'accès des conteneurs aux ressources
- Defender for Containers architecture
- Concepts de multilocation dans AKS
- Bonnes pratiques d'isolation des clusters
- Azure Policy built-in definitions pour AKS
- Kubernetes : Pod Security Standards et RBAC
- Registre Terraform : azurerm_kubernetes_cluster