Ce document décrit les bonnes pratiques à suivre pour planifier vos règles de contrôle des accès basé sur les rôles (RBAC). Pour savoir comment mettre en œuvre le contrôle RBAC dans Google Kubernetes Engine (GKE), consultez la page Configurer le contrôle des accès basé sur les rôles.
RBAC est une fonctionnalité de sécurité de base de Kubernetes qui vous permet de créer des autorisations précises pour gérer les actions que les utilisateurs et les charges de travail peuvent effectuer sur les ressources de vos clusters. En tant qu'administrateur de plate-forme, vous créez des rôles RBAC et associez ces rôles à des sujets, qui sont des utilisateurs authentifiés, tels que des comptes de service ou des groupes Google Groupes.
Avant de commencer
Avant de lire ce document, assurez-vous de connaître les concepts suivants :
pour obtenir un récapitulatif des conseils figurant dans ce document, consultez la section Checklist.
Fonctionnement du contrôle RBAC
RBAC accepte les types de rôles et de liaisons suivants :
- ClusterRole: ensemble d'autorisations pouvant être appliquées à n'importe quel espace de noms ou à l'ensemble du cluster.
- Rôle: ensemble d'autorisations limitées à un seul espace de noms.
- ClusterRoleBinding : attribuez un rôle
ClusterRole
à un utilisateur ou à un groupe pour tous les espaces de noms du cluster. - RoleBinding : attribuez un rôle
Role
ouClusterRole
à un utilisateur ou à un groupe au sein d'un espace de noms spécifique.
Vous définissez des autorisations sous forme de rules
, définies dans un Role
ou un ClusterRole
. Chaque champ rules
d'un rôle se compose d'un groupe d'API, de ressources d'API au sein de ce groupe d'API et des verbes (actions) autorisés sur ces ressources. Vous pouvez également cantonner les verbes aux instances nommées des ressources d'API à l'aide du champ resourceNames
. Pour obtenir un exemple, consultez la section Restreindre l'accès à des instances de ressources spécifiques.
Après avoir défini un rôle, vous devez utiliser une liaison RoleBinding
ou ClusterRoleBinding
pour lier le rôle à un sujet. Choisissez le type de liaison selon que vous souhaitez accorder des autorisations dans un seul ou bien plusieurs espaces de noms.
Conception de rôle RBAC
Utiliser le principe du moindre privilège
Lorsque vous attribuez des autorisations dans un rôle RBAC, appliquez le principe du moindre privilège en n'accordant que les autorisations minimales nécessaires pour effectuer une tâche. Le principe du moindre privilège réduit le risque d'élévation des privilèges si votre cluster est compromis, et réduit la probabilité d'un incident de sécurité en cas d'accès excessifs.
Lorsque vous concevez vos rôles, gardez en tête les principaux risques liés à l'élévation des privilèges, tels que les verbes escalate
ou bind
, l'accès create
pour les PersistentVolumes ou l'accès create
pour les requêtes de signature de certificat. Pour obtenir la liste des risques, consultez la page Kubernetes RBAC – Risques liés à l'élévation des privilèges.
Éviter les rôles et les groupes par défaut
Kubernetes crée un ensemble d'objets ClusterRole et ClusterRoleBinding par défaut que vous pouvez utiliser pour la découverte des API et pour activer la fonctionnalité de composants gérés. Les autorisations accordées par ces rôles par défaut peuvent être étendues en fonction du rôle. Kubernetes dispose également d'un ensemble d'utilisateurs et de groupes d'utilisateurs par défaut, identifiés par le préfixe system:
.
Par défaut, Kubernetes et GKE associent automatiquement ces rôles aux groupes par défaut et à divers sujets. Pour obtenir la liste complète des rôles et des liaisons par défaut créés par Kubernetes, consultez la page Rôles et liaisons de rôles par défaut.
Le tableau suivant décrit certains rôles, utilisateurs et groupes par défaut. Nous recommandons d'éviter d'interagir avec ces rôles, utilisateurs et groupes, sauf si vous les avez évalués avec soin, car interagir avec ces ressources peut avoir des conséquences inattendues sur la stratégie de sécurité de votre cluster.
Nom | Type | Description |
---|---|---|
cluster-admin |
ClusterRole | Accorde à un sujet l'autorisation d'effectuer n'importe quelle opération sur n'importe quelle ressource du cluster. |
system:anonymous |
Utilisateur | Kubernetes attribue cet utilisateur aux requêtes de serveur d'API pour lesquelles aucune information d'authentification n'est fournie. En associant un rôle à cet utilisateur, vous attribuez à tout utilisateur non authentifié les autorisations accordées par ce rôle. |
system:unauthenticated |
Groupe | Kubernetes attribue ce groupe aux requêtes de serveur d'API pour lesquelles aucune information d'authentification n'est fournie. En associant un rôle à ce groupe, vous attribuez à tout utilisateur non authentifié les autorisations accordées par ce rôle. |
system:authenticated |
Groupe | GKE attribue ce groupe aux requêtes de serveur d'API effectuées par tout utilisateur connecté avec un compte Google, y compris tous les comptes Gmail. Dans la pratique, ce n'est pas très différent de En associant un rôle à ce groupe, vous attribuez à tout utilisateur disposant d'un compte Google, y compris de tous les comptes Gmail, les autorisations accordées par ce rôle. |
system:masters |
Groupe | Par défaut, Kubernetes attribue le ClusterRole L'ajout de vos propres sujets à ce groupe leur donne accès à toute opération sur n'importe quelle ressource de votre cluster. |
Si possible, évitez de créer des liaisons qui impliquent les utilisateurs, rôles et groupes par défaut. Cela peut avoir des conséquences inattendues sur la stratégie de sécurité de votre cluster. Exemple :
- En associant le ClusterRole
cluster-admin
par défaut au groupesystem:unauthenticated
, vous permettez à tous les utilisateurs non authentifiés d'accéder à toutes les ressources du cluster (y compris les secrets). Ces liaisons à privilèges élevés sont activement ciblées par des attaques telles que les campagnes massives de logiciels malveillants. - En associant un rôle personnalisé au groupe
system:unauthenticated
, vous attribuez aux utilisateurs non authentifiés les autorisations accordées par ce rôle.
Dans la mesure du possible, respectez les consignes suivantes :
- N'ajoutez pas vos propres sujets au groupe
system:masters
. - N'associez pas le groupe
system:unauthenticated
à des rôles RBAC. - N'associez pas le groupe
system:authenticated
à des rôles RBAC. - N'associez pas l'utilisateur
system:anonymous
à des rôles RBAC. - N'associez pas le ClusterRole
cluster-admin
à vos propres sujets ou à l'un des utilisateurs et groupes par défaut. Si votre application nécessite de nombreuses autorisations, déterminez les autorisations exactes requises et créez un rôle spécifique à cet effet. - Évaluez les autorisations accordées par d'autres rôles par défaut avant de lier des sujets.
- Évaluez les rôles associés aux groupes par défaut avant de modifier les membres de ces groupes.
Détecter et empêcher l'utilisation des rôles et des groupes par défaut
Vous devez évaluer vos clusters pour déterminer si vous avez lié l'utilisateur system:anonymous
ou les groupes system:unauthenticated
ou system:authenticated
à l'aide de ClusterRoleBindings et de RoleBindings.
ClusterRoleBindings
Répertoriez les noms de tous les ClusterRoleBindings ayant pour sujet
system:anonymous
,system:unauthenticated
ousystem:authenticated
:kubectl get clusterrolebindings -o json \ | jq -r '["Name"], ["-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
Le résultat ne doit répertorier que les objets ClusterRoleBinding suivants :
Name ---- "system:basic-user" "system:discovery" "system:public-info-viewer"
Si la sortie contient d'autres liaisons autres que celles par défaut, procédez comme suit pour chaque liaison supplémentaire. Si le résultat ne contient pas de liaisons autres que celles par défaut, ignorez les étapes suivantes.
Listez les autorisations du rôle associé à la liaison :
kubectl get clusterrolebinding CLUSTER_ROLE_BINDING_NAME -o json \ | jq ' .roleRef.name +" " + .roleRef.kind' \ | sed -e 's/"//g' \ | xargs -l bash -c 'kubectl get $1 $0 -o yaml'
Remplacez
CLUSTER_ROLE_BINDING_NAME
par le nom de l'objet ClusterRoleBinding autre que celui par défaut.Le résultat ressemble à ce qui suit :
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: ... rules: - apiGroups: - "" resources: - secrets verbs: - get - watch - list
Si vous déterminez que les autorisations dans la sortie peuvent être accordées en toute sécurité aux utilisateurs ou aux groupes par défaut, aucune autre action n'est requise. Si vous constatez que les autorisations accordées par la liaison ne sont pas sécurisées, passez à l'étape suivante.
Supprimez une liaison non sécurisée de votre cluster :
kubectl delete clusterrolebinding CLUSTER_ROLE_BINDING_NAME
Remplacez
CLUSTER_ROLE_BINDING_NAME
par le nom de l'objet ClusterRoleBinding à supprimer.
RoleBindings
Répertoriez l'espace de noms et le nom de tous les objets RoleBinding ayant pour sujet
system:anonymous
,system:unauthenticated
ousystem:authenticated
:kubectl get rolebindings -A -o json \ | jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
Si votre cluster est correctement configuré, la sortie doit être vide. Si la sortie contient d'autres liaisons autres que celles par défaut, procédez comme suit pour chaque liaison supplémentaire. Si le résultat est vide, ignorez les étapes suivantes.
Si vous ne connaissez que le nom de l'objet RoleBinding, vous pouvez utiliser la commande suivante pour rechercher les liaisons de rôles correspondantes dans tous les espaces de noms :
kubectl get rolebindings -A -o json \ | jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(.metadata.name == "ROLE_BINDING_NAME") | [.metadata.namespace, .metadata.name]) | @tsv'
Remplacez
ROLE_BINDING_NAME
par le nom de l'objet RoleBinding autre que celui par défaut.Listez les autorisations du rôle associé à la liaison :
kubectl get rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE -o json \ | jq ' .roleRef.name +" " + .roleRef.kind' \ | sed -e 's/"//g' \ | xargs -l bash -c 'kubectl get $1 $0 -o yaml --namespace ROLE_BINDING_NAMESPACE'
Remplacez les éléments suivants :
ROLE_BINDING_NAME
: nom de l'objet RoleBinding autre que celui par défaut.ROLE_BINDING_NAMESPACE
: espace de noms de l'objet RoleBinding autre que celui par défaut.
Le résultat ressemble à ce qui suit :
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: ... rules: - apiGroups: - "" resources: - secrets verbs: - get - watch - list
Si vous déterminez que les autorisations dans la sortie peuvent être accordées en toute sécurité aux utilisateurs ou aux groupes par défaut, aucune autre action n'est requise. Si vous constatez que les autorisations accordées par la liaison ne sont pas sécurisées, passez à l'étape suivante.
Supprimez une liaison non sécurisée de votre cluster :
kubectl delete rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE
Remplacez les éléments suivants :
ROLE_BINDING_NAME
: nom de l'objet RoleBinding à supprimer.ROLE_BINDING_NAMESPACE
: espace de noms de l'objet RoleBinding à supprimer.
Limiter les autorisations au niveau de l'espace de noms
Utilisez les liaisons et les rôles comme suit, en fonction des besoins de votre charge de travail ou de l'utilisateur :
- Pour accorder l'accès aux ressources d'un seul espace de noms, utilisez un objet
Role
avec unRoleBinding
. - Pour accorder l'accès aux ressources de plusieurs espaces de noms, utilisez un objet
ClusterRole
avec unRoleBinding
pour chaque espace de noms. - Pour accorder l'accès aux ressources de tous les espaces de noms du cluster, utilisez un objet
ClusterRole
avec unClusterRoleBinding
.
Accordez des autorisations pour le moins d'espaces de noms possible.
Ne pas utiliser de caractères génériques
Le caractère *
est un caractère générique qui s'applique à tous les champs de vos règles. Évitez d'utiliser des caractères génériques dans vos règles. Spécifiez explicitement les groupes d'API, les ressources et les verbes dans les règles RBAC. Par exemple, si vous spécifiez *
dans le champ verbs
, vous attribuez les autorisations get
, list
, watch
, patch
, update
, deletecollection
. et delete
sur les ressources concernées. Le tableau suivant montre des exemples décrivant le bon usage des caractères génériques dans vos règles :
Recommandé | Déconseillé |
---|---|
- rules: apiGroups: ["apps","extensions"] resources: ["deployments"] verbs: ["get","list","watch"] Attribue les verbes |
- rules: apiGroups: ["*"] resources: ["deployments"] verbs: ["get","list","watch"] Attribue les verbes à |
- rules: apiGroups: ["apps", "extensions"] resources: ["deployments"] verbs: ["get", "list", "watch"] N'attribue que les verbes |
- rules: apiGroups: ["apps", "extensions"] resources: ["deployments"] verbs: ["*"] Attribue tous les verbes, y compris |
Utiliser des règles distinctes pour accorder l'accès selon le principe du moindre privilège à des ressources spécifiques
Lorsque vous planifiez vos règles, essayez d'appliquer la procédure générale suivante afin de concevoir plus efficacement des règles basées sur le principe du moindre privilège, dans chaque rôle :
- Rédigez des règles RBAC distinctes pour chaque verbe sur chaque ressource à laquelle un sujet doit accéder.
- Après avoir rédigé les règles, analysez-les pour vérifier si plusieurs d'entre elles ont la même liste
verbs
. Combinez alors ces règles en une seule. - Veillez à conserver toutes les autres règles indépendamment les unes des autres.
Cette approche permet de structurer davantage la conception de règles : les règles qui attribuent les mêmes verbes à plusieurs ressources sont combinées et celles qui attribuent des verbes différents aux ressources sont individualisées.
Par exemple, si votre charge de travail nécessite des autorisations get pour la ressource deployments
, mais aussi des autorisations list
et watch
sur les ressources daemonsets
, vous devez utiliser des règles distinctes lors de la création d'un rôle. Lorsque vous liez le rôle RBAC à votre charge de travail, il ne pourra pas utiliser le verbe watch
sur la ressource deployments
.
Autre exemple : si votre charge de travail nécessite les autorisations get
et watch
à la fois sur la ressource pods
et sur la ressource daemonsets
, vous pouvez les combiner en une seule règle, car la charge de travail requiert les mêmes verbes sur les deux ressources.
Dans le tableau suivant, les deux conceptions de règles fonctionnent, mais les règles individualisées limitent plus précisément l'accès aux ressources en fonction de vos besoins :
Recommandé | Déconseillé |
---|---|
- rules: apiGroups: ["apps"] resources: ["deployments"] verbs: ["get"] - rules: apiGroups: ["apps"] resources: ["daemonsets"] verbs: ["list", "watch"] Accorde l'accès |
- rules: apiGroups: ["apps"] resources: ["deployments", "daemonsets"] verbs: ["get","list","watch"] Accorde les verbes à la fois aux objets Deployment et DaemonSet. Un sujet qui n'a pas forcément besoin d'un accès |
- rules: apiGroups: ["apps"] resources: ["daemonsets", "deployments"] verbs: ["list", "watch"] Combine deux règles, car le sujet a besoin des mêmes verbes pour les ressources |
- rules: apiGroups: ["apps"] resources: ["daemonsets"] verbs: ["list", "watch"] - rules: apiGroups: ["apps"] resources: ["deployments"] verbs: ["list", "watch"] Ces règles de division auront le même résultat que la règle combinée, mais créeront un encombrement inutile dans le fichier manifeste du rôle. |
Limiter l'accès à des instances de ressources spécifiques
Le contrôle RBAC vous permet d'utiliser le champ resourceNames
dans vos règles pour limiter l'accès à une instance nommée spécifique d'une ressource. Par exemple, si vous écrivez un rôle RBAC nécessitant de mettre à jour (update
) l'objet ConfigMap seccomp-high
et rien d'autre, vous pouvez utiliser resourceNames
pour ne spécifier que ce ConfigMap. Utilisez autant que possible le champ resourceNames
.
Recommandé | Déconseillé |
---|---|
- rules: apiGroups: [""] resources: ["configmaps"] resourceNames: ["seccomp-high"] verbs: ["update"] Limite le sujet à la seule mise à jour du ConfigMap |
- rules: apiGroups: [""] resources: ["configmaps"] verbs: ["update"] L'objet peut mettre à jour le ConfigMap |
- rules: apiGroups: [""] resources: ["configmaps"] verbs: ["list"] - rules: apiGroups: [""] resources: ["configmaps"] resourceNames: ["seccomp-high"] verbs: ["update"] Accorde l'accès |
- rules: apiGroups: [""] resources: ["configmaps"] verbs: ["update", "list"] Accorde l'accès |
Ne pas autoriser les comptes de service à modifier des ressources RBAC
N'associez pas les ressources Role
ou ClusterRole
disposant des autorisations bind
, escalate
, create
, update
ou patch
sur le groupe d'API rbac.authorization.k8s.io
à des comptes de service situés dans n'importe quel espace de noms. Plus particulièrement, les autorisations escalate
et bind
peuvent permettre à un pirate informatique de contourner les mécanismes de prévention des élévations intégrés à RBAC.
Comptes de service Kubernetes
Créer un compte de service Kubernetes pour chaque charge de travail
Créez un compte de service Kubernetes distinct pour chaque charge de travail. Associez un objet Role
ou ClusterRole
, selon le principe du moindre privilège, à ce compte de service.
Ne pas utiliser le compte de service par défaut
Kubernetes crée dans chaque espace de noms un compte de service nommé default
. Ce compte de service default
est automatiquement attribué aux pods qui ne spécifient pas explicitement de compte de service dans le fichier manifeste. Évitez d'associer un objet Role
ou ClusterRole
au compte de service default
. Kubernetes pourrait alors attribuer le compte de service default
à un pod qui n'a pas besoin de l'accès accordé à ces rôles.
Ne pas installer automatiquement les jetons de compte de service
Le champ automountServiceAccountToken
de la spécification de pod indique à Kubernetes d'injecter un jeton d'identifiant pour un compte de service Kubernetes dans le pod. Le pod peut utiliser ce jeton pour envoyer des requêtes authentifiées au serveur d'API Kubernetes. La valeur par défaut de ce champ est true
.
Dans toutes les versions de GKE, définissez automountServiceAccountToken=false
dans la spécification de pod si vos pods n'ont pas besoin de communiquer avec le serveur d'API.
Préférer les jetons éphémères aux jetons basés sur des secrets
Par défaut, le processus kubelet sur le nœud récupère un jeton de compte de service de courte durée alterné automatiquement pour chaque pod. Le kubelet installe ce jeton sur le pod en tant que volume projeté, sauf si vous définissez le champ automountServiceAccountToken
sur false
dans la spécification du pod. Tous les appels à l'API Kubernetes à partir du pod utilisent ce jeton pour s'authentifier auprès du serveur d'API.
Si vous récupérez manuellement les jetons du compte de service, évitez d'utiliser des secrets Kubernetes pour stocker le jeton. Les jetons de compte de service basés sur des secrets constituent des identifiants d'ancienne génération : ils n'expirent pas et ne sont pas alternés automatiquement. Si vous avez besoin d'identifiants pour des comptes de service, utilisez l'API TokenRequest
pour obtenir des jetons de courte durée qui sont automatiquement alternés.
Examiner régulièrement les autorisations RBAC
Examinez régulièrement vos rôles RBAC et vos accès, afin d'identifier les chemins d'élévation potentiels et les règles redondantes. Par exemple, considérons une situation dans laquelle vous ne supprimez pas un objet RoleBinding
qui lie un objet Role
doté de droits spécifiques à un utilisateur supprimé. Si un pirate informatique crée un compte utilisateur dans cet espace de noms, en reprenant le nom de l'utilisateur supprimé, il est alors lié à cet objet Role
et va hériter du même accès. Des examens périodiques permettent de réduire ce risque.
Checklist
Étape suivante
- Consultez les conseils visant à renforcer la sécurité dans GKE.
- Consultez les bonnes pratiques sur le contrôle RBAC dans Kubernetes.
- Découvrez nos autres bonnes pratiques.
- Affichez des exemples de fichiers manifestes pour les rôles de cluster courants