Ingress hardening
How the Traefik ingress strips spoofable identity headers before requests reach Scrydon services.
Every external request entering Scrydon passes through Traefik. Before the request reaches any application, a header-stripping middleware scrubs identity-bearing headers that could otherwise let an attacker impersonate an internal caller.
Why this matters
Internal service callers in Scrydon are identified by headers issued by their Dapr sidecar — a sidecar token, a caller app ID, a caller namespace. If an external attacker could set those headers on an inbound request, they could impersonate an internal service and bypass the application-layer identity check.
The defence is straightforward: strip every internal-identity header at the ingress edge, before the request reaches any application code.
What gets stripped
The Traefik middleware sets the following headers to empty on every inbound request:
| Header | Purpose (when set legitimately by Dapr) |
|---|---|
dapr-api-token | Proof that a request traversed a Dapr sidecar |
dapr-caller-app-id | The internal app ID of the caller |
dapr-caller-namespace | The Kubernetes namespace of the caller |
x-scrydon-internal-dev | Dev-mode bypass marker (rejected outside dev anyway) |
A legitimate internal request never enters through the ingress — it travels mesh-internal. A request that does enter through the ingress has, by definition, no legitimate need for any of these headers, so stripping them costs nothing and stops spoofing.
TLS termination
Traefik handles TLS termination. The recommended posture:
- TLS 1.2+ only. TLS 1.0 / 1.1 disabled.
- HSTS with
max-age=31536000andincludeSubDomains. - Certificate management via cert-manager. The chart provisions a cert-manager
Certificateresource if you opt in. - Cipher suites restricted to AEAD-only (e.g.
TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256).
The exact cipher suite list is configurable in the Helm chart under traefik.tls.options.
Rate limiting
The ingress applies per-IP rate limits on auth endpoints to slow brute-force attempts:
- Sign-in: 10 requests per minute per IP.
- Password reset: 5 requests per minute per IP.
- API key validation: 60 requests per minute per IP.
Limits are configurable in the Helm chart under traefik.middleware.rateLimit.
Behind a TLS-terminating load balancer? Per-IP limits (and audit-log client IPs) are only accurate if Traefik trusts the upstream load balancer's source range — otherwise every request is attributed to the load balancer's IP. If an Azure Application Gateway, AWS ALB, or similar terminates TLS in front of Traefik, set
forwardedHeaders.trustedIPson the Traefik entrypoints. See Behind a TLS-terminating load balancer.
CORS
By default, CORS is disabled for the platform API — the only legitimate web origin is your Scrydon UI itself, served from the same domain. If your deployment hosts the UI on a separate domain (rare but supported), set the allowed origins explicitly in platform.cors.origins. Wildcards are not accepted.
What you can verify
After deployment, you can verify the hardening from any internet-reachable client:
# Header stripping — these headers should not appear in the response,
# and the service should not honour them.
curl -i https://scrydon.yourcompany.internal/health \
-H "dapr-caller-app-id: api-platform" \
-H "x-scrydon-internal-dev: 1"
# TLS configuration — version + cipher
openssl s_client -connect scrydon.yourcompany.internal:443 -tls1_3 < /dev/nullRelated
- SPIFFE / mTLS — the internal identity model that ingress stripping protects.
- Network boundary — full inbound / outbound model.