
Cheatsheet sécurité CKS. Examen 100% pratique orienté sécurisation de clusters Kubernetes. Cette page couvre les commandes essentielles, organisées par domaine d’examen.
Tableau “besoin → commande”
Section intitulée « Tableau “besoin → commande” »| Besoin | Commande |
|---|---|
| Bloquer tout trafic entrant | k apply -f deny-all-ingress.yaml |
| Créer un Role pour lire les pods | k create role pod-reader --verb=get,list --resource=pods |
| Tester les permissions d’un SA | k auth can-i get pods --as=system:serviceaccount:ns:sa |
| Appliquer PSA restricted | k label ns <ns> pod-security.kubernetes.io/enforce=restricted |
| Scanner une image | trivy image --severity CRITICAL,HIGH nginx:1.25 |
| Audit CIS Benchmark | kube-bench run --targets master |
| Voir les audit logs | cat /var/log/kubernetes/audit.log | jq 'select(.verb=="create")' |
| Identifier les alertes Falco | tail -f /var/log/falco/falco.log |
| Vérifier le chiffrement etcd | cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep encryption |
| Obtenir le digest d’une image | skopeo inspect docker://nginx:1.25 | jq -r '.Digest' |
Bootstrap de session
Section intitulée « Bootstrap de session »# Alias fondamentauxalias k=kubectlalias kn='kubectl config set-context --current --namespace'export do="--dry-run=client -o yaml"
# Autocomplétionsource <(kubectl completion bash)complete -F __start_kubectl k
# Vérifier le contextekubectl config current-contextCluster Setup (10%)
Section intitulée « Cluster Setup (10%) »NetworkPolicy deny-all Ingress
Section intitulée « NetworkPolicy deny-all Ingress »apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: deny-all-ingress namespace: productionspec: podSelector: {} policyTypes: - IngressBut : Bloquer tout trafic entrant vers les Pods du namespace.
Piège : podSelector: {} = tous les Pods. Sans règle ingress, tout est bloqué.
NetworkPolicy deny-all Egress
Section intitulée « NetworkPolicy deny-all Egress »apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: deny-all-egress namespace: productionspec: podSelector: {} policyTypes: - EgressPiège : Bloque aussi le DNS ! Ajoutez une règle autorisant le port 53 vers CoreDNS si nécessaire.
NetworkPolicy autoriser un flux précis
Section intitulée « NetworkPolicy autoriser un flux précis »apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-frontend-to-backend namespace: productionspec: podSelector: matchLabels: app: backend policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 8080kube-bench — Audit CIS
Section intitulée « kube-bench — Audit CIS »kube-bench run --targets masterkube-bench run --targets nodekube-bench run --json > cis-results.jsonBut : Vérifier la conformité CIS Benchmark.
Piège : Les résultats FAIL nécessitent souvent d’éditer /etc/kubernetes/manifests/*.yaml.
TLS Ingress — Secret
Section intitulée « TLS Ingress — Secret »openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout tls.key -out tls.crt -subj "/CN=app.example.com"
kubectl create secret tls app-tls --cert=tls.crt --key=tls.key -n productionCluster Hardening (15%)
Section intitulée « Cluster Hardening (15%) »RBAC — Créer un Role
Section intitulée « RBAC — Créer un Role »k create role pod-reader --verb=get,list,watch --resource=pods -n productionk create clusterrole node-viewer --verb=get,list --resource=nodesBut : Limiter les permissions au strict nécessaire.
Piège : Role = namespaced, ClusterRole = cluster-scoped.
RBAC — Lier à un ServiceAccount
Section intitulée « RBAC — Lier à un ServiceAccount »k create rolebinding app-pod-reader \ --role=pod-reader \ --serviceaccount=production:app-sa \ -n productionFormat SA : namespace:nom
RBAC — Tester les permissions
Section intitulée « RBAC — Tester les permissions »k auth can-i create pods -n production --as=system:serviceaccount:production:app-sak auth can-i --list --as=system:serviceaccount:production:app-sa -n productionBut : Vérifier qu’un SA n’a pas trop de droits.
Piège : Toujours tester avec --as= avant de valider.
Identifier les permissions excessives
Section intitulée « Identifier les permissions excessives »# Qui a cluster-admin ?kubectl get clusterrolebindings -o json | \ jq '.items[] | select(.roleRef.name=="cluster-admin") | {name: .metadata.name, subjects: .subjects}'ServiceAccount — Désactiver automount
Section intitulée « ServiceAccount — Désactiver automount »apiVersion: v1kind: Podmetadata: name: secure-podspec: serviceAccountName: restricted-sa automountServiceAccountToken: false containers: - name: app image: nginx:1.25But : Empêcher le Pod d’appeler l’API Kubernetes. Piège : Par défaut, le token est monté automatiquement.
API Server — Vérifier les flags
Section intitulée « API Server — Vérifier les flags »cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -E "anonymous-auth|authorization-mode|admission-plugins"Flags sécurisés :
--anonymous-auth=false--authorization-mode=Node,RBAC--enable-admission-plugins=NodeRestriction
System Hardening (15%)
Section intitulée « System Hardening (15%) »Seccomp — RuntimeDefault
Section intitulée « Seccomp — RuntimeDefault »apiVersion: v1kind: Podmetadata: name: seccomp-podspec: securityContext: seccompProfile: type: RuntimeDefault containers: - name: app image: nginx:1.25But : Filtrer les syscalls dangereux (ptrace, mount, etc.). Piège : Sans Seccomp, le conteneur peut exécuter n’importe quel syscall.
AppArmor — Annotation
Section intitulée « AppArmor — Annotation »apiVersion: v1kind: Podmetadata: name: apparmor-pod annotations: container.apparmor.security.beta.kubernetes.io/app: localhost/k8s-nginxspec: containers: - name: app image: nginx:1.25Format : container.apparmor.security.beta.kubernetes.io/<container-name>: localhost/<profile-name>
# Vérifier les profils chargésaa-statuscat /sys/kernel/security/apparmor/profilesSecurityContext — Pod durci complet
Section intitulée « SecurityContext — Pod durci complet »apiVersion: v1kind: Podmetadata: name: hardened-podspec: securityContext: runAsNonRoot: true runAsUser: 1000 seccompProfile: type: RuntimeDefault containers: - name: app image: nginx:1.25 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {}Champs à mémoriser :
runAsNonRoot: trueallowPrivilegeEscalation: falsereadOnlyRootFilesystem: truecapabilities.drop: ["ALL"]
Identifier les Pods à risque
Section intitulée « Identifier les Pods à risque »# Pods privilégiéskubectl get pods -A -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged == true) | .metadata.namespace + "/" + .metadata.name'
# Pods rootkubectl get pods -A -o json | jq '.items[] | select(.spec.securityContext.runAsNonRoot != true) | .metadata.namespace + "/" + .metadata.name'Minimize Vulnerabilities (20%)
Section intitulée « Minimize Vulnerabilities (20%) »Pod Security Admission — Appliquer restricted
Section intitulée « Pod Security Admission — Appliquer restricted »kubectl label namespace production \ pod-security.kubernetes.io/enforce=restricted \ pod-security.kubernetes.io/enforce-version=latestNiveaux : privileged (aucune restriction) < baseline < restricted (strict).
Modes : enforce (bloque), warn (avertit), audit (log).
Tester un Pod non conforme
Section intitulée « Tester un Pod non conforme »kubectl run test --image=nginx -n production --dry-run=serverSortie si enforce=restricted : Error from server (Forbidden): violates PodSecurity "restricted:latest"
Secrets — Chiffrement etcd
Section intitulée « Secrets — Chiffrement etcd »# Vérifier si configurécat /etc/kubernetes/manifests/kube-apiserver.yaml | grep encryptioncat /etc/kubernetes/enc/enc.yamlPiège : Les Secrets sont encodés base64 par défaut, pas chiffrés !
OPA Gatekeeper — Contraintes
Section intitulée « OPA Gatekeeper — Contraintes »kubectl get constraintskubectl describe constraint no-latest-tagBut : Politiques d’admission personnalisées (bloquer tag latest, etc.).
Supply Chain Security (20%)
Section intitulée « Supply Chain Security (20%) »Trivy — Scanner une image
Section intitulée « Trivy — Scanner une image »trivy image nginx:1.25trivy image --severity CRITICAL,HIGH nginx:1.25trivy image --ignore-unfixed nginx:1.25trivy image --format json -o results.json nginx:1.25But : Détecter les CVE avant déploiement.
Piège : --ignore-unfixed = montre uniquement les CVE avec patch disponible.
Trivy — Scanner le cluster
Section intitulée « Trivy — Scanner le cluster »trivy k8s --report summary clusterScanner toutes les images du cluster
Section intitulée « Scanner toutes les images du cluster »for img in $(kubectl get pods -A -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n' | sort -u); do echo "=== $img ===" trivy image --severity CRITICAL --quiet "$img"doneImage digest — Obtenir le hash
Section intitulée « Image digest — Obtenir le hash »skopeo inspect docker://nginx:1.25 | jq -r '.Digest'Usage dans un Pod :
image: nginx@sha256:6db391d1c0cfb30588ba0bf72ea999404f2764febf0f1f196acd5867ac7efa7eBut : Image immuable, protège contre le tag poisoning.
Identifier les Pods sans digest
Section intitulée « Identifier les Pods sans digest »kubectl get pods -A -o json | jq '.items[] | select(.spec.containers[].image | test(":[^@]+$")) | .metadata.namespace + "/" + .metadata.name'Runtime Security (20%)
Section intitulée « Runtime Security (20%) »Audit logs — Analyser
Section intitulée « Audit logs — Analyser »# Créations de Secretscat /var/log/kubernetes/audit.log | jq 'select(.verb=="create" and .objectRef.resource=="secrets")'
# Actions d'un utilisateurcat /var/log/kubernetes/audit.log | jq 'select(.user.username=="suspect")'
# Échecscat /var/log/kubernetes/audit.log | jq 'select(.responseStatus.code >= 400)'But : Investigation post-incident.
Créer une policy d’audit
Section intitulée « Créer une policy d’audit »apiVersion: audit.k8s.io/v1kind: Policyrules:- level: Metadata resources: - group: "" resources: ["secrets"]- level: RequestResponse resources: - group: "" resources: ["pods"]- level: None users: ["system:kube-proxy"]Niveaux : None < Metadata < Request < RequestResponse
Falco — Lire les alertes
Section intitulée « Falco — Lire les alertes »tail -f /var/log/falco/falco.loggrep "Critical\|Error\|Warning" /var/log/falco/falco.logsystemctl status falcoBut : Détection runtime (shell dans conteneur, accès fichiers sensibles, etc.).
Immuabilité — Filesystem lecture seule
Section intitulée « Immuabilité — Filesystem lecture seule »securityContext: readOnlyRootFilesystem: truevolumeMounts:- name: tmp mountPath: /tmpvolumes:- name: tmp emptyDir: {}But : L’attaquant ne peut pas modifier les binaires.
Piège : L’application doit écrire quelque part → ajouter des volumes emptyDir.
Commandes à connaître par cœur
Section intitulée « Commandes à connaître par cœur »# NetworkPolicyk get netpol -Ak apply -f deny-all.yaml
# RBACk create role <name> --verb=get,list --resource=podsk create rolebinding <name> --role=<role> --serviceaccount=<ns>:<sa>k auth can-i <verb> <resource> --as=system:serviceaccount:<ns>:<sa>
# PSAk label ns <ns> pod-security.kubernetes.io/enforce=restricted
# Scantrivy image --severity CRITICAL,HIGH <image>kube-bench run --targets master
# Audit/Falcocat /var/log/kubernetes/audit.log | jq '...'tail -f /var/log/falco/falco.log
# AppArmor/Seccompaa-statusls /var/lib/kubelet/seccomp/À retrouver vite dans la doc
Section intitulée « À retrouver vite dans la doc »Ne perdez pas de temps à mémoriser, utilisez kubectl explain :
- Syntaxe complète NetworkPolicy (
k explain networkpolicy.spec) - Champs securityContext (
k explain pod.spec.securityContext) - Format EncryptionConfiguration etcd
- Options ImagePolicyWebhook
- Règles Falco personnalisées
- Policy Gatekeeper ConstraintTemplate (syntaxe Rego)
Dépannage rapide
Section intitulée « Dépannage rapide »| Problème | Commande |
|---|---|
| Pod rejeté par PSA | k run test --dry-run=server |
| NetworkPolicy inactive | k describe netpol <name> |
| Audit logs vides | grep audit /etc/kubernetes/manifests/kube-apiserver.yaml |
| Falco silencieux | systemctl status falco |
| API Server down | journalctl -u kubelet + vérifier YAML |
| kube-bench FAIL | kube-bench run --targets master |
À retenir
Section intitulée « À retenir »- NetworkPolicies : deny-all d’abord, whitelist ensuite
- RBAC : moindre privilège, jamais cluster-admin sauf pour admins
- ServiceAccounts :
automountServiceAccountToken: falsepar défaut - SecurityContext :
drop ALL,readOnlyRootFilesystem: true,runAsNonRoot: true - PSA :
restrictedsur les namespaces de production - Secrets : chiffrement etcd obligatoire, RBAC strict
- Trivy : scanner CRITICAL/HIGH avant déploiement
- Digests : utiliser
@sha256:...pour images immuables - Audit logs : tracer les actions pour investigation
- Falco : surveiller les alertes runtime en continu