Remarque perev. : L'original de cet article a été publié sur le blog officiel de Kubernetes et écrit par Andrew Martin, l'un des fondateurs de la jeune société britannique Control Plane, spécialisée dans la sécurité des applications cloud natives fonctionnant sur K8.
La sécurité à Kubernetes a parcouru un long chemin depuis l'arrivée du projet, mais des écueils persistent. Nous proposons une liste de recommandations utiles sur la façon de protéger les clusters et d'augmenter leur stabilité en cas de piratage: nous allons commencer par le plan de contrôle, continuer avec les charges de travail et la sécurité du réseau, et terminer par une évaluation de la sécurité future.
Partie 1: Plan de contrĂ´le
Le plan de contrôle est le cerveau de Kubernetes. Il a une idée générale de chaque conteneur et pod s'exécutant dans le cluster, peut planifier de nouveaux pods (qui peuvent contenir des conteneurs avec un accès root à leurs nœuds parents) et peut lire tous les secrets stockés dans le cluster. Il s'agit d'un composant très important qui nécessite une protection constante contre les fuites accidentelles de données et les actions malveillantes: à la fois lors de son accès, lorsque rien ne se produit et lorsque les données sont transmises sur le réseau.
1. TLS ubiquitaire
Pour chaque composant qui prend en charge TLS, il doit être activé - pour empêcher le reniflement du trafic, la vérification de l'identité du serveur et (dans le cas de Mutual TLS) la vérification de l'identité du client."Veuillez noter que certains composants et méthodes d'installation peuvent activer les ports locaux pour HTTP, les administrateurs doivent donc se familiariser avec les paramètres de chaque composant pour identifier les chemins possibles pour le trafic non sécurisé."
Depuis la documentation de Kubernetes
Le schéma de réseau ci-dessous de
Lucas Käldström montre où TLS est idéalement nécessaire: entre chaque composant de l'assistant, et entre Kubelet et le serveur API. Le classique
Kelsey Hightower Kubernetes The Hard Way et la
documentation de sécurité sur etcd offrent des instructions détaillées pour atteindre ces objectifs.

Historiquement, la mise à l'échelle automatique des nœuds Kubernetes n'était pas facile, car chaque nœud nécessitait une clé TLS pour se connecter au maître, et garder les secrets dans les images de base est une mauvaise pratique.
L'amorçage Kubelet TLS permet au nouveau Kubelet de créer une demande de signature de certificat afin que les certificats soient générés au démarrage:

2. Privilèges minimum dans RBAC, désactivation d'ABAC, surveillance des journaux
Le contrôle d'accès basé sur les rôles (RBAC) fournit une gestion de stratégie précise par laquelle les utilisateurs accèdent aux ressources telles que les espaces de noms.
Le contrôle d'accès basé sur les attributs (ABAC) dans Kubernetes a été remplacé par RBAC depuis K8s 1.6 et ne doit pas être activé du côté serveur de l'API. Utilisez plutôt RBAC:
--authorization-mode=RBAC
(ou cet indicateur pour GKE: --no
--no-enable-legacy-authorization
).
Il existe de nombreux
bons exemples de stratégies RBAC pour divers services dans un cluster, ainsi que de la
documentation . Mais ne vous arrêtez pas là : les paramètres compétents pour les stratégies RBAC peuvent être obtenus en utilisant
audit2rbac Ă partir des journaux d'
audit
.
Des politiques RBAC incorrectes ou trop permissives constituent un risque pour la sécurité si le foyer est compromis. Le maintien des règles du RBAC avec des privilèges minimaux, leur audit permanent et leur amélioration devraient faire partie de «l'hygiène technique de la dette» que les équipes appliquent dans le cycle de vie du développement.
La journalisation d'audit (bêta dans Kubernetes 1.10) offre une API de journalisation personnalisée pour les charges de travail (telles que les demandes et les réponses) et au niveau des métadonnées. Le niveau de journalisation peut être configuré conformément à la politique de sécurité de l'organisation -
GKE applique des valeurs par défaut raisonnables pour ceux qui commencent tout juste à l'
utiliser .
Pour les demandes de lecture telles que
get ,
list et
watch , seul l'objet demandé est stocké dans les journaux d'audit, sans objet de réponse. Pour les requêtes impliquant des données sensibles comme
Secret ou
ConfigMap , seules les métadonnées sont exportées. Pour toutes les autres demandes, les deux objets sont enregistrés dans les journaux d'audit: à la fois la demande et la réponse.
N'oubliez pas: le stockage de ces journaux à l'intérieur du cluster est un risque de sécurité en cas de compromis. Ces journaux, comme tous les autres sensibles à la sécurité, doivent être placés en dehors du cluster afin d'éviter des conséquences négatives en cas de vulnérabilité.
3. Utilisez l'authentification tierce pour le serveur API
La centralisation de l'authentification et de l'autorisation pour l'ensemble de l'organisation (c'est-à -dire, l'authentification unique) facilite les processus d'acceptation et de départ de nouveaux employés, garantissant des droits d'accès cohérents.L'intégration de Kubernetes avec des fournisseurs d'authentification tiers (comme Google ou GitHub) offre des garanties d'identité à partir d'une plate-forme distante (avec une protection comme l'authentification à deux facteurs) et élimine la nécessité pour les administrateurs de reconfigurer le serveur API dans Kubernetes pour ajouter / supprimer des utilisateurs.
Dex est un fournisseur OpenID Connect Identity (OIDC) et OAuth 2.0 avec des plug-ins. Pusher est allé encore plus loin en fournissant
des outils personnalisables , auxquels s'ajoutent d'
autres aides axées sur d'autres applications.
4. Séparez et placez votre cluster, etc. derrière le pare-feu
etcd stocke des informations sur l'état et les secrets de Kubernetes, est un composant essentiel des K8 - il doit être protégé séparément du reste du cluster.L'accès en écriture à etcd sur le serveur API équivaut à attribuer des droits root à l'ensemble du cluster, et même l'accès en lecture peut être facilement utilisé pour augmenter les privilèges.
Le planificateur Kubernetes dans etcd recherche les définitions de pod qui n'ont pas de nœud. Il envoie ensuite tous les pods trouvés au Kubelet disponible pour la planification. La validation de ces pods est effectuée par le serveur API avant de les écrire dans etcd, de sorte que les attaquants écrivant directement dans etcd peuvent contourner de nombreux mécanismes de sécurité - par exemple,
PodSecurityPolicies
.
etcd doit être configuré avec les
deux certificats TLS (
client et
homologue ) et déployé sur des nœuds dédiés. Pour réduire le risque de vol et d'utilisation de clés privées des nœuds de travail, vous pouvez également limiter le pare-feu du cluster API Server.
5. Rotation des clés de cryptage
La rotation régulière des clés de sécurité et des certificats est la meilleure pratique de sécurité qui vous permet de limiter le "rayon de destruction" lorsque la clé est compromise.Kubernetes effectuera
automatiquement la rotation de certains certificats (en particulier, les certificats client et serveur Kubelet) en créant de nouveaux CSR après l'expiration des certificats actuels.
Cependant, les
clés symétriques utilisées par le serveur API pour crypter les valeurs etcd ne sont pas tournées automatiquement - cela doit être
fait manuellement . Cette opération nécessite un accès maître, donc les services gérés (comme GKE et AKS) cachent le problème à l'utilisateur.
Partie 2: charges de travail
Avec une sécurité minimale au niveau du plan de contrôle, le cluster peut déjà fonctionner en toute sécurité. Cependant, comme pour un navire avec une cargaison potentiellement dangereuse, les conteneurs d'un tel navire doivent protéger la cargaison en cas d'accident ou de fuite imprévus. Il en va de même pour les charges de travail Kubernetes (pods,
déploiements ,
travaux ,
ensembles , etc.) - elles peuvent être fiables au moment du déploiement, mais si elles sont accessibles de l'extérieur, il y a toujours un risque qu'elles soient exploitées ultérieurement par [les attaquants]. Ce risque peut être atténué en exécutant des charges de travail avec des privilèges minimaux et leur configuration sécurisée.
6. Utilisez les fonctionnalités de sécurité Linux et PodSecurityPolicies
Le noyau Linux possède de nombreuses extensions de sécurité se chevauchant partiellement (capacités, SELinux, AppArmor, seccomp-bpf) qui peuvent être configurées pour accorder aux applications des privilèges minimaux.Des utilitaires comme
bane vous aideront à générer des profils pour AppArmor, et
docker-slim vous aidera à générer des profils seccomp, mais soyez prudent: pour identifier tous les effets secondaires de l'application de ces politiques, vous avez besoin d'une suite de tests complète qui vérifie l'intégralité du code de l'application.
PodSecurityPolicies régit l'utilisation de ces extensions de sécurité, ainsi que d'autres directives de sécurité Kubernetes. Ils sont responsables des exigences minimales qui doivent être remplies pour accéder au serveur API, y compris les profils de sécurité, l'indicateur de privilège, le réseau hôte partagé, les processus ou les espaces de noms pour IPC.
Ces directives sont importantes car elles aident à empêcher les processus conteneurisés d'échapper à leurs limites isolées.
L'exemple PodSecurityPolicy de Tim Allclair est très polyvalent - vous pouvez le prendre comme base et le personnaliser pour votre cas.
7. Effectuer une analyse statique de YAML
Si PodSecurityPolicies restreint l'accès au serveur API, une analyse statique peut également être utilisée dans le processus de développement pour modéliser les exigences réglementaires de l'organisation et l'appétit pour le risque.Les informations sensibles ne doivent pas être stockées dans des ressources YAML comme les foyers (
pods ,
déploiements ,
ensembles , etc.), et les
ConfigMaps et
Secrets sensibles doivent être cryptés avec des utilitaires comme
Vault (avec un opérateur de CoreOS),
git-crypt ,
secrets scellés ou
cloud KMS fournisseur .
L'analyse statique de la configuration YAML peut être utilisée comme base de sécurité lors du démarrage.
kubesec génère des évaluations des risques pour les ressources:
{ "score": -30, "scoring": { "critical": [{ "selector": "containers[] .securityContext .privileged == true", "reason": "Privileged containers can allow almost completely unrestricted host access" }], "advise": [{ "selector": "containers[] .securityContext .runAsNonRoot == true", "reason": "Force the running image to run as a non-root user to ensure least privilege" }, { "selector": "containers[] .securityContext .capabilities .drop", "reason": "Reducing kernel capabilities available to a container limits its attack surface", "href": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" }] } }
Et
kubetest est un cadre pour les tests unitaires des configurations Kubernetes:
#
Ces utilitaires implémentent l'approche de
décalage à gauche (c'est-à -dire qu'ils déplacent la validation et la vérification aux premiers stades du cycle de développement). Les tests de sécurité au stade du développement donnent aux utilisateurs un retour rapide sur le code et la configuration, qui peuvent ensuite être rejetés par vérification manuelle ou automatisée, et peuvent également faciliter l'introduction de pratiques de sécurité supplémentaires.
8. Exécutez les conteneurs non root
Les conteneurs qui s'exécutent en tant que root ont souvent beaucoup plus de droits que ne l'exigent leurs charges de travail, et s'ils sont compromis, ils aident les attaquants à atteindre de grandes capacités.Les conteneurs reposent toujours sur le modèle de sécurité UNIX traditionnel (appelé DAC,
contrôle d'accès discrétionnaire ) - tout est un fichier et des droits sont accordés aux utilisateurs et aux groupes.
Les espaces de noms utilisateur ne fonctionnent pas dans Kubernetes. Cela signifie que la table d'ID utilisateur dans le conteneur est mappée à la table utilisateur hôte et que le démarrage du processus avec des privilèges root à l'intérieur du conteneur le fait s'exécuter avec des privilèges root sur l'hôte. Bien que des mécanismes soient ajoutés à tout cela pour empêcher la sortie du conteneur, l'exécution en tant que root à l'intérieur du conteneur n'est pas recommandée.
De nombreuses images de conteneurs utilisent l'utilisateur root pour exécuter le PID 1: si ce processus est compromis, l'attaquant obtient root dans le conteneur et, avec toute erreur de configuration, l'opération du problème devient beaucoup plus facile.
Bitnami a
fait un excellent travail de traduction de leurs images de conteneur aux utilisateurs
réguliers (non root) (ce qui est également l'exigence d'OpenShift par défaut), ce qui peut également simplifier votre migration vers des images non root.
Ce fragment PodSecurityPolicy empêche les processus racine de s'exécuter dans le conteneur et de remonter à la racine:
# Required to prevent escalations to root. allowPrivilegeEscalation: false runAsUser: # Require the container to run without root privileges. rule: 'MustRunAsNonRoot'
Les conteneurs qui n'utilisent pas root ne peuvent pas occuper des ports privilégiés, c'est-à -dire jusqu'à 1024 (la capacité correspondante dans le noyau Linux -
CAP_NET_BIND_SERVICE
est responsable), cependant, l'utilisation des
services permet de contourner cette limitation. Voici un exemple pour l'application MyApp, qui occupe le port 8443 dans le conteneur, mais
Service le rend disponible sur le port 443, en mandatant les demandes de
targetPort
:
kind: Service apiVersion: v1 metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 443 targetPort: 8443
La nécessité d'exécuter des charges de travail sans utiliser root restera jusqu'à ce que l'espace de nom de l'utilisateur ou
le temps de fonctionnement pour le lancement de conteneurs sans root soient inclus dans l'exécution du conteneur.
9. Utilisez des politiques de réseau
Par défaut, le réseau Kubernetes autorise tout le trafic entre les pods. Ce paramètre peut être limité par la stratégie réseau - NetworkPolicy .
Les services traditionnels sont limités aux pare-feu utilisant des adresses IP statiques et des plages de ports pour chaque service. Parce que ces adresses IP changent très rarement, elles ont historiquement été utilisées comme une forme d'authentification. Les conteneurs ont rarement des adresses IP statiques - leur nature implique la possibilité d'une suppression et d'une recréation rapides, pour eux, la découverte de services est utilisée à la place des adresses IP statiques. Ces fonctionnalités compliquent considérablement la configuration et la vérification des pare-feu.
Étant donné que Kubernetes stocke toutes les données sur l'état du système dans etcd, il est possible de configurer un pare-feu dynamique - s'il existe le support nécessaire dans le plugin réseau CNI. Calico, Cilium, kube-router, Romana et Weave Net - tous ces plugins prennent en charge les politiques réseau.
Il est important de noter que les politiques fonctionnent sur le principe de la fermeture en cas de défaillance, c'est-à -dire que l'absence d'un
podSelector
ici par défaut est égale à toutes les valeurs possibles (caractère générique):
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny spec: podSelector:
Ce qui suit est un exemple de
NetworkPolicy , qui interdit tout de la sortie sauf UDP 53 (DNS), qui empêche également les connexions entrantes à l'application.
NetworkPolicies sont des stratégies avec
état , de sorte que l'application recevra toujours des réponses aux connexions sortantes.
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: myapp-deny-external-egress spec: podSelector: matchLabels: app: myapp policyTypes: - Egress egress: - ports: - port: 53 protocol: UDP - to: - namespaceSelector: {}
Les stratégies de réseau Kubernetes ne peuvent pas être appliquées aux noms DNS. La raison en est que DNS prend en charge la répétition alternée vers plusieurs adresses IP et les réponses dynamiques en fonction de l'adresse IP accédant, de sorte que les stratégies réseau s'appliquent uniquement aux adresses IP fixes ou
podSelector
(pour les adresses IP dynamiques Kubernetes).
La meilleure pratique consiste à commencer par interdire tout le trafic pour l'espace de noms et à ajouter pas à pas les itinéraires requis par l'application pour réussir les tests d'acceptation. Le processus peut être difficile, donc ControlPlane a développé
netassert , un utilitaire pour tester la sécurité du réseau dans les scripts DevSecOps avec nmap hautement parallèle:
k8s: # used for Kubernetes pods deployment: # only deployments currently supported test-frontend: # pod name, defaults to `default` namespace test-microservice: 80 # `test-microservice` is the DNS name of the target service test-database: -80 # `test-frontend` should not be able to access test-database's port 80 169.254.169.254: -80, -443 # AWS metadata API metadata.google.internal: -80, -443 # GCP metadata API new-namespace:test-microservice: # `new-namespace` is the namespace name test-database.new-namespace: 80 # longer DNS names can be used for other namespaces test-frontend.default: 80 169.254.169.254: -80, -443 # AWS metadata API metadata.google.internal: -80, -443 # GCP metadata API
Une API avec des métadonnées d'un fournisseur de cloud est une source constante d'escalade potentielle (démontrée
par la récente
prime de bogue de Shopify ), donc des tests spéciaux confirmant que l'API est bloquée sur le réseau de conteneurs aideront à se protéger contre les erreurs de configuration.
10. Numérisez des images et exécutez IDS
Les serveurs Web sont un tremplin pour attaquer les réseaux auxquels ils sont connectés. L'analyse des fichiers installés dans les images vous permet de vérifier qu'il n'existe aucune vulnérabilité connue qu'un attaquant pourrait utiliser pour accéder à distance au conteneur. Les systèmes de détection d'intrusion (IDS) enregistrent ces événements s'ils se produisent.Kubernetes permet des soumissions au cluster via un ensemble de vérifications de contrôle (dans le
contrôleur d'admission ), qui s'appliquent non seulement aux pods, mais également à d'autres ressources comme les
déploiements . Dans ceux-ci, chaque sous-marin peut être validé pour l'admission ou son contenu peut être modifié, en plus des webhooks du côté backend sont désormais également pris en charge.

Ces webhooks peuvent être utilisés par des outils d'analyse d'images de conteneur pour vérifier les images avant leur déploiement sur le cluster. Les images qui échouent à la validation ne recevront pas l'approbation du contrôleur.
L'analyse des images de conteneurs à la recherche de vulnérabilités connues permet de réduire le temps pendant lequel un attaquant peut tirer parti d'un CVE ouvert. Pour empêcher le déploiement d'images présentant des vulnérabilités critiques dans le pipeline de déploiement, vous pouvez utiliser des utilitaires gratuits tels que
Clair de CoreOS et
Micro Scanner d'Aqua.
Des outils tels que
Grafeas vous permettent de stocker des métadonnées d'image pour des vérifications continues de conformité et de vulnérabilité à l'aide d'une signature de conteneur unique (ou d'un hachage spécial d'
adressage de contenu ). La numérisation d'une image de conteneur à l'aide de ce hachage équivaut à numériser des images déployées en production et peut être effectuée en continu sans avoir besoin d'accéder aux environnements de production.
Des vulnérabilités 0day inconnues existeront toujours, donc Kubernetes devrait déployer un système de détection d'intrusion comme
Twistlock ,
Aqua ou
Sysdig Secure . IDS détecte un comportement inhabituel dans le conteneur et l'arrête ou le tue.
Falco de Sysdig est un moteur de règles Open Source et le point de départ de cet écosystème.
Partie 3: L'avenir
La prochaine étape de la sécurité dans «l'évolution du cloud natif» semble être le maillage de service, bien que son adoption ne se produise pas immédiatement: cette migration nécessite de déplacer la complexité des applications vers l'infrastructure de maillage, et les organisations doivent mettre en œuvre cette meilleure pratique.

11. Lancez le maillage de service
Le maillage de service est un réseau de connexions chiffrées persistantes établies entre des «proxy connectés» (similaires à «side-car») , des proxys hautes performances comme Envoy et Linkerd. Il apporte la gestion, la surveillance et les politiques du trafic, le tout sans modification des microservices.Le transfert de la sécurité et du code réseau des microservices vers un ensemble de bibliothèques partagées et testées au combat était déjà possible avec
Linkerd , et
Istio de Google, IBM et Lyft a apporté une alternative à cet espace. Avec l'ajout de
SPIFFE pour l'identité cryptographique de chaque module et de nombreuses autres fonctionnalités, Istio peut simplifier le déploiement de la sécurité réseau de nouvelle génération.
Dans les réseaux de «confiance zéro», il peut ne pas être nécessaire d'avoir un pare-feu traditionnel ou des politiques de réseau Kubernetes, car chaque interaction se produit à l'aide de mTLS (Mutual TLS), qui non seulement garantit la sécurité de l'interaction, mais confirme également l'identité des deux services. .
Ce passage des approches réseau traditionnelles aux principes de sécurité du monde de Cloud Native ne sera pas facile pour ceux qui ont une mentalité de sécurité traditionnelle. Comme introduction à ce nouveau monde, nous recommandons fortement
le livre Zero Trust Networking par
Evan Gilman de SPIFFE.
Istio 0.8 LTS est actuellement disponible et le projet approche rapidement de sa version 1.0. Le versioning du projet en termes de stabilité est réalisé de manière similaire au modèle Kubernetes: un noyau stable avec des API distinctes pour lesquelles leur statut alpha ou beta est indiqué à l'aide d'espaces de noms. Attendez-vous à voir Istio se développer dans les prochains mois.
Conclusion
Les applications cloud natives disposent d'un ensemble plus détaillé de primitives de sécurité légères qui aident à protéger les charges de travail et l'infrastructure. La puissance et la flexibilité de ces outils sont à la fois une bénédiction et une malédiction: sans une automatisation suffisante [pour leur utilisation], exposer des applications dangereuses pour aller au-delà du conteneur ou leur modèle d'isolement est devenu encore plus facile.
Les utilitaires de protection sont plus accessibles que jamais, cependant, pour réduire le potentiel d'attaque et le risque de configurations incorrectes, vous devez les utiliser avec prudence.
Si la sécurité ralentit la vitesse de l’organisation à apporter des changements, ce ne sera jamais une priorité. L'utilisation des principes de la livraison continue en relation avec la chaîne d'approvisionnement des logiciels permet à l'organisation d'atteindre la conformité réglementaire, un audit continu et une gestion améliorée sans affecter les performances de l'entreprise.
L'amélioration rapide et incrémentielle de la sécurité est le moyen le plus simple avec une suite de tests complète. Continuous Security — pipeline', , , .
PS du traducteur
Lisez aussi dans notre blog: