
Les secrets sont essentiels au fonctionnement de nombreux systèmes en production. Leur exposition involontaire constitue l'un des risques majeurs à maîtriser. Les développeurs doivent tout mettre en œuvre pour protéger les secrets de leurs applications.
Le problème se corse encore lorsqu'une entreprise migre vers une architecture en microservices et que plusieurs services doivent accéder à différents secrets pour fonctionner correctement. D'où un nouveau défi : comment distribuer, gérer, surveiller et faire tourner les secrets applicatifs sans risquer une exposition involontaire ?
Les Secrets Kubernetes
Kubernetes propose un objet appelé Secret, qui sert à stocker les données sensibles d'une application : mots de passe, clés SSH, clés d'API, tokens, etc. Un Secret Kubernetes peut être injecté dans un conteneur de Pod sous forme de variable d'environnement ou monté en tant que fichier. Les Secrets Kubernetes permettent ainsi de dissocier les données sensibles et la configuration du déploiement applicatif.
Par exemple, un Secret Kubernetes peut être créé avec la commande kubectl create secret :
https://gist.github.com/02c582490747681776f1f480ec2f4165
ou via un fichier Kubernetes db-credentials.yaml qui décrit le même secret :
Attention : stocker des données sensibles dans un Secret Kubernetes ne suffit pas à les sécuriser. Par défaut, toutes les données contenues dans les Secrets Kubernetes sont en clair, simplement encodées en base64.
Depuis la version 1.13, Kubernetes prend en charge le chiffrement des données des Secrets au repos, via l'objet EncryptionConfiguration associé à un fournisseur de chiffrement intégré ou externe.
Liste des fournisseurs de chiffrement actuellement pris en charge :
Fournisseurs intégrés : aescbc, aesgsm, secretbox
Cela dit, le chiffrement des Secrets au repos n'est pas activé par défaut. Et même activé, il reste insuffisant à lui seul et ne constitue pas une solution complète de gestion des secrets.
Une solution complète doit également couvrir la distribution et la rotation des secrets, un contrôle d'accès granulaire, la journalisation des accès, le suivi de l'utilisation, le versionnage, un stockage fortement chiffré, une API simple à utiliser, un ou plusieurs SDK clients, sans oublier quelques autres fonctionnalités utiles.
Gestion des secrets dans le cloud
Plusieurs fournisseurs cloud proposent des services de gestion des secrets, intégrés à leur plateforme, pour vous aider à protéger les secrets nécessaires à l'accès aux applications, services et API. Ces services évitent d'inscrire en dur des informations sensibles en clair et de réinventer un cycle de vie maison pour la gestion des secrets. Ils permettent de contrôler l'accès aux secrets applicatifs grâce à des permissions fines et à un audit complet.
Intégrer Kubernetes aux services de gestion des secrets
De manière générale, n'importe quelle application peut utiliser le SDK ou l'API du fournisseur pour accéder aux secrets stockés dans un service de gestion des secrets. Cela suppose le plus souvent de modifier le code applicatif ou de recourir à des scripts d'amorçage ou à des Init containers s'appuyant sur des outils CLI clients ou des API web.
Simplifiez les choses avec l'outil secrets-init
Nous publions aujourd'hui doitintl/secrets-init — un outil open source (Apache License 2.0) qui simplifie l'intégration des services cloud-native de gestion des secrets avec des workloads conteneurisés s'exécutant sur des clusters Kubernetes managés ou auto-gérés.
Concrètement, secrets-init est un système init minimaliste, conçu pour s'exécuter en tant que PID 1 dans un environnement de conteneur, à la manière de dumb-init. Il offre une intégration fluide avec plusieurs services cloud-native de gestion des secrets, parmi lesquels :
Pourquoi un système init dans un conteneur Docker ?
Consultez l'explication du dépôt Yelp dumb-init
En résumé :
- Transmission correcte des signaux
- Récupération des processus zombies orphelins
Ce que fait secrets-init
Le binaire secrets-init s'exécute en tant que PID 1, comme un système init simple servant de ENTRYPOINT ou de première commande du conteneur. Il lance un processus enfant et relaie tous les signaux système à la session enracinée sur ce processus enfant. C'est l'essence même d'un processus init. Par ailleurs, secrets-init transmet presque toutes les variables d'environnement sans modification, en remplaçant les variables de secret spéciales par les valeurs récupérées auprès des services de gestion des secrets.
Intégration avec Docker
secrets-init est un fichier binaire compilé statiquement (sans dépendance externe), qui s'embarque facilement dans n'importe quelle image Docker. Il vous suffit de télécharger le binaire secrets-init et de l'utiliser comme ENTRYPOINT du conteneur Docker.
Par exemple :
https://gist.github.com/7efe25155c034ee1b978a2477b3224e4
Intégration avec Kubernetes
Pour utiliser secrets-init avec un objet Kubernetes (Pod/Deployment/Job, etc.) sans modifier l'image Docker, injectez secrets-init dans le Pod cible via un initContainer. Vous pouvez utiliser l'image Docker doitint/secrets-init ou créer la vôtre. Copiez le binaire secrets-init depuis l'init container vers un volume partagé, puis modifiez la command du Pod pour exécuter secrets-init en première commande.
Intégration avec AWS Secrets Manager
Pour commencer à utiliser secrets-init avec AWS Secrets Manager, l'utilisateur doit définir un ARN de secret AWS comme valeur de variable d'environnement. secrets-init résoudra alors cette valeur, à partir de l'ARN spécifié, vers la valeur du secret référencé.
Exemple d'utilisation de secrets-init avec un Job Kubernetes :
https://gist.github.com/6ae6d57ed08b26c64f534f87fc1872df
Intégration avec AWS Systems Manager Parameter Store
AWS Systems Manager Parameter Store permet de stocker des paramètres applicatifs en clair ou chiffrés (assimilables à des secrets).
Comme dans l'exemple précédent, l'utilisateur peut indiquer un ARN AWS Parameter Store comme valeur de variable d'environnement. secrets-init résoudra alors cette valeur, à partir de l'ARN spécifié, vers la valeur du paramètre référencé.
Exemple de format AWS Systems Manager Parameter Store :
https://gist.github.com/9a7a83ec1659c391412557e5af340f42
Pour résoudre les secrets AWS depuis AWS Secrets Manager et Parameter Store, secrets-init doit s'exécuter sous un rôle IAM disposant des permissions nécessaires pour accéder aux secrets souhaités.
Cela passe par l'attribution d'un rôle IAM à un Pod Kubernetes ou à une tâche ECS. Voir l'article EKS Introducing fine-grained IAM roles for service accounts.
Il est aussi possible d'attribuer un rôle IAM à l'instance EC2 sur laquelle s'exécute le conteneur, mais cette option est nettement moins sécurisée et n'est pas recommandée.
Intégration avec Google Secret Manager
Google Cloud a récemment lancé un nouveau service pour gérer les secrets dans le cloud : Google Secret Manager
L'utilisateur peut indiquer un nom de secret Google, avec le préfixe reconnu par secrets-init (gcp:secretmanager:) suivi du nom du secret (projects/{PROJECT_ID}/secrets/{SECRET_NAME} ou projects/{PROJECT_ID}/secrets/{SECRET_NAME}/versions/{VERSION}), comme valeur de variable d'environnement. secrets-init résoudra alors cette valeur, à partir du nom spécifié, vers la valeur du secret référencé.
https://gist.github.com/65d46eb2b1fe44417a9d91828c94712d
Pour résoudre les secrets Google depuis Google Secret Manager, secrets-init doit s'exécuter sous un rôle IAM disposant des permissions nécessaires pour accéder aux secrets souhaités.
Cela passe par l'attribution d'un rôle IAM à un Pod Kubernetes via Workload Identity. Il est aussi possible d'attribuer un rôle IAM à l'instance GCE sur laquelle s'exécute le conteneur, mais cette option est moins sécurisée.
(15–03–2020) Mise à jour : Admission Webhook Kubernetes
Le projet kube-secrets-init implémente un admission webhook Kubernetes qui injecte un initContainer dans tout Pod comportant des références explicites (variables d'environnement) ou implicites (Secrets et ConfigMaps Kubernetes) à des secrets cloud.
Liens utiles
- Article du blog DoiT Kubernetes GKE Workload Identity
- Dépôt GitHub doitintl/secrets-init
- Dépôt GitHub de l'admission webhook Kubernetes kube-secrets-init
Conclusion
J'espère que cet article vous sera utile. N'hésitez pas à partager vos commentaires et vos questions.
Envie d'en lire davantage ? Consultez notre blog ou suivez Alexei sur Twitter.