SAML en Kong mediante Keycloak
El plugin oficial saml de Kong requiere una licencia Enterprise. Después de revisar las alternativas abiertas de la comunidad o de código libre no he encontrado un plugin SAML directo, mantenido y compatible con Kong 3.x que resulte razonable recomendar.
En este laboratorio utilizaremos una arquitectura distinta y completamente abierta: Keycloak actuará como Service Provider SAML y como broker de identidad, mientras Kong utilizará el plugin abierto de la comunidad o código libre kong-openid-connect instalado en el artículo anterior. La autenticación del usuario sí ocurre mediante una petición y una respuesta SAML reales. Keycloak valida el XML firmado y entrega a Kong un Authorization Code de OpenID Connect.
Todas las respuestas incluidas en el artículo proceden de la VM del laboratorio.
El plugin SAML oficial de Kong es propietario y no puede utilizarse sin una licencia Enterprise. Esta solución no es una reimplementación ni un sustituto directo de su API: traslada la terminación SAML a Keycloak y mantiene OIDC entre Keycloak y Kong.
Este laboratorio continúa desde OpenID Connect en Kong. Reutiliza kong-openid-connect, el Gateway kong, el servicio echo, KIC 3.5 y la dirección 192.168.121.200.
1. ¿Por qué usar un broker?
SAML 2.0 intercambia autenticación mediante XML, firmas digitales, metadatos, una entidad emisora, una audiencia y un Assertion Consumer Service (ACS). Implementar correctamente todas esas validaciones dentro de un plugin Lua pequeño sería una decisión de seguridad difícil de justificar.
Keycloak es un proyecto de código abierto activo que admite identity brokering y proveedores SAML. En esta arquitectura cada componente se encarga del protocolo que conoce:
- Keycloak genera la
SAMLRequest. - El IdP autentica al usuario y firma la
SAMLResponse. - Keycloak valida firma, destino, audiencia y tiempos de la aserción.
- Keycloak transforma la identidad SAML en una sesión OIDC.
- Kong valida el flujo OIDC y protege la ruta.
No necesitamos crear un KongConsumer: la identidad y la sesión se resuelven entre el IdP, el realm broker y el plugin OIDC.
2. Flujo completo del laboratorio
Kong solo participa en el tramo OpenID Connect. El realm kong-saml-broker actúa como Service Provider SAML, envía la AuthnRequest al IdP y valida la SAMLResponse firmada. Después transforma esa identidad en un código OIDC que Kong puede validar para crear la sesión.
Utilizamos dos realms en una única instancia de Keycloak para que el escenario sea autocontenido:
| Realm | Función |
|---|---|
saml-idp | IdP SAML y usuario alice |
kong-saml-broker | SP SAML para el IdP y proveedor OIDC para Kong |
En producción, saml-idp se sustituiría por Entra ID, Okta, ADFS u otro IdP corporativo.
3. Requisito: instalar el plugin abierto de la comunidad o código libre
El puente reutiliza el adaptador del post 15, fijado al commit a4ff261, y lua-resty-openidc v1.9.0:
cd ~/kic-auth
chmod +x 15-install-community-oidc.sh
./15-install-community-oidc.sh
Comprobamos que Kong lo ha cargado:
sudo kubectl get deployment kong-gateway -n kong \
-o jsonpath='{.spec.template.spec.containers[?(@.name=="proxy")].env[?(@.name=="KONG_PLUGINS")].value}{"\n"}'
bundled,oidc,kong-openid-connect
4. Desplegar los realms SAML
16-keycloak.yaml crea un ConfigMap, un Deployment y un Service. El primer realm registra el cliente OIDC de Kong:
{
"clientId": "kong-saml-gateway",
"protocol": "openid-connect",
"publicClient": false,
"secret": "kong-saml-gateway-secret",
"standardFlowEnabled": true,
"redirectUris": ["http://echo.javiercd.es/saml/callback"]
}
El realm saml-idp registra como Service Provider al broker:
{
"clientId": "http://saml.192.168.121.200.nip.io/realms/kong-saml-broker",
"protocol": "saml",
"redirectUris": [
"http://saml.192.168.121.200.nip.io/realms/kong-saml-broker/broker/saml-idp/endpoint"
],
"attributes": {
"saml.assertion.signature": "true",
"saml.server.signature": "true",
"saml.force.post.binding": "true",
"saml_name_id_format": "email"
}
}
El usuario de prueba es:
Usuario: alice
Contraseña: alice-password
NameID: alice@example.test
Keycloak se publica en:
http://saml.192.168.121.200.nip.io
El manifiesto usa start-dev, H2 efímero, HTTP y credenciales conocidas. Solo es válido para este laboratorio.
5. Configurar la confianza SAML
16-configure-saml-broker.sh realiza la parte que normalmente configuraríamos en la consola:
- Obtiene un token de administración.
- Descarga el descriptor SAML del realm IdP.
- Extrae su certificado X.509.
- Registra
saml-idpcomo proveedor del realm broker. - Activa la validación de firmas y exige aserciones firmadas.
Las URL relevantes son:
Entity ID del SP:
http://saml.192.168.121.200.nip.io/realms/kong-saml-broker
Single Sign-On Service del IdP:
http://saml.192.168.121.200.nip.io/realms/saml-idp/protocol/saml
ACS:
http://saml.192.168.121.200.nip.io/realms/kong-saml-broker/broker/saml-idp/endpoint
El script de despliegue configura la API de administración mediante un port-forward al pod nuevo. Esto evita escribir accidentalmente en un pod anterior durante un reinicio.
6. Guardar los secretos de Kong
16-saml-bridge-secrets.yaml separa el secreto OIDC y la clave de sesión del KongPlugin:
apiVersion: v1
kind: Secret
metadata:
name: saml-bridge-secrets
namespace: javier
stringData:
client-secret: '"kong-saml-gateway-secret"'
session-secret: '"SAMLbridgeSessionSecret32bytes12"'
type: Opaque
Las comillas dobles forman parte de los valores porque KIC interpreta los valores de configPatches como JSON.
7. Configurar Kong
Kong no procesa XML SAML. El parámetro kc_idp_hint envía al navegador directamente al proveedor SAML configurado en el broker:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: saml
namespace: javier
plugin: kong-openid-connect
config:
client_id: kong-saml-gateway
discovery: http://saml.192.168.121.200.nip.io/realms/kong-saml-broker/.well-known/openid-configuration
redirect_uri: http://echo.javiercd.es/saml/callback
scope: openid profile email
response_type: code
token_endpoint_auth_method: client_secret_post
authorization_params:
kc_idp_hint: saml-idp
session_cookie_name: kong_saml_bridge_session
session_cookie_lifetime: 3600
session_storage: cookie
session_cookie_secure: false
session_cookie_httponly: true
session_cookie_samesite: Lax
ssl_verify: false
configPatches:
- path: /client_secret
valueFrom:
secretKeyRef:
name: saml-bridge-secrets
key: client-secret
- path: /session_secret
valueFrom:
secretKeyRef:
name: saml-bridge-secrets
key: session-secret
La HTTPRoute aplica el recurso a /saml. El mismo prefijo incluye /saml/callback.
8. Desplegar el laboratorio
Todos los manifiestos y scripts están en posts/16-autenticacion-saml del repositorio de ejemplos:
cd ~/kic-auth
chmod +x 16-configure-saml-broker.sh
chmod +x 16-deploy-saml-bridge-lab.sh
chmod +x 16-test-saml-bridge.sh
./16-deploy-saml-bridge-lab.sh
Salida real:
deployment "keycloak-saml" successfully rolled out
httproute.gateway.networking.k8s.io/keycloak-saml configured
Broker SAML configurado.
kongplugin.configuration.konghq.com/saml unchanged
httproute.gateway.networking.k8s.io/saml configured
Puente SAML a OIDC desplegado.
9. Probar el flujo SAML
9.1. Redirección inicial
curl -sS -D - -o /dev/null http://echo.javiercd.es/saml
Respuesta real, abreviando únicamente la cookie y los valores aleatorios:
HTTP/1.1 302 Moved Temporarily
Set-Cookie: session=<cookie-cifrada>; Path=/; SameSite=Lax; HttpOnly
Location: http://saml.192.168.121.200.nip.io/realms/kong-saml-broker/protocol/openid-connect/auth?scope=openid%20profile%20email&kc_idp_hint=saml-idp&nonce=<nonce>&client_id=kong-saml-gateway&redirect_uri=http%3A%2F%2Fecho.javiercd.es%2Fsaml%2Fcallback&state=<state>&response_type=code
Server: kong/3.10.0.16-enterprise-edition
El navegador continúa hacia el endpoint SAML del IdP. La redirección contiene una SAMLRequest y un RelayState reales.
9.2. Login desde el navegador
Abrimos:
http://echo.javiercd.es/saml
Iniciamos sesión como alice. En el primer acceso, Keycloak puede pedir confirmar el perfil que creará en el realm broker. Después recibiremos:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Hola desde Kong Gateway KIC
