ldc-cluster-k8s/infrastructure/traefik/helm-release.yaml
2026-09-10 10:25:49 +02:00

481 lines
17 KiB
YAML

---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: traefik
namespace: common-services
spec:
interval: 1m0s
chart:
spec:
chart: traefik
version: 35.2.0
sourceRef:
kind: HelmRepository
name: traefik
namespace: common-services
values:
image:
tag: v3.3.6
rbac:
enabled: true
globalArguments:
- "--global.checknewversion"
- "--global.sendanonymoususage"
- "--accesslog=true"
- "--entryPoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--providers.kubernetescrd.allowCrossNamespace=true"
- "--entryPoints.web.proxyProtocol.trustedIPs=${OVH_LOAD_BALANCER_EGRESS_IP}/32"
- "--entryPoints.websecure.proxyProtocol.trustedIPs=${OVH_LOAD_BALANCER_EGRESS_IP}/32"
- "--entryPoints.websecure.forwardedHeaders.trustedIPs=${OVH_LOAD_BALANCER_EGRESS_IP}/32"
additionalArguments:
#- "--log.level=DEBUG"
- "--entrypoints.web.http.middlewares=common-services-crowdsec-bouncer@kubernetescrd"
- "--entrypoints.websecure.http.middlewares=common-services-crowdsec-bouncer@kubernetescrd"
deployment:
replicas: 2
podDisruptionBudget:
enabled: true
minAvailable: 1
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: traefik
app.kubernetes.io/instance: traefik-common-services
topologyKey: kubernetes.io/hostname
ports:
traefik:
port: 9000
expose:
default: false
protocol: TCP
web:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
port: 8443
expose:
default: true
exposedPort: 443
protocol: TCP
tls:
enabled: true
metrics:
port: 9100
expose:
default: false
protocol: TCP
providers:
kubernetesCRD:
enabled: true
ingresssClass: traefik
kubernetesIngress:
enabled: true
experimental:
plugins:
bouncer:
moduleName: github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin
version: v1.4.5
volumes:
- name: crowdsec-lapi-secret
mountPath: /etc/traefik/crowdsec
type: secret
secretName: crowdsec-lapi-secret
service:
enabled: true
type: LoadBalancer
annotations:
loadbalancer.ovhcloud.com/class: "octavia"
loadbalancer.openstack.org/proxy-protocol: "v2"
loadbalancer.openstack.org/keep-floatingip: "true"
# Protection Flux : empêche la suppression accidentelle
kustomize.toolkit.fluxcd.io/prune: disabled
spec:
externalTrafficPolicy: Local
ingressRoute:
dashboard:
enabled: true
extraObjects:
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: crowdsec-bouncer
namespace: common-services
spec:
plugin:
bouncer:
forwardedHeadersTrustedIps: "${OVH_LOAD_BALANCER_EGRESS_IP}/32"
enabled: true
crowdsecMode: stream
crowdsecLapiScheme: http
crowdsecLapiHost: crowdsec-service.common-services.svc.cluster.local:8080
crowdsecLapiPath: /
crowdsecLapiKeyFile: /etc/traefik/crowdsec/BOUNCER_KEY_traefik
crowdsecAppsecEnabled: true
crowdsecAppsecHost: crowdsec-appsec-service.common-services.svc.cluster.local:7422
crowdsecAppsecPath: /
crowdsecAppsecFailureBlock: true
crowdsecAppsecUnreachableBlock: true
crowdsecAppsecBodyLimit: 10485760
- apiVersion: traefik.io/v1alpha1 # Redirect www URLs to their no-www equivalent
kind: Middleware
metadata:
name: redirect-www-to-no-www
namespace: common-services
spec:
# Redirect a request from an url to another with regex matching and replacement
redirectRegex:
# Apply a permanent redirection (HTTP 301)
permanent: true
# The regular expression to match and capture elements from the request URL
regex: "^https?://www\\.(.+)"
# How to modify the URL to have the new target URL
replacement: "https://${1}"
- apiVersion: traefik.io/v1alpha1 # Redirect www URLs to their no-www equivalent
kind: Middleware
metadata:
name: redirect-www-to-no-www
namespace: production
spec:
# Redirect a request from an url to another with regex matching and replacement
redirectRegex:
# Apply a permanent redirection (HTTP 301)
permanent: true
# The regular expression to match and capture elements from the request URL
regex: "^https?://www\\.(.+)"
# How to modify the URL to have the new target URL
replacement: "https://${1}"
- apiVersion: traefik.io/v1alpha1 # Redirect www URLs to their no-www equivalent
kind: Middleware
metadata:
name: redirect-www-to-no-www
namespace: staging
spec:
# Redirect a request from an url to another with regex matching and replacement
redirectRegex:
# Apply a permanent redirection (HTTP 301)
permanent: true
# The regular expression to match and capture elements from the request URL
regex: "^https?://www\\.(.+)"
# How to modify the URL to have the new target URL
replacement: "https://${1}"
- apiVersion: traefik.io/v1alpha1 # Redirect www URLs to their no-www equivalent
kind: Middleware
metadata:
name: redirect-www-to-no-www
namespace: review
spec:
# Redirect a request from an url to another with regex matching and replacement
redirectRegex:
# Apply a permanent redirection (HTTP 301)
permanent: true
# The regular expression to match and capture elements from the request URL
regex: "^https?://www\\.(.+)"
# How to modify the URL to have the new target URL
replacement: "https://${1}"
# Redirection to www for common-services namespace
# TODO: remove this middleware when all sites been updated
- apiVersion: traefik.io/v1alpha1 # Redirect no-www URLs to their www equivalent
kind: Middleware
metadata:
name: redirect-no-www-to-www
namespace: common-services
spec:
# Redirect a request from an url to another with regex matching and replacement
redirectRegex:
# Apply a permanent redirection (HTTP 301)
permanent: true
# The regular expression to match and capture elements from the request URL
regex: "^https?://(?:www\\.)?(.+)"
# How to modify the URL to have the new target URL
replacement: "https://www.${1}"
# Redirection to www for production namespace
- apiVersion: traefik.io/v1alpha1 # Redirect no-www URLs to their www equivalent
kind: Middleware
metadata:
name: redirect-no-www-to-www
namespace: production
spec:
# Redirect a request from an url to another with regex matching and replacement
redirectRegex:
# Apply a permanent redirection (HTTP 301)
permanent: true
# The regular expression to match and capture elements from the request URL
regex: "^https?://(?:www\\.)?(.+)"
# How to modify the URL to have the new target URL
replacement: "https://www.${1}"
# Redirection from www to domain for staging
- apiVersion: traefik.io/v1alpha1 # Redirect no-www URLs to their www equivalent
kind: Middleware
metadata:
name: redirect-no-www-to-www
namespace: staging
spec:
redirectRegex:
# Apply a permanent redirection (HTTP 301)
permanent: true
# The regular expression to match and capture elements from the request URL
regex: "^https?://www\\.(.+)"
# How to modify the URL to have the new target URL
replacement: "https://${1}"
# Redirection from www to domain for review
- apiVersion: traefik.io/v1alpha1 # Redirect no-www URLs to their www equivalent
kind: Middleware
metadata:
name: redirect-no-www-to-www
namespace: review
spec:
redirectRegex:
# Apply a permanent redirection (HTTP 301)
permanent: true
# The regular expression to match and capture elements from the request URL
regex: "^https?://www\\.(.+)"
# How to modify the URL to have the new target URL
replacement: "https://${1}"
# customResponseHeaders middleware
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: coop-middleware
namespace: review
spec:
headers:
customResponseHeaders:
Cross-Origin-Opener-Policy: "same-origin"
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: coop-middleware
namespace: staging
spec:
headers:
customResponseHeaders:
Cross-Origin-Opener-Policy: "same-origin"
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: coop-middleware
namespace: production
spec:
headers:
customResponseHeaders:
Cross-Origin-Opener-Policy: "same-origin"
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: admin-ldc-whitelist
namespace: common-services
spec:
ipAllowList:
sourceRange:
- 163.172.132.215 # Proxy Cloud Navigation LDC
- 51.159.133.41 # Proxy Cloud Navigation LDC
- 51.159.82.143 # Proxy Cloud Navigation LDC
- 135.125.42.187 # Proxy Cloud Navigation LDC
- 37.64.103.132 # Willow Creation
- 88.86.232.178 # Cafel
- 57.128.69.87 # K8S Node 1
- 57.128.110.168 # K8S Node 2
- 57.128.111.33 # K8S Node 3
- 54.38.0.22 # K8S Node 4
- 57.128.71.23 # K8S Node 5
- 51.68.88.158/32 # prod-k8s-ldc-web-nopreempt-node-796d8b
- 51.68.92.100/32 # prod-k8s-ldc-web-nopreempt-node-8f841b
- 51.68.92.60/32 # prod-k8s-ldc-web-nopreempt-node-399aa9
- 51.68.87.150/32 # prod-k8s-ldc-web-nopreempt-node-b5417b
- 51.68.90.203/32 # prod-k8s-ldc-web-nopreempt-node-e3ac48
- 137.74.211.112/32 # dev-test-k8s-ldc-web-nopreempt-node-17257c
- 146.59.240.51/32 # dev-test-k8s-ldc-web-nopreempt-node-54e828
- 146.59.241.151/32 # dev-test-k8s-ldc-web-nopreempt-node-93017a
- 46.18.126.208/28 # LDC
- 62.193.56.48/32 # OPENevents - Bureau Neuville
- 86.65.205.240/28 # LDC
- 135.125.42.176/28 # LDC
- 149.202.23.64/26 # LDC
- 151.80.95.176/28 # LDC
- 217.15.92.64/28 # LDC
- 3.77.67.4 # UptimeRobot
- 3.79.134.69 # UptimeRobot
- 18.192.166.72 # UptimeRobot
- 18.193.252.127 # UptimeRobot
- 52.28.162.93 # UptimeRobot
- 52.59.43.236 # UptimeRobot
- 63.178.84.147 # UptimeRobot
- 24.144.78.39 # UptimeRobot
- 24.144.78.185 # UptimeRobot
- 64.225.81.248 # UptimeRobot
- 64.225.82.147 # UptimeRobot
- 143.198.249.237 # UptimeRobot
- 143.198.250.89 # UptimeRobot
- 143.244.196.21 # UptimeRobot
- 143.244.196.211 # UptimeRobot
- 152.42.149.135 # UptimeRobot
- 159.223.243.219 # UptimeRobot
- 161.35.247.201 # UptimeRobot
- 167.99.18.52 # UptimeRobot
- 188.166.201.79 # UptimeRobot
- 206.189.241.133 # UptimeRobot
- 209.38.53.7 # UptimeRobot
- 49.13.24.81 # UptimeRobot
- 49.13.130.29 # UptimeRobot
- 49.13.134.145 # UptimeRobot
- 78.47.98.55 # UptimeRobot
- 88.99.80.227 # UptimeRobot
- 142.132.180.39 # UptimeRobot
- 157.90.155.240 # UptimeRobot
- 157.90.156.63 # UptimeRobot
- 168.119.53.160 # UptimeRobot
- 168.119.96.239 # UptimeRobot
- 49.13.164.148 # UptimeRobot
- 49.13.167.123 # UptimeRobot
- 78.46.190.63 # UptimeRobot
- 78.47.173.76 # UptimeRobot
- 128.140.41.193 # UptimeRobot
- 128.140.106.114 # UptimeRobot
- 159.69.158.189 # UptimeRobot
- 167.235.143.113 # UptimeRobot
- 168.119.123.75 # UptimeRobot
- 78.46.215.1 # UptimeRobot
- 91.99.101.207 # UptimeRobot
- 46.224.188.186 # BugSmash
- 178.156.178.124 # BugSmash
- 5.161.29.18 # BugSmash
# AJOUT : Service Octavia en parallèle
- apiVersion: v1
kind: Service
metadata:
name: traefik-octavia
namespace: common-services
annotations:
loadbalancer.ovhcloud.com/class: "octavia"
loadbalancer.openstack.org/proxy-protocol: "v2"
loadbalancer.openstack.org/keep-floatingip: "true"
# Protection Flux : empêche la suppression accidentelle
kustomize.toolkit.fluxcd.io/prune: disabled
spec:
type: LoadBalancer
externalTrafficPolicy: Local
loadBalancerIP: "${TRAEFIK_LOAD_BALANCER_IP_OCTAVIA}"
selector:
app.kubernetes.io/name: traefik
app.kubernetes.io/instance: traefik-common-services
ports:
- name: web
port: 80
targetPort: 8000
protocol: TCP
- name: websecure
port: 443
targetPort: 8443
protocol: TCP
- apiVersion: v1
kind: Service
metadata:
name: blackhole
namespace: common-services
spec:
# Placeholder : jamais contacté, le middleware renvoie 403 avant.
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
- apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: deny-ip-blocklist
namespace: common-services
spec:
# ipAllowList rejette en 403
ipAllowList:
sourceRange:
- 192.0.2.1/32 # TEST-NET-1 (RFC 5737) : ne matche aucun client réel => deny
- apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: security-ip-blocklist
namespace: common-services
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: >-
ClientIP(`45.88.138.45/32`) ||
ClientIP(`8.34.210.32/32`) ||
ClientIP(`8.34.210.37/32`) ||
ClientIP(`8.34.210.42/32`) ||
ClientIP(`8.34.210.43/32`) ||
ClientIP(`8.34.210.45/32`) ||
ClientIP(`34.68.34.65/32`) ||
ClientIP(`34.68.34.66/32`) ||
ClientIP(`34.68.34.67/32`) ||
ClientIP(`34.68.34.69/32`) ||
ClientIP(`34.68.34.71/32`) ||
ClientIP(`34.68.34.72/32`) ||
ClientIP(`34.68.34.77/32`) ||
ClientIP(`34.68.34.79/32`) ||
ClientIP(`34.68.34.81/32`) ||
ClientIP(`34.68.34.84/32`) ||
ClientIP(`94.74.106.96/32`) ||
ClientIP(`20.220.225.223/32`) ||
ClientIP(`52.182.173.140/32`)
priority: 100000
middlewares:
- name: deny-ip-blocklist
namespace: common-services
services:
- name: blackhole
port: 80
- apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: blackhole
namespace: common-services
labels:
kubernetes.io/service-name: blackhole
addressType: IPv4
endpoints:
- addresses:
- 192.0.2.1 # TEST-NET-1 : non-routable, jamais contacté
conditions:
ready: true
ports:
- name: http
port: 80
protocol: TCP