Why a WAF at the Ingress Layer?
Kubernetes Ingress controllers handle routing, but they don't inspect HTTP payloads for attacks like SQL injection, XSS, or path traversal. Adding a Web Application Firewall (WAF) at the ingress layer — before traffic reaches your services — gives you a centralized chokepoint for threat detection and blocking.
Traefik v3 supports Coraza as a middleware plugin. Coraza is an open-source WAF engine that runs the OWASP Core Rule Set (CRS). The combination is entirely self-hosted, zero-licensing-cost, and runs natively inside your cluster.
Installation
We use the Traefik Helm chart with the Coraza plugin enabled at install time:
helm repo add traefik https://traefik.github.io/charts
helm install traefik traefik/traefik \
--namespace traefik \
--create-namespace \
--set "experimental.plugins.coraza.moduleName=github.com/jcchavezs/coraza-middleware-traefik" \
--set "experimental.plugins.coraza.version=v0.2.1"
cert-manager for TLS
cert-manager handles all TLS certificate provisioning and renewal via Let's Encrypt. A single ClusterIssuer covers all namespaces:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: snaveenkumar0601@gmail.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: traefik
Coraza WAF Middleware
The Coraza middleware is defined as a Traefik Middleware resource. It loads the OWASP CRS rules and runs in detection mode first — you can switch to blocking mode once you've tuned the false positive rate.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: coraza-waf
namespace: traefik
spec:
plugin:
coraza:
directives: |
SecRuleEngine DetectionOnly
SecRequestBodyAccess On
SecResponseBodyAccess On
Include @owasp_crs/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
Include @owasp_crs/REQUEST-901-INITIALIZATION.conf
Include @owasp_crs/REQUEST-942-APPLICATION-ATTACK-SQLI.conf
Include @owasp_crs/REQUEST-941-APPLICATION-ATTACK-XSS.conf
Include @owasp_crs/REQUEST-932-APPLICATION-ATTACK-RCE.conf
SecAuditLog /dev/stdout
SecAuditLogFormat JSON
Attaching WAF to Ingress
Apply the middleware to any Ingress via annotation:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: default
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/router.middlewares: traefik-coraza-waf@kubernetescrd
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
tls:
- hosts: [app.example.com]
secretName: app-tls
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
Tuning and False Positives
Running CRS out of the box in blocking mode will almost certainly cause false positives — especially for APIs that send JSON bodies. The recommended workflow:
- Start with
SecRuleEngine DetectionOnlyand monitor audit logs - Identify false positive rule IDs from Kibana or log queries
- Add targeted exclusions for known-safe patterns
- Switch to
SecRuleEngine Ononce false positive rate is acceptable
Results
After deploying this stack on the SIEMply Secure platform, we had full TLS automation across all services and WAF coverage on all externally-facing ingress routes. The Coraza audit logs (JSON format, shipped to Elasticsearch via Filebeat) gave us complete visibility into blocked and detected requests.
Running a WAF in detection mode for two weeks before enabling blocking is not optional — it's how you avoid breaking your own platform on day one.
Key Takeaways
- Traefik + Coraza is a fully open-source WAF stack — no licensing overhead
- cert-manager + Let's Encrypt eliminates all manual TLS work
- Always run in detection mode first; audit logs are essential for tuning
- Ship Coraza JSON audit logs to your SIEM for correlation with other security events