Aller au contenu
English
English
Conteneurs & Orchestration high

Kyverno, Policy Engine Kubernetes en YAML et CEL

50 min de lecture

Logo Kubernetes

Kyverno est un policy engine Kubernetes qui permet de valider, muter, générer des ressources et vérifier les signatures d'images. Projet CNCF Graduated depuis mars 2026, Kyverno utilise des policies YAML et supporte CEL. Ce guide est utile en complément d'une préparation CKS pour traduire les exigences sécurité en policies concrètes.

Un point de calendrier à connaître avant d'écrire votre première policy, parce qu'il détermine quelle syntaxe apprendre. Les policy types CEL sont arrivés en deux temps : ValidatingPolicy et ImageValidatingPolicy en v1.14, puis MutatingPolicy, GeneratingPolicy et DeletingPolicy en v1.15. Depuis la v1.19, les CRD historiques ClusterPolicy, Policy et CleanupPolicy sont dépréciés, leur suppression étant annoncée pour la v1.20. La dépréciation se voit : depuis cette version, les CRD portent deprecated: true et l'API renvoie un avertissement à chaque application.

La conséquence pratique : si vous démarrez aujourd'hui, écrivez vos policies en CEL. Le DSL YAML historique reste présent dans ce guide parce que la plupart des clusters en production en sont encore là et qu'il faut savoir le lire, pas parce qu'il faudrait en écrire de nouvelles.

Vous n'avez d'ailleurs pas à vous en souvenir : l'API vous le dit à chaque apply.

Sortie
Warning: kyverno.io/v1 ClusterPolicy is deprecated and will be removed in a
future release; migrate to ValidatingPolicy, MutatingPolicy, GeneratingPolicy
or ImageValidatingPolicy (policies.kyverno.io)

La ressource est créée malgré tout et fonctionne normalement : c'est un avertissement, pas un refus. Le groupe policies.kyverno.io/v1 offre par ailleurs plus de types que les cinq cités ici, chacun ayant une variante à portée de namespace : NamespacedValidatingPolicy, NamespacedMutatingPolicy et ainsi de suite. Utile quand une équipe doit poser ses propres règles sans toucher au cluster entier.

Un mot sur le positionnement par rapport à la CKS : le curriculum de la certification ne cite pas Kyverno comme compétence requise. Il mentionne Pod Security Standards, registres autorisés, signature et validation d'artefacts et analyse statique. Kyverno est un outil pratique pour implémenter ces exigences sur un cluster réel, mais ce n'est pas un sujet d'examen en soi.

  • Quand utiliser Kyverno (et quand ne pas l'utiliser)
  • Installer Kyverno et comprendre sa complexité opérationnelle
  • Créer des policies de validation orientées sécurité
  • Vérifier les signatures d'images (Supply Chain Security)
  • Diagnostiquer les violations avec les PolicyReports

Kyverno suit un cycle de versions aligné sur Kubernetes. Chaque version majeure en supporte plusieurs, mais les fonctionnalités disponibles varient d'une combinaison à l'autre : c'est le couple Kyverno et Kubernetes qu'il faut vérifier, pas l'un des deux isolément.

KyvernoChart HelmNotes
1.19.x3.9.xBranche courante, celle de ce guide ; dépréciation des CRD kyverno.io/v1
1.18.x3.8.xBranche précédente
1.17.x3.7.xFin de support

Le support communautaire dure environ trois mois par branche mineure : la sortie de la version n+1 met fin aux correctifs de la version n. Le projet annonce tester la 1.19 sur Kubernetes 1.33 à 1.35. Les versions hors de cette plage, dont les 1.36 et 1.37 de cette formation, peuvent fonctionner, mais elles ne sont pas testées par le projet : les exemples ci-dessous ont été rejoués ici, ce qui n'est pas une garantie de support.

Les exemples de ce guide ont été rejoués sur Kyverno v1.19.1, installé par le chart 3.9.1, sur un cluster Kubernetes 1.37. L'installation prend une quarantaine de secondes et déploie quatre contrôleurs : admission, background, cleanup et reports. Ce n'est donc pas un composant d'appoint, et c'est une raison de plus de mesurer son impact avant de le passer en mode bloquant.

Chaque outil a son domaine d'excellence. Ce tableau vous aide à choisir en fonction de votre besoin réel, pas de la popularité de l'outil.

BesoinOutil recommandéPourquoi
Validation simple, pas de dépendanceVAPNatif, GA depuis K8s 1.30
Profils sécurité standard (runAsNonRoot...)Pod Security Admission3 profils prêts à l'emploi
Mutation simple (defaults)MutatingAdmissionPolicyNatif et activé depuis K8s 1.36
Mutation avancée (sidecars, foreach, contexte)KyvernoPlus riche que CEL seul
Génération automatique (NetworkPolicies)KyvernoFonctionnalité unique
Vérification signatures imagesKyvernoIntégration Cosign/Sigstore
Culture OPA/Rego existanteGatekeeperÉcosystème Rego

Règle de décision simple : si vous avez besoin de génération, de vérification de signature ou d'une mutation que CEL ne sait pas exprimer, Kyverno est probablement le bon choix. Sinon, commencez par les solutions natives : PSA, ValidatingAdmissionPolicy, et MutatingAdmissionPolicy depuis la 1.36.

Ce partage a bougé en cours de route, et la version de votre cluster décide. Jusqu'à Kubernetes 1.35, l'API server savait refuser une ressource avec une ValidatingAdmissionPolicy, sans savoir la modifier. Depuis la 1.36, MutatingAdmissionPolicy est GA et activée par défaut : la mutation simple en CEL est devenue native, et Kyverno 1.19 la prend d'ailleurs en charge.

Restent trois capacités sans équivalent natif : générer une ressource en réaction à une autre, interroger un registry pour vérifier une signature, et produire des PolicyReports. S'y ajoute une mutation plus riche que CEL, avec patchStrategicMerge, contexte et foreach. C'est ce qui justifie encore d'ajouter une dépendance au control plane.

  • Mutation riche : injecter des sidecars, appliquer une règle à chaque conteneur avec foreach, s'appuyer sur un contexte externe. Les defaults simples, eux, relèvent désormais de MutatingAdmissionPolicy
  • Génération : créer automatiquement NetworkPolicies, Secrets, ResourceQuotas
  • Vérification d'images : Cosign, Sigstore, attestations SLSA
  • PolicyReports : audit de conformité natif

Le point commun de ces quatre situations est le rapport bénéfice / dette d'exploitation. Chaque webhook ajouté au cluster est un composant à maintenir, à mettre à jour au rythme de Kubernetes et à surveiller. Si le besoin se couvre avec un mécanisme déjà présent dans l'API server, l'ajout de Kyverno coûte plus qu'il ne rapporte.

  • Validation simple sans mutation → préférez VAP (natif, pas de dépendance)
  • Defaults simples à poser → préférez MutatingAdmissionPolicy, native depuis la 1.36
  • Profils sécurité standards → préférez Pod Security Admission (plus simple)
  • Cluster sans HA → Kyverno est un webhook d'admission, composant sensible
  • Équipe déjà formée à Rego → préférez Gatekeeper

Installer Kyverno revient à insérer un composant entre l'API server et toutes les écritures de ressources du cluster. Cette position explique l'essentiel de ses contraintes d'exploitation : sa disponibilité conditionne celle des déploiements, ses certificats TLS ont une durée de vie limitée, et ses droits RBAC couvrent une large partie du cluster. Avant d'écrire une seule policy, décidez donc comment le cluster se comporte quand Kyverno est indisponible.

En production, déployez avec HA :

Fenêtre de terminal
helm install kyverno kyverno/kyverno \
--set admissionController.replicas=3 \
--set backgroundController.replicas=2 \
-n kyverno --create-namespace

Si Kyverno bloque le cluster :

Fenêtre de terminal
# Supprimer les webhooks en urgence
kubectl delete validatingwebhookconfiguration kyverno-resource-validating-webhook-cfg
kubectl delete mutatingwebhookconfiguration kyverno-resource-mutating-webhook-cfg

Deux méthodes coexistent, et le choix n'est pas cosmétique. Le chart Helm expose les réglages de production, nombre de réplicas par contrôleur, ressources, exclusions de namespaces, et permet une mise à jour maîtrisée. Le manifeste install.yaml déploie une configuration figée, pratique pour un cluster jetable mais difficile à personnaliser ensuite. Dans les deux cas, Kyverno doit vivre dans un namespace dédié : le projet interdit explicitement de le faire cohabiter avec d'autres applications, kube-system compris.

Fenêtre de terminal
# Ajouter le repo Helm
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
# Installer Kyverno avec HA
helm install kyverno kyverno/kyverno \
-n kyverno --create-namespace \
--set admissionController.replicas=2 \
--wait --timeout 5m

Vérifier l'installation :

Fenêtre de terminal
kubectl get pods -n kyverno
NAME READY STATUS RESTARTS AGE
kyverno-admission-controller-b469db77f-57xcn 1/1 Running 0 39s
kyverno-admission-controller-b469db77f-8k2lp 1/1 Running 0 39s
kyverno-background-controller-6674dc69f5-spbvp 1/1 Running 0 39s
kyverno-cleanup-controller-5bb56f66f4-psp8f 1/1 Running 0 39s
kyverno-reports-controller-647dd56678-56kmg 1/1 Running 0 39s

Cet exemple rejoint directement l'objectif CKS « Use appropriate pod security standards ». Les deux onglets produisent le même refus, par des chemins très différents : la version CEL évalue une expression booléenne sur l'objet soumis, là où la version historique compare la ressource à un motif YAML appliqué récursivement. La version CEL gagne sur la lisibilité des conditions complexes, notamment l'exclusion des namespaces système, qui tient ici en une seule ligne matchConditions.

apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata:
name: require-run-as-non-root
spec:
validationActions: [Deny]
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
matchConditions:
- name: exclude-system-ns
expression: >-
!(['kube-system','kyverno'].exists(ns, object.metadata.namespace == ns))
validations:
- expression: >-
object.spec.containers.all(c,
has(c.securityContext) &&
has(c.securityContext.runAsNonRoot) &&
c.securityContext.runAsNonRoot == true
)
message: "Tous les conteneurs doivent avoir runAsNonRoot: true."

Ces trois règles ferment les portes qui donnent au conteneur un accès direct au nœud : un volume hostPath monte un répertoire de l'hôte dans le pod, hostNetwork place le pod dans l'espace réseau du nœud, hostPID et hostIPC lui donnent vue sur les processus et la mémoire partagée de l'hôte. Chaque règle est indépendante et échoue séparément, ce qui rend le diagnostic lisible : Kyverno indique le chemin exact qui a déclenché le refus, par exemple rule deny-hostpath failed at path /spec/volumes/0/hostPath/.

Notez l'ancre =(volumes) : elle rend le contrôle conditionnel. Un pod sans aucun volume passe la règle au lieu d'échouer sur un champ absent.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: deny-host-access
spec:
background: true
rules:
- name: deny-hostpath
match:
any:
- resources:
kinds:
- Pod
validate:
failureAction: Enforce
message: "Les volumes hostPath sont interdits"
pattern:
spec:
=(volumes):
- X(hostPath): "null"
- name: deny-host-network
match:
any:
- resources:
kinds:
- Pod
validate:
failureAction: Enforce
message: "hostNetwork n'est pas autorisé"
pattern:
spec:
=(hostNetwork): false
- name: deny-host-pid-ipc
match:
any:
- resources:
kinds:
- Pod
validate:
failureAction: Enforce
message: "hostPID et hostIPC sont interdits"
pattern:
spec:
=(hostPID): false
=(hostIPC): false

Ce contrôle relie Kyverno au domaine Supply Chain Security de la CKS. La boucle foreach parcourt chaque conteneur du pod, ce qui évite l'angle mort classique d'une règle qui ne vérifierait que le premier. Attention au piège de l'image sans registre explicite : un manifeste qui demande nginx:1.29.2 ne correspond à aucun des motifs autorisés et sera refusé, alors que l'image viendrait bien de Docker Hub. Le développeur doit écrire docker.io/library/nginx:1.29.2 pour passer la règle. C'est l'effet recherché, à condition de l'expliquer dans le message d'erreur.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
spec:
background: true
rules:
- name: validate-registries
match:
any:
- resources:
kinds:
- Pod
validate:
failureAction: Enforce
message: "Images autorisées uniquement depuis gcr.io ou docker.io/library"
foreach:
- list: "request.object.spec.containers"
deny:
conditions:
all:
- key: "{{ element.image }}"
operator: AnyNotIn
value:
- "gcr.io/*"
- "docker.io/library/*"

Vérification des signatures d'images (Supply Chain)

Section intitulée « Vérification des signatures d'images (Supply Chain) »

Vérifier une signature à l'admission déplace le contrôle au dernier moment utile : peu importe ce qui s'est passé dans la chaîne de build, une image non signée par la clé attendue n'entre pas dans le cluster. Kyverno résout la référence d'image auprès du registre, récupère la signature Cosign associée et la valide contre la clé publique déclarée dans la policy. Conséquence à anticiper : le contrôleur d'admission a besoin d'un accès réseau sortant vers le registre, et un registre privé impose de lui fournir des identifiants de lecture.

ImageValidatingPolicy sépare deux préoccupations que la syntaxe historique mélangeait. Le bloc attestors déclare qui a le droit de signer ; le bloc validations décrit ce qu'on exige de l'image une fois la signature vérifiée. C'est là qu'on ajouterait une condition sur une attestation SLSA ou sur le contenu d'un SBOM.

Deux détails coûtent une heure de débogage si on les ignore, tous deux mesurés sur Kyverno 1.19.1. La clé publique ne vit pas dans un Secret : le champ key accepte data, du PEM en clair, ou kms, jamais secretRef, et l'API rejette la policy sur unknown field "spec.attestors[0].cosign.key.secretRef". Et le nom d'un attestor ne doit porter aucun tiret, parce qu'il est référencé depuis une expression CEL : my-cosign-key s'y lit comme une soustraction et rend undeclared reference to 'key'.

apiVersion: policies.kyverno.io/v1
kind: ImageValidatingPolicy
metadata:
name: verify-image-signature
spec:
validationActions: [Deny]
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
matchImageReferences:
- glob: "gcr.io/my-project/*"
attestors:
- name: mycosignkey
cosign:
key:
data: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
validations:
- expression: >-
images.containers.map(image,
verifyImageSignatures(image, [attestors.mycosignkey])).all(e, e > 0)
message: "Image must be signed with our Cosign key."

Une expression "true" fonctionne aussi : les attestors sont évalués avant les validations, et une image non signée est refusée dans les deux cas. La différence est le message. Rejoué sur un cluster kind en 1.37.0, une image publique non signée donne image docker.io/library/busybox:1.37@sha256:… is not verified avec "true", contre Image must be signed with our Cosign key. avec l'appel explicite à verifyImageSignatures. Sur un refus en production, la seconde formulation vaut mieux.

La règle verifyImages inscrit la clé publique en clair dans la policy, ce qui reste acceptable, une clé publique n'étant pas un secret, mais complique la rotation : en changer oblige à modifier chaque policy concernée. Le background: false n'est pas un détail : vérifier des signatures suppose des appels réseau vers le registre, opération trop coûteuse pour être rejouée en tâche de fond sur toutes les ressources existantes.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-cosign
spec:
background: false
rules:
- name: verify-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "gcr.io/my-project/*"
failureAction: Enforce
attestors:
- entries:
- keys:
publicKeys: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----

La mutation permet de modifier automatiquement les ressources. C'est une fonctionnalité mature de Kyverno :

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-security-defaults
spec:
background: false # Mutation = pas de background
rules:
- name: add-security-context
match:
any:
- resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
spec:
containers:
- (name): "*"
securityContext:
+(runAsNonRoot): true
+(allowPrivilegeEscalation): false
+(readOnlyRootFilesystem): true

La syntaxe de mutation Kyverno utilise des opérateurs spéciaux pour contrôler le comportement. Comprendre ces opérateurs est essentiel pour écrire des mutations efficaces.

OpérateurEffetUsage
(key)Ancre conditionnelleCibler des conteneurs spécifiques
+(key)Ajouter si absentDefaults non intrusifs
<(key)Ancre globaleConditionner sur un autre endroit de la ressource

Exemple concret : Si vous voulez ajouter runAsNonRoot: true uniquement aux pods qui n'ont pas déjà cette valeur, utilisez +(runAsNonRoot): true. Cela évite de surcharger une configuration explicite du développeur.

La mutation ne connaît que ces trois ancres. Il n'existe pas d'ancre de suppression : pour retirer un champ, on passe par patchesJson6902 et son opération remove. Les ancres =() d'égalité, ^() d'existence et X() de négation appartiennent à la validation, pas à la mutation, et c'est là qu'on les rencontre plus haut dans ce guide.

La génération répond à un problème récurrent : une ressource de sécurité doit exister dans chaque namespace, et personne ne pense à la créer. Ici, la création d'un namespace déclenche celle d'une NetworkPolicy qui bloque par défaut tout le trafic entrant et sortant. Le champ synchronize: true change le contrat : Kyverno ne se contente pas de créer la ressource, il la remet en état si quelqu'un la modifie ou la supprime. C'est ce qui distingue la génération d'un simple script d'initialisation.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: generate-default-deny
spec:
rules:
- name: create-network-policy
match:
any:
- resources:
kinds:
- Namespace
exclude:
any:
- resources:
namespaces:
- kube-system
- kyverno
generate:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
name: default-deny
namespace: "{{request.object.metadata.name}}"
synchronize: true
data:
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress

Effet : Chaque nouveau namespace reçoit automatiquement une NetworkPolicy default-deny.

Déployer une policy directement en mode bloquant (Enforce) est risqué. Kyverno permet un déploiement progressif, avec deux modes et des dérogations par namespace.

ValeurEffetPhase
EnforceBloque la requêteProduction
AuditLog dans PolicyReportsDécouverte

Stratégie recommandée :

  1. Démarrez avec Audit : Les violations sont enregistrées dans les PolicyReports. Regardez-les pour comprendre l'impact.
  2. Ajoutez des dérogations : passez à Enforce sur les namespaces critiques, la production, tout en restant en Audit ailleurs.
  3. Généralisez Enforce : Une fois tous les workloads conformes, passez globalement en mode bloquant.

Stratégie progressive, avec dérogation sur la production :

spec:
rules:
- name: require-labels
match:
any:
- resources:
kinds:
- Pod
validate:
failureAction: Audit # Permissif par défaut
failureActionOverrides:
- action: Enforce
namespaces:
- production # Strict en production
message: "Le label 'app' est obligatoire"
pattern:
metadata:
labels:
app: "?*"

La CLI permet de tester les policies localement avant déploiement, sans cluster, ce qui la rend utilisable dans un job de pipeline. Deux commandes couvrent l'essentiel : kyverno apply évalue une policy contre un ou plusieurs manifestes et affiche le compte pass / fail / warn / error / skip, tandis que kyverno test exécute une suite de cas décrite dans un fichier kyverno-test.yaml. La commande apply sert aussi de contrôle syntaxique : une policy mal formée remonte en error avant même d'atteindre le cluster.

Fenêtre de terminal
# Installer via Krew
kubectl krew install kyverno
# Tester une policy sur un manifeste
kyverno apply ./policy.yaml --resource ./deployment.yaml
# Générer un fichier de test à partir d'une policy et d'une ressource
kyverno create test -p policy.yaml -r deployment.yaml \
--pass require-run-as-non-root,run-as-non-root,api-paiement,production,Pod
# Exécuter une suite de tests
kyverno test ./policy-tests/

La sortie de kyverno apply sur un pod qui viole la policy de l'exemple 1 ressemble à ceci :

Applying 1 policy rule(s) to 1 resource(s)...
policy require-run-as-non-root -> resource equipe-web/Pod/nginx-sans-securite failed:
1 - Tous les conteneurs doivent avoir runAsNonRoot: true.
pass: 0, fail: 1, warn: 0, error: 0, skip: 0

Un réflexe fréquent consiste à chercher une commande kyverno validate pour contrôler la syntaxe : elle n'existe pas. La CLI 1.19.1 expose apply, completion, create, docs, fix, jp, migrate, oci, test et version. Pour détecter une policy invalide, passez donc par kyverno apply.

La CLI Kyverno figure au programme de la certification Kyverno Certified Associate, délivrée par la Linux Foundation. Pour la CKS, elle n'est pas exigée mais reste un atout : elle permet d'éprouver une policy avant de la déployer, précisément le réflexe que l'examen valorise.

Quand une policy Kyverno « ne marche pas », le symptôme ne dit jamais lequel des deux problèmes vous avez. Soit la policy est rejetée ou inactive, et rien n'est évalué ; soit elle fonctionne mais ne sélectionne pas les ressources que vous croyiez viser, et son silence ressemble à une panne.

Cette distinction structure tout le diagnostic qui suit, et elle se tranche en une commande : une règle acceptée porte Ready: True dans son statut. Si c'est le cas, cherchez du côté du match et du mode d'application, jamais du côté de l'installation.

Le diagnostic suit deux pistes distinctes qu'il ne faut pas confondre. La première concerne la policy elle-même : est-elle acceptée par Kyverno ? La réponse est dans kubectl describe, au niveau du champ status.conditions. La seconde concerne les ressources évaluées : quelles violations ont été relevées ? Elles vivent dans les PolicyReports, à raison d'une ressource par objet évalué, alimentée seulement si la policy est en mode Audit ou si background: true est actif.

Fenêtre de terminal
# Lister les policies
kubectl get clusterpolicies,policies -A
# Détails d'une policy (erreurs, conditions)
kubectl describe clusterpolicy <name>
# PolicyReports (un rapport par objet évalué)
kubectl get policyreport -A
# Détail des violations
kubectl describe policyreport -n <namespace>
# Résumé rapide
kubectl get policyreport -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.summary}{"\n"}{end}'

Voici les problèmes les plus fréquents et comment les résoudre rapidement.

SymptômeCause probableSolution
Policy "Ready: False"Erreur de syntaxekubectl describe clusterpolicy
Pas de violation en Auditbackground: falseAjouter background: true
Mutation non appliquéePod déjà existantRecréer le pod
Webhook timeoutKyverno surchargéAugmenter replicas

Astuce : Le champ status.conditions d'une ClusterPolicy contient les messages d'erreur détaillés. Regardez-le en premier.

  1. Les CRD ClusterPolicy et CleanupPolicy sont dépréciées depuis la 1.19, leur suppression étant annoncée pour la v1.20
  2. validationFailureAction est déprécié : utilisez validate.failureAction au niveau de la règle
  3. Composant sensible, déployez avec HA, surveillez les webhooks
  4. Meilleur pont CKS : vérification d'images (Supply Chain Security)
  5. Si validation simple → préférez VAP (natif, pas de dépendance)
  6. Fonctionnalités uniques : génération et mutation mature
  7. kyverno validate n'existe pas : la CLI se contrôle avec kyverno apply et kyverno test

Ces questions portent uniquement sur ce guide : le positionnement de Kyverno face aux solutions natives, la syntaxe des règles de validation et de mutation, et la lecture des PolicyReport.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
8 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens ce site gratuitement, sans publicité, sans profilage et sans compte à créer. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn