Eprouve en production : les locataires repondaient, le site non — son SSH vient de `flotte` et vivait du rebond par la frontiere. Et rien ne designait la frontiere elle-meme, si bien que monter le tunnel faisait perdre le moyen de le corriger. Une regle par port : OPNsense refuse deux ports dans un champ. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.9 KiB
L'accès d'administration — un tunnel nominatif
Pour qui : celui qui administre le site et ses écosystèmes, et celui qui se demande par où un humain entre, avec quelle clé, et ce qu'il peut atteindre une fois entré.
Décidé le 2026-09-17, en réponse à une question : le runner ne devrait-il pas être le rebond SSH des admins ?
Pourquoi pas le runner
Le runner du site détient la clé de la voûte du site et les clés SSH qui configurent toutes les machines. En faire la porte des humains réunirait deux pouvoirs que tout le reste du dépôt sépare :
- une session humaine compromise (un agent SSH transféré de trop) deviendrait le plan de contrôle — pas seulement un rebond ;
- il ne doit jamais entrer chez un locataire (charte des responsabilités) ; en faire le passage obligé des admins créerait ce chemin en fait ;
- il est reconstructible par le code, et c'est sa vertu. Un point d'entrée doit survivre à la reconstruction de ce qu'il sert ;
- « qui est entré » et « qu'est-ce qui a été déployé » cesseraient de se raconter séparément.
Ce qui a été construit
Un second tunnel WireGuard sur la frontière — l'instance admins, port 51821 — à côté du
tunnel site-à-site vers le site pair (instance chezlePro, port 51820), jamais mêlé à lui.
| déclaré | SITE-<nom>/plan/10-intrants.yml, clé acces_admin_vpn |
| réconcilié | scripts/vpn_admin.py (make vpn-admin-plan, make vpn-admin-appliquer) |
| réseau | 10.37.29.0/24, la frontière en .1 |
| un pair | une personne ET un appareil — révoquer l'appareil perdu ne coupe pas les autres |
| clés | seule la clé publique est au plan ; la privée ne quitte jamais l'appareil |
Le réseau du tunnel est un réseau d'administration, et tout en dérive : les pare-feux des
machines du site (resoudre_flux), le contrat vers les locataires (site_intrants, donc les
pare-feux de leurs machines) et les règles de la frontière (devis_opnsense). Rien à recopier
— une liste recopiée prend toujours du retard sur celle qu'elle suit.
Ajouter un appareil
python3 scripts/vpn_admin.py pair-nouveau --nom prenom-appareil # tire la paire de clés
# coller le bloc `pairs:` rendu dans SITE-<nom>/plan/10-intrants.yml
make vpn-admin-plan # lire ce qui changerait
CONFIRMER=true make vpn-admin-appliquer # poser le pair
python3 scripts/vpn_admin.py config --nom prenom-appareil # la config de l'appareil
make flux && make deployer-groupe GROUPE=serveur_durci # les pare-feux des machines
La clé privée ne s'affiche qu'une fois, au moment où elle est tirée : elle appartient à
l'appareil. Perdue, on en tire une autre ; l'ancienne se révoque par etat: absent.
Retirer un accès
etat: absent sur le pair, puis CONFIRMER=true make vpn-admin-appliquer. Le script retire
aussi tout pair attaché à notre instance que le plan ne déclare plus : un accès qui
survivrait à la décision de le retirer est exactement ce qu'on ne veut pas.
Deux trous que seul l'usage a montrés (2026-09-17, une heure après la pose)
- Le SSH des machines du site. Le socle déclare son 22 en
pair: [flotte, externe], jamaisadmin: la source dérivée est le site lui-même. L'exploitant y arrivait par rebond sur la frontière — la connexion partait alors du boîtier, que pf laisse sortir sans règle. Par le tunnel, il arrive comme une source extérieure, et plus rien ne l'autorisait. Les locataires, eux, marchaient : leur règle SSH naît denftables_admin_ssh, qui contient déjà le tunnel. - La frontière elle-même. Aucun flux ne la désignait comme destination d'administration : monter le tunnel faisait perdre sa console et son API — donc le moyen même de réparer la règle manquante. La panne se referme sur celui qui la répare : il a fallu remettre l'adresse d'avant pour poser le correctif.
Les deux règles sont désormais émises par devis_opnsense dès que acces_admin_vpn est
déclaré (ports_frontiere, par défaut 22 et 443). Une règle par port : OPNsense refuse
« 22,443 » dans un champ de port, et aucun flux jusque-là n'en portait deux.
Ce que le tunnel donne, et ce qu'il ne donne pas
AllowedIPs est dérivé de la carte : zones du site, fabric, lien de transit et supernets
des locataires. Ce que la frontière laisse ensuite passer reste décidé par les flux déclarés —
SSH partout, et les consoles d'administration (Grafana, Icinga Web, la forge, le runner).
Le seul port ouvert sur l'Internet par cette voie est le 51821/udp, vers l'adresse publique de la frontière. Tout le reste voyage dans le tunnel.
Ce qui n'est pas fait : l'enregistrement des sessions (un rebond dédié le permettrait, pas un tunnel), et la double authentification — la possession de l'appareil fait foi.