Compare commits

...
Author SHA1 Message Date
Dorian ac05da7001 docs(backend): corrige la justification du CORP same-origin (no-cors, pas d'ingress)
Airflow / Construction de l'image (push) Successful in 1m17s
Backend / Tests exigeant une base (push) Failing after 4m50s
Backend / Analyse statique de sécurité (push) Successful in 7s
Airflow / Lint et intégrité des DAGs (push) Successful in 9m34s
Backend / Audit des dépendances (push) Successful in 9m36s
Backend / Lint, typage et tests (push) Successful in 10m7s
SonarQube / test-ml (push) Failing after 6m8s
SonarQube / build-front (push) Successful in 10m15s
SonarQube / build-back (push) Successful in 10m47s
SonarQube / test-front (push) Failing after 5m13s
SonarQube / test-back (push) Failing after 5m22s
SonarQube / SonarQube (push) Skipped
2026-09-23 10:30:06 +02:00
Dorian cfc194a3fb fix(backend): ajoute l'en-tete Cross-Origin-Resource-Policy sur toutes les reponses 2026-09-23 09:36:10 +02:00
Johan LEROYandGitHub 59f050ec5e Merge pull request #147 from ineszang/test/integration-api-db-ml
test(ml,backend): tests d'intégration API ↔ DB ↔ ML, et surveillance de dérive
2026-09-22 16:52:55 +02:00
4 changed files with 13 additions and 4 deletions
+3
View File
@@ -16,6 +16,9 @@ EN_TETES: Final[dict[str, str]] = {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Referrer-Policy": "no-referrer",
# same-origin : aucun client ne charge l'API en no-cors depuis une autre origine
# (proxy.conf.json en dev, reverse proxy nginx ensuite, cf. docs/architecture/20-backend.md).
"Cross-Origin-Resource-Policy": "same-origin",
}
PREFIXE_AUTHENTIFICATION: Final = "/auth"
+2 -1
View File
@@ -23,8 +23,9 @@ async def interroge(
("x-content-type-options", "nosniff"),
("x-frame-options", "DENY"),
("referrer-policy", "no-referrer"),
("cross-origin-resource-policy", "same-origin"),
],
ids=["nosniff", "anti_iframe", "referrer"],
ids=["nosniff", "anti_iframe", "referrer", "corp"],
)
async def test_every_response_carries_the_security_headers(
client: AsyncClient, entete: str, valeur: str
+7 -2
View File
@@ -423,8 +423,13 @@ Le reste, par ordre de surface :
écriture des journaux. C'est la troisième ligne de défense : la première est de ne rien passer
de secret au logger, la deuxième de ne jamais mettre un jeton dans une URL.
- En-têtes posés par l'application : `X-Content-Type-Options`, `X-Frame-Options`,
`Referrer-Policy`, plus `Cache-Control: no-store` sur `/auth/*`. HSTS et CSP appartiennent au
terminateur TLS, que l'application ne connaît pas : le reverse proxy les pose
`Referrer-Policy`, `Cross-Origin-Resource-Policy: same-origin`, plus `Cache-Control: no-store`
sur `/auth/*`. Le CORP est fixé à `same-origin` parce qu'aucun client légitime ne charge l'API
en `no-cors` (image, script, média) depuis une autre origine : le frontend l'appelle en relatif
(`/api/v1`), sur sa propre origine, via `proxy.conf.json` en dev et le reverse proxy nginx
(`infra/proxy/conf.d/enervision.conf`) en recette et en production. Les appels `HttpClient`, en
mode `cors`, n'y sont de toute façon pas soumis. HSTS et CSP appartiennent au terminateur TLS, que
l'application ne connaît pas : le reverse proxy les pose
([ADR 0007](../adr/0007-terminaison-tls-et-reverse-proxy-nginx.md)).
- Le conteneur tourne en utilisateur non-root, avec un `HEALTHCHECK` sur `/api/v1/health/live`.
- TLS, limitation de débit au frontal et journal d'accès sont portés par le reverse proxy.
+1 -1
View File
@@ -39,7 +39,7 @@ lecture seule ; plusieurs lignes resteront à compléter une fois les endpoints
| Cinq gardes de configuration qui refusent le démarrage plutôt que de dégrader silencieusement | `app/core/config.py` | A05 |
| Documentation interactive fermée hors développement, `/metrics` derrière un jeton, sonde qui ne publie plus de version | `app/main.py`, `app/api/security.py` | A05 |
| Scan dynamique OWASP ZAP de l'API authentifiée (compte `lecteur` jetable), non bloquant, configuration par défaut du backend uniquement (ni TLS ni en-têtes du reverse proxy) | `.github/workflows/dast.yml`, `scripts/dast-token.sh` | A05, API8 Security Misconfiguration |
| En-têtes `nosniff`, `DENY`, `no-referrer`, et `no-store` sur les routes d'authentification | `app/api/middleware.py` | A05 |
| En-têtes `nosniff`, `DENY`, `no-referrer`, `Cross-Origin-Resource-Policy: same-origin`, et `no-store` sur les routes d'authentification | `app/api/middleware.py` | A05 |
| Refus de rétrograder ou désactiver le dernier administrateur actif | `app/services/user.py` | A04 Insecure Design |
| Amorçage du premier administrateur hors dépôt, mot de passe jamais dans `argv` ni dans Git | `app/cli.py` | A02, A05 |
| Réponse de l'API Mock bornée avant écriture : timeout, plafond de sites et de mesures, bornes physiques par grandeur, recopie des seuls champs attendus | `app/etl/mock_api_import.py` | API10 Unsafe Consumption of APIs |