Set-OPS-Public/roles/amorcage_acces/tasks/main.yml

166 lines
6.2 KiB
YAML
Raw Normal View History

---
# Amorcage des acces — D-67. Voir defaults/main.yml pour la doctrine, et
# docs/autorisation.md §6 pour le runbook de reprise.
- name: Résoudre la connexion à l'annuaire
ansible.builtin.include_role:
name: resoudre_annuaire
- name: Exiger le secret d'amorçage et le mot de passe d'annuaire (Vault)
ansible.builtin.assert:
that:
- amorcage_acces_secret | length > 0
- amorcage_acces_admin_password | length > 0
fail_msg: >-
`vault_sysadmin_amorcage` et `vault_openldap_admin` sont requis (voûte).
Le premier est un jeton d'amorçage à usage unique — pas un mot de passe
permanent : voir docs/autorisation.md §6.
when: amorcage_acces_actif | bool
# --- LE CŒUR DU RÔLE : on REGARDE avant d'agir --------------------------------
# La condition n'est pas la conformité, c'est l'EXISTENCE. Un compte présent est
# laissé strictement intact, quel que soit son état — c'est ce qui distingue ce
# rôle de tous les autres du dépôt (D-67).
- name: Le compte d'amorçage existe-t-il déjà ?
community.general.ldap_search:
dn: "ou=people,{{ resoudre_annuaire_base_dn }}"
scope: onelevel
filter: "(uid={{ amorcage_acces_uid }})"
server_uri: "ldapi:///"
bind_dn: "{{ resoudre_annuaire_bind_dn }}"
bind_pw: "{{ amorcage_acces_admin_password }}"
register: amorcage_acces_existant
changed_when: false
no_log: true
when: amorcage_acces_actif | bool
- name: Retenir si l'amorçage a déjà eu lieu
ansible.builtin.set_fact:
amorcage_acces_deja_fait: >-
{{ (amorcage_acces_existant.results | default([]) | length) > 0 }}
when: amorcage_acces_actif | bool
- name: Annoncer que l'amorçage est déjà fait (aucune action)
ansible.builtin.debug:
msg: >-
Compte `{{ amorcage_acces_uid }}` déjà présent : Set-OPS n'y touche pas.
Les habilitations sont gouvernées par une personne (D-67) — voir
docs/autorisation.md §6.
when:
- amorcage_acces_actif | bool
- amorcage_acces_deja_fait | bool
# --- Tout ce qui suit ne s'exécute QUE si le compte est absent -----------------
# Le mot de passe est HACHÉ par slapd lui-même. `ldap_entry` écrirait la chaîne
# littéralement : le jeton d'amorçage se retrouverait en clair dans la base, lisible
# par quiconque peut lire l'annuaire.
- name: Hacher le jeton d'amorçage (slappasswd, SSHA)
ansible.builtin.command:
argv:
- slappasswd
- "-h"
- "{SSHA}"
- "-s"
- "{{ amorcage_acces_secret }}"
register: amorcage_acces_hache
changed_when: false
no_log: true
when:
- amorcage_acces_actif | bool
- not amorcage_acces_deja_fait | bool
# Le changement forcé s'appuie sur `pwdReset`, qui vient de l'overlay `ppolicy`.
# On le DÉTECTE au lieu de le supposer : sans l'overlay, l'attribut est inconnu du
# schéma et l'entrée entière est rejetée — panne obscure, et le compte n'existe pas
# du tout. Mesuré le 2026-08-07 : seul `back_mdb` était chargé.
- name: L'overlay ppolicy est-il chargé (attribut `pwdReset` connu) ?
ansible.builtin.command:
argv:
- ldapsearch
- "-Y"
- EXTERNAL
- "-H"
- "ldapi:///"
- "-b"
- "cn=schema,cn=config"
- "(olcAttributeTypes=*pwdReset*)"
- dn
register: amorcage_acces_ppolicy
changed_when: false
failed_when: false
when:
- amorcage_acces_actif | bool
- not amorcage_acces_deja_fait | bool
- name: Retenir si le changement forcé est applicable
ansible.builtin.set_fact:
amorcage_acces_reset_possible: >-
{{ amorcage_acces_changement_force | bool
and 'dn:' in (amorcage_acces_ppolicy.stdout | default('')) }}
when:
- amorcage_acces_actif | bool
- not amorcage_acces_deja_fait | bool
- name: Créer le compte d'amorçage du sysadmin
community.general.ldap_entry:
dn: "uid={{ amorcage_acces_uid }},ou=people,{{ resoudre_annuaire_base_dn }}"
objectClass:
- inetOrgPerson
- organizationalPerson
- person
- top
attributes:
uid: "{{ amorcage_acces_uid }}"
cn: "{{ amorcage_acces_nom }}"
sn: "{{ amorcage_acces_nom.split(' ') | last }}"
userPassword: "{{ amorcage_acces_hache.stdout | trim }}"
pwdReset: "{{ 'TRUE' if amorcage_acces_reset_possible | bool else omit }}"
mail: "{{ amorcage_acces_courriel | default(omit, true) }}"
server_uri: "ldapi:///"
bind_dn: "{{ resoudre_annuaire_bind_dn }}"
bind_pw: "{{ amorcage_acces_admin_password }}"
no_log: true
when:
- amorcage_acces_actif | bool
- not amorcage_acces_deja_fait | bool
# `groupOfNames` EXIGE au moins un membre : un groupe vide est refusé par le
# schéma — ce qui tombe bien, un groupe d'habilitation sans personne n'aurait
# aucun sens à l'amorçage.
- name: Créer le groupe d'habilitation avec le sysadmin pour membre
community.general.ldap_entry:
dn: "cn={{ amorcage_acces_groupe }},ou=groups,{{ resoudre_annuaire_base_dn }}"
objectClass:
- groupOfNames
- top
attributes:
cn: "{{ amorcage_acces_groupe }}"
member: "uid={{ amorcage_acces_uid }},ou=people,{{ resoudre_annuaire_base_dn }}"
description: >-
Habilitation d'administration. Amorcé par Set-OPS, gouverné ensuite par
une personne — le dépôt ne réconcilie pas ses membres (D-67).
server_uri: "ldapi:///"
bind_dn: "{{ resoudre_annuaire_bind_dn }}"
bind_pw: "{{ amorcage_acces_admin_password }}"
no_log: true
when:
- amorcage_acces_actif | bool
- not amorcage_acces_deja_fait | bool
- name: Annoncer la reprise en main
ansible.builtin.debug:
msg: >-
{{ [
'Accès d amorçage créé : uid=' ~ amorcage_acces_uid ~ ', groupe=' ~ amorcage_acces_groupe ~ '.',
'Mot de passe en voûte sous `vault_sysadmin_amorcage`.',
(amorcage_acces_reset_possible | bool)
| ternary('Changement FORCÉ à la première ouverture (ppolicy actif).',
'ATTENTION : rien ne force le changement — l overlay ppolicy n est pas chargé. '
~ 'Le changer à la main dès la première connexion (docs/autorisation.md §6).'),
'À partir d ici, Set-OPS ne touche plus aux habilitations (D-67).'
] }}
when:
- amorcage_acces_actif | bool
- not amorcage_acces_deja_fait | bool