Set-OPS-Public/roles/serveur_keycloak/tasks/rbac-oidc.yml
Daniel Allaire 72a5fdbbc4 Portabilité from-zero : 4 correctifs débusqués par la reconstruction
Reconstruction complète prouvée (14 VM + sauvegardes + AC supprimées, puis
`make myDay` rebâtit tout ; `make valider` entièrement vert). Bugs corrigés :

- client_pki : empreinte du root CA dérivée dynamiquement de l'autorité
  (au lieu d'une valeur figée en Vault) — une AC régénérée a une empreinte neuve.
- serveur_keycloak : assignation de rôle tolérante aux utilisateurs absents
  (annuaire vide sur un from-zero).
- serveur_prometheus : ne scrute que les hôtes ACTIFS (client_metrique ∩ hotes_actifs).
- nftables résolu : compatible Docker — remplace la seule table setops_flux (pas de
  flush ruleset, préserve les tables Docker) + forward autorise docker0/established.
  Sans ça, forward policy drop coupait Collabora (conteneur).

Ajoute playbooks/proxmox/supprimer_vm_debian.yml (suppression par VMID, garde-fous).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 06:45:12 -04:00

99 lines
4.4 KiB
YAML

---
# RBAC OIDC : rôles de realm + mapper de rôles sur les clients concernés + assignations.
# Additif et idempotent (create-si-absent, kcadm à chaud — pas de restart Keycloak).
# Permet à une app (ex. Grafana) de mapper un rôle du realm vers son niveau de droit.
- name: Assurer les roles de realm (kcadm, idempotent)
ansible.builtin.shell:
executable: /bin/bash
cmd: |
set -euo pipefail
KC={{ serveur_keycloak_home }}/bin/kcadm.sh
"$KC" config credentials --server http://localhost:8080 --realm master \
--user {{ serveur_keycloak_admin_user }} --password "$KC_ADMIN_PW" >/dev/null
if "$KC" get roles/{{ item }} -r {{ serveur_keycloak_realm }} >/dev/null 2>&1; then
echo SETOPS_OK
else
"$KC" create roles -r {{ serveur_keycloak_realm }} -s name={{ item }} >/dev/null
echo SETOPS_CHANGED
fi
environment:
KC_ADMIN_PW: "{{ serveur_keycloak_admin_password }}"
loop: "{{ serveur_keycloak_realm_roles }}"
register: serveur_keycloak_role_reg
changed_when: "'SETOPS_CHANGED' in serveur_keycloak_role_reg.stdout"
no_log: true
when:
- not ansible_check_mode
- serveur_keycloak_realm_roles | length > 0
- name: Assurer le mapper de roles de realm sur les clients (claim 'roles')
ansible.builtin.shell:
executable: /bin/bash
cmd: |
set -euo pipefail
KC={{ serveur_keycloak_home }}/bin/kcadm.sh
"$KC" config credentials --server http://localhost:8080 --realm master \
--user {{ serveur_keycloak_admin_user }} --password "$KC_ADMIN_PW" >/dev/null
CID=$("$KC" get clients -r {{ serveur_keycloak_realm }} -q clientId={{ item }} 2>/dev/null \
| grep -oP '"id"\s*:\s*"\K[^"]+' | head -1)
if [ -z "$CID" ]; then echo "SETOPS_OK client absent"; exit 0; fi
if "$KC" get clients/$CID/protocol-mappers/models -r {{ serveur_keycloak_realm }} 2>/dev/null \
| grep -q '"realm-roles"'; then
echo SETOPS_OK
else
"$KC" create clients/$CID/protocol-mappers/models -r {{ serveur_keycloak_realm }} \
-s name=realm-roles -s protocol=openid-connect \
-s protocolMapper=oidc-usermodel-realm-role-mapper \
-s 'config."claim.name"=roles' \
-s 'config."jsonType.label"=String' \
-s 'config."multivalued"=true' \
-s 'config."id.token.claim"=true' \
-s 'config."access.token.claim"=true' \
-s 'config."userinfo.token.claim"=true' >/dev/null
echo SETOPS_CHANGED
fi
environment:
KC_ADMIN_PW: "{{ serveur_keycloak_admin_password }}"
loop: "{{ serveur_keycloak_role_mapper_clients }}"
register: serveur_keycloak_mapper_reg
changed_when: "'SETOPS_CHANGED' in serveur_keycloak_mapper_reg.stdout"
no_log: true
when:
- not ansible_check_mode
- serveur_keycloak_role_mapper_clients | length > 0
- name: Assigner les roles de realm aux utilisateurs (add-roles idempotent)
ansible.builtin.shell:
executable: /bin/bash
cmd: |
set -euo pipefail
KC={{ serveur_keycloak_home }}/bin/kcadm.sh
"$KC" config credentials --server http://localhost:8080 --realm master \
--user {{ serveur_keycloak_admin_user }} --password "$KC_ADMIN_PW" >/dev/null
# L'utilisateur doit exister dans le realm (Keycloak fédère LDAP à la demande).
# from-zero : l'annuaire peut être vide -> on n'échoue pas ; l'assignation
# s'appliquera quand l'utilisateur existera (synchro / 1re connexion).
if ! "$KC" get users -r {{ serveur_keycloak_realm }} -q username={{ item.user }} --fields username 2>/dev/null \
| grep -q '"{{ item.user }}"'; then
echo SETOPS_SKIP
exit 0
fi
if "$KC" get-roles -r {{ serveur_keycloak_realm }} --uusername {{ item.user }} 2>/dev/null \
| grep -q '"{{ item.role }}"'; then
echo SETOPS_OK
else
"$KC" add-roles -r {{ serveur_keycloak_realm }} --uusername {{ item.user }} --rolename {{ item.role }} >/dev/null
echo SETOPS_CHANGED
fi
environment:
KC_ADMIN_PW: "{{ serveur_keycloak_admin_password }}"
loop: "{{ serveur_keycloak_role_assignments }}"
loop_control:
label: "{{ item.user }} -> {{ item.role }}"
register: serveur_keycloak_assign_reg
changed_when: "'SETOPS_CHANGED' in serveur_keycloak_assign_reg.stdout"
no_log: true
when:
- not ansible_check_mode
- serveur_keycloak_role_assignments | length > 0