>
E-NO
Kubernetes 8 min de lecture

Durcissement de la sécurité du versioning des Custom Resource Definitions Kubernetes : guide pratique

calendar_today Publié : 2026-08-26
update Dernière mise à jour : 2026-08-26
analytics Efficacité SEO : 100%
Illustration du guide technique pour « Durcissement de la sécurité du versioning des Custom Resource Definitions Kubernetes : guide pratique ».

Introduction

Les Custom Resource Definitions (CRD) de Kubernetes étendent l'API Kubernetes, mais le versioning introduit des risques de sécurité souvent négligés. Une CRD peut avoir plusieurs versions (par exemple, v1alpha1, v1beta1, v1), et chaque version peut avoir un schéma, des règles de validation et une logique de conversion différents. S'il n'est pas correctement sécurisé, le versioning peut entraîner une élévation de privilèges, une corruption des données ou des accès non intentionnels. Ce guide fournit une approche pratique pour durcir le versioning des CRD, avec des commandes concrètes, des exemples de configuration et des étapes de vérification.

Le public visé comprend les ingénieurs plateforme, les consultants DevOps et les équipes techniques de startups responsables de la maintenance des clusters Kubernetes. L'accent est mis sur la sécurité opérationnelle : observer avant de modifier, minimiser le rayon d'impact, utiliser des espaces réservés plutôt que des secrets, vérifier chaque étape et documenter les procédures de récupération.

Tout au long de ce guide, nous utilisons une CRD d'exemple appelée widgets.example.com pour illustrer les concepts. Nous supposons un cluster exécutant Kubernetes 1.25+ avec kubectl configuré et les autorisations appropriées pour créer des CRD et accéder au serveur d'API.

Inventaire des versions et de l'environnement

Avant d'effectuer toute modification, faites l'inventaire de l'état actuel de vos CRD et de leurs versions. Cela inclut l'identification des CRD installées, de leurs versions, du statut de stockage et des stratégies de conversion.

Commencez par lister toutes les CRD du cluster :

kubectl get crd

La sortie attendue comprend une liste des noms de CRD et leurs dates de création. Pour voir les détails d'une CRD spécifique, utilisez :

kubectl get crd widgets.example.com -o yaml

Cela affiche la spécification complète. Cherchez le champ spec.versions pour voir toutes les versions définies. Par exemple :

spec:
  versions:
    - name: v1beta1
      served: true
      storage: false
      schema: ...
    - name: v1
      served: true
      storage: true
      schema: ...

Prêtez attention à :

  • Quelle version est la version de stockage (une seule peut l'être).
  • Quelles versions sont servies (les clients peuvent les utiliser).
  • Si une stratégie de conversion est définie (par exemple, None ou Webhook).

Vérifiez si des webhooks de conversion sont configurés :

kubectl get crd widgets.example.com -o jsonpath='{.spec.conversion}'

Si la sortie inclut strategy: Webhook, alors la conversion est gérée par un webhook. Notez le service et le chemin du webhook, car c'est un risque de sécurité potentiel s'il n'est pas correctement authentifié.

Inspectez également les ressources personnalisées existantes de ce type pour voir quelles versions sont utilisées :

kubectl get widgets.example.com --all-namespaces -o wide

Le -o wide peut inclure la version dans la colonne VERSION. Sinon, utilisez -o custom-columns pour l'afficher :

kubectl get widgets.example.com --all-namespaces -o custom-columns=NAME:.metadata.name,NAMESPACE:.metadata.namespace,APIVERSION:.apiVersion

Enregistrez l'état actuel et les horodatages. Cet inventaire vous aide à comprendre l'impact de tout changement de versioning. Conservez une copie de la définition de la CRD et une liste des ressources avant de faire des modifications.

Liste de contrôle pratique pour l'inventaire de l'environnement :

  • kubectl version pour confirmer les versions du client et du serveur.
  • kubectl get crd widgets.example.com -o yaml > crd-backup.yaml pour sauvegarder la définition actuelle.
  • kubectl get widgets.example.com -A -o json > widgets-backup.json pour sauvegarder toutes les instances.
  • kubectl get apiservice | grep widgets.example.com pour voir le statut du service d'API agrégé.
  • kubectl describe crd widgets.example.com pour voir les événements et les conditions de statut.

Question rapide 1 sur 2

Quelle est la seule version qui peut être marquée comme version de stockage dans une CRD ?

Selon l'exemple de CRD, une CRD peut avoir plusieurs versions, mais une et une seule version doit être marquée comme version de stockage.

Chemin de configuration sécurisé

Lors de la configuration de la sécurité du versioning des CRD, suivez le principe du moindre privilège et validez tout. Le chemin sûr implique de définir des schémas appropriés, des RBAC et d'utiliser des webhooks de conversion de manière sécurisée.

1. Définir des schémas stricts

Chaque version de votre CRD doit avoir un schéma qui valide la structure et les contraintes. Utilisez la validation de schéma OpenAPI v3. Un schéma faible peut permettre des champs arbitraires, ce qui pourrait être exploité. Exemple pour v1 :

schema:
  openAPIV3Schema:
    type: object
    required: ["spec"]
    properties:
      spec:
        type: object
        required: ["size"]
        properties:
          size:
            type: integer
            minimum: 1
            maximum: 100
          replicas:
            type: integer
            minimum: 0
            maximum: 10
        additionalProperties: false
    additionalProperties: false

Définissez additionalProperties: false pour rejeter les champs inconnus. Cela empêche les attaquants d'injecter des données inattendues.

2. Implémenter des RBAC pour les versions de CRD

Les RBAC peuvent contrôler l'accès à des versions d'API spécifiques. Par défaut, les autorisations accordées sur une ressource s'appliquent à toutes les versions. Pour restreindre l'accès à certaines versions, vous pouvez utiliser resourceNames ou des rôles séparés. Par exemple, pour autoriser uniquement la lecture des ressources v1 mais pas v1beta1, créez un rôle :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: widget-v1-reader
rules:
- apiGroups: ["example.com"]
  resources: ["widgets"]
  verbs: ["get", "list", "watch"]
  # Pas de moyen de spécifier la version directement, mais vous pouvez utiliser resourceNames ou vous fier à l'agrégation.

En réalité, les RBAC de Kubernetes ne prennent pas en charge l'autorisation spécifique à une version directement. Le groupe d'API est spécifié, mais pas la version. Pour appliquer des restrictions de version, vous devez utiliser des webhooks d'admission ou des groupes d'API séparés par version. Alternativement, vous pouvez utiliser des politiques OPA/Gatekeeper. Nous couvrirons les webhooks d'admission plus tard.

3. Utiliser des webhooks de conversion de manière sécurisée

Si vous avez plusieurs versions, les webhooks de conversion permettent à Kubernetes de convertir les ressources entre les versions. Le webhook doit être servi via HTTPS avec un certificat valide. Configurez la conversion de la CRD avec caBundle pour faire confiance à l'autorité de certification du webhook. Exemple :

conversion:
  strategy: Webhook
  webhook:
    conversionReviewVersions: ["v1", "v1beta1"]
    clientConfig:
      service:
        namespace: conversion-webhook
        name: conversion-service
        path: /convert
      caBundle: <certificat CA encodé en base64>

Définissez toujours conversionReviewVersions sur les versions que votre webhook prend en charge. Assurez-vous que le service du webhook n'est accessible qu'à l'intérieur du cluster et utilisez une authentification mutuelle TLS si possible.

4. Appliquer les modifications graduellement

Lors de la modification du versioning des CRD, évitez de supprimer ou de modifier brusquement les versions servies. Suivez un processus graduel :

  • D'abord, ajoutez une nouvelle version avec served: true et storage: false.
  • Permettez aux clients de migrer, puis définissez storage: true après les tests.
  • Dépréciez l'ancienne version en définissant served: false plus tard.
  • Enfin, supprimez l'ancienne version si aucune ressource ne l'utilise.

Pour vérifier quelles ressources utilisent encore une ancienne version :

kubectl get widgets.example.com --all-namespaces --field-selector apiVersion=example.com/v1beta1

Ou utilisez :

kubectl get widgets.example.com --all-namespaces -o json | jq '.items[] | select(.apiVersion=="example.com/v1beta1")'

Exemple : Mise à jour sécurisée d'une CRD

Supposons que vous souhaitiez ajouter v2 comme nouvelle version de stockage. Étapes :

  1. Sauvegardez la CRD actuelle :
kubectl get crd widgets.example.com -o yaml > crd-backup.yaml
  1. Modifiez la CRD pour ajouter v2 avec served: true et storage: false :
kubectl edit crd widgets.example.com

Ajoutez sous spec.versions :

- name: v2
  served: true
  storage: false
  schema: ...

Enregistrez et quittez.

  1. Vérifiez que v2 est servie mais pas en stockage :
kubectl get crd widgets.example.com -o jsonpath='{.spec.versions[*].name} {"\n"}'
kubectl get crd widgets.example.com -o jsonpath='{.spec.versions[?(@.storage==true)].name}'

La première sortie attendue liste toutes les versions incluant v2, la deuxième sortie montre encore v1.

  1. Testez la création d'une ressource v2 :
kubectl apply -f - <<EOF
apiVersion: example.com/v2
kind: Widget
metadata:
  name: test-widget-v2
spec:
  size: 10
EOF
  1. Après un test réussi, basculez le stockage vers v2 :
kubectl patch crd widgets.example.com --type='json' -p='[{"op": "replace", "path": "/spec/versions/1/storage", "value": true}, {"op": "replace", "path": "/spec/versions/0/storage", "value": false}]'

(En supposant que l'ordre du tableau des versions : index 0 = v1, index 1 = v2). Ajustez les chemins en conséquence.

  1. Vérifiez que la version de stockage a changé :
kubectl get crd widgets.example.com -o jsonpath='{.spec.versions[?(@.storage==true)].name}'

Sortie : v2.

Vérification et diagnostic

Après avoir effectué des modifications, vérifiez que tout fonctionne comme prévu et diagnostiquez tout problème.

Vérifier le statut de la CRD

Utilisez kubectl describe crd pour voir les conditions de statut :

kubectl describe crd widgets.example.com

Cherchez la condition Established à true et aucun avertissement NonStructuralSchema. Si le schéma n'est pas structurel, Kubernetes peut rejeter la CRD ou ne pas la servir.

Tester les opérations sur les ressources

Essayez de créer, obtenir et lister des ressources dans chaque version :

# Créer une ressource v1
kubectl apply -f - <<EOF
apiVersion: example.com/v1
kind: Widget
metadata:
  name: test-v1
spec:
  size: 5
EOF

# Obtenir via v1
kubectl get widgets.v1.example.com test-v1 -o yaml

# Obtenir via v2 (la conversion devrait avoir lieu si le webhook est configuré)
kubectl get widgets.v2.example.com test-v1 -o yaml

Si la conversion n'est pas définie, la récupération via v2 échouera car la version de stockage est v2 mais l'objet a été créé avec v1 ? En réalité, si le stockage est v2 et que vous créez une ressource v1, Kubernetes la convertira en v2 pour le stockage si un webhook de conversion existe, ou si aucune conversion, il la rejettera. Vérifiez le comportement attendu.

Vérifier les journaux d'audit

Activez la journalisation d'audit de Kubernetes pour surveiller l'accès aux versions de CRD. Cherchez les requêtes vers /apis/example.com/v1beta1/widgets si vous essayez de détecter l'utilisation de versions dépréciées. Exemple de fragment de politique d'audit :

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  resources:
  - group: "example.com"
    resources: ["widgets"]

Ensuite, consultez les journaux d'audit avec des outils comme kubectl logs -n kube-system kube-apiserver-<node> ou si vous utilisez un Kubernetes géré, utilisez la journalisation du fournisseur cloud.

Diagnostiquer les échecs des webhooks de conversion

Si le webhook de conversion est mal configuré, vous pouvez voir des erreurs comme :

Vérifiez les journaux du pod du webhook :

  • conversion webhook not reachable
  • x509: certificate signed by unknown authority
kubectl logs -n conversion-webhook deploy/conversion-service

Testez l'endpoint du webhook directement depuis l'intérieur du cluster :

kubectl run -it --rm debug --image=curlimages/curl -- sh
# dans le pod :
curl -k https://conversion-service.conversion-webhook.svc/convert -d '{"apiVersion":"apiextensions.k8s.io/v1","kind":"ConversionReview",...}'

Assurez-vous que caBundle est correctement encodé en base64. Utilisez base64 -w0 sur Linux.

Question rapide 2 sur 2

Lors de l'ajout de v2 en tant que nouvelle version servie mais pas comme version de stockage, que devez-vous définir pour les champs `served` et `storage` de v2 ?

L'exemple de mise à jour sécurisée d'une CRD du guide montre l'ajout de v2 avec served: true et storage: false pour tester avant de basculer le stockage.

Modes de défaillance et récupération

Comprenez les modes de défaillance courants et comment récupérer.

Défaillance : CRD avec schéma invalide provoque des erreurs du serveur d'API

Si vous appliquez une CRD avec un schéma non structurel ou un OpenAPI invalide, le serveur d'API peut la rejeter. Exemple d'erreur :

The CustomResourceDefinition "widgets.example.com" is invalid: spec.validation.openAPIV3Schema.properties[spec].type: Required value: must not be empty at root

Récupération : corrigez le schéma et réappliquez. Si la CRD fonctionnait auparavant et que vous avez commis une erreur, restaurez à partir de la sauvegarde :

kubectl apply -f crd-backup.yaml

Défaillance : Suppression d'une version encore utilisée

Si vous définissez served: false pour une version qui a des ressources, ces ressources deviennent inaccessibles via l'API, bien qu'elles restent dans etcd. Vous devez les migrer avant de supprimer le service. Pour récupérer, définissez à nouveau served: true et effectuez la migration.

Défaillance : Webhook de conversion hors service

Si le webhook de conversion est hors service, les requêtes nécessitant une conversion échoueront. Exemple d'erreur : conversion webhook not reachable. Récupération : corrigez le déploiement du webhook. Si le webhook ne peut pas être restauré rapidement, vous pouvez changer la stratégie conversion en None temporairement, mais cela peut entraîner une incohérence des données si plusieurs versions existent. Il est préférable de restaurer le webhook.

Défaillance : Changement de version de stockage entraîne une perte de données

Changer la version de stockage sans conversion appropriée peut entraîner une perte de données si des champs sont supprimés. Assurez-vous toujours que le webhook de conversion est en place et testé avant de basculer le stockage. Si une perte de données se produit, restaurez à partir d'une sauvegarde etcd si disponible.

Étapes de récupération

  1. Identifiez l'opération en échec et les messages d'erreur.
  2. Vérifiez les événements du cluster : kubectl get events --sort-by='.lastTimestamp'.
  3. Vérifiez les journaux du serveur d'API pour des erreurs détaillées (nécessite un accès au plan de contrôle).
  4. Sauvegardez l'état actuel : kubectl get crd widgets.example.com -o yaml > crd-current.yaml.
  5. Tentez de revenir à la CRD précédemment bonne : kubectl apply -f crd-backup.yaml.
  6. Si des ressources sont manquantes ou corrompues, restaurez à partir d'un instantané etcd (voir la récupération après sinistre etcd).
  7. Après la récupération, vérifiez avec des requêtes en lecture seule avant d'activer les écritures.

Liste de contrôle opérationnelle

Utilisez cette liste de contrôle avant et après avoir apporté des modifications de versioning.

#ContrôleCommande / ActionRésultat attendu
1Sauvegarder la CRDkubectl get crd widgets.example.com -o yaml > crd-backup-$(date +%Y%m%d).yamlFichier créé avec la définition actuelle de la CRD
2Lister les ressources existantes par versionkubectl get widgets.example.com -A -o json | jq -r '.items[] | .apiVersion' | sort | uniq -cNombre de ressources par version
3Vérifier la stratégie de conversionkubectl get crd widgets.example.com -o jsonpath='{.spec.conversion.strategy}'None ou Webhook
4Valider le schéma hors ligneUtilisez kubectl apply --dry-run=client -f crd-new.yamlAucune erreur de schéma
5Tester d'abord sur un cluster de stagingAppliquez les modifications à un cluster non-productionAucun comportement inattendu
6Surveiller les journaux d'auditSuivez les journaux d'audit pour le groupe example.comSeulement les requêtes attendues
7Vérifier le service de chaque versionkubectl get crd widgets.example.com -o jsonpath='{range .spec.versions[*]}{.name}{" served="}{.served}{" storage="}{.storage}{"\n"}{end}'Indicateurs served/storage corrects
8Tester le CRUD des ressources dans toutes les versions serviesScript qui crée, obtient, liste, supprime une ressource de test dans chaque versionSuccès sans erreurs
9Vérifier l'utilisation de versions dépréciéeskubectl get widgets.example.com -A -o json | jq '.items[] | select(.apiVersion | contains("v1beta1"))'Liste vide (aucune ressource utilisant une version dépréciée)
10Documenter la procédure de rollbackRédiger un runbook pour annuler les modifications de CRDÉtapes claires pour la récupération

Conclusion

Sécuriser le versioning des CRD Kubernetes est essentiel pour maintenir un système d'extension d'API robuste et sûr. En suivant les pratiques de ce guide—inventorier les versions, définir des schémas stricts, contrôler l'accès, utiliser des webhooks de conversion de manière sécurisée et vérifier les modifications—vous pouvez prévenir de nombreux problèmes de sécurité et opérationnels courants.

Commencez par une vérification à faible risque : inventoriez vos CRD actuelles, identifiez leurs versions et paramètres de conversion, et exécutez les commandes de la liste de contrôle. Ensuite, implémentez progressivement des améliorations, en testant chaque changement dans un environnement de staging. N'oubliez jamais de sauvegarder avant de faire des modifications et d'avoir un plan de retour en arrière.

Un flux de travail fiable rend les échecs visibles, protège les données sensibles, limite les changements aux ressources prévues et définit la récupération avant qu'un incident ne force la décision. Appliquez ces principes pour durcir dès aujourd'hui le versioning de vos CRD Kubernetes.

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