feat/tls-hardening #8

Merged
AzSiAz merged 9 commits from feat/tls-hardening into main 2026-07-16 20:03:10 +02:00
Owner

feat: durcissement TLS — PUBLIC_URL parsé, HSTS, Sec-Fetch-Site, chart publicUrl/HTTPRoute

Indara est toujours derrière un reverse proxy qui termine le TLS ; PUBLIC_URL est la seule source dont dispose le backend pour connaître le schéma public. Cette branche verrouille toute la chaîne.

Spec : docs/superpowers/specs/2026-07-16-tls-hardening-design.md · Plan : docs/superpowers/plans/2026-07-16-tls-hardening.md

Serveur (Rust)

  • parse_public_url (indara-core) : PUBLIC_URL parsé au boot — https obligatoire hors loopback (localhost/127.0.0.1/::1), pas de sous-chemin/query/fragment, normalisation sans / final. Nouveau champ ServerConfig.https. L'état d$
  • Cookies : helper browser_cookie partagé (oidc_flow + sid) — Secure piloté par config.https, host-only verrouillé par test (jamais d'attribut Domain → jamais envoyé aux sous-domaines frères). HttpOnly/SameSite=Lax/Path=/ i$
  • HSTS : Strict-Transport-Security: max-age=63072000 sur toutes les réponses quand l'origine publique est https (layer outermost : couvre SPA, openapi.json, opensearch.xml, erreurs). Jamais en dev localhost.
  • CSRF défense en profondeur : Sec-Fetch-Site rejeté si same-site/cross-site (un frère compromis du homelab est same-siteSameSite=Lax ne le bloque pas), absence tolérée ; le check Origin exact reste obligatoire. Appliqué à tout$

Chart Helm — ⚠️ breaking

  • publicUrl requis et validé https:// au templating (défaut http://localhost:3000 supprimé).
  • ingress.host supprimé : l'hôte est dérivé de publicUrl (helpers indara.publicUrl/indara.publicHost) — plus de typo possible entre redirect OIDC et Ingress.
  • Nouveau template HTTPRoute (gateway.networking.k8s.io/v1) : activable seul ou avec l'Ingress (split-DNS : Gateway Cilium interne + Ingress Traefik externe, même hostname). parentRefs requis quand activé.
  • README : exemple d'installation avec TLS, section « Exposure (Ingress / HTTPRoute) », tableau des values à jour.

Breaking changes (release notes)

  1. publicUrl est requis (plus de défaut) et doit être https://….
  2. ingress.host n'existe plus — retirer la valeur, l'hôte vient de publicUrl.
  3. Un PUBLIC_URL http:// non-loopback échoue désormais au boot du serveur.

Vérification

  • cargo test --workspace : 98/98 verts (7 nouveaux tests : parsing, cookies, HSTS, Sec-Fetch-Site) ; cargo clippy --workspace : 0 warning ; helm lint : OK.
  • Revue par task (spec + qualité) puis revue finale whole-branch : chaîne CSRF vérifiée route par route (tous les extracteurs session passent par validate_session_mutation), flow OIDC intact, aucun issue Critical/Important.

🤖 Generated with Claude Code

# feat: durcissement TLS — PUBLIC_URL parsé, HSTS, Sec-Fetch-Site, chart publicUrl/HTTPRoute Indara est toujours derrière un reverse proxy qui termine le TLS ; `PUBLIC_URL` est la seule source dont dispose le backend pour connaître le schéma public. Cette branche verrouille toute la chaîne. Spec : `docs/superpowers/specs/2026-07-16-tls-hardening-design.md` · Plan : `docs/superpowers/plans/2026-07-16-tls-hardening.md` ## Serveur (Rust) - **`parse_public_url`** (`indara-core`) : `PUBLIC_URL` parsé au boot — https obligatoire hors loopback (`localhost`/`127.0.0.1`/`::1`), pas de sous-chemin/query/fragment, normalisation sans `/` final. Nouveau champ `ServerConfig.https`. L'état d$ - **Cookies** : helper `browser_cookie` partagé (`oidc_flow` + `sid`) — `Secure` piloté par `config.https`, host-only verrouillé par test (jamais d'attribut `Domain` → jamais envoyé aux sous-domaines frères). `HttpOnly`/`SameSite=Lax`/`Path=/` i$ - **HSTS** : `Strict-Transport-Security: max-age=63072000` sur toutes les réponses quand l'origine publique est https (layer outermost : couvre SPA, `openapi.json`, `opensearch.xml`, erreurs). Jamais en dev localhost. - **CSRF défense en profondeur** : `Sec-Fetch-Site` rejeté si `same-site`/`cross-site` (un frère compromis du homelab est *same-site* — `SameSite=Lax` ne le bloque pas), absence tolérée ; le check `Origin` exact reste obligatoire. Appliqué à tout$ ## Chart Helm — ⚠️ breaking - **`publicUrl` requis et validé `https://` au templating** (défaut `http://localhost:3000` supprimé). - **`ingress.host` supprimé** : l'hôte est dérivé de `publicUrl` (helpers `indara.publicUrl`/`indara.publicHost`) — plus de typo possible entre redirect OIDC et Ingress. - **Nouveau template HTTPRoute** (`gateway.networking.k8s.io/v1`) : activable seul ou avec l'Ingress (split-DNS : Gateway Cilium interne + Ingress Traefik externe, même hostname). `parentRefs` requis quand activé. - README : exemple d'installation avec TLS, section « Exposure (Ingress / HTTPRoute) », tableau des values à jour. ## Breaking changes (release notes) 1. `publicUrl` est requis (plus de défaut) et doit être `https://…`. 2. `ingress.host` n'existe plus — retirer la valeur, l'hôte vient de `publicUrl`. 3. Un `PUBLIC_URL` `http://` non-loopback échoue désormais au boot du serveur. ## Vérification - `cargo test --workspace` : 98/98 verts (7 nouveaux tests : parsing, cookies, HSTS, Sec-Fetch-Site) ; `cargo clippy --workspace` : 0 warning ; `helm lint` : OK. - Revue par task (spec + qualité) puis revue finale whole-branch : chaîne CSRF vérifiée route par route (tous les extracteurs session passent par `validate_session_mutation`), flow OIDC intact, aucun issue Critical/Important. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
AzSiAz self-assigned this 2026-07-16 20:00:41 +02:00
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
AzSiAz merged commit 9bce0082fc into main 2026-07-16 20:03:10 +02:00
AzSiAz deleted branch feat/tls-hardening 2026-07-16 20:03:10 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
AzSiAz/Indara!8
No description provided.