mTLS — certificats client hub ↔ agent
Chaque agent reçoit un certificat client X.509 signé par le hub dès le
premier boot. À partir de ce moment, chaque handshake TLS vers
api.monsys.ai prouve deux choses : que la connexion possède un
bearer token valide (comme avant), et que le côté client détient la
clé privée correspondante dans /var/lib/monsys/mtls/client.key. Un
token volé seul ne suffit plus à usurper un agent — l’attaquant doit
aussi exfiltrer la clé locale, qui ne quitte jamais l’hôte.
Modèle de menace
Avant mTLS (bearer uniquement) :
- Vol de token via dump d’inventaire, ligne de log ou scrape mémoire → un attaquant peut appeler tout endpoint agent jusqu’à ce que l’opérateur fasse une rotation.
Après mTLS :
- Le vol de token requiert également
/var/lib/monsys/mtls/client.key(root-owned, mode 600) à exfiltrer séparément. - Un proxy mal configuré qui stripperait le cert est rejeté — Caddy
positionne l’en-tête
X-Monsys-Client-Verifiedà partir du fingerprint cert, et le middleware hub avorte si le CN ne matche pas l’agent_id du bearer.
Fonctionnement
- Bootstrap CA (une fois). Au premier démarrage, le hub génère une
CA RSA-4096, chiffre la clé privée avec
CLOUD_ENCRYPTION_KEY(AES-256-GCM), et stocke les deux dans la ligne singletonhub_settings. Le cert CA public est aussi exposé sans authentification viaGET /api/v1/agents/ca-certpour que les agents puissent l’épingler. - Émission cert par agent. L’agent appelle
POST /api/v1/agents/issue-client-certavec son bearer token. Le hub signe un cert RSA-2048 (CN = agent_id UUID, OU = tenant_id UUID), valide 365 jours, stocke le cert public dansagent_certificates, retourne cert + key + CA PEM une seule fois. - Persistence. L’agent écrit trois fichiers mode 600 sous
/var/lib/monsys/mtls/:client.crt,client.key,hub-ca.crt. - Toute requête suivante utilise le cert. Caddy est configuré
avec
client_auth.mode = verify_if_givencontre la CA hub, donc les anciens agents bearer-only continuent de fonctionner pendant le déploiement. - Propagation Caddy. Après vérification, Caddy injecte
X-Monsys-Client-Subject(DN complet) etX-Monsys-Client-Verified(fingerprint cert) dans la requête upstream. Les copies entrantes de ces en-têtes sont d’abord supprimées pour qu’un client non-mTLS ne puisse pas les falsifier. - Cross-check hub. Le middleware
AgentAuthextrait le CN du DN sujet et le compare à l’agent_id résolu par le bearer. Match : succès +last_seen_atmis à jour sur la ligne cert. Mismatch : HTTP 401 +integrity_anomalyenregistré — signal fort de vol de token ou de mauvaise configuration proxy.
Déploiement — ce qui change pour les agents existants
Rien d’immédiat. Le mode verify_if_given de Caddy permet aux
connexions non-mTLS de continuer. À la prochaine auto-update (ou
restart manuel), le nouveau binaire appelle issue-client-cert une
fois et tout le trafic suivant est mTLS-authentifié. Pas de downtime,
pas de re-enrôlement, pas de changement de token.
La composante Trust Score agent_health applique une pénalité douce
(-5 points) aux agents n’ayant pas encore bootstrappé de cert. Ça
nudge les opérateurs à déployer le nouveau binaire sans forcer une
coupure dure.
Notes opérationnelles
| Sujet | Détail |
|---|---|
| Expiration CA | 10 ans depuis le premier boot. Alerte câblée sur ca_not_after pour automatisation future. |
| Expiration cert client | 365 jours. L’agent re-fetch automatiquement dans les 30 jours avant expiration. |
| Clé privée CA | Chiffrée AES-256-GCM dans hub_settings.ca_key_enc. La restauration nécessite la même CLOUD_ENCRYPTION_KEY — backup hors-bande. |
| Rotation | POST /api/v1/agents/issue-client-cert effectue la rotation : ancienne ligne marquée revoked_at = NOW(), revoke_reason = 'rotated', nouvelle ligne insérée en une tx. |
| Révocation | L’opérateur positionne revoked_at en DB. Le middleware hub rejette les certs révoqués même si Caddy les accepte (jusqu’à un futur endpoint CRL). |
| Storage | Clés client RSA-2048, CA RSA-4096. Ed25519 réservé aux Emergency Action Tokens où nous contrôlons les deux côtés. |
Endpoints
| Méthode | Path | Auth | Quoi |
|---|---|---|---|
| GET | /api/v1/agents/ca-cert | aucune | Certificat public de la CA hub (pour trust pinning) |
| POST | /api/v1/agents/issue-client-cert | bearer | Émission ou rotation du cert client + clé privée de l’agent appelant |
Fichiers sur l’hôte agent
/var/lib/monsys/mtls/├── client.crt # certificat client rsa-2048 (PEM)├── client.key # clé privée rsa-2048 (PEM, mode 600)└── hub-ca.crt # racine CA hub (PEM)Mapping de conformité : ISO 27001 A.8.20 (Sécurité du réseau) +
CRA Annexe I §3 (communication sécurisée par défaut). Les deux
contrôles sont automatiquement évalués via un comptage des lignes
actives, non-révoquées, dans agent_certificates.