Implications des opérateurs Kubernetes en matière de sécurité
Chris Laux
15 février 2022
0 minutes de lectureAux débuts de Kubernetes, la gestion des ressources était simple : il suffisait de définir les ressources en YAML et de transmettre ces définitions au cluster. Mais cette méthode demandait trop de travail manuel, à un niveau trop bas.
L’étape suivante dans l’évolution de Kubernetes a été l’adoption des charts Helm. Parfois présenté comme le « gestionnaire de paquets pour Kubernetes », Helm permet aux développeurs de partager des configurations complètes d’applications à l’aide d’un langage de templates. Le partage des configurations s’en est trouvé facilité, et le déploiement des charts pouvait se faire simplement en une commande.
Mais Helm est une extension externe, dont les capacités se limitent à ce que permet l’API Kubernetes existante. L’étape logique suivante a donc consisté à étendre l’API Kubernetes à l’aide d’opérateurs. Cette approche nous a permis d’ajouter des fonctionnalités personnalisées depuis le cluster.
Les opérateurs Kubernetes utilisent leurs boucles de contrôle pour exécuter des tâches auparavant confiées à des opérateurs humains. Pour créer un opérateur Kubernetes, le développeur définit du code personnalisé qui interagit avec l’API Kubernetes et automatise le cycle de vie de l’application. Ce code personnalisé s’exécute généralement dans un ou plusieurs pods du cluster, mais il peut tout aussi bien interagir avec le cluster depuis l’extérieur, avec une authentification adaptée.
Vous vous dites que cette configuration pourrait présenter des vulnérabilités ? C’est le cas. Comme toujours, les nouvelles abstractions s’accompagnent de nouveaux problèmes de sécurité Kubernetes.
Dans cet article, nous verrons des exemples de définition précise des autorisations des opérateurs, les rôles complémentaires des créateurs d’opérateurs et des utilisateurs finaux dans la sécurité, ainsi que quelques façons d’utiliser les opérateurs pour renforcer la sécurité des services Kubernetes.
Sécurité Kubernetes avec RBAC
Si nous déployons un opérateur Kubernetes dans un cluster, nous devons considérer les bonnes pratiques générales de sécurité Kubernetes comme le fondement de nos mesures propres aux opérateurs. Examinons d’abord ces considérations générales.
Le principal système d’autorisations de Kubernetes est le contrôle d’accès basé sur les rôles (RBAC), qui doit être activé au démarrage du cluster. Il fournit des ressources d’autorisation supplémentaires : Roles et RoleBindings, qui ne s’appliquent qu’à l’espace de noms où elles sont définies ; et ClusterRoleset ClusterRoleBindings, qui s’appliquent à l’ensemble du cluster (et ne doivent être utilisés qu’en cas de nécessité).
Les Roles définissent les modalités d’accès aux ressources pour les acteurs privilégiés, et les RoleBindings associent des acteurs humains ou des composants logiciels aux Roles. Comme pour la sécurité générale des systèmes d’exploitation, il est important d’accorder uniquement les autorisations strictement nécessaires et de vérifier régulièrement que celles qui ont été accordées restent justifiées.
Voici un exemple de rôle qui autorise la lecture des ressources de pods dans l’espace de noms spécifié :
La chaîne vide de apiGroups indique l’API principale. Pour l’associer à ce rôle, nous pouvons définir une liaison de rôle qui l’attribue à un compte utilisateur spécifique :
Les déploiements d’opérateurs sont souvent fournis avec leurs propres rôles et liaisons. L’utilisateur doit prendre le temps de les examiner, ainsi que la documentation, afin de savoir précisément quels droits un tiers accorde dans son cluster.
Périmètres et autorisations
La sécurité des opérateurs Kubernetes repose sur une chaîne de confiance. Celle-ci commence par les auteurs de l’opérateur et leur dépôt, puis englobe notamment la manière dont l’opérateur est livré au cluster de l’utilisateur. Comme avec le système RBAC, il est judicieux de limiter autant que possible les autorisations de l’opérateur. Malheureusement, la plupart des opérateurs Kubernetes ont besoin de privilèges assez étendus pour fonctionner. Les développeurs doivent donc trouver un équilibre prudent entre sécurité et utilité.
Comme les rôles et les liaisons de rôles, les opérateurs peuvent être limités à un espace de noms (périmètre d’espace de noms) ou agir sur tous les espaces de noms du cluster (périmètre de cluster). Les applications Kubernetes peuvent être isolées dans leurs propres espaces de noms afin de les séparer les unes des autres et du système Kubernetes.
Dans la mesure du possible, les développeurs d’opérateurs devraient privilégier les variantes limitées à un espace de noms. Cela évite que les problèmes ne se propagent aux autres déploiements du même cluster. Si un opérateur doit fournir des services à tous les déploiements d’un cluster, il faut utiliser un opérateur à l’échelle du cluster. Un exemple bien connu est le déploiement qui provisionne automatiquement des certificats pour les applications.
Pour empêcher les pods et les conteneurs de manipuler le reste du système Kubernetes, vous pouvez utiliser les securityContexts, qui s’appliquent également aux conteneurs d’opérateurs. Voici un exemple d’extrait YAML limitant les droits d’un pod :
Dans cet exemple, nous partons du principe que le conteneur s’exécute sur le cluster Kubernetes qu’il gère. Cet extrait empêche les processus d’obtenir les privilèges root et de modifier leur système de fichiers racine. Si l’opérateur est compromis, quelle qu’en soit la raison, les possibilités de l’attaquant sur le système hôte seront limitées.
L’étape suivante consiste à définir des restrictions de sécurité des pods à l’échelle du cluster. Avant la version 1.21 de Kubernetes, nous utilisions l’objet PodSecurityPolicy (PSP). Celui-ci est désormais obsolète. Son successeur, PodSecurityAdmission (PSA), est une fonctionnalité bêta de Kubernetes 1.23.
Malheureusement, cette nouvelle fonctionnalité PSA n’offre pas le même contrôle personnalisé et précis que le YAML présenté plus haut. À la place, nous choisissons parmi trois niveaux de stratégie — privilégié, référence et restreint — à appliquer à chaque espace de noms.
Dans cet exemple, notre espace de noms est configuré pour appliquer le niveau de sécurité de référence intermédiaire et émettre des avertissements au niveau restreint, dont le nom est particulièrement bien choisi. Les définitions exactes de ces stratégies figurent dans la documentation Kubernetes sur les normes de sécurité des pods.
Les avantages des opérateurs en matière de sécurité
Même si les opérateurs Kubernetes soulèvent certaines questions de sécurité, ils peuvent aussi renforcer la sécurité d’un cluster. Comme nous l’avons vu, les opérateurs Kubernetes exécutent les actions et appliquent les configurations habituellement confiées à des opérateurs humains, qui peuvent — et font régulièrement — des erreurs. La configuration et le contrôle assurés par un programme sont plus fiables et reproductibles que les actions d’un opérateur humain.
Lorsqu’ils sont correctement conçus, les opérateurs éliminent les erreurs dues à la négligence, voire à la malveillance. La rapidité d’intervention est également essentielle à la sécurité. Les opérateurs logiciels ont un avantage considérable sur les opérateurs humains pour réagir aux problèmes, qu’il s’agisse de les signaler ou de les résoudre.
La plupart des déploiements sur un cluster répondent aux besoins quotidiens de l’application, mais il est également possible d’y déployer des services dédiés à la gestion de la sécurité. Leur boucle de contrôle est alors idéalement pilotée par un opérateur.
Des solutions pour sécuriser les déploiements Kubernetes
Le développement des opérateurs Kubernetes a permis d’étendre l’API Kubernetes avec une logique personnalisée au sein d’un cluster. Mal gérée, cette fonctionnalité supplémentaire peut être exploitée par des acteurs malveillants. Mais en tant que développeurs, nous pouvons sécuriser nos déploiements Kubernetes grâce à des règles d’autorisation et à d’autres restrictions. RBAC est la principale fonctionnalité Kubernetes de gestion des autorisations et permet de définir les privilèges.
Les opérateurs peuvent également améliorer la sécurité en remplaçant des processus manuels souvent sujets à l’erreur humaine. Ils nous permettent d’exécuter des services de sécurité dédiés, comme Snyk, au sein d’un cluster.
Snyk protège contre les vulnérabilités potentielles présentées dans cet article, et bien d’autres, en signalant aux développeurs les problèmes de sécurité dès qu’ils surviennent pendant le codage. En particulier, Snyk fournit un opérateur Kubernetes que nous pouvons installer dans notre cluster. Snyk détecte alors les vulnérabilités et les signale lorsqu’elles apparaissent dans les charges de travail existantes ou nouvelles du cluster.
Sécurisez votre infrastructure dès la source
Snyk automatise la sécurité et la conformité de l’IaC dans vos workflows, et détecte les ressources dont la configuration a dérivé ou qui sont manquantes.
