TP16 : HTTPS avec cert-manager et IAM avec Keycloak (OIDC)
Deux briques transverses de toute plateforme : le chiffrement des échanges (HTTPS, certificats renouvelés automatiquement par cert-manager) et la gestion des identités et des accès (IAM) avec Keycloak, fournisseur d’identité open source qui implémente OAuth 2.0 et OpenID Connect. Sans nom de domaine public, Let’s Encrypt est impossible : vous créez votre propre autorité de certification de lab, comme le font les entreprises pour leurs services internes.
Fichiers de départ :
manifests.zip
1. Objectifs pédagogiques
À l’issue du TP, vous serez capable de :
- expliquer la chaîne de confiance TLS (CA, certificat, clé privée, SAN) ;
- installer cert-manager, créer une CA de lab et des ClusterIssuers, obtenir des certificats automatiquement pour un Ingress ;
- distinguer authentification et autorisation, OAuth 2.0 et OpenID Connect ;
- configurer un realm, un client OIDC, des rôles et des utilisateurs dans Keycloak ;
- protéger une application sans modifier son code avec oauth2-proxy, et filtrer l’accès par rôle ;
- lire le contenu d’un jeton JWT (claims
iss,aud,exp,realm_access.roles).
Les images de cette page sont des schémas explicatifs, pas des captures d’écran.
2. Environnement du TP
- Le cluster K3s du TP14 (≥ 2 Go de RAM libres pour Keycloak),
kubectlet Helm (TP15). - Dans
/etc/hostsde la VM de lab :<IP-du-nœud> whoami.lab.local keycloak.lab.local. - Déployer l’application :
kubectl apply -f manifests/00-app.yaml.
| Terme | Signification |
|---|---|
| CA | Autorité de certification : signe les certificats ; on lui fait confiance, donc à ce qu’elle signe. |
| SAN | Subject Alternative Name : noms DNS pour lesquels un certificat est valide. |
| Issuer | Ressource cert-manager qui sait signer des certificats (autosigné, CA, ACME…). |
| OAuth 2.0 | Protocole de délégation d’autorisation (jeton d’accès). |
| OpenID Connect | Couche d’authentification au-dessus d’OAuth 2.0 (jeton d’identité id_token). |
| Realm | Espace isolé de Keycloak : utilisateurs, rôles, clients. |
| Client | Application déclarée dans le realm, qui délègue l’authentification à Keycloak. |
3. Partie 1 : cert-manager et CA de lab
-
Installer cert-manager avec ses CRD :
helm repo add jetstack https://charts.jetstack.io && helm repo update helm install cert-manager jetstack/cert-manager -n cert-manager --create-namespace --set crds.enabled=true kubectl -n cert-manager get pods -
Compléter
manifests/10-issuers.yaml(émetteurcaqui utilise le Secretlab-ca), puis l’appliquer :kubectl apply -f manifests/10-issuers.yaml kubectl get clusterissuers # READY True kubectl -n cert-manager get certificate lab-ca -
Exporter le certificat public de la CA et lui faire confiance sur la VM de lab :
kubectl -n cert-manager get secret lab-ca -o jsonpath='{.data.ca\.crt}' | base64 -d > lab-ca.crt openssl x509 -in lab-ca.crt -noout -subject -dates sudo cp lab-ca.crt /usr/local/share/ca-certificates/lab-ca.crt && sudo update-ca-certificatesOn ne diffuse jamais la clé privée de la CA (
tls.key) : quiconque la possède peut émettre des certificats valides pour n’importe quel nom.
4. Partie 2 : Ingress HTTPS
-
Compléter
manifests/20-ingress-tls.yaml: bloctlset entréewebsecureuniquement. Appliquer, puis observer le travail de cert-manager :kubectl apply -f manifests/20-ingress-tls.yaml kubectl -n tp16 get certificate,certificaterequest kubectl -n tp16 describe certificate whoami-tls curl -v https://whoami.lab.local 2>&1 | grep -E 'subject|issuer|SSL certificate verify' -
Vérifier le SAN et la durée de validité (
openssl s_client -connect whoami.lab.local:443 -servername whoami.lab.local </dev/null | openssl x509 -noout -text | grep -A1 'Subject Alternative'). -
Supprimer le Secret
whoami-tls: que fait cert-manager ? Quel champ duCertificaterègle le renouvellement anticipé (renewBefore) ?
5. Partie 3 : Déployer Keycloak
-
Créer le mot de passe administrateur, appliquer la résolution DNS interne puis Keycloak :
kubectl create namespace keycloak kubectl -n keycloak create secret generic keycloak-admin --from-literal=password="$(openssl rand -base64 18)" kubectl apply -f manifests/05-coredns-custom.yaml # adapter l'IP, puis redémarrer coredns kubectl apply -f manifests/30-keycloak.yaml kubectl -n keycloak rollout status deploy/keycloak -
Se connecter à
https://keycloak.lab.local(utilisateuradmin, mot de passe lu dans le Secret).
6. Partie 4 : Realm, client, rôles et utilisateurs
-
Créer le realm
lab. -
Créer les rôles de realm
user,developer,admin. -
Créer trois utilisateurs (
alice→admin,bob→developer,carol→user) avec un mot de passe non temporaire. -
Créer le client
whoami:- Client authentication : On (client confidentiel), flux Standard flow uniquement ;
- Valid redirect URIs :
https://whoami.lab.local/oauth2/callback; - onglet Client scopes → whoami-dedicated : ajouter un mapper Audience qui inclut
whoamidans le claimaud; - copier le Client secret (onglet Credentials).
-
Obtenir un jeton pour
bobet le décoder (le flux password est utilisé ici uniquement pour l’observer ; activez temporairement Direct access grants, puis désactivez-le) :TOKEN=$(curl -s https://keycloak.lab.local/realms/lab/protocol/openid-connect/token \ -d grant_type=password -d client_id=whoami -d client_secret=<secret> \ -d username=bob -d password=<mdp> | jq -r .access_token) echo "$TOKEN" | cut -d. -f2 | tr '_-' '/+' | base64 -d 2>/dev/null | jq '{iss, aud, exp, preferred_username, realm_access}' -
Consulter la découverte OIDC :
curl -s https://keycloak.lab.local/realms/lab/.well-known/openid-configuration | jq .
7. Partie 5 : Protéger l’application avec oauth2-proxy
-
Créer le Secret d’oauth2-proxy et une copie du certificat public de la CA dans le namespace
tp16:kubectl -n tp16 create secret generic oauth2-proxy \ --from-literal=client-secret=<secret-du-client> \ --from-literal=cookie-secret="$(openssl rand -base64 32 | tr -- '+/' '-_' | head -c 32)" kubectl -n tp16 create secret generic lab-ca-public --from-file=ca.crt=lab-ca.crt -
Compléter
manifests/40-oauth2-proxy.yaml(--allowed-role=developer,--allowed-role=admin), l’appliquer, puis faire pointer l’Ingresswhoamivers le Serviceoauth2-proxy. -
Tester dans un navigateur (après avoir importé
lab-ca.crtdans son magasin de certificats) ou avec un tunnel SSH :aliceetbobaccèdent à whoami : repérer les en-têtesX-Auth-Request-UseretX-Auth-Request-Email;carol(rôleuser) reçoit un 403.
-
Se déconnecter (
/oauth2/sign_out) et expliquer pourquoi la session Keycloak peut survivre (SSO).
Défi
- Écrire un middleware Express qui valide lui-même le jeton JWT (signature via le JWKS de Keycloak,
iss,aud,exp) et protègePOST /api/adminpour le seul rôleadmin.- Remplacer la CA de lab par un émetteur ACME pointant vers un serveur de test local (
step-caou Pebble) pour observer le protocole ACME utilisé par Let’s Encrypt.
8. Livrables
Captures à déposer dans captures/ :
| Fichier | Contenu attendu |
|---|---|
clusterissuers.png |
kubectl get clusterissuers et le Certificate de la CA |
https-curl.png |
curl -v https://whoami.lab.local : certificat vérifié, émis par la CA de lab |
keycloak-realm.png |
Realm lab avec ses rôles et ses utilisateurs |
jwt-decoded.png |
Jeton décodé : iss, aud, exp, rôles |
oauth2-allowed.png |
Accès autorisé (bob) avec les en-têtes X-Auth-Request-* |
oauth2-403.png |
Accès refusé (carol) |
Ainsi que les manifests complétés. Jamais la clé privée de la CA, le secret du client ou le mot de passe admin.