--- client_pki_paquets: - step-cli client_pki_steppath: "/etc/step" # L'AC INTERNE SE DÉRIVE DU GROUPE QUI LA PORTE, elle ne se nomme pas (2026-08-25). # # Cette URL écrivait `infra-pki-01` EN DUR. Chez un tenant ça marchait toujours : la # nomenclature nomme sa PKI ainsi, donc le littéral et la réalité coïncidaient. Le SITE # est le premier à l'appeler autrement — `site-pki-01` — et les cinq machines ont essayé # de s'enrôler auprès d'un hôte qui n'existe nulle part : # # lookup infra-pki-01.genese.internal ... no such host # # Le message accusait le DNS, alors que c'était le nom qui était faux. Un littéral qui a # raison par coïncidence est un bogue qui attend son premier cas particulier. # # `groups['serveur_step_ca']` dit qui porte l'autorité, dans un tenant comme sur un site. # Pas de repli : sans autorité déclarée, s'adresser à un nom inventé produirait exactement # la panne qu'on vient de corriger. Le rôle refuse (voir tasks/main.yml). client_pki_ca_hote: "{{ (groups['serveur_step_ca'] | default([])) | first | default('', true) }}" client_pki_ca_url: "https://{{ client_pki_ca_hote }}.{{ domaine_interne }}:8443" client_pki_provisioner: "admin@{{ domaine_interne }}" # Identite de l'hote. client_pki_nom_cert: "{{ ansible_fqdn | default(ansible_hostname) }}" client_pki_cert: "{{ client_pki_steppath }}/certs/{{ client_pki_nom_cert }}.crt" client_pki_cle: "{{ client_pki_steppath }}/certs/{{ client_pki_nom_cert }}.key" # LE CERTIFICAT DOIT COUVRIR LES NOMS SOUS LESQUELS ON APPELLE LE SERVICE (2026-08-25). # # Les SANs ne portaient que l'identite de la MACHINE — FQDN, nom court, IP. Or un service # se declare `expose:` au plan, sous un nom qui lui survivra : `forge.genese.internal` # reste le nom de la forge meme si elle demenage de `site-forge-01` a `site-forge-02`. # # Ce nom etait publie partout — plancher /etc/hosts, zone DNS — et couvert nulle part. Le # clonage du genome a bute dessus : « certificate subject name (site-forge-01.genese # .internal) does not match target hostname 'forge.genese.internal' ». Du TLS correct, sur # un nom que personne ne peut appeler : la meme panne que le depot a deja rencontree cote # resolution, ici cote certificat. # # ON N'AJOUTE QUE CE QUE CET HOTE SERT REELLEMENT : `edge` nomme le groupe qui rend le # service, et l'hote doit en faire partie. Un certificat qui revendiquerait le nom d'un # service rendu ailleurs serait une usurpation, pas une commodite. client_pki_expositions: "{{ hosts_statiques_expositions | default([]) }}" client_pki_sans: >- {{ ([client_pki_nom_cert, ansible_hostname | default(''), ansible_host | default('')] + (client_pki_expositions | selectattr('edge', 'defined') | selectattr('fqdn', 'defined') | selectattr('edge', 'in', group_names) | map(attribute='fqdn') | list)) | select | unique | list }} # L'empreinte du root CA n'est PAS un intrant : elle est DERIVEE a chaud depuis l'AC # (tasks/main.yml), parce qu'un from-zero regenere l'autorite avec une empreinte neuve. # La stocker en voute donnerait une valeur perimee des la premiere reconstruction. # Pour epingler explicitement une empreinte : `client_pki_ca_fingerprint_override`. client_pki_ca_fingerprint: "" # Secret OBLIGATOIRE (Ansible Vault). client_pki_provisioner_password: "{{ vault_step_ca_provisioner_password | default('') }}" # rempli depuis la voute (vault_step_ca_provisioner_password) # Depot apt officiel Smallstep (partage avec serveur_step_ca). client_pki_depot_cle_url: "https://packages.smallstep.com/keys/apt/repo-signing-key.gpg" client_pki_depot_cle_fichier: "/etc/apt/keyrings/smallstep.asc" client_pki_depot_uri: "https://packages.smallstep.com/stable/debian" client_pki_depot_suite: "debs" # QUI PEUT LIRE LA CLE PRIVEE (2026-08-25). # # Elle est en `0600 root:root`, et c'est le bon defaut. Les consommateurs TLS habituels — # nginx, Postfix, Dovecot — demarrent en root, lisent la cle, puis deprivilegient : ils # n'ont jamais eu besoin d'autre chose. # # Forgejo tourne en `git` DES LE DEPART. Sur la forge du site, qui sert le genome sans # edge devant elle, la cle etait donc illisible par le seul processus qui en a besoin. # # Un GROUPE lecteur et `0640` reglent ca sans ouvrir la cle a tout le monde. On declare le # groupe explicitement, service par service : elargir par defaut serait exactement le # genre de commodite qui finit par rendre une cle privee lisible par `nogroup`. client_pki_cle_groupe: "root" client_pki_cle_mode: "0600" # LE CERTIFICAT, LUI, EST PUBLIC — et l'etait deja avant d'etre sur ce disque : il est # presente a chaque poignee de main, a quiconque se connecte. Le garder en `0600` ne # protegeait rien et empechait tout service non-root de le lire. Le certificat racine est # d'ailleurs deja en `0644` juste a cote, pour la meme raison. client_pki_cert_mode: "0644" # Services a recharger apres un renouvellement de cert : les VRAIS consommateurs # (nginx sur l'edge, postfix/dovecot sur le mail, slapd sur l'annuaire). Sans ca, # le cert est renouvele sur disque mais le service sert l'ancien jusqu'a un reload. client_pki_reload_services: [] # Marge avant echeance (secondes) sous laquelle le role RE-EMET le certificat plutot que # d'attendre le renouvellement automatique. 3600 = une heure : large devant le minuteur # (~14 min), serre devant la duree de vie (24 h). client_pki_marge_renouvellement: 3600 # --- Sonde de supervision (docs/supervision-conception.md) -------------------------- # # LES SEUILS DECOULENT DU MOMENT OU LE RENOUVELLEMENT EST DU — pas d'une intuition. # # `cert-renewer@.service` porte `ExecCondition=step certificate needs-renewal`, qui dit # oui au TIERS RESTANT : 8 h pour un certificat de 24 h. Le minuteur repasse toutes les # 15 minutes (`OnCalendar=*:1/15`). En marche normale, un certificat ne descend donc # jamais durablement sous 8 h. # # PREMIERE VERSION FAUSSE, ET INSTRUCTIVE (2026-09-09) : avert a 12 h, crit a 4 h. Deux # machines du site sur sept sont passees en AVERTISSEMENT — sur des certificats # parfaitement sains, simplement pas encore eligibles au renouvellement. La sonde criait # AVANT que le mecanisme ne soit cense agir. # # Les seuils sont donc SOUS le point de renouvellement : # 6 h -> le renouvellement est du depuis 2 h et n'a pas abouti : huit fenetres de # quinze minutes manquees. Ce n'est plus un hoquet. # 3 h -> plus aucune marge ; la panne est certaine au prochain cycle. # # Un seuil au-dessus du point de renouvellement ne previent pas : il ment. client_pki_sonde_avert_h: 6 client_pki_sonde_crit_h: 3 # Port local ou comparer le certificat SERVI a celui du disque. Vide = pas de comparaison # (l'hote n'expose rien en TLS, ou son consommateur n'ecoute pas en local). client_pki_sonde_port: ""