E-NO
Kubernetes 9 min de lecture

Durcissement de la sécurité des Secrets Kubernetes avec exemples pratiques

calendar_today Publié : 2026-07-10
update Dernière mise à jour : 2026-07-10
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Durcissement de la sécurité des Secrets Kubernetes avec exemples pratiques ».

Intro

Les Secrets Kubernetes stockent identifiants, jetons, clés d'API et autres configurations sensibles. Traitez-les comme des joyaux de la couronne. Ce guide montre comment durcir les Secrets dans de vrais clusters avec des exemples YAML et des commandes kubectl pratiques. Vous apprendrez à :

  • Inventorier et classifier les Secrets selon leur sensibilité et leur propriétaire
  • Activer le chiffrement au repos pour les Secrets dans le magasin de données de l'API server (serveur d'API)
  • Appliquer le principe du moindre privilège avec RBAC (Role‑Based Access Control) : contrôle d'accès basé sur les rôles, et des comptes de service dédiés par charge de travail
  • Consommer les Secrets via des montages de fichiers en lecture seule au lieu de variables d'environnement
  • Ajouter des politiques réseau default‑deny au niveau de l'espace de noms avec des autorisations explicites
  • Exécuter des vérifications rapides, à faible risque, pour valider le durcissement

Question rapide 1 sur 2

Laquelle des propositions suivantes est une alternative recommandée à l'utilisation de Secrets pour un composant cloud-native qui doit s'authentifier auprès d'une autre application au sein du même cluster Kubernetes ?

Dans le passage de référence [4], il est indiqué que si votre composant cloud-native doit s'authentifier auprès d'une autre application dont vous savez qu'elle s'exécute dans le même cluster Kubernetes, vous pouvez utiliser un ServiceAccount et ses tokens pour identifier votre client.

Workflow Overview

Appliquez les étapes espace de noms par espace de noms :

  1. Inventorier et classifier
  2. Chiffrer au repos
  3. Verrouiller RBAC et comptes de service
  4. Utiliser les Secrets en toute sécurité dans les pods
  5. Contenir l'exposition réseau
  6. Ajouter des contrôles et de la rotation

1) Inventorier et classifier les Secrets

Listez tous les Secrets et identifiez les propriétaires :

kubectl get secrets -A -o wide

Ajoutez des étiquettes cohérentes pour faciliter les requêtes :

kubectl label secret db-credentials owner=payments purpose=database -n team-apps --overwrite

Créez un nouveau Secret avec un nommage clair et une portée définie :

kubectl create secret generic db-credentials \
  --from-literal=username=app \
  --from-literal=password='S3cr3t!' \
  -n team-apps

Conseil : préférez un Secret par application ou composant plutôt que des Secrets partagés entre plusieurs applications. Cela limite le rayon d'impact et simplifie le RBAC.

2) Chiffrer les Secrets au repos

Les Secrets résident dans le magasin de données de l'API server (Application Programming Interface server : serveur d'interface de programmation d'applications). Activez le chiffrement pour qu'ils soient chiffrés sur disque.

Exemple de EncryptionConfiguration (fournisseur aescbc) :

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: <clé-32-octets-encodée-en-base64>
  - identity: {}

Étapes de haut niveau :

  • Placez le fichier sur chaque nœud control‑plane.
  • Démarrez l'API server avec --encryption-provider-config=/chemin/vers/config.yaml.
  • Redémarrez l'API server et lancez kubectl get secrets --all-namespaces -o json | kubectl replace -f - pour rechiffrer les données existantes.

Dans les clusters gérés, activez le paramètre « Secrets encryption » fourni par la plateforme.

3) Verrouiller RBAC et comptes de service

Accordez l'accès en lecture uniquement aux charges de travail qui ont besoin d'un Secret spécifique.

Compte de service qui ne monte pas le jeton par défaut :

apiVersion: v1
kind: ServiceAccount
metadata:
  name: web-sa
  namespace: team-apps
automountServiceAccountToken: false

Rôle autorisant get sur un seul Secret :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: read-db-credentials
  namespace: team-apps
rules:
- apiGroups: ["
  resources: ["secrets
d  resourceNames: ["db-credentials
d  verbs: ["get

RoleBinding :

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: bind-read-db-credentials
  namespace: team-apps
subjects:
- kind: ServiceAccount
  name: web-sa
  namespace: team-apps
roleRef:
  kind: Role
  name: read-db-credentials
  apiGroup: rbac.authorization.k8s.io

Testez :

kubectl auth can-i get secret db-credentials \
  --as=system:serviceaccount:team-apps:web-sa \
  -n team-apps

4) Utiliser les Secrets en toute sécurité dans les pods

Montez les Secrets comme des fichiers en lecture seule ; évitez les variables d'environnement qui peuvent fuiter dans les logs et /proc.

Extrait de spécification de pod (Deployment) :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: team-apps
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      serviceAccountName: web-sa
      automountServiceAccountToken: false
      containers:
      - name: app
        image: your-registry/web:1.0.0
        volumeMounts:
        - name: db-secret
          mountPath: /var/run/secrets/app
          readOnly: true
        env:
        - name: DB_USER_FILE
          value: /var/run/secrets/app/username
        - name: DB_PASS_FILE
          value: /var/run/secrets/app/password
      volumes:
      - name: db-secret
        secret:
          secretName: db-credentials

L'application lit les fichiers au démarrage (cat $DB_USER_FILE). Si les variables d'environnement sont inévitables, limitez-les aux conteneurs strictement nécessaires et n'utilise jamais envFrom avec un Secret entier.

Rendez les Secrets immuables pour empêcher les modifications accidentelles :

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: team-apps
type: Opaque
immutable: true
data:
  username: YXBw
  password: UzNjcjN0IQ==

La rotation se fait en créant db-credentials-v2, en mettant à jour le Deployment pour le référencer, en déployant le roulement, puis en supprimant l'ancien Secret après validation.

5) Contenir l'exposition réseau

Les politiques réseau ne protègent pas directement les Secrets, mais elles limitent les déplacements latéraux.

Refus par défaut de tout trafic entrant et sortant :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: team-apps
spec:
  podSelector: {}
  policyTypes: [Ingress, Egress]

Autorisez le trafic DNS sortant (adaptez les sélecteurs à votre cluster) :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-egress
  namespace: team-apps
spec:
  podSelector: {}
  policyTypes: [Egress]
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

Ajoutez des politiques d'autorisation explicites pour chaque dépendance requise.

6) Ajouter des vérifications et audits rapides

Exécutez ces contrôles légers régulièrement.

Qui peut lire quels Secrets

kubectl auth can-i --list \
  --as=system:serviceaccount:team-apps:web-sa \
  -n team-apps | grep secrets || true

Pods qui référencent des Secrets via des variables d'environnement (nécessite jq) :

kubectl get pods -A -o json | jq -r '
  .items[]
  | select((.spec.containers // [])
    | map(.env // [] | map(has("valueFrom
) and .valueFrom.secretKeyRef != null) | any) | any)
  | [.metadata.namespace, .metadata.name] | @tsv'

Secrets non immuables :

kubectl get secrets -A -o json | jq -r '
  .items[] | select(.immutable != true) | [.metadata.namespace, .metadata.name] | @tsv'

Rôles/ClusterRoles à portée large pouvant lire de nombreux Secrets :

kubectl get role,clusterrole -A -o yaml | grep -n "resources: \[secrets\]" || true

Confirmer le chiffrement au repos – inspectez le drapeau --encryption-provider-config de l'API server sur les nœuds control‑plane ou le réglage du service géré.

Question rapide 2 sur 2

Quelle est une raison clé d'éviter d'utiliser des variables d'environnement pour injecter des secrets dans les pods ?

Le passage de référence [1] indique : « Veuillez noter que la méthode des variables d'environnement peut être plus sujette aux fuites en raison des vidages de crash dans les journaux et de la nature non confidentielle des variables d'environnement sous Linux, contrairement au mécanisme de permissions sur les fichiers. »

Local Pilot Plan

Commencez petit, mesurez, puis étendez.

Périmètre

  • Espace de noms : team-apps
  • Charge de travail : un seul Deployment web qui a besoin de db-credentials

Critères de succès

  • Seul web-sa peut get le Secret db-credentials dans team-apps
  • Aucun pod dans team-apps ne consomme de Secrets via des variables d'environnement
  • L'espace de noms possède une politique réseau default‑deny avec des autorisations explicites

Étapes

  1. Créer l'espace de noms et le compte de service
   kubectl create namespace team-apps
   kubectl apply -f - <<'EOF'
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: web-sa
     namespace: team-apps
   automountServiceAccountToken: false
   EOF
  1. Créer le Secret
   kubectl create secret generic db-credentials \
     --from-literal=username=app \
     --from-literal=password='S3cr3t!' \
     -n team-apps
  1. Appliquer le RBAC au moindre privilège
   kubectl apply -f - <<'EOF'
   apiVersion: rbac.authorization.k8s.io/v1
   kind: Role
   metadata:
     name: read-db-credentials
     namespace: team-apps
   rules:
   - apiGroups: ["
     resources: ["secrets
d     resourceNames: ["db-credentials
d     verbs: ["get
   ---
   apiVersion: rbac.authorization.k8s.io/v1
   kind: RoleBinding
   metadata:
     name: bind-read-db-credentials
     namespace: team-apps
   subjects:
   - kind: ServiceAccount
     name: web-sa
     namespace: team-apps
   roleRef:
     kind: Role
     name: read-db-credentials
     apiGroup: rbac.authorization.k8s.io
   EOF
   kubectl auth can-i get secret db-credentials \
   --as=system:serviceaccount:team-apps:web-sa \
   -n team-apps
  1. Déployer l'application avec montage de Secrets en fichiers
   kubectl apply -f - <<'EOF'
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: web
     namespace: team-apps
   spec:
     replicas: 1
     selector:
       matchLabels:
         app: web
     template:
       metadata:
         labels:
           app: web
       spec:
         serviceAccountName: web-sa
         automountServiceAccountToken: false
         containers:
         - name: app
           image: your-registry/web:1.0.0
           volumeMounts:
           - name: db-secret
             mountPath: /var/run/secrets/app
             readOnly: true
           env:
           - name: DB_USER_FILE
             value: /var/run/secrets/app/username
           - name: DB_PASS_FILE
             value: /var/run/secrets/app/password
         volumes:
         - name: db-secret
           secret:
             secretName: db-credentials
   EOF
  1. Appliquer default‑deny et autoriser DNS
   kubectl apply -f - <<'EOF'
   apiVersion: networking.k8s.io/v1
   kind: NetworkPolicy
   metadata:
     name: default-deny-all
     namespace: team-apps
   spec:
     podSelector: {}
     policyTypes: [Ingress, Egress]
   ---
   apiVersion: networking.k8s.io/v1
   kind: NetworkPolicy
   metadata:
     name: allow-dns-egress
     namespace: team-apps
   spec:
     podSelector: {}
     policyTypes: [Egress]
     egress:
     - to:
       - namespaceSelector:
           matchLabels:
             kubernetes.io/metadata.name: kube-system
         podSelector:
           matchLabels:
             k8s-app: kube-dns
       ports:
       - protocol: UDP
         port: 53
       - protocol: TCP
         port: 53
   EOF
  1. Valider
   # Seul web-sa peut lire db-credentials
   kubectl auth can-i get secret db-credentials \
     --as=system:serviceaccount:team-apps:web-sa \
     -n team-apps

   # Le SA par défaut ne doit pas pouvoir
   kubectl auth can-i get secret db-credentials \
     --as=system:serviceaccount:team-apps:default \
     -n team-apps

   # Aucun pod ne consomme de Secrets via des variables d'env
   kubectl get pods -n team-apps -o json | jq -r '
     .items[]
     | select((.spec.containers // [])
       | map(.env // [] | map(has("valueFrom
d) and .valueFrom.secretKeyRef != null) | any) | any)
     | .metadata.name' | wc -l

   # Les politiques réseau existent
   kubectl get networkpolicy -n team-apps
  1. Documenter la rotation de db-credentials
  • Créer db-credentials-v2
  • Mettre à jour le Deployment pour référencer db-credentials-v2
  • Déployer le roulement et vérifier
  • Supprimer db-credentials après validation

Plan de retour arrière

  • Conservez l'ancien Secret jusqu'à la fin de la validation.
  • En cas d'échec du déploiement, rétablissez la référence au Secret précédent dans le Deployment et relancez les tests.

Conclusion

Vous disposez maintenant d'un chemin pratique pour durcir les Secrets Kubernetes : inventorier, chiffrer au repos, appliquer le moindre privilège, garder les Secrets hors des variables d'environnement, restreindre l'exposition réseau et vérifier avec des contrôles reproductibles. Lancez un pilote dans un espace de noms, mesurez les résultats, puis étendez progressivement.

Suivez quelques indicateurs clés au fur et à mesure de l'expansion :

  • Nombre de Secrets par espace de noms et présence d'étiquettes propriétaire
  • Rôles pouvant lire des Secrets arbitraires vs Rôles limités à des noms précis
  • Pods consommant des Secrets via variables d'environnement vs montages de fichiers
  • Espaces de noms couverts par des politiques réseau default‑deny

Une approche par étapes garde les changements sûrs et observables tout en améliorant votre posture de sécurité pas à pas.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO