Pourquoi et comment sécuriser les pods avec les contextes de sécurité Kubernetes
Comment s’assurer que chaque ressource dans Kubernetes dispose des autorisations dont elle a besoin, tout en évitant une attribution excessive d’autorisations ? En d’autres termes, comment pouvez-vous définir des autorisations sur une base granulaire qui respecte le principe du moindre privilège ?
Le contexte de sécurité Kubernetes est la réponse à cette question. Le contexte de sécurité est un outil qui permet aux administrateurs de définir des paramètres de sécurité pour chaque ressource. Il rend possible l’attribution à chaque ressource des autorisations spécifiques dont elle a besoin pour accéder aux ressources du serveur hôte, tout en refusant l’accès à celles dont elle n’a pas spécifiquement besoin.
Cet article présente une vue d’ensemble du contexte de sécurité Kubernetes, notamment son fonctionnement, la façon de définir un contexte de sécurité et les limites à prendre en compte lorsque vous utilisez le contexte de sécurité dans Kubernetes.
Qu’est-ce que le contexte de sécurité Kubernetes ?
Dans Kubernetes, un contexte de sécurité définit les privilèges pour chaque pod et chaque container. Vous pouvez utiliser le contexte de sécurité pour accorder aux containers ou aux pods des autorisations telles que le droit d’accéder à un fichier externe ou de s’exécuter en mode privilégié.
Contextes de sécurité internes et externes
La complexité du contexte de sécurité de Kubernetes réside dans le fait que certaines des règles que vous pouvez définir sont appliquées en interne directement par Kubernetes, tandis que d’autres s’intègrent avec des outils de contexte de sécurité externes, à savoir AppArmor et SELinux.
Ainsi, il est possible de se représenter le contexte de sécurité de Kubernetes comme un moyen de définir certaines autorisations pour les pods et les containers, ainsi que d’intégrer Kubernetes avec des outils de sécurité externes qui s’exécutent sur l’hôte plutôt que directement dans Kubernetes.
Contextes de sécurité et RBAC
Le contexte de sécurité est semblable au contrôle d’accès basé sur les rôles de Kubernetes ou RBAC, mais distinct de celui-ci. Les principales différences sont les suivantes :
- Étendue des ressources : RBAC peut être appliqué à une variété de ressources Kubernetes, comme les pods, les nœuds et même des clusters entiers. Le contexte de sécurité attribue des autorisations uniquement aux pods.
- Actions : RBAC peut accorder diverses autorisations en fonction de « verbes » que les administrateurs peuvent définir dans des politiques RBAC. Le contexte de sécurité est plus restrictif, dans la mesure où il permet uniquement à des administrateurs d’attribuer des types spécifiques de capacités prédéfinies, comme l’exécution en mode privilégié (bien que les contextes de sécurité soient plus flexibles si vous définissez des règles en utilisant SELinux ou AppArmor).
- Extensibilité : comme précisé ci-dessus, les contextes de sécurité peuvent être étendus par le biais d’intégrations avec des cadres externes, dont SELinux et AppArmor. RBAC de Kubernetes ne peut pas utiliser d’outils externes pour définir des politiques.
Pour cette raison, vous devez considérer le contexte de sécurité comme un moyen de définir des types supplémentaires d’autorisations de sécurité pour les containers et les pods que RBAC n’est pas en mesure de gérer. Pour la plupart des environnements Kubernetes, vous préférerez utiliser le contexte de sécurité et RBAC en même temps, car ils sont complémentaires.
Contextes de sécurité et Pod Security Policies
De nombreuses règles de sécurité que vous pouvez définir grâce aux contextes de sécurité peuvent également être configurées par le biais des pod security policies, qui sont un outil différent.
Pourquoi Kubernetes prendrait-il en charge à la fois les contextes de sécurité et les pod security policies ? La réponse est que les contextes de sécurité remplacent en fait les pod security policies. Les pod security policies, qui peuvent être utilisées pour configurer les autorisations pour tous les pods qui s’exécutent au sein d’un cluster, fournissent un contrôle moins granulaire que les contextes de sécurité, ceux-ci pouvant être appliqués à des pods de façon individuelle.
À partir de la version 1.21 de Kubernetes, les pod security policies sont considérées comme obsolètes, bien qu’elles soient actuellement encore prises en charge. Les pod security policies seront complètement supprimées avec Kubernetes 1.25. Toutes les pod security policies que vous aurez définies seront alors ignorées.
Comment utiliser le contexte de sécurité Kubernetes ?
L’utilisation du contexte de sécurité dans Kubernetes est très simple (en particulier si vous utilisez uniquement le contexte de sécurité interne et que vous n’intégrez pas SELinux ou AppArmor). Il vous suffit d’inclure un bloc de code de contexte de sécurité dans le fichier de déploiement que vous créez lors du déploiement d’un pod.
Par exemple, le bloc suivant demande à Kubernetes d’exécuter un pod avec un ID d’utilisateur de 1000. Il attribue également un ID de groupe de 2000 à tous les containers du pod :
Spec:
securityContext:
runAsUser: 1000
fsGroup: 2000
Contrairement à RBAC, le contexte de sécurité ne vous impose pas de définir plusieurs types de fichiers (comme des Roles et des RoleBindings) afin d’appliquer une règle de sécurité. Vous devez tout simplement ajouter le code de contexte de sécurité requis lorsque vous déclarez un déploiement. À partir de cet instant, Kubernetes appliquera automatiquement les règles.
Pour une vue d’ensemble complète des types d’autorisations que vous pouvez attribuer (ou refuser) avec un contexte de sécurité, consultez la documentation de Kubernetes. Outre les autorisations liées aux ID d’utilisateur et de groupe, la plupart des administrateurs trouveront intéressant d’utiliser des paramètres qui permettent d’exécuter le pod ou le container en mode privilégié. Un container s’exécutant en mode privilégié dispose de quasiment tous les mêmes droits d’accès aux ressources au niveau du noyau sur l’hôte qu’un processus s’exécutant en tant que root, c’est pourquoi il est généralement préférable d’interdire le mode privilégié. Définissez plutôt les autorisations sur une base granulaire, par exemple en autorisant le container ou le pod à effectuer une liaison avec un port spécifique ou à exécuter certains fichiers binaires externes, tout en refusant l’accès aux ressources extérieures au container.
Travailler avec des contextes de sécurité externes
La mise en œuvre d’un contexte de sécurité basé sur des outils externes comme SELinux et AppArmor nécessite d’effectuer quelques actions supplémentaires. Voici les étapes de base à suivre.
Charger le module SELinux ou AppArmor
Tout d’abord, vous devez vérifier que le module du noyau associé au framework que vous utilisez (c’est-à-dire SELinux ou AppArmor) est installé et chargé sur le ou les nœuds qui accueilleront vos containers ou pods.
Dans la plupart des cas, Kubernetes affecte automatiquement les pods ou les containers aux nœuds, c’est la raison pour laquelle vous ne saurez pas à l’avance quel nœud accueillera quel container ou pod. Vous devrez donc généralement installer AppArmor ou SELinux sur chaque nœud de votre cluster si vous souhaitez définir des contextes de sécurité par le biais de l’un de ces frameworks.
Charger un profil
Une fois les modules chargés, vous devez charger le profil AppArmor ou SELinux que vous utiliserez pour définir les autorisations. Par exemple, ce profil AppArmor refuse la possibilité d’écrire des fichiers :
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
Enregistrez le profil dans le système de fichiers du nœud à un emplacement que Kubernetes peut lire.
Pour rappel, comme vous ne savez probablement pas quel nœud exécutera quels containers ou quels pods, vous devrez charger le profil sur chaque nœud de votre cluster. Pour charger le profil de façon efficace (c’est-à-dire pour éviter d’avoir à vous connecter en SSH à chaque nœud et à appliquer les profils manuellement), consultez la documentation de Kubernetes relative aux profils de nœuds.
Appliquer le profil dans Kubernetes
Pour terminer, ajoutez un bloc de contexte de sécurité à votre fichier de déploiement pour demander à Kubernetes de référencer le profil de contexte de sécurité externe et de l’appliquer au déploiement :
apiVersion: v1
kind: Pod
metadata:
name: apparmor-demo
annotations:
container.apparmor.security.beta.kubernetes.io/hello: /path/to/policy-file
Appliquez la déclaration avec :
kubectl create -f ./deployment.yml
À partir de maintenant, Kubernetes appliquera la politique que vous avez configurée par le biais d’AppArmor ou de SELinux, comme si vous configuriez directement un contexte de sécurité dans un fichier de déploiement.
Limites des contextes de sécurité
Le contexte de sécurité de Kubernetes est un outil puissant qui permet de définir certains types d’autorisations sur une base granulaire. Cependant, il présente pour le moment des limites assez significatives.
Pas de prise en charge de Windows
L’outil de contexte de sécurité ne traite actuellement que les privilèges et les autorisations qui sont valides sur un serveur Linux. Si vous exécutez des containers Windows dans Kubernetes, les contextes de sécurité ne vous seront d’aucune utilité.
Sécurité limitée au niveau du pod/container
Le contexte de sécurité peut définir des autorisations uniquement pour des pods ou des containers. Il ne peut pas contrôler les privilèges des autres couches de votre pile.
Bien sûr, la plupart des règles que vous pouvez appliquer avec les contextes de sécurité n’ont de sens que lorsqu’elles sont appliquées à des containers ou à des pods. Il ne serait pas logique, par exemple, de demander à un nœud de fonctionner en mode non privilégié.
Cependant, le contexte de sécurité reste un outil qui ne sert qu’à gérer les problèmes de sécurité au niveau des pods ou des containers. D’autres outils (comme RBAC) vous seront nécessaires pour sécuriser les nœuds, les utilisateurs, les comptes de service, etc.
Il s’agit d’une fonction évolutive
Les contextes de sécurité sont une fonctionnalité relativement nouvelle pour Kubernetes, qui continuent encore d’évoluer. Certains paramètres (comme fsGroupChangePolicy, introduit avec une prise en charge bêta dans Kubernetes 1.20) ne sont pas encore complètement pris en charge. D’autres définitions pourraient apparaître prochainement.
Par conséquent, bien que vous puissiez certainement utiliser les contextes de sécurité dans les clusters de production dès à présent, il est important de suivre de très près l’évolution de cette fonctionnalité, car des modifications seront peut-être apportées à certains types de définitions dans les prochaines versions.
Problèmes d’efficacité des outils
Comme expliqué précédemment, l’une des principales limites de certains contextes de sécurité (notamment ceux qui utilisent les profils SELinux ou AppArmor) est qu’ils nécessitent le déploiement de ressources externes sur chaque nœud de votre cluster. Il existe des moyens d’automatiser ce processus, mais rien que la configuration de cette automatisation demande beaucoup de travail. Le déploiement peut également être complexe si vous avez des nœuds qui exécutent différentes distributions Linux. Si tel est le cas, vous devrez peut-être personnaliser votre configuration AppArmor ou SELinux pour chaque distribution.
On peut toutefois espérer que des outils permettant de simplifier le déploiement des profils de politique à travers les nœuds seront disponibles à l’avenir. Cependant, à l’heure actuelle, ne sous-estimez pas l’effort nécessaire à la configuration des nœuds.
Malgré ces inconvénients, les contextes de sécurité restent une ressource importante qui permet de combler les lacunes potentielles du contrôle d’accès dans les clusters Kubernetes. Même si leur portée est limitée et qu’ils ne constituent pas une solution de contrôle d’accès complète en soi, vous devriez exploiter les contextes de sécurité pour renforcer la sécurité globale de votre cluster.