ProHoster > Blog > administration > L'ABC de la sécurité dans Kubernetes : authentification, autorisation, audit
L'ABC de la sécurité dans Kubernetes : authentification, autorisation, audit
Tôt ou tard, dans le fonctionnement de tout système, la question de la sécurité se pose : assurer l'authentification, la séparation des droits, l'audit et d'autres tâches. Déjà créé pour Kubernetes de nombreuses solutions, qui vous permettent d'être conforme aux normes même dans des environnements très exigeants... Le même matériel est consacré aux aspects de base de la sécurité mis en œuvre dans les mécanismes intégrés des K8. Tout d'abord, il sera utile à ceux qui commencent à se familiariser avec Kubernetes - comme point de départ pour étudier les questions liées à la sécurité.
Authentification
Il existe deux types d'utilisateurs dans Kubernetes :
les Comptes de service — comptes gérés par l'API Kubernetes ;
Utilisateurs — des utilisateurs « normaux » gérés par des services externes indépendants.
La principale différence entre ces types est que pour les comptes de service, il existe des objets spéciaux dans l'API Kubernetes (ils sont appelés ainsi : ServiceAccounts), qui sont liés à un espace de noms et à un ensemble de données d'autorisation stockées dans le cluster dans des objets de type Secrets. Ces utilisateurs (comptes de service) sont principalement destinés à gérer les droits d'accès à l'API Kubernetes des processus exécutés dans le cluster Kubernetes.
Les utilisateurs ordinaires n'ont pas d'entrées dans l'API Kubernetes : ils doivent être gérés par des mécanismes externes. Ils sont destinés aux personnes ou processus vivant en dehors du cluster.
Chaque demande d'API est associée soit à un compte de service, soit à un utilisateur, ou est considérée comme anonyme.
Les données d'authentification de l'utilisateur comprennent :
Nom d'utilisateur — nom d'utilisateur (sensible à la casse !) ;
UID - une chaîne d'identification de l'utilisateur lisible par machine qui est « plus cohérente et unique que le nom d'utilisateur » ;
Groupes — liste des groupes auxquels appartient l'utilisateur ;
Extra — des champs supplémentaires pouvant être utilisés par le mécanisme d'autorisation.
Kubernetes peut utiliser un grand nombre de mécanismes d'authentification : certificats X509, jetons Bearer, proxy d'authentification, HTTP Basic Auth. Grâce à ces mécanismes, vous pouvez implémenter un grand nombre de schémas d'autorisation : d'un fichier statique avec des mots de passe à OpenID OAuth2.
De plus, il est possible d'utiliser plusieurs régimes d'autorisation simultanément. Par défaut, le cluster utilise :
jetons de compte de service - pour les comptes de service ;
X509 - pour les utilisateurs.
La question de la gestion des ServiceAccounts dépasse le cadre de cet article, mais pour ceux qui souhaitent se familiariser plus en détail avec cette question, je recommande de commencer par pages de documentation officielle. Nous examinerons de plus près la question du fonctionnement des certificats X509.
Certificats pour les utilisateurs (X.509)
La manière classique de travailler avec des certificats implique :
traiter une demande de certificat à l'aide des clés CA du cluster Kubernetes, obtenir un certificat utilisateur (pour obtenir un certificat, vous devez utiliser un compte ayant accès à la clé CA du cluster Kubernetes, qui se trouve par défaut dans /etc/kubernetes/pki/ca.key):
ou comment aucunoption recommandée - vous n'avez pas besoin de spécifier le certificat racine (dans ce cas, kubectl ne vérifiera pas l'exactitude du serveur API du cluster) :
Pour faciliter le transfert de la config entre comptes et serveurs, il est utile d'éditer les valeurs des clés suivantes :
certificate-authority
client-certificate
client-key
Pour ce faire, vous pouvez encoder les fichiers qui y sont spécifiés en base64 et les enregistrer dans la configuration, en ajoutant le suffixe au nom des clés -data, c'est à dire. avoir reçu certificate-authority-data etc
Certificats avec kubeadm
Avec la sortie Kubernetes 1.15 travailler avec des certificats est devenu beaucoup plus facile grâce à la version alpha de son support dans utilitaire Kubeadm. Par exemple, voici à quoi pourrait désormais ressembler la génération d'un fichier de configuration avec des clés utilisateur :
kubeadm alpha kubeconfig user --client-name=mynewuser --apiserver-advertise-address 192.168.100.200
NB: Requis adresse publicitaire peut être trouvé dans la configuration du serveur API, qui se trouve par défaut dans /etc/kubernetes/manifests/kube-apiserver.yaml.
La configuration résultante sera sortie sur la sortie standard. Il doit être enregistré dans ~/.kube/config compte utilisateur ou vers un fichier spécifié dans une variable d'environnement KUBECONFIG.
Creusez plus profondément
Pour ceux qui souhaitent mieux comprendre les problèmes décrits :
Un article distinct sur l'utilisation de certificats dans la documentation officielle de Kubernetes ;
bon article de Bitnami, dans lequel la délivrance des certificats est abordée d'un point de vue pratique.
Le compte autorisé par défaut n'a pas le droit d'opérer sur le cluster. Pour accorder des autorisations, Kubernetes implémente un mécanisme d'autorisation.
Avant la version 1.6, Kubernetes utilisait un type d'autorisation appelé ABAC (Contrôle d'accès basé sur les attributs). Des détails à ce sujet peuvent être trouvés dans documents officiels. Cette approche est actuellement considérée comme héritée, mais vous pouvez toujours l'utiliser avec d'autres types d'authentification.
La manière actuelle (et plus flexible) de diviser les droits d'accès à un cluster s'appelle RBAC (Contrôle d'accès basé sur le rôle) (Contrôle d'accès basé sur les rôles). Il a été déclaré stable depuis la version Kubernetes 1.8. RBAC met en œuvre un modèle de droits dans lequel tout ce qui n'est pas explicitement autorisé est interdit. Pour activer RBAC, vous devez démarrer le serveur API Kubernetes avec le paramètre --authorization-mode=RBAC. Les paramètres sont définis dans le manifeste avec la configuration du serveur API, qui se trouve par défaut le long du chemin /etc/kubernetes/manifests/kube-apiserver.yaml, dans la section command. Cependant, RBAC est déjà activé par défaut, vous ne devriez donc probablement pas vous en soucier : vous pouvez le vérifier par la valeur authorization-mode (dans le déjà mentionné kube-apiserver.yaml). À propos, parmi ses significations, il peut y avoir d'autres types d'autorisation (node, webhook, always allow), mais nous laisserons leur considération en dehors du cadre du matériel.
D'ailleurs, nous avons déjà publié статью avec une description assez détaillée des principes et des caractéristiques du travail avec RBAC, je me limiterai donc davantage à une brève liste des bases et des exemples.
Les entités API suivantes sont utilisées pour contrôler l'accès dans Kubernetes via RBAC :
Role и ClusterRole — les rôles qui servent à décrire les droits d'accès :
Role vous permet de décrire les droits au sein d'un espace de noms ;
ClusterRole - au sein du cluster, y compris vers des objets spécifiques au cluster tels que des nœuds, des URL non liées aux ressources (c'est-à-dire non liées aux ressources Kubernetes - par exemple, /version, /logs, /api*);
RoleBinding и ClusterRoleBinding - utilisé pour la reliure Role и ClusterRole à un utilisateur, un groupe d'utilisateurs ou un ServiceAccount.
Les entités Role et RoleBinding sont limitées par l'espace de noms, c'est-à-dire doit être dans le même espace de noms. Cependant, un RoleBinding peut référencer un ClusterRole, ce qui vous permet de créer un ensemble d'autorisations génériques et de contrôler l'accès à l'aide de celles-ci.
Les rôles décrivent les droits à l'aide d'ensembles de règles contenant :
ressources (numériques: pod, namespace, deployment et ainsi de suite.);
Verbes (verbes: set, update etc).
noms de ressources (resourceNames) - pour le cas où vous devez donner accès à une ressource spécifique, et non à toutes les ressources de ce type.
Une analyse plus détaillée de l'autorisation dans Kubernetes peut être trouvée sur la page documents officiels. A la place (ou plutôt en plus de cela), je donnerai des exemples qui illustrent son travail.
Exemples d'entités RBAC
Simple Role, qui vous permet d'obtenir une liste et l'état des pods et de les surveiller dans l'espace de noms target-namespace:
Exemple ClusterRole, qui vous permet d'obtenir une liste et l'état des pods et de les surveiller dans tout le cluster :
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# секции "namespace" нет, так как ClusterRole задействует весь кластер
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
Exemple RoleBinding, ce qui permet à l'utilisateur mynewuser "lire" les pods dans l'espace de noms my-namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: target-namespace
subjects:
- kind: User
name: mynewuser # имя пользователя зависимо от регистра!
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # здесь должно быть “Role” или “ClusterRole”
name: pod-reader # имя Role, что находится в том же namespace,
# или имя ClusterRole, использование которой
# хотим разрешить пользователю
apiGroup: rbac.authorization.k8s.io
Audit d'événement
Schématiquement, l'architecture Kubernetes peut être représentée comme suit :
Le composant clé de Kubernetes responsable du traitement des requêtes est serveur api. Toutes les opérations sur le cluster passent par là. Vous pouvez en savoir plus sur ces mécanismes internes dans l'article «Que se passe-t-il dans Kubernetes lorsque vous exécutez kubectl run ?».
L'audit système est une fonctionnalité intéressante de Kubernetes, qui est désactivée par défaut. Il vous permet de consigner tous les appels à l'API Kubernetes. Comme vous pouvez le deviner, toutes les actions liées à la surveillance et à la modification de l'état du cluster sont effectuées via cette API. Une bonne description de ses capacités peut (comme d'habitude) être trouvée dans documents officiels K8. Ensuite, j'essaierai de présenter le sujet dans un langage plus simple.
ainsi, pour permettre l'audit, nous devons transmettre trois paramètres requis au conteneur dans le serveur API, qui sont décrits plus en détail ci-dessous :
En plus de ces trois paramètres nécessaires, il existe de nombreux paramètres supplémentaires liés à l'audit : de la rotation des journaux aux descriptions des webhooks. Exemple de paramètres de rotation des journaux :
Comme déjà mentionné, tous les paramètres sont définis dans le manifeste avec la configuration du serveur API (par défaut /etc/kubernetes/manifests/kube-apiserver.yaml), dans la rubrique command. Revenons sur les 3 paramètres requis et analysons-les :
audit-policy-file — chemin d'accès au fichier YAML décrivant la politique d'audit. Nous reviendrons sur son contenu plus tard, mais pour l'instant je noterai que le fichier doit être lisible par le processus api-server. Par conséquent, il est nécessaire de le monter à l'intérieur du conteneur, pour lequel vous pouvez ajouter le code suivant aux sections appropriées de la configuration :
audit-log-path - chemin d'accès au fichier journal. Le chemin doit également être accessible au processus api-server, nous décrivons donc son montage de la même manière :
audit-log-format — format du journal d'audit. La valeur par défaut est json, mais l'ancien format de texte est également disponible (legacy).
Politique d'audit
Parlons maintenant du fichier mentionné décrivant la politique de journalisation. Le premier concept de politique d’audit est level, niveau de journalisation. Ils sont les suivants :
None - ne vous connectez pas ;
Metadata — métadonnées de la demande de journalisation : utilisateur, heure de la demande, ressource cible (pod, espace de noms, etc.), type d'action (verbe), etc. ;
Request — enregistrer les métadonnées et le corps de la demande ;
RequestResponse - enregistrer les métadonnées, le corps de la demande et le corps de la réponse.
Les deux derniers niveaux (Request и RequestResponse) n'enregistre pas les requêtes qui n'ont pas accédé aux ressources (accès aux URL dites non-ressources).
De plus, toutes les demandes passent plusieurs étapes:
RequestReceived — l'étape au cours de laquelle la demande est reçue par le processeur et n'a pas encore été transmise plus loin dans la chaîne des processeurs ;
ResponseStarted — les en-têtes de réponse sont envoyés, mais avant l'envoi du corps de la réponse. Généré pour les requêtes de longue durée (par exemple, watch);
ResponseComplete — le corps de la réponse a été envoyé, aucune autre information ne sera envoyée ;
Panic — des événements sont générés lorsqu'une situation anormale est détectée.
Pour ignorer toutes les étapes que vous pouvez utiliser omitStages.
Dans un fichier de stratégie, nous pouvons décrire plusieurs sections avec différents niveaux de journalisation. La première règle de correspondance trouvée dans la description de la stratégie sera appliquée.
Le démon kubelet surveille les modifications dans le manifeste avec la configuration du serveur API et, le cas échéant, redémarre le conteneur avec le serveur API. Mais il y a un détail important : les modifications dans le fichier de stratégie seront ignorées par celui-ci. Après avoir modifié le fichier de stratégie, vous devrez redémarrer le serveur API manuellement. Puisque le serveur API est démarré en tant que nacelle statique, équipe kubectl delete ne le fera pas redémarrer. Vous devrez le faire manuellement docker stop sur kube-masters, où la politique d'audit a été modifiée :
Lors de l'activation de l'audit, il est important de se rappeler que la charge sur kube-apiserver augmente. En particulier, la consommation de mémoire pour stocker le contexte de la requête augmente. La journalisation ne commence qu'après l'envoi de l'en-tête de réponse. La charge dépend également de la configuration de la stratégie d'audit.
Exemples de politiques
Examinons la structure des fichiers de stratégie à l'aide d'exemples.
Voici un fichier simple policypour tout enregistrer au niveau Metadata:
Dans la stratégie, vous pouvez spécifier une liste d'utilisateurs (Users и ServiceAccounts) et les groupes d'utilisateurs. Par exemple, c'est ainsi que nous ignorerons les utilisateurs du système, mais enregistrerons tout le reste au niveau Request:
ressources (numériques, Comme suit: pod, configmaps etc.) et les groupes de ressources (apiGroups).
Faites attention! Les ressources et groupes de ressources (groupes API, c'est-à-dire apiGroups), ainsi que leurs versions installées dans le cluster, peuvent être obtenus à l'aide des commandes :
kubectl api-resources
kubectl api-versions
La politique d'audit suivante est fournie à titre de démonstration des meilleures pratiques en matière de Documentation Alibaba Cloud:
apiVersion: audit.k8s.io/v1beta1
kind: Policy
# Не логировать стадию RequestReceived
omitStages:
- "RequestReceived"
rules:
# Не логировать события, считающиеся малозначительными и не опасными:
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: "" # это api group с пустым именем, к которому относятся
# базовые ресурсы Kubernetes, называемые “core”
resources: ["endpoints", "services"]
- level: None
users: ["system:unsecured"]
namespaces: ["kube-system"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["configmaps"]
- level: None
users: ["kubelet"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["nodes"]
- level: None
userGroups: ["system:nodes"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["nodes"]
- level: None
users:
- system:kube-controller-manager
- system:kube-scheduler
- system:serviceaccount:kube-system:endpoint-controller
verbs: ["get", "update"]
namespaces: ["kube-system"]
resources:
- group: "" # core
resources: ["endpoints"]
- level: None
users: ["system:apiserver"]
verbs: ["get"]
resources:
- group: "" # core
resources: ["namespaces"]
# Не логировать обращения к read-only URLs:
- level: None
nonResourceURLs:
- /healthz*
- /version
- /swagger*
# Не логировать сообщения, относящиеся к типу ресурсов “события”:
- level: None
resources:
- group: "" # core
resources: ["events"]
# Ресурсы типа Secret, ConfigMap и TokenReview могут содержать секретные данные,
# поэтому логируем только метаданные связанных с ними запросов
- level: Metadata
resources:
- group: "" # core
resources: ["secrets", "configmaps"]
- group: authentication.k8s.io
resources: ["tokenreviews"]
# Действия типа get, list и watch могут быть ресурсоёмкими; не логируем их
- level: Request
verbs: ["get", "list", "watch"]
resources:
- group: "" # core
- group: "admissionregistration.k8s.io"
- group: "apps"
- group: "authentication.k8s.io"
- group: "authorization.k8s.io"
- group: "autoscaling"
- group: "batch"
- group: "certificates.k8s.io"
- group: "extensions"
- group: "networking.k8s.io"
- group: "policy"
- group: "rbac.authorization.k8s.io"
- group: "settings.k8s.io"
- group: "storage.k8s.io"
# Уровень логирования по умолчанию для стандартных ресурсов API
- level: RequestResponse
resources:
- group: "" # core
- group: "admissionregistration.k8s.io"
- group: "apps"
- group: "authentication.k8s.io"
- group: "authorization.k8s.io"
- group: "autoscaling"
- group: "batch"
- group: "certificates.k8s.io"
- group: "extensions"
- group: "networking.k8s.io"
- group: "policy"
- group: "rbac.authorization.k8s.io"
- group: "settings.k8s.io"
- group: "storage.k8s.io"
# Уровень логирования по умолчанию для всех остальных запросов
- level: Metadata
Pour répondre rapidement aux événements d'audit, il est possible décrire le webhook. Cette question est abordée dans documents officiels, je vais le laisser en dehors du cadre de cet article.
Les résultats de
L'article donne un aperçu des mécanismes de sécurité de base dans les clusters Kubernetes, qui vous permettent de créer des comptes d'utilisateurs personnalisés, de séparer leurs droits et d'enregistrer leurs actions. J'espère qu'il sera utile à ceux qui sont confrontés à de tels problèmes en théorie ou en pratique. Je vous recommande également de lire la liste d'autres documents sur le thème de la sécurité dans Kubernetes, qui est donnée dans "PS" - vous trouverez peut-être parmi eux les détails nécessaires sur les problèmes qui vous concernent.