--- # Projette LA declaration unique (`resoudre_politique_mdp`) dans le realm, et durcit # la federation pour que l'annuaire soit consulte au lieu d'etre contourne. # # Sans cela, les regles n'existaient QUE cote LDAP — et LDAP ne sait que refuser, # sans jamais dire pourquoi a l'ecran. Pire : Keycloak ecrivait `userPassword` # directement, donc l'overlay `ppolicy` n'interceptait meme pas. Mesure du # 2026-08-08 : `abcd` refuse par l'operation etendue LDAP, accepte par Keycloak, # puis actif pour l'authentification. # # La conformite se teste partout ici de la meme facon : fusionner l'attendu dans le # reel ne change rien => c'est deja conforme. Ca evite d'enumerer les champs deux fois. - name: Résoudre la politique de mot de passe (déclaration unique) ansible.builtin.include_role: name: resoudre_politique_mdp - name: Obtenir un jeton d'administration ansible.builtin.uri: url: "http://localhost:8080/realms/master/protocol/openid-connect/token" method: POST body_format: form-urlencoded body: grant_type: password client_id: admin-cli username: "{{ serveur_keycloak_admin_user }}" password: "{{ serveur_keycloak_admin_password }}" register: serveur_keycloak_pol_jeton no_log: true - name: Lire le realm ansible.builtin.uri: url: "http://localhost:8080/admin/realms/{{ serveur_keycloak_realm }}" headers: Authorization: "Bearer {{ serveur_keycloak_pol_jeton.json.access_token }}" register: serveur_keycloak_pol_realm no_log: true - name: Composer l'état attendu du realm ansible.builtin.set_fact: serveur_keycloak_realm_attendu: >- {{ {'passwordPolicy': resoudre_politique_mdp_keycloak} | combine(resoudre_politique_mdp_brute) }} - name: Appliquer la politique de mot de passe au realm ansible.builtin.uri: url: "http://localhost:8080/admin/realms/{{ serveur_keycloak_realm }}" method: PUT status_code: [204] headers: Authorization: "Bearer {{ serveur_keycloak_pol_jeton.json.access_token }}" body_format: json body: "{{ serveur_keycloak_realm_attendu }}" no_log: true changed_when: true when: >- (serveur_keycloak_pol_realm.json | combine(serveur_keycloak_realm_attendu)) != serveur_keycloak_pol_realm.json # --- Durcissement de la federation -------------------------------------------- # Voir `serveur_keycloak_ldap_durcissement` (defaults) pour ce que chaque cle repare. - name: Lire la fédération LDAP ansible.builtin.uri: url: >- http://localhost:8080/admin/realms/{{ serveur_keycloak_realm }}/components?type=org.keycloak.storage.UserStorageProvider headers: Authorization: "Bearer {{ serveur_keycloak_pol_jeton.json.access_token }}" register: serveur_keycloak_pol_fed no_log: true - name: Exiger une fédération LDAP en place ansible.builtin.assert: that: - (serveur_keycloak_pol_fed.json | length) == 1 fail_msg: >- {{ serveur_keycloak_pol_fed.json | length }} fournisseur(s) de stockage d'utilisateurs dans le realme « {{ serveur_keycloak_realm }} » — il en faut exactement un. Durcir le mauvais serait pire que ne rien durcir. - name: Durcir la fédération LDAP ansible.builtin.uri: url: >- http://localhost:8080/admin/realms/{{ serveur_keycloak_realm }}/components/{{ serveur_keycloak_pol_fed.json[0].id }} method: PUT status_code: [204] headers: Authorization: "Bearer {{ serveur_keycloak_pol_jeton.json.access_token }}" body_format: json body: >- {{ serveur_keycloak_pol_fed.json[0] | combine({ 'config': serveur_keycloak_pol_fed.json[0].config | combine(serveur_keycloak_ldap_durcissement) }) }} no_log: true changed_when: true when: >- (serveur_keycloak_pol_fed.json[0].config | combine(serveur_keycloak_ldap_durcissement)) != serveur_keycloak_pol_fed.json[0].config - name: Reconcilier les mappeurs d'attributs ansible.builtin.include_tasks: attributs-ldap.yml - name: Activer le journal des évènements ansible.builtin.include_tasks: journalisation.yml