Gate the n8n trigger endpoints on Keycloak

Every webhook on this instance was answering unauthenticated requests, the
stock watchlist included — it returned references and stock levels and let
anyone clear entries. The A2A facade in front of these workflows enforces a
bearer, but the workflows stayed reachable directly, facade bypassed.

Keycloak's userinfo is the authenticator: 200 for a valid bearer in the realm,
401 otherwise, which is the auth-request contract exactly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Stéphane Tailland
2026-08-31 07:56:13 +02:00
parent 06d0ab5e2d
commit 0847e11713
+10
View File
@@ -27,6 +27,16 @@ spec:
TIMEZONE: Europe/Paris TIMEZONE: Europe/Paris
INGRESS_CLASS: nginx INGRESS_CLASS: nginx
INGRESS_BODY_SIZE: "50m" INGRESS_BODY_SIZE: "50m"
# Every trigger endpoint is gated by this. Keycloak's userinfo answers 200
# for a valid bearer in the realm and 401 otherwise, which is exactly the
# auth-request contract, so nothing had to be built for it. In-cluster,
# over http: the subrequest never leaves the cluster and needs no CA.
#
# It authenticates, it does not authorise: any token this realm issued
# gets through, including an agent's own service account. The finer grain
# belongs to the workflow, which exchanges the caller's token and is
# refused by the domain if the caller may not read it.
N8N_WEBHOOK_AUTH_URL: http://keycloak.keycloak.svc.cluster.local:8080/realms/classic-models/protocol/openid-connect/userinfo
TLS_ISSUER_NAME: sttlab-local-ca TLS_ISSUER_NAME: sttlab-local-ca
TLS_ISSUER_KIND: ClusterIssuer TLS_ISSUER_KIND: ClusterIssuer
VAULT_SERVER: https://vault.sttlab.eu VAULT_SERVER: https://vault.sttlab.eu