Set-OPS-Public/roles/client_pki/defaults/main.yml
Daniel Allaire 90228cb55e supervision : la sonde se declare dans le role, comme le flux
LE CONSTAT. 39 roles declarent leurs flux, 32 leur empreinte, 32 leur
authentification — tous derives. Et 19 groupes sur 19 declaraient une
surveillance en prose que RIEN n executait ; Icinga en surveillait deux.
La carte disait ce qui etait surveille, et personne ne surveillait.

LE MECANISME. Un role declare ses sondes dans meta/supervision.yml et
depose lui-meme son script dans /usr/local/lib/setops/sondes/. Le porteur
client_sante les fait toutes tourner et pousse un resultat passif par
sonde, sans savoir ce qu elles mesurent. serveur_icinga derive les objets
Service ET le filtre de permission d API des memes declarations. Ajouter
une sonde ne demande de toucher ni au porteur ni a Icinga.

PREMIERE SONDE : client_pki/certificat. Heures restantes sur le certificat
reellement pose, chaine verifiee, et empreinte SERVIE comparee au disque
quand un service le consomme. 14/14 au tenant, 7/7 au site.

QUATRE OBSTACLES, ET TROIS SONT LA MEME LECON.

La sonde a rendu 14/14 en CRITIQUE sur une PKI saine : openssl verify
-CAfile racine ne trouve pas l intermediaire qui signe nos certificats.
step certificate verify, lui, repond VALIDE.

Deployee au site, elle a rendu 5/7 : le seuil d avertissement (12 h)
etait AU-DESSUS du point de renouvellement (8 h, le tiers restant). Elle
criait avant que le mecanisme ne soit cense agir. Seuils ramenes a 6 h et
3 h. Un seuil se DERIVE du moment ou le mecanisme surveille agit.

Une alarme toujours allumee ne vaut pas mieux qu une alarme jamais
allumee : elle apprend a ne plus regarder. Une sonde se prouve DEUX FOIS,
verte sur le sain et rouge sur le casse.

Le filtre d API etait ecrit avant la lecture des declarations : les
services auraient existe et Icinga aurait refuse leurs resultats.

Et mon controle negatif a casse un service reel : substituer le certificat
d hote a fait propager un cert sans sa clef vers node_exporter. Un controle
negatif se fait sur une COPIE.

P64 tient les deux bouts : declaree sans etre deposee, ou deposee sans
etre declaree. Trois controles negatifs rejoues.

make prouver : CONFORME, 64 OK, 0 echec, 0 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-09 21:45:49 -04:00

129 lines
6.7 KiB
YAML

---
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: ""