Sécurisez vos secrets Kubernetes en 5 minutes chrono

Vos mots de passe en base64 sont une passoire. Apprenez à implémenter External Secrets Operator pour synchroniser vos coffres-forts cloud nativement sans jamais exposer vos clés.

Le leurre du Base64 et l'impératif de sécurité Kubernetes

Architecture conceptuelle montrant la synchronisation sécurisée des secrets d'un coffre cloud vers Kubernetes

Stocker des secrets applicatifs au sein de Kubernetes à l'aide de l'objet natif Secret revient à encoder de manière simpliste une information sensible en Base64. Cette méthode offre une illusion de sécurité immédiatement brisée par n'importe quel utilisateur ou processus malveillant disposant d'un simple droit de lecture sur le namespace. Pour assurer une véritable étanchéité de vos environnements, il est indispensable de déléguer la gestion, la rotation et le stockage de vos clés à un coffre-fort externe managé, tout en permettant à vos applications de les consommer nativement.

Le piège de la sérialisation en clair et le défi du GitOps

Le déploiement moderne s'appuie massivement sur des méthodologies GitOps, où l'intégralité de l'infrastructure et de la configuration applicative est versionnée dans un dépôt Git. Écrire des secrets natifs Kubernetes dans vos fichiers YAML, même encodés en Base64, est une faille de sécurité critique car le Base64 n'est pas un chiffrement mais un simple format de sérialisation. N'importe quel développeur ou outil de CI/CD ayant accès au dépôt Git peut décoder instantanément vos mots de passe de base de données ou vos clés API tierces.

Pour résoudre ce problème structurel, l'utilisation de l'outil External Secrets Operator s'impose comme le standard de l'industrie. Cet opérateur Kubernetes fait office de passerelle dynamique entre vos fournisseurs de secrets externes (comme AWS Secrets Manager, HashiCorp Vault ou Google Secret Manager) et l'API Kubernetes. Il permet de récupérer de manière sécurisée les informations sensibles à la volée, sans jamais stocker la moindre clé secrète en clair dans vos configurations versionnées.

Mise en place de l'environnement et installation de l'opérateur

Avant d'entamer l'implémentation opérationnelle, nous devons déployer le contrôleur au sein de notre cluster Kubernetes à l'aide du gestionnaire de paquets Helm. Cette méthode garantit l'application de toutes les ressources personnalisées nécessaires, y compris les définitions de ressources personnalisées (CRD) indispensables au bon fonctionnement de l'opérateur.

# Ajout du dépôt Helm officiel pour External Secrets Operator
helm repo add external-secrets https://charts.external-secrets.io

# Mise à jour des index locaux pour récupérer les dernières versions stables
helm repo update

# Installation de l'opérateur dans un namespace dédié avec création automatique de ce dernier
helm install external-secrets external-secrets/external-secrets \
  --namespace external-secrets \
  --create-namespace \
  --set installCRDs=true

La commande helm install déploie trois composants principaux dans le namespace external-secrets : le contrôleur principal, l'injecteur de webhook pour la validation des schémas, et le validateur de certificats. L'argument --set installCRDs=true est crucial car il installe les Custom Resource Definitions requises pour manipuler nos futurs objets personnalisés.

Mise en œuvre initiale : valider le flux de secrets

Pour s'assurer du bon fonctionnement de la chaîne de communication, nous allons mettre en place une configuration de validation de principe simple. Ce premier jalon fonctionnel utilise une authentification par clé d'API statique stockée localement afin de valider la connectivité globale.

Déclaration du magasin de secrets et du récepteur local

Nous commençons par créer un objet SecretStore. Cet objet indique à l'opérateur comment se connecter à notre fournisseur de secrets (ici AWS Secrets Manager) et quelles informations d'identification utiliser pour valider l'accès.

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: aws-store-validation
  namespace: staging
spec:
  provider:
    aws:
      service: SecretsManager
      region: eu-west-3
      auth:
        secretRef:
          accessKeyIDSecretRef:
            name: aws-static-creds
            key: access-key-id
          secretAccessKeySecretRef:
            name: aws-static-creds
            key: secret-access-key

Examinons en détail la configuration de cette ressource technique :

  • spec.provider.aws.service : Indique à l'opérateur que le fournisseur cible est le service managé AWS Secrets Manager.
  • spec.provider.aws.region : Spécifie la région géographique AWS où les secrets applicatifs sont physiquement stockés.
  • spec.provider.aws.auth.secretRef : Pointe vers un secret Kubernetes préexistant contenant des clés d'accès AWS statiques. Cette approche est utile pour un test initial mais doit être proscrite en environnement de production.

Nous déclarons maintenant l'objet ExternalSecret. C'est cette ressource qui va commander à l'opérateur d'extraire la donnée du coffre AWS pour générer le secret Kubernetes natif final.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-db-secret
  namespace: staging
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-store-validation
    kind: SecretStore
  target:
    name: k8s-db-secret-native
    creationPolicy: Owner
  data:
    - secretKey: database-password
      remoteRef:
        key: staging/database/credentials
        property: password

Voici l'analyse des paramètres clés de cet objet de synchronisation :

  • spec.refreshInterval : Intervalle de temps après lequel l'opérateur interroge à nouveau le coffre externe pour vérifier si une rotation de clé a eu lieu.
  • spec.target.name : Nom du secret natif Kubernetes qui sera créé et géré dynamiquement par l'opérateur.
  • spec.target.creationPolicy : La valeur Owner indique que l'opérateur gère l'intégralité du cycle de vie du secret natif et le supprimera si la ressource parent est détruite.
  • spec.data.remoteRef.key : Le chemin exact ou le nom de l'entrée de secret enregistrée dans AWS Secrets Manager.
  • spec.data.remoteRef.property : La clé spécifique du payload JSON stocké dans le coffre distant dont on souhaite extraire la valeur.

Configuration de niveau production avec authentification sans clé

Workflow d'authentification IRSA entre Kubernetes et AWS Secrets Manager

Dans un environnement de production hautement sécurisé, l'utilisation de clés d'accès statiques AWS est une faille de sécurité majeure. Si un attaquant parvient à compromettre le cluster, il pourrait extraire ces clés à vie longue. Nous devons implémenter le mécanisme d'authentification IAM Roles for Service Accounts (IRSA) pour éliminer totalement l'usage de credentials persistants.

L'architecture de sécurité par identité fédérée

Le principe de l'identité fédérée repose sur l'établissement d'une relation de confiance mutuelle entre le fournisseur d'identité OIDC de votre cluster Kubernetes et le service de gestion des accès de votre fournisseur cloud.

Flux détaillé d'accès aux secrets Kubernetes via authentification IAM fédérée OIDC

Le schéma ci-dessus illustre le flux d'accès sécurisé et temporaire. L'opérateur s'associe à un compte de service Kubernetes configuré avec une annotation spécifique contenant l'identifiant du rôle cloud. Lors de la requête, le jeton Web d'identité de Kubernetes est échangé contre un jeton de session temporaire AWS via STS. Ce mécanisme élimine le risque lié à la fuite de clés statiques.

Le ClusterSecretStore global de production

Pour optimiser l'administration de nos ressources, nous allons déclarer un ClusterSecretStore. Contrairement au SecretStore standard limité à un seul namespace, cette ressource globale est accessible depuis l'ensemble du cluster Kubernetes, simplifiant grandement la maintenance opérationnelle.

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: aws-cluster-store
spec:
  provider:
    aws:
      service: SecretsManager
      region: eu-west-3
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-irsa-sa
            namespace: external-secrets

Détaillons les paramètres de cette ressource d'infrastructure globale :

  • kind: ClusterSecretStore : Déclare une portée globale à l'échelle du cluster. Les équipes de développement peuvent ainsi lier leurs demandes de secrets sans avoir à configurer l'accès au cloud.
  • spec.provider.aws.auth.jwt : Configure l'authentification par jeton de compte de service. L'opérateur utilisera le jeton projeté dans le pod par le compte de service external-secrets-irsa-sa du namespace external-secrets pour s'authentifier de manière transparente auprès d'AWS.

Le composant ExternalSecret résilient et templatisé

En production, il est fréquent que les applications exigent des formats spécifiques de fichiers de configuration ou des structures JSON complexes regroupant plusieurs variables d'environnement. Nous exploitons ici les fonctionnalités de templating avancées d'External Secrets Operator.

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: payment-service-secrets
  namespace: production
spec:
  refreshInterval: 15m
  secretStoreRef:
    name: aws-cluster-store
    kind: ClusterSecretStore
  target:
    name: payment-app-config
    creationPolicy: Owner
    template:
      engineVersion: v2
      type: Opaque
      data:
        application.yaml: |
          database:
            username: "{{ .db_user }}"
            password: "{{ .db_password }}"
          api:
            key: "{{ .api_key }}"
  data:
    - secretKey: db_user
      remoteRef:
        key: prod/payment/db
        property: username
    - secretKey: db_password
      remoteRef:
        key: prod/payment/db
        property: password
    - secretKey: api_key
      remoteRef:
        key: prod/api/gateway
        property: private_key

Cette configuration avancée apporte de nombreux avantages pour la résilience de vos environnements :

  • spec.refreshInterval : Abaissé à 15 minutes pour garantir une propagation rapide des secrets lors des rotations automatiques planifiées sur le service de coffre-fort cloud.
  • spec.target.template.engineVersion : L'utilisation de la version de moteur v2 permet de manipuler les données via des fonctions Go-template avancées pour reformater des chaînes à la volée.
  • spec.target.template.data : Nous générons directement un fichier application.yaml complet contenant nos variables injectées de manière structurée. L'application consomme ainsi un unique fichier de configuration monté dans son système de fichiers, simplifiant le code applicatif.

Pour vérifier la bonne synchronisation de vos ressources de production, vous pouvez interroger l'état d'avancement directement via l'interface en ligne de commande kubectl.

# Commande d'inspection du statut de synchronisation
kubectl get externalsecret payment-service-secrets -n production

Résultat:

NAME                      STORE               REFRESH   STATUS         READY
payment-service-secrets   aws-cluster-store   15m       SecretSynced   True

Isolation des environnements

Pour des raisons de sécurité évidentes en production, isolez vos configurations. N'utilisez pas un unique ClusterSecretStore pour le staging et la production si vos environnements AWS sous-jacents sont physiquement cloisonnés sur différents comptes cloud.

Exploitation, surveillance et dépannage du système

Visualisation des métriques et alertes de synchronisation de secrets Kubernetes

L'utilisation d'un opérateur de synchronisation implique une dépendance vis-à-vis des composants réseau et des APIs du cloud provider. En tant que DevOps, vous devez mettre en place un système de supervision proactif et connaître les commandes clés pour investiguer en cas de dysfonctionnement de la chaîne de synchronisation.

Surveillance opérationnelle et logs de synchronisation

En cas de rupture de synchronisation, l'analyse détaillée des événements Kubernetes de l'objet défaillant fournit généralement la cause exacte de l'anomalie.

# Extraction des événements spécifiques liés à la ressource en échec
kubectl describe externalsecret payment-service-secrets -n production

Résultat:

Events:
  Type     Reason   Age                From                            Message
  ----     ------   ----               ----                            -------
  Warning  UpdateFailed 4m (x12 over 1h)  external-secrets-controller     AccessDenied: User is not authorized to perform: secretsmanager:GetSecretValue on resource: prod/payment/db

Dans l'exemple de diagnostic ci-dessus, le message d'erreur indique clairement un problème d'autorisations IAM au niveau du cloud provider. Le rôle associé au compte de service Kubernetes ne dispose pas de la politique de sécurité adéquate l'autorisant à lire la ressource prod/payment/db. La résolution de cette anomalie passe par la correction de la politique d'accès AWS IAM sans qu'il soit nécessaire de redéployer le moindre fichier de configuration dans Kubernetes.

Limites de requêtes d'API Cloud

La valeur par défaut du paramètre refreshInterval ne doit pas être configurée avec une fréquence trop élevée (comme quelques secondes). Un intervalle trop agressif risque de saturer les quotas d'appels d'API de votre fournisseur de cloud (API Throttling), bloquant l'accès à l'ensemble de vos secrets et pénalisant l'ensemble de vos applications.

Vers un cycle de vie sécurisé de vos données sensibles

External Secrets Operator s'affirme comme le composant incontournable pour les infrastructures résilientes et modernes basées sur GitOps. En retirant la responsabilité du stockage des secrets de vos dépôts de code et en automatisant l'intégration avec des coffres cloud robustes via IAM, vous éradiquez définitivement le risque de fuite d'informations sensibles.

Les prochaines étapes pour vos grappes Kubernetes

Pour parfaire la sécurité opérationnelle de vos grappes de production, couplez l'implémentation d'External Secrets Operator à un gestionnaire d'admission de politiques de sécurité comme Kyverno ou OPA Gatekeeper. Ces outils vous permettront d'interdire purement et simplement la création manuelle de secrets natifs orphelins, imposant à vos équipes d'utiliser la cinématique de validation sécurisée décrite dans ce guide.

Espace commentaire

Écrire un commentaire

Rejoignez la discussion

Vous devez être connecté pour poster un message.

29 commentaires

rbesnard
Auteur
Avatar de rbesnard
rbesnard
Auteur

Oui, l'opérateur est agnostique. Il suffit de changer le provider dans le SecretStore. Regarde la doc pour le bloc vault, c'est très similaire.

25/05/2026 à 00:02

Est-ce qu'on peut utiliser ça avec Vault ? Le doc parle surtout d'AWS.

24/05/2026 à 16:45
rbesnard
Auteur
Avatar de rbesnard
rbesnard
Auteur

Fais un kubectl describe externalsecret <ton-secret> -n <namespace>. Si tu vois AccessDenied, c'est ton rôle IAM qui n'a pas les permissions secretsmanager:GetSecretValue. Check tes politiques AWS.

24/05/2026 à 12:00
astrid-gay
Membre
Avatar de astrid-gay
astrid-gay
Membre

Super tuto. Par contre j'ai une erreur UpdateFailed en boucle. Je n'arrive pas à comprendre si c'est un problème de droits sur le ClusterSecretStore ou autre chose.

24/05/2026 à 05:27

Rejoindre la communauté

Recevoir les derniers articles gratuitement en créant un compte !

S'inscrire