# ADR-001 : Proxy de périphérie & autorisation — Pomerium vs Traefik

**Statut :** Proposé
**Date :** 2026-07-01
**Décideurs :** Louis (+ équipe dev)
**Contexte déclencheur :** volonté de remplacer Traefik par Pomerium pour centraliser la matrice d'autorisation (routes × utilisateur / claims / token) et fermer les trous d'auth connus.

---

## Contexte

**Stack actuelle (chaîne d'accès)**
- **Traefik** en périphérie : terminaison TLS + ACME Let's Encrypt + routage par hostname.
- **nginx par app** : proxy local + injection du jeton API serveur (ex. `/hub/` → `Authorization: Bearer`, `/api` ERPNext).
- **hub Node** : `HUB_GATE` + jeton same-origin (voir patchwork ci-dessous).
- **Authentik (staff)** `auth.targo.ca` — OIDC ; forward-auth déjà en place sur le desk ERPNext.
- **Authentik (client)** `id.gigafibre.ca` — SSO client, IdP distinct.

**Contraintes réelles (vécues, documentées)**
- **SNAT FortiGate** → les ACL par IP sont impossibles au niveau proxy. ⇒ l'autorisation DOIT être *identitaire*, pas réseau. (Argument pour un proxy identity-aware… mais Authentik le fournit déjà.)
- **Let's Encrypt HTTP-01 fragile** : le redirect HTTP de Traefik a déjà cassé le challenge (correctif override netplan). Toute solution ACME en HTTP-01 hérite de cette fragilité.
- **HA FortiGate** + hôtes à ressources limitées (caps stricts 2 cœurs par endroits).
- **Trous d'auth connus** : routes `/hub` ouvertes ; `/campaigns` a déjà été public (incident cartes-cadeaux) ; authz en 2 couches, non uniforme.

**Nature du trafic (déterminante)**
- **Machine-to-machine / webhooks non-interactifs** (la majorité du volume sensible) : SPA ops → `/hub` (Bearer same-origin), Twilio, Giftbit, n8n, cron legacy F → hub, portail client. **Aucun ne peut faire un login OIDC interactif.**
- **Humains / navigateur** : SPA ops, desk ERPNext, UI n8n, GUI GenieACS, admin Nextcloud, etc.

**Objectif visé :** centraliser la matrice d'autorisation (routes × utilisateur/claims/token), refermer les trous, idéalement en remplaçant Traefik.

---

## Faits Pomerium (vérifiés 2026-07 sur la doc officielle)

| Dimension | Réalité |
|---|---|
| Rôle | Reverse proxy *identity-aware* ; authz à chaque requête via IdP OIDC ; route plusieurs upstreams par hostname. |
| **TLS / ACME (Autocert)** | Let's Encrypt via **HTTP-01 (port 80) ou TLS-ALPN-01 (port 443) uniquement** — **DNS-01 non supporté, pas de wildcard**. Exige un *Autocert Directory* persistant partagé (fs / S3 / GCS). |
| **Policy (PPL)** | YAML **config-as-code** par route : `email` / `domain` / `groups` / `claims` / appareil / jour. **Policy Builder visuel = Enterprise.** |
| **Auth machine (service accounts)** | **Enterprise / Zero UNIQUEMENT.** Le client présente un JWT Pomerium en `Bearer`. **Indisponible en OSS.** |
| Directory sync (groupes/rôles ext.) | **Enterprise.** |
| Déploiement | 4 services (proxy / authenticate / authorize / **databroker**), all-in-one possible. **HA ⇒ databroker PostgreSQL** (in-memory = 1 instance ; file = 1 instance persistée). |
| Console / GUI de gestion (la « matrice ») | **Enterprise / Zero (commercial).** OSS = fichiers de config. |
| IdP | OIDC générique ⇒ **Authentik compatible** comme fournisseur. |

> Sources : pomerium.com/docs (autorisation, service-accounts, autocert, internals/architecture), github.com/pomerium/pomerium.

**Conséquence directe sur le souhait « matrice par token ou utilisateur » :**
- **par UTILISATEUR (humain, OIDC)** → faisable en **OSS** (PPL par route) *et* déjà couvrable par **Authentik forward-auth**.
- **par TOKEN (machine)** → la façon Pomerium = **service accounts = Enterprise/Zero (payant)**. En OSS, les tokens machine restent gérés **au hub (`HUB_GATE`)** — Pomerium ne centralise pas ça gratuitement.
- **UI de matrice gérable** → **Enterprise/Zero.**

---

## Options considérées

### Option A — Remplacer Traefik par Pomerium (OSS)
| Complexité | Coût licence | Effort migration | Risque |
|---|---|---|---|
| Élevée | 0 $ | Élevé | **Élevé** |

**Contre :**
- Reprendre **tout** le TLS/ACME : HTTP-01 (fragilité déjà vécue) **sans** échappatoire DNS-01/wildcard.
- Router **tout** le public + les webhooks : en OSS, impossible d'authentifier les tokens machine → ces routes restent **publiques + auth applicative** = statu quo (on n'y gagne rien).
- **HA impose PostgreSQL** (databroker) : statefulness + sauvegarde + 4 services sur des hôtes à 2 cœurs.
- On **reconstruit le edge** sans obtenir la matrice-par-token (qui est Enterprise).

**Pour :** SSO humain uniforme ; authz identitaire (utile vu l'impossibilité d'ACL IP au FGT).
→ **Non recommandé.**

### Option B — Cohabitation : Traefik au edge + Pomerium en couche authz (OSS)
| Complexité | Coût | Effort | Risque |
|---|---|---|---|
| Moyenne | 0 $ | Moyen | Moyen |

Traefik **garde** TLS/ACME/edge (éprouvé). Pomerium derrière, **devant les apps humaines**, applique PPL par identité. Le trafic machine/API continue par `HUB_GATE`. **Adoption incrémentale, une app à la fois.**

**Pour :** faible risque, l'essentiel de la valeur (SSO + PPL policy-as-code sur les apps humaines), pas de big-bang TLS.
**Contre :** 2 proxies à opérer ; databroker Pomerium (Postgres si HA) ; double hop.

### Option C — Pas de Pomerium : durcir l'existant (Authentik forward-auth + HUB_GATE)
| Complexité | Coût | Effort | Risque |
|---|---|---|---|
| Faible | 0 $ | **Faible** | **Faible** |

Étendre le **forward-auth Authentik** (middleware Traefik, déjà utilisé sur le desk ERPNext) à **toutes** les routes humaines encore ouvertes + fermer les `/hub` non gardées au `HUB_GATE`.

**Pour :** effort/risque minimal, 0 nouveau composant, referme les **vrais** trous connus. Authentik a ses propres policies/entitlements par application.
**Contre :** pas de policy-as-code par-claim façon PPL (autorisation plus grossière : authentifié/pas authentifié + policies Authentik).

### Option D — Pomerium Enterprise / Zero
| Complexité | Coût | Effort | Risque |
|---|---|---|---|
| Moyenne-élevée | **Licence $** | Moyen | Moyen |

Seulement si la **matrice gérable** (UI, par utilisateur **et** par token/service-account, directory sync) devient une exigence dure.
**Pour :** service accounts (machine), Policy Builder, directory sync, console.
**Contre :** coût ; console = dépendance de plus (ou control-plane **hébergé** = sessions/politiques chez le fournisseur).

---

## Analyse des compromis

- **« Par token » centralisé** est le cœur du souhait — et c'est précisément une capacité **Enterprise**. En OSS, garder l'auth API **au hub** est le pattern standard et correct ; ça n'a pas à monter dans le proxy.
- **« Par utilisateur »** est faisable partout : OSS Pomerium (PPL) **ou** Authentik forward-auth (qu'on utilise déjà).
- **TLS/ACME** : Traefik est en place, éprouvé, et gère déjà le HTTP-01 fragile ; Pomerium autocert = **même classe de fragilité, sans DNS-01**. ⇒ argument fort pour **garder Traefik au edge**.
- **FGT SNAT (pas d'ACL IP)** : pousse vers une authz **identitaire** — offerte par Pomerium **et** Authentik. Le besoin est réel mais **Authentik le couvre déjà**.
- **Ressources / HA** : Pomerium OSS en HA = + PostgreSQL + 4 services. Coût ops non nul sur hôtes contraints.
- **Différenciateur réel de Pomerium** (vs Authentik) : PPL **policy-as-code** par route/claim (GitOps), authz **continue par requête** (pas seulement au login), contexte (appareil/heure), et **JWT signé** transmis aux upstreams. C'est ce qui justifierait B — pas le remplacement de Traefik.

---

## Conséquences

- **Plus facile** (B ou C) : SSO humain uniforme devant les apps → referme le gros des trous d'accès navigateur.
- **Plus difficile** (si A) : tout le edge/TLS à re-stabiliser ; l'auth machine **toujours** pas centralisée sans Enterprise.
- **À revisiter quoi qu'il arrive** : l'auth API du hub reste au `HUB_GATE` ; les webhooks (Twilio/Giftbit) resteront des **routes publiques + vérification de signature applicative** (aucun proxy n'y change rien).

---

## Recommandation

1. **Court terme — Option C (faible risque, ~80 % de la valeur sécurité).** Forward-auth Authentik sur toutes les routes humaines encore ouvertes via Traefik + audit/fermeture des `/hub` non gardées au `HUB_GATE`. Referme les trous connus avec ce qu'on a déjà.
2. **Si on veut policy-as-code par-claim + un vrai edge identity-aware devant les apps — Option B.** Pomerium **en couche derrière Traefik**, adopté **app par app**, en commençant par une app humaine à faible trafic (ex. UI n8n ou GUI GenieACS) pour valider l'OIDC Authentik + PPL + le placement TLS **avant** d'élargir.
3. **Ne pas** faire A (remplacement total). **D (Enterprise)** seulement si une « matrice par token gérée » devient une exigence business chiffrée.

**En une phrase :** Pomerium est un bon outil pour l'*autorisation identitaire des apps humaines* (Option B), pas pour *remplacer Traefik* ni pour *centraliser les tokens machine en gratuit* — et l'essentiel du gain sécurité s'obtient d'abord sans lui (Option C).

---

## Actions

1. [ ] **Générer l'inventaire des routes** (host × public / humain / machine × auth actuelle) — c'est la vraie « matrice » d'aujourd'hui, base de toute décision. *(Dérivable des confs Traefik/nginx + routeur SPA + endpoints hub.)*
2. [ ] **Option C** : activer le middleware forward-auth Authentik sur les hosts humains encore ouverts ; fermer les `/hub` non gardées.
3. [ ] *(Optionnel B)* PoC Pomerium OSS **derrière** Traefik sur 1 app humaine + IdP Authentik + une policy PPL ; mesurer le coût ops (databroker, autocert placement).
4. [ ] **Décider D** uniquement avec un besoin chiffré « matrice par token gérée ».
