xpeditis2.0/infra/prod/k8s/base/08-traefik-middlewares.yaml
2026-09-07 21:40:50 +02:00

149 lines
3.9 KiB
YAML

# =============================================================================
# Middlewares Traefik
# =============================================================================
# Reference dans les Ingress via l'annotation :
# traefik.ingress.kubernetes.io/router.middlewares:
# xpeditis-prod-<nom>@kubernetescrd
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: security-headers
namespace: xpeditis-prod
spec:
headers:
# HSTS : 1 an, sous-domaines inclus, eligible au preload.
# A n'activer qu'une fois certain que TOUS les sous-domaines sont en HTTPS,
# car la decision est irreversible cote navigateur pendant un an.
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
forceSTSHeader: true
contentTypeNosniff: true
browserXssFilter: true
referrerPolicy: "strict-origin-when-cross-origin"
customResponseHeaders:
# DENY et non SAMEORIGIN : l'application n'a aucun usage legitime d'une
# iframe, et c'est la meilleure protection contre le clickjacking.
X-Frame-Options: "DENY"
Permissions-Policy: "camera=(), microphone=(), geolocation=(), payment=(self), interest-cohort=()"
Cross-Origin-Opener-Policy: "same-origin"
Cross-Origin-Resource-Policy: "same-site"
# Masque la stack technique.
Server: ""
X-Powered-By: ""
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
namespace: xpeditis-prod
spec:
rateLimit:
# Limite de bordure, volontairement large : elle protege l'infrastructure.
# La limite metier fine reste celle de CustomThrottlerGuard cote NestJS.
average: 50
period: 1s
burst: 100
sourceCriterion:
ipStrategy:
# 1 = on prend l'avant-derniere IP de X-Forwarded-For, c'est-a-dire
# celle que Cloudflare a inscrite : la vraie IP du visiteur.
# Sans cela toutes les requetes seraient comptees sur l'IP Cloudflare
# et un seul abuseur ferait tomber la limite pour tout le monde.
depth: 1
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit-auth
namespace: xpeditis-prod
spec:
rateLimit:
# Beaucoup plus stricte sur /api/v1/auth : connexion, inscription,
# reinitialisation de mot de passe, liens magiques transporteurs.
# 5 req/s en pointe suffit largement a un usage humain.
average: 5
period: 1s
burst: 10
sourceCriterion:
ipStrategy:
depth: 1
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: compress
namespace: xpeditis-prod
spec:
compress:
minResponseBodyBytes: 1024
excludedContentTypes:
- image/png
- image/jpeg
- image/webp
- application/pdf
---
# Chaine appliquee au trafic public standard.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: public-chain
namespace: xpeditis-prod
spec:
chain:
middlewares:
- name: security-headers
- name: rate-limit
- name: compress
---
# Chaine appliquee aux routes d'authentification.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: auth-chain
namespace: xpeditis-prod
spec:
chain:
middlewares:
- name: security-headers
- name: rate-limit-auth
- name: compress
---
# Restriction par IP, utilisee pour Grafana. Remplacez les valeurs par vos IP
# d'administration -- les memes que admin_ip_allowlist cote Terraform.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: admin-ip-allowlist
namespace: monitoring
spec:
ipAllowList:
sourceRange:
- 203.0.113.7/32
ipStrategy:
depth: 1
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: security-headers
namespace: monitoring
spec:
headers:
stsSeconds: 31536000
stsIncludeSubdomains: true
contentTypeNosniff: true
referrerPolicy: "strict-origin-when-cross-origin"
customResponseHeaders:
X-Frame-Options: "DENY"