fix(infra): lève les points de revue du reverse proxy
Compose interpole tout le fichier avant n'importe quelle sous-commande : la garde
`${PUBLIC_HOST:?}` de l'overlay cassait `stack-down` et `stack-logs` autant que le
démarrage. La valeur retombe sur `enervision.local`, et `stack-up` vérifie à la place
que le certificat présent couvre l'hôte demandé, ce qui est la condition réelle à tenir.
La CSP `script-src 'self'` bloquait le gestionnaire `onload` que l'inlining du CSS
critique d'Angular pose sur la feuille de styles : l'application se serait affichée sans
style derrière le proxy. `inlineCritical` passe à faux, le build de production ne produit
plus aucun script en ligne.
La zone de limitation resserrée ne couvre plus que les routes qui vérifient un secret.
Derrière le NAT de l'école, où une seule adresse porte toute la promotion, `/auth/me` et
`/auth/refresh` y auraient produit des 429 en usage normal.
Enfin `certbot/certbot` est épinglé en v5.8.0 pour que Dependabot puisse le suivre, le
proxy attend une API saine plutôt que démarrée, et la redirection vers `$host` est actée
comme risque accepté : figer un nom canonique couperait l'accès par adresse IP, seule
voie ouverte sur la machine cible.
This commit is contained in:
@@ -73,8 +73,30 @@ Swagger, il publiera les métriques avec.
|
||||
`$proxy_add_x_forwarded_for`, qui ajoute l'IP réelle en fin de chaîne. C'est exactement ce que
|
||||
lit `get_client_ip()`. Toute autre forme ferait compter la limitation de débit par IP sur l'IP
|
||||
du proxy, c'est-à-dire globalement.
|
||||
- `--forwarded-allow-ips=*` reste sans conséquence : uvicorn s'en sert pour réécrire
|
||||
`request.client` depuis `X-Forwarded-For`, et `get_client_ip()` est le seul lecteur de
|
||||
`request.client` du backend, en dernier recours quand l'en-tête est absent.
|
||||
- Une limitation de débit au frontal existe désormais, distincte de celle de l'application : 20
|
||||
requêtes par seconde sur l'API, 30 par minute sur `/api/v1/auth/`.
|
||||
requêtes par seconde sur l'API, et 30 par minute sur les seules routes qui vérifient un secret,
|
||||
`login`, `password`, `forgot-password` et `reset-password`. `/auth/me` et `/auth/refresh` en
|
||||
sont exclues : elles partent à chaque chargement de page, et le NAT de l'école donnant une seule
|
||||
adresse à toute la promotion, la zone resserrée les aurait transformées en 429 en démonstration.
|
||||
- **La CSP contraint le build du frontend.** `script-src 'self'` interdit les gestionnaires
|
||||
d'événements en ligne, et l'inlining du CSS critique d'Angular produisait exactement cela :
|
||||
`<link rel="stylesheet" media="print" onload="this.media='all'">`. La feuille serait restée en
|
||||
`media="print"`, donc l'application entière sans style. D'où `styles.inlineCritical: false` dans
|
||||
`angular.json`. `style-src` garde `'unsafe-inline'`, dont Angular a besoin pour les styles de
|
||||
composants injectés à l'exécution.
|
||||
- **La redirection 80 vers 443 conserve `$host`.** Un client qui forge son en-tête `Host` obtient
|
||||
donc une redirection vers l'hôte de son choix. Risque accepté : un navigateur ne peut pas être
|
||||
amené à envoyer un `Host` étranger, aucun cache ne s'intercale, et figer un nom canonique
|
||||
couperait l'accès par adresse IP, seule voie ouverte sur `10.0.0.10`.
|
||||
- **Aucun `:?` dans l'overlay.** Compose interpole tout le fichier avant n'importe quelle
|
||||
sous-commande : une garde y casserait `stop` et `logs` autant que `up`. `PUBLIC_HOST` retombe
|
||||
donc sur `enervision.local`, et `make stack-up` vérifie à la place que le certificat présent
|
||||
couvre l'hôte demandé, ce qui est la condition réelle à tenir.
|
||||
- Le proxy attend une API saine et pas seulement démarrée : le `HEALTHCHECK` de l'image du backend
|
||||
sert de condition à `depends_on`, faute de quoi les premiers appels à `/api/` répondent 502.
|
||||
- La ligne API8 transport de `owasp-traceabilite.md` se referme.
|
||||
- **Let's Encrypt n'est pas prouvé.** Le chemin ACME est livré, monté et documenté ; il n'a pas
|
||||
été exercé faute de domaine. Le certificat de démonstration est auto-signé, le navigateur
|
||||
|
||||
@@ -134,6 +134,13 @@ Compose.
|
||||
`/sites`, `authInterceptor` pose le jeton porteur sur les requêtes sortantes et déclenche le
|
||||
rafraîchissement sur 401. Détail complet dans
|
||||
[31-contrat-authentification.md](31-contrat-authentification.md).
|
||||
- **La CSP posée par le reverse proxy contraint le build.** `script-src 'self'` interdit les
|
||||
gestionnaires d'événements en ligne ; l'inlining du CSS critique en produisait un
|
||||
(`<link media="print" onload="this.media='all'">`), ce qui aurait laissé l'application sans
|
||||
style derrière le proxy. D'où `optimization.styles.inlineCritical: false` dans la configuration
|
||||
de production d'`angular.json`. La contrepartie est un rendu non stylé très bref au premier
|
||||
affichage. `style-src` conserve `'unsafe-inline'` : Angular injecte les styles de composants à
|
||||
l'exécution, et s'en passer demanderait un `ngCspNonce` que le SPA statique ne peut pas produire.
|
||||
|
||||
## Tests
|
||||
|
||||
|
||||
Reference in New Issue
Block a user