Demande : « ne pas avoir le basic auth Traefik quand on est sur le Wi-Fi partagé avec le homelab ». La réponse intuitive — une règle `ClientIP(192.168.1.0/24)` — ne peut pas marcher, et la variante « je regarde CF-Connecting-IP » est un contournement d'authentification. Ce commit écrit la mesure pour qu'on ne re-découvre ni l'une ni l'autre. Mesuré (2026-07-28, homelab) : - `kadans.arcodange.fr` résout vers Cloudflare MÊME depuis le LAN, et redescend par le tunnel cloudflared. L'adresse de socket vue par Traefik est donc toujours celle d'un pod, en 10.42.x.x. - Traefik SAIT qui est le vrai client (journal d'accès : l'IPv6 de la maison, `2a01:cb04:dff:cf00::/64` — pas l'IPv4 qu'`ipify` injecte dans `localIp`), car l'entrypoint `web` fait confiance aux en-têtes venant de 10.42.0.0/16. - Mais le matcher de routeur `ClientIP()`, lui, juge la SOCKET. Prouvé par trois routeurs temporaires vers un Service sans endpoint (503 = règle matchée, 401 = repli sur le routeur normal) : témoin 503, `ClientIP(<IPv6 maison>)` 401, `ClientIP(10.42.0.0/16)` 503. Sondes retirées après mesure. D'où deux pièges, écrits là où on les rencontrerait : - `localIp@file` sur un routeur `.fr` laisserait entrer Internet entier, parce que `10.42.0.0/16` est dans son `sourceRange` et qu'`ipAllowList` juge lui aussi la socket. Vérifié : aucun routeur `.fr` ne le porte aujourd'hui — le piège est latent, et les cinq endroits d'où on pourrait le recopier (2 gabarits `.fr`, 3 values `.lab`) portent désormais l'avertissement. - Un en-tête posé par le client ne peut pas piloter une exemption d'auth : Cloudflare ne retire pas les en-têtes inconnus, et Traefik reste joignable en direct sur 192.168.1.201. Voie retenue, et pourquoi celle-là : la décision « suis-je à la maison ? » doit être prise là où la vraie IP est native et non falsifiable, donc au bord, chez Cloudflare. Une règle de transformation y pré-remplit l'en-tête `Authorization` pour les IP du foyer. Traefik ne bouge pas, aucun certificat public à produire, aucun changement DNS. Surface d'attaque ajoutée : AUCUNE — `kadans:kkadans` est déjà en clair dans le chart de kadans, Cloudflare ne fait que le taper à notre place. Et quand l'IP du foyer dérive, la règle cesse de matcher : le navigateur redemande le mot de passe. Dégradation douce, pas de panne. Le doc écrit l'action Cloudflare mot pour mot (expression, en-tête, valeur, et l'équivalent Terraform pour `cms/cloudflare`) plutôt que de la supposer faite, avec les deux commandes qui la vérifient — et nomme le repli si Cloudflare refuse de modifier `Authorization` : Cloudflare Access avec une politique de bypass, PAS un en-tête secret. Enfin, un contre-exemple utile : le bouncer CrowdSec, lui, juge la VRAIE IP (journal à l'appui). Son `clientTrustedIPs` contient `10.42.0.0/16` sans que ce soit un trou — noté pour que personne ne « corrige » cette ligne en croyant y reproduire le piège. ⚠ Aucun des réglages en cause ne vit dans ce dépôt : les valeurs Helm de Traefik, `dynamic.yaml`/`localIp` et le Middleware crowdsec sont dans `factory` (ansible), le tunnel et le DNS dans `cms`. Ce dépôt reçoit la mesure et les garde-fous parce que c'est lui qui héberge les gabarits `.fr` et les consommateurs de `localIp@file`. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01GdUCA5Uz8QyMwa2P4Pg2hK
Vault
- Les playbooks ansible configurent la base de données postgres et le minimum requis pour permetre au dépot "tools" d'appliquer via un workflow gitea action une configuration vault via tofu.
- Configuration des backend d'authentification et des roles pour postgres et kubernetes. Définition de rôles "${app}-ops" pour permettre au dépot d'une application de définir ses propres dépendances dans vault. Rotation de credentials postgres pour les applications.
- Le dépot de l'application webapp gère l'obtention de ses crédentials pour postgres.
flowchart LR
classDef playbook stroke:#0f0,fill:#440,stroke-width: 1px
classDef tofu stroke:#f00,fill:#404,stroke-width: 2px
classDef argocd stroke:#00f,fill:#044,stroke-width: 3px
classDef database stroke:#bb0,fill:#ff0,stroke-width: 5px,color: black
classDef secret stroke:#f00,fill:#f00,stroke-width: 5px,color: yellow
classDef secretOperator stroke:#f00,fill:DarkRed,stroke-width: 5px,color: Orange
subgraph git_code[factory.git]
subgraph ansible_collection
setup_playbook[playbook arcodange.factory.setup]:::playbook
tools_playbook[playbook arcodange.factory.tools]:::playbook
end
git_code_tofu_vault{{tofu}}:::tofu
end
subgraph git_tools[tools.git]
argocd_tools{{Argo CD Apps}}:::argocd
git_tools_tofu_vault{{tofu}}:::tofu
end
subgraph git_webapp[webapp.git]
webapp["Go(lang) web app"]
argocd_webapp{{Argo CD App}}:::argocd
git_webapp_tofu_vault{{tofu}}:::tofu
end
subgraph servers
subgraph k3s
subgraph k3s_ns_tools[ns:tools]
argocd{{Argo CD}}:::argocd
pgbouncer
subgraph vault
subgraph vault_auth[auth]
subgraph vault_auth_openid[openid]
end
vault_auth_jwt[jwt]
vault_auth_k8s[kubernetes]
vault_auth_jwt_role_gitea_cicd[gitea_cicd role]
vault_auth_jwt_role_gitea_cicd_webapp_ops[gitea_cicd_webapp ops role]
vault_auth_k8s_role_vso[vault-secret-operator role]
vault_auth_k8s_role_webapp[webapp role]
subgraph policies
policy_default[default]
policy_webapp[webapp]
policy_webapp_ops[webapp ops]
policy_admin[admin]
policy_vso[edit-vso-client-cache]
end
end
subgraph vault_secrets[secrets]
subgraph kvv2
google/credentials
webapp/config
end
end
subgraph vault_postgres[postgres]
creds/creds-editor
creds/webapp
end
subgraph vault_transit[transit]
end
end
vault-secret-operator:::secretOperator
end
subgraph k3s_ns_webapp[ns:webapp]
webapp_deployment[deployment:webapp]
webapp_postgres_creds_secret[secret:postgres creds]:::secret
webapp_config_secret[secret:config]:::secret
webapp_service_account[sa:webapp]
end
end
subgraph postgres
root_credentials
postgres_db[(postgres)]:::database
webapp_credentials:::secret
webapp_db[(webpp)]:::database
vault_creds_editor_role{{credentials_editor}}
end
end
setup_playbook -. setup postgres .-> postgres
tools_playbook -.-o git_code_tofu_vault
git_code_tofu_vault -..-> vault_auth_openid
git_code_tofu_vault -..-> vault_auth_jwt -- tofu:factory --- vault_auth_jwt_role_gitea_cicd
git_code_tofu_vault -..-> kvv2
git_code_tofu_vault -..-> google/credentials
linkStyle 0,1 stroke:#ff3,stroke-width:1px,color:DarkKhaki;
linkStyle 2,3,5,6 stroke:#f3f,stroke-width:2px,color:DarkOrange;
git_tools -.-o argocd_tools
argocd_tools -.-> pgbouncer
argocd_tools -.-> vault
argocd_tools -.-> vault-secret-operator
argocd_tools o--o argocd
linkStyle 7,8,9,10,11 stroke:#3ff,stroke-width:3px,color:DarkSlateBlue;
git_tools_tofu_vault -..-> vault_auth_k8s -- sa:vso --- vault_auth_k8s_role_vso
git_tools_tofu_vault -..-> webapp/config
git_tools_tofu_vault -..-> vault_transit
git_tools_tofu_vault -..-> vault_postgres
vault_auth_k8s ---> k3s
vault_postgres --> pgbouncer x==> postgres; webapp_deployment --> pgbouncer
linkStyle 12,14,15,16 stroke:#f3f,stroke-width:2px,color:DarkOrange;
linkStyle 18,19,20 stroke:gold,stroke-width:2px;
vault_transit x---x vault-secret-operator
vault-secret-operator x---x vault_auth_k8s_role_vso
vault_auth_jwt_role_gitea_cicd x--x policy_default
vault_auth_k8s_role_vso x--x policy_vso
creds/webapp -.-> webapp_credentials
creds/webapp -.-> vault-secret-operator
vault-secret-operator -.-> webapp_postgres_creds_secret
webapp/config -.-> vault-secret-operator
vault-secret-operator -.-> webapp_config_secret
argocd_webapp -.-> k3s_ns_webapp
webapp --o webapp_deployment
webapp_postgres_creds_secret --o webapp_deployment
webapp_deployment --> webapp_service_account
vault_auth_jwt -- tofu:tools --- vault_auth_jwt_role_gitea_cicd_webapp_ops
vault_auth_jwt_role_gitea_cicd_webapp_ops x--x policy_webapp_ops
vault_auth_k8s -- sa:webapp --- vault_auth_k8s_role_webapp x-- tofu:webapp --x policy_webapp
git_webapp_tofu_vault -.-> vault_auth_k8s_role_webapp
git_webapp_tofu_vault -.-> creds/webapp
root_credentials x--x postgres_db
webapp_credentials x--x webapp_db
tools_playbook --> vault_creds_editor_role
vault_creds_editor_role -. change password .-> webapp_credentials
vault_postgres x--x vault_creds_editor_role