La gestion des identités dans Azure Kubernetes Service (AKS)

La gestion des identités constitue un aspect majeur de la sécurité d’une entreprise. L’attribution d’une identité numérique à chaque utilisateur, la détermination des accès autorisés (ou non) pour chacun ou encore le suivi des authentifications font partie des éléments incontournables à mettre en place.
Dans le cadre du Mois de la Sécurité dans le Cloud, nous vous proposons aujourd’hui de faire un point sur les questions relatives à l’Identity & Access Management (IAM) dans Azure Kubernetes Service (AKS).
AKS a en effet beaucoup évolué depuis sa mise en route et une clarification de l’état actuel apparaît comme une bonne idée.
Revue rapide de Kubernetes dans un contexte Azure
Dans cette première partie, nous allons revoir de haut l’architecture de Kubernetes et quelles parties sont concernées par les sujets IAM.
D’une manière très simplifiée, Kubernetes est composé :
- du control plane, qui, comme son nom l’indique, contrôle tout,
- du worker plane, contrôlé par le control plane, qui héberge les applications à travers différents objets de l’API Kubernetes.
Maintenant que nous avons établi cette vision, nous pourrions nous demander lesquelles de ces parties sont concernées par des sujets IAM. Et pour faire simple, la réponse est : toutes ces parties !
Parce que le control plane est tellement important dans la préservation de l’intégrité de Kubernetes, il existe en effet beaucoup de sujets en rapport avec l’IAM dans le control plane AKS. Nous commencerons par ces sujets dans la prochaine partie.
Il y a également des éléments à bien appréhender relatifs au worker plane et enfin, non moins importants, les besoins d’IAM relatifs aux applications vivant dans Kubernetes. Ces sujets constitueront donc nos 3e et 4e parties. Toutefois, nous resterons très « High Level » pour cette 4e section, parce qu’elle est assez complexe et mériterait probablement un article à part entière.
Je vous propose à présent d’examiner le mapping de ces briques Kubernetes dans Azure.
AKS est un service PaaS, et en tant que tel, largement géré par la plateforme Azure.
Pourtant, plusieurs de ses composants sont plutôt catégorisés usuellement dans la catégorie IaaS :
- Un Virtual Network et un Subnet (que nous créons avant d’ailleurs)
- Des Virtual Machine Scale Sets
- Un Network Security Group
- Un Load Balancer
Ce sont les ressources Azure que nous avons après le Build. Avant le Build, nous avons besoin des ressources suivantes :
- Un groupe de ressources, bien évidemment
- Une clé SSH
- Un groupe Azure Active Directory (AAD) : nous aborderons le sujet plus en détail dans la partie suivante
- Des identités managées, de type System Assigned ou User Assigned (même commentaire que pour le groupe AAD).
IAM dans le control plane
Abordons à présent le cœur du sujet ! Cette partie est probablement la plus longue et la plus riche en termes de concepts, puisque, comme nous l’avons dit, le control plane contrôle tout.
Authentification avec l’intégration Azure Active Directory
Nous avons mentionné le besoin d’un groupe Azure Active Directory (AAD). Ce prérequis est directement en rapport avec l’authentification, spécifiquement des admins AKS dans le plan Kubernetes, et l’intégration d’AKS avec AAD.
Pour simplifier, par cette intégration, nous n’avons pas besoin d’utiliser les commandes kubectl en rapport avec les CSR parce que le fournisseur d’identité dans le plan Kubernetes est le même que dans Azure, à savoir Azure Active Directory.
Cette intégration a évolué pour le meilleur ces dernières années, en devenant beaucoup plus simple à mettre en œuvre et à maintenir. On parle d’ailleurs à présent de « AKS-managed Azure AD » en opposition à « Azure AD Integration (legacy) ».
Cette intégration legacy s’appuie sur l’usage de deux applications registrations dans Azure AD, l’une désignée comme l’application serveur, et l’autre comme l’application cliente.
Toujours d’un point de vue simplifié, l’application serveur a accès au tenant Azure AD, afin de récupérer des informations sur les utilisateurs qui tentent d’accéder au cluster AKS, pour valider leurs accès.
L’application cliente est celle qui est atteinte par les utilisateurs s’authentifiant sur AKS et interagit sur l’application serveur, évitant une interaction directe des utilisateurs.
Dans le nouveau modèle d’intégration, l’expérience utilisateur n’est guère changée, et le mécanisme est vraisemblablement le même, mais les administrateurs qui s’occupent de cette configuration voient leurs actions simplifiées en se contentant de spécifier au Build le fameux groupe AAD dont nous parlions précédemment. Ce groupe Azure AD se voit attribué des accès cluster admin sur le cluster dès sa création.
Du point de vue de la configuration, nous retrouvons l’object id du groupe, ainsi que le tenant id Azure AD dans la configuration aadProfile :
Ces paramètres sont configurables simplement avec un outil capable d’interagir avec l’API Azure telle que Azure CLI ou Terraform par exemple :
En tant que membre de ce groupe admin, on peut facilement s’authentifier sur le cluster :
Si l’on cherche un peu dans le cluster AKS, dans le plan Kubernetes, on peut trouver un cluster role binding au nom évocateur :
Et si l’on observe cet objet de près :
On retrouve dans la section subject du cluster role binding l’object id du groupe AAD.
Passons maintenant à des aspects plus orientés utilisateurs qu’administrateurs.
Les autorisations pour les utilisateurs non admin
RBAC depuis le plan de contrôle Azure
Revenons un peu en arrière.
Dans la section précédente, nous avons pu voir qu’un utilisateur, membre du groupe AAD assigné au cluster, peut récupérer un accès cluster admin dans Kubernetes.
Cela étant, nous avons pris un petit raccourci.
Pour commencer, insistons sur ce fait : le cluster AKS est un objet qui vit dans le control plane Azure. En tant que tel, il est donc sujet aux autorisations dans Azure par l’usage de rôles Azure. Parmi les rôles built-in, deux sont importants à noter pour le moment :
- Le rôle Azure Kubernetes Service Cluster User
- Le rôle Azure Kubernetes Service Cluster Admin role
La partie importante, spécifiquement, pour le premier rôle est l’action :
Microsoft.ContainerService/managedClusters/listClusterUserCredential/action.
A travers cette action, un utilisateur peur exécuter la commande az aks get-credentials qui, comme son nom l’indique, permet de récupérer localement le fichier config utilisé pour l’authentification dans Kubernetes.
Pour un utilisateur non admin, le workflow de log on ressemblerait à ceci :
On note le message d’erreur après l’authentification Azure AD, qui est ce à quoi nous nous attendons, puisque nous n’avons qu’un droit pour récupérer les credentials Kubernetes et rien d’autre.
Pouvons-nous faire davantage uniquement depuis le control plane Azure ?
Jetons un œil sur la configuration RBAC de notre cluster AKS. Nous pouvons voir qu’il y a plusieurs options :
Ce paramètre est d’ailleurs également accessible par az cli :
az aks show -n aks-1 -g rsg-aksIdentityState1 | jq .aadProfile.enableAzureRbac true
Lorsque nous avons un résultat sur true, ceci indique que nous pouvons – dans la pratique – utiliser un rôle Azure pour gérer l’accès dans Kubernetes. Il faut donc trouver un rôle qui correspond à notre besoin parmi les rôles built-in d’Azure, comme le rôle Azure Kubernetes Service RBAC Reader :
Ce rôle, qui présente des dataActions, permet un certain nombre d’actions dans Kubernetes.
En donnant ce rôle à un utilisateur sur un cluster configuré avec RBAC Azure, celui-ci peut réaliser les actions incluses dans le rôle sur le cluster :
En revanche, ce même rôle sur un cluster sans RBAC Azure ne permettra pas d’accès au cluster :
Malgré un niveau d’accès similaire dans le plan Azure, parce que le cluster n’accepte que le RBAC natif de Kubernetes, il n’est pas possible pour l’utilisateur d’accéder aux objets dans le plan Kubernetes.
Pour permettre des accès, nous avons dans ce cas besoin de droits donnés par un role binding dans Kubernetes.
RBAC natif dans le plan Kubernetes
Illustrons ce propos avec un utilisateur que nous appellerons Leonard.
Leonard dispose uniquement du rôle Azure Kubernetes Service Cluster User sur les clusters aks-1 et aks-2. Si nous lui attribuons le cluster role admin sur le cluster aks-2 dans le namespace default:
Leonard est en mesure de réaliser des actions sur le scope default namespace du cluster :
Sur le cluster aks-1, sans aucun role binding additionnel :
Le maillon faible de l’héritage et comment le gérer
Revenons sur le rôle Azure Kubernetes Service Cluster Admin. Ce rôle contient l’action particulière suivante :
Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action
Dans ce rôle seul, cela ne constitue pas à proprement parler un problème. Néanmoins, si nous considérons le rôle Contributor :
Il faut bien comprendre que l’action « * » inclut toutes les actions non spécifiées dans la section notActions. Dans le cas de Contributor, l’action
Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action
n’est pas dans cette liste de notActions et donc par défaut incluse dans les actions disponibles du rôle.
De fait, un utilisateur qui serait Contributor à un niveau plus élevé dans la hiérarchie des objets Azure pourrait donc avoir cette action sur un cluster AKS. Ce qui permet d’utiliser la commande az aks get-credentials avec le switch –admin.
Illustrons ce propos avec une utilisatrice que nous appellerons Penny :
Penny est Azure Kubernetes Service Cluster User mais également Contributor, par héritage de la souscription :
Elle est donc en mesure d’utiliser le switch –admin :
C’est un problème, causé par l’héritage, qui permet d’utiliser le compte local de Kubernetes pour s’attribuer des droits élevés. Heureusement, il est possible de désactiver ce compte admin local comme on peut le voir sur le portail :
En essayant la même commande que précédemment sur ce cluster, nous obtenons le résultat ci-dessous :
Ainsi le problème d’héritage peut être compensé, ce qui nous permet de conclure les sujets RBAC du control plane et de passer aux aspects Identités managées.
Les identités managées dans le control plane
Le point important est qu’un cluster AKS est en mesure d’utiliser des identités Azure managées, afin d’accéder sans gestion de mot de passe à d’autres services Azure, comme, par exemple, un Azure Container Registry.
Sans configuration spécifique, l’identité managée du control plane est une identité de type system assigned qui est créé au moment du Build du cluster. Nous avons accès à cette information à travers Azure CLI :
Si cela suffit dans la plupart des cas, il peut arriver que l’on souhaite que le cluster AKS ait déjà des accès au moment de sa création. Un cas d’usage de besoin d’accès avant le Build est dans l’usage d’un cluster privé avec une zone DNS déjà existante. Dans ce cas, AKS requiert un droit d’écriture sur la zone DNS afin de pouvoir enregistrer l’adresse IP du private Endpoint. Plus d’informations sur le sujet dans cet autre article ici.
IAM dans le worker plane
Le worker plane est moins riche en sujets IAM que le control plane. Des managed Identities lui sont associées mais leur cycle de vie est entièrement géré par le control plane.
De fait, on retrouve toutes ces identités dans le resource group créé automatiquement à la création de l’instance AKS.
On peut voir qu’elles sont associées avec le(s) VMSS qui agissent en tant que node pools.
A propos de ces identités, on peut déterminer quels sont leurs usages en observant leur nom.
Par exemple, l’identité utilisée par Kubelet se termine systématiquement par le suffix agent-pool. Une ligne de commande Azure CLI permet d’ailleurs de vérifier la concordance de cette identité avec la configuration AKS :
De la même manière que pour le control plane, si l’on ne le spécifie pas, Kubelet sera associé à une identité de type System Assigned.
Dans notre exemple, nous avons une autre identité comportant la mention policy et une autre qui fait clairement référence à l’Azure Key Vault Secret Store provider. Encore une fois, on peut valider que la configuration AKS associe bien ces identités avec ces deux add-ons qui sont activés sur le cluster :
Dans certains cas, récupérer les informations sur les identités des add-ons permet de réaliser certaines configurations spécifiques entre AKS et le plan Azure. Par exemple pour le Key Vault Secret store, nous utilisons le client id de la managed identity associé à l’add-on dans le manifest yaml de l’objet secret store de la manière ci-dessous :
On note le paramètre useVMManagedIdentity configuré en true.
On peut trouver des détails sur ce sujet Secret Store sur la documentation Azure ou sur cet autre article de blog.
Gestion des identités pour les applications
Une difficulté pour les applications dans AKS est le manque de compatibilité des managed Identities Azure avec les containers vivant dans les Pods AKS. En effet, puisque par nature un conteneur isole un runtime du reste du système, il devient difficile de s’appuyer sur une identité associée à ce même système, par design non accessible depuis le runtime dans le container.
Ce manque a bien entendu été identifié par les équipes AKS et on a pu voir le développement de solutions pour porter les managed identities dans le plan Kubernetes. Pour les nommer, nous avons :
- Pod Identity v1
- Workload Identity (ou Pod Identity v2)
Commençons par la v1, même si, comme son numéro de version le laisse soupçonner, celle-ci est en phase d’être dépréciée au profit de la v2.
Pod Identity
L’objectif de Pod Identity est de porter la fonctionnalité des managed Identities dans les pods AKS.
L’architecture, explicitée dans la documentation du projet, s’appuie sur des Custom Resource Definitions ainsi qu’un couple Kubernetes Deployment et DaemonSet qui de manière simplifiée gèrent les authentifications des briques applicatives.
Source: Documentation Azure GitHub
Le projet a vu son propre AKS add-on ajouté dans les solutions preview d’AKS et il est également utilisé par des produits de l’écosystème Kubernetes :
- Velero Backup
- Azure Key Vault CSI Secret store
- Application Gateway as Ingress Controller
- Azure Service Operator
Dans un souci de continuité et de simplicité, nous allons reprendre l’exemple de Key Vault CSI Secret Store. Dans le cas où l’on utiliserait Pod Identity pour un secret store dans Kubernetes, nous utiliserions cette fois ci le paramètre usePodIdentity avec la valeur true, et dans ce cas le paramètre userAssigned IdentityId serait configuré avec le client id de l’identité managée Azure. Mais en supplément, cette identité managée se verrait attribuer un équivalent Kubernetes, appelé PodIdentity, et un objet podIdentityBinding serait spécifié à travers un label sur les pods devant lire dans ce secret store. En parallèle, l’identité managée devrait bien entendu avoir des accès sur l’instance de Key Vault dans le plan Azure.
Pour plus de détails, je vous invite à consulter la documentation Azure ou cet article de blog “AKS: Use AAD identity for pods and make your SecOps happy“.
Bien que la solution fournisse les fonctionnalités attendues, un certain nombre de limitations ont orienté un changement de stratégie vers un nouveau projet appelé Workload Identity.
Workload Identity
Workload Identity est le dernier projet en date pour mettre en œuvre l’authentification Azure AD dans des applications hébergées sur Kubernetes. Bien qu’on lui donne le nom de Pod Identity v2, son architecture est radicalement différente de celle de Pod Identity v1. En lieu et place de CRDs et d’interception du trafic IMDS, on utilise à la place des service accounts Kubernetes et la fonctionnalité Workload Identity Federation. L’excellent article de Geert Baeke explore Workload Identity en profondeur.
Bien que non supportées dans les premières version, les Managed Identities sont à présent bien supportées pour les workloads sur Azure. De fait, la solution fait maintenant parfaitement sens tant pour gérer des access applicatifs à Azure depuis AKS ou un autre Kubernetes Cloud-managed ou On-Premise.
Bien qu’encore relativement légères, l’empreinte de Workload Identity dans le scope Kubernetes s’étend avec à présent Asure Service Operator en plus de Key Vault CSI Secret Store.
L’essentiel à retenir sur l’IAM dans AKS
Bien que l’on retrouve des sujets IAM à littéralement tous les étages de AKS / Kubernetes, de par l’intégration Azure AD, on est en mesure de gérer les accès et interactions d’AKS en nous appuyant fortement sur AAD.
Quelques recommandations dans la logique des sujets discutés :
- Pour le control plane:
- Utiliser l’authentification AAD. La mise en œuvre est simple et nous permet de nous appuyer sur les options de sécurité de l’IdP de Microsoft ;
- Désactiver le local admin account pour empêcher les élévations de privilèges non contrôlés ;
- Préférer l’utilisation du rôle Azure Kubernetes Service User et de rôles natifs pour plus de granularité sur les accès aux objets Kubernetes ;
- Utiliser de préférence une identité managée de type User Assigned.
- Pour le worker plane:
- Identifier les identités managées par Kubelet et les add-ons pour être granulaire sur les autorisations associées à chacune ;
- Additionnellement, configurer des Activity Logs Alerts sur ces identités.
- Pour les applications:
- Adopter Workload Identity pour les nouveaux développements ;
- Si possible, utiliser workload identity pour les outils tiers.
Vous souhaitez en savoir plus sur la sécurité dans le Cloud ? Retrouvez tous les autres articles de cette série :
- La cybersécurité : un enjeu stratégique pour les entreprises
- Les enjeux de la cybersécurité face à l’évolution des systèmes d’information
- Déléguer la gestion des utilisateurs et des équipements dans Azure AD et Intune
- Azure Sphere : la Cybersécurité pour quoi, qui, quand et comment ?
- Pourquoi se former sur la cybersécurité ?
- Concilier Agilité et Sécurité : le manifeste Agile et l’OWASP à notre secours !
- La sécurité dans GitHub