Set-OPS-Public/roles/serveur_nextcloud/tasks/oidc.yml
Daniel Allaire a08c61bb4e acces : Forgejo et Nextcloud cables, et le claim groups emis
Les deux services n'etaient pas encore deployes : les cabler maintenant vaut
mieux que les corriger apres. `porte_par` passe de `aucun` a `claim-groupe`.

Forgejo recoit --group-claim-name + --admin-group, et sa tache passe de « creer
si absent » a add-oauth OU update-oauth : le meme defaut que la federation
Keycloak — cree une fois, jamais corrige — l'attendait sinon.

Nextcloud recoit --mapping-groups + --group-provisioning, plus une tache qui
verse les membres du groupe d'habilitation dans le groupe interne `admin` : etre
dans un groupe projete ne donne aucun pouvoir en soi.

Le maillon qui manquait aux deux : AUCUN mapper de protocole n'emettait le claim.
Les groupes existaient dans le realm et n'apparaissaient dans aucun jeton — un
cablage correct des deux cotes et rien au milieu. `oidc-group-membership-mapper`
pose sur les trois clients, `full.path=false` pour que le claim porte `sysadmin`
et non `/sysadmin`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:49:28 -04:00

86 lines
3.8 KiB
YAML

---
- name: SSO OIDC (occ, en www-data avec TLS PG)
become: true
become_user: "{{ serveur_nextcloud_utilisateur }}"
environment:
PGSSLMODE: "{{ serveur_nextcloud_pg_sslmode }}"
PGSSLROOTCERT: "{{ serveur_nextcloud_ca_racine }}"
when: not ansible_check_mode
block:
- name: Installer + activer l'app user_oidc (idempotent)
ansible.builtin.shell:
executable: /bin/bash
cmd: |
set -eo pipefail
OCC="php {{ serveur_nextcloud_racine }}/occ"
if $OCC app:list | grep -qw user_oidc; then echo SETOPS_OK; else $OCC app:install user_oidc && echo SETOPS_CHANGED; fi
register: serveur_nextcloud_oidc_app
changed_when: "'SETOPS_CHANGED' in serveur_nextcloud_oidc_app.stdout"
- name: Ne plus annoncer le formulaire de connexion locale
# Masquage, pas fermeture : `?direct=1` reste le chemin de secours documente par
# l'amont. Voir serveur_nextcloud_connexion_locale dans defaults/main.yml.
ansible.builtin.command:
argv:
- php
- "{{ serveur_nextcloud_racine }}/occ"
- "config:system:set"
- "hide_login_form"
- "--type=boolean"
- "--value={{ 'false' if serveur_nextcloud_connexion_locale | bool else 'true' }}"
changed_when: false
- name: Configurer le fournisseur OIDC Keycloak (upsert idempotent)
ansible.builtin.command:
argv:
- php
- "{{ serveur_nextcloud_racine }}/occ"
- "user_oidc:provider"
- "{{ serveur_nextcloud_oidc_nom }}"
- "--clientid={{ serveur_nextcloud_oidc_client_id }}"
- "--clientsecret={{ serveur_nextcloud_oidc_client_secret }}"
- "--discoveryuri={{ serveur_nextcloud_oidc_discovery }}"
- "--scope=openid email profile"
- "--mapping-uid=preferred_username"
- "--mapping-email=email"
- "--mapping-display-name=name"
- "--mapping-groups={{ serveur_nextcloud_oidc_groupe_claim }}"
- "--group-provisioning=1"
- "--unique-uid=0"
changed_when: false
no_log: true
# Les groupes projetes depuis LDAP arrivent dans Nextcloud, mais y etre membre
# ne donne aucun pouvoir : l'administration est un GROUPE NEXTCLOUD nomme
# `admin`. On y verse le groupe d'habilitation, une fois qu'il existe.
#
# Sans cela, `meta/acces.yml` restait `porte_par: aucun` et l'administration
# passait par le compte local de secours — ce qui contredit « une identite, un
# mot de passe » (2026-08-07).
- name: Verser le groupe d'administration dans le groupe `admin` de Nextcloud
ansible.builtin.shell:
executable: /bin/bash
cmd: |
set -eo pipefail
OCC="php {{ serveur_nextcloud_racine }}/occ"
G="{{ serveur_nextcloud_oidc_groupe_admin }}"
# Le groupe n'existe qu'apres la premiere connexion d'un membre : son
# absence n'est donc PAS une erreur au premier deploiement.
if ! $OCC group:list --output=json | grep -q "\"$G\""; then
echo "SETOPS_OK (groupe '$G' pas encore provisionne — a la premiere connexion)"
exit 0
fi
CHANGED=0
for U in $($OCC group:list --output=json | python3 -c "
import json,sys
print(' '.join((json.load(sys.stdin).get('$G') or [])))"); do
if ! $OCC group:list --output=json | python3 -c "
import json,sys
sys.exit(0 if '$U' in (json.load(sys.stdin).get('admin') or []) else 1)"; then
$OCC group:adduser admin "$U" >/dev/null && CHANGED=1
fi
done
[ "$CHANGED" = 1 ] && echo SETOPS_CHANGED || echo SETOPS_OK
register: serveur_nextcloud_grp_admin
changed_when: "'SETOPS_CHANGED' in serveur_nextcloud_grp_admin.stdout"
when: serveur_nextcloud_oidc_groupe_admin | length > 0