--- # Passerelle SSO OIDC générique (oauth2-proxy) : place Keycloak DEVANT n'importe quelle # application sans OIDC natif. L'app reçoit l'utilisateur via en-têtes (auth « external »). # Binaire Go statique depuis les releases GitHub (pas d'apt). Requiert client_pki (confiance # step_ca pour joindre Keycloak) + résolution de l'hôte Keycloak. # v7.15.5 (2026-10-03) : deux versions de correctifs apres v7.15.3, toutes deux de securite. serveur_oauth2_proxy_version: "v7.15.5" # L'EMPREINTE DE L'ARCHIVE, ECRITE ICI ET NON LUE A COTE DU TELECHARGEMENT (2026-10-03). # Le role installait le binaire de la passerelle SSO sans rien verifier. La somme publiee # par le projet (`*-sha256sum.txt`, meme canal que l'archive) a ete recalculee sur l'archive # le jour meme ; l'ecrire dans le depot fige ce qui a ete relu, et une archive remplacee # plus tard — sur GitHub ou dans le depot de binaires du site — est REFUSEE. # Changer de version = changer cette ligne, apres la meme relecture. serveur_oauth2_proxy_sha256: "f63f94bf72c5f46ab002a0a275aa8b3cf19b4d828aed08a13978cb9a62c3a1fd" serveur_oauth2_proxy_archive: "oauth2-proxy-{{ serveur_oauth2_proxy_version }}.linux-amd64.tar.gz" serveur_oauth2_proxy_url: >- https://github.com/oauth2-proxy/oauth2-proxy/releases/download/{{ serveur_oauth2_proxy_version }}/{{ serveur_oauth2_proxy_archive }} serveur_oauth2_proxy_binaire: "/usr/local/bin/oauth2-proxy" serveur_oauth2_proxy_utilisateur: "oauth2-proxy" serveur_oauth2_proxy_config: "/etc/oauth2-proxy/oauth2-proxy.cfg" serveur_oauth2_proxy_service: "oauth2-proxy" # Écoute (l'edge nginx proxifie ici). serveur_oauth2_proxy_ecoute: "0.0.0.0:4180" # OIDC (Keycloak) — realm applicatif. serveur_oauth2_proxy_realm: "{{ identite_realm | default('chezlepro') }}" # DERIVE de l'exposition que le plan declare pour l'IdP (voir tasks/main.yml). La valeur # ci-dessous n'est qu'un REPLI, utilise si l'application n'expose rien : un nom fabrique # par convention n'est resolu par personne. serveur_oauth2_proxy_issuer_derive: true serveur_oauth2_proxy_app_idp: "keycloak" serveur_oauth2_proxy_issuer: "https://keycloak.{{ domaine_interne }}/realms/{{ serveur_oauth2_proxy_realm }}" serveur_oauth2_proxy_client_id: "" # OBLIGATOIRE (par instance) serveur_oauth2_proxy_client_secret: "" # OBLIGATOIRE (voûte) # DERIVE de l'exposition que le plan declare pour l'application protegee. # `instancier` pose `serveur_oauth2_proxy_hostname` depuis `expose:` ; l'URL de retour # s'en deduit. Une valeur posee dans les group_vars gagne encore — et le repli reste # vide, pour que l'assertion refuse un deploiement sans exposition plutot que de # fabriquer un nom que personne ne resout. serveur_oauth2_proxy_redirect_url: >- {{ ('https://' ~ serveur_oauth2_proxy_hostname ~ '/oauth2/callback') if (serveur_oauth2_proxy_hostname | default('') | length > 0) else '' }} # Application protégée (upstream local). serveur_oauth2_proxy_upstream: "" # OBLIGATOIRE (ex. http://127.0.0.1:8080) # Secret de cookie (voûte) — 32 octets en base64 URL-SAFE (alphabet `-_`, RFC 4648 §5). # # Le base64 STANDARD ne convient PAS, et l'erreur ne le dit pas : oauth2-proxy décode en # `RawURLEncoding`, et un secret contenant `+` ou `/` fait échouer le décodage. Il retombe # alors sur la chaîne BRUTE et se plaint de sa longueur — « is 44 bytes » — sans jamais # mentionner l'encodage. Constaté le 2026-08-07 : le service redémarrait en boucle. # # Générer avec : `openssl rand -base64 32 | tr '+/' '-_'` serveur_oauth2_proxy_cookie_secret: "{{ vault_oauth2_cookie | default('') }}" # * = tout utilisateur authentifié par Keycloak. serveur_oauth2_proxy_email_domains: "*" # IdP interne de confiance : les utilisateurs LDAP n'ont pas le drapeau email_verified. serveur_oauth2_proxy_allow_unverified_email: true # Bundle d'AC système (racine step_ca via client_pki) pour joindre Keycloak en HTTPS. serveur_oauth2_proxy_ca_bundle: "/etc/ssl/certs/ca-certificates.crt" # Cache d'artefacts DU CONTROLEUR (pas de la cible). Le controleur telecharge une fois, # puis pousse par SSH : aucun flux nouveau, et l'artefact devient deployable hors ligne. # Surchargeable par `setops_cache_artefacts` pour partager un cache commun. serveur_oauth2_proxy_cache_local: "{{ setops_cache_artefacts | default(lookup('env', 'HOME') + '/.cache/setops') }}" # --- SONDE DE SUPERVISION ------------------------------------------------------------- # # CE QUE LA REPONSE DOIT CONTENIR. Un code 200 ne suffit pas : un serveur peut rendre 200 # sur une page d'erreur, une redirection de courtoisie ou un cache perime. On exige donc # une chaine que SEUL le bon service produit. # # C'EST AUSSI LA MISE EN DEFAUT DE LA SONDE : y mettre une chaine introuvable la rend # CRITIQUE sans rien casser, ce qui rend la seconde preuve REJOUABLE. Une sonde se prouve # deux fois — verte sur le sain, rouge sur le casse. serveur_oauth2_proxy_sonde_attendu: "OK" # LE PORT QUE LA SONDE INTERROGE, DERIVE DE L'ECOUTE (2026-09-28). Il etait ecrit en dur # (4180) dans le gabarit : une passerelle deplacee aurait fait crier une sonde saine. serveur_oauth2_proxy_sonde_port: "{{ serveur_oauth2_proxy_ecoute.split(':') | last }}" # L'URL DE RETOUR QUE LA SONDE PRESENTE A KEYCLOAK. Vide = celle que la passerelle envoie # vraiment (le cas normal). Mise en defaut PAR PARAMETRE de la seconde etape : une URL que # le client n'autorise pas — Keycloak refuse (400), comme il refuserait tout le monde. # Chaque mise en defaut laisse UNE erreur dans le journal du realm ; le cas sain, aucune. serveur_oauth2_proxy_sonde_retour: ""