vídeo local
Descripción
En este post exploraremos en profundidad cómo centralizar y simplificar la gestión de accesos en Grafana mediante la integración con Keycloak utilizando el protocolo OpenID Connect. A través de una arquitectura basada en contenedores, descrita en nuestro fichero docker-compose, se delega por completo el proceso de autenticación a sistemas especializados, lo que permite que Grafana “herede” la información de usuario y el role que debe tener en la sesión de Grafana gestionar internamente la base de datos de usuarios como source of trhuth; o sea, tenemos un S.S.O (Single Sign On) integrado nativamente con Grafana.
Visión General de la Arquitectura
El entorno que proponemos se apoya en una infraestructura compuesta por Grafana, configurado para desactivar su propio login interno, y autenticado a través del método Auth Proxy. El fichero docker-compose.yaml muestra cómo se definen las variables de entorno esenciales en Grafana, entre las cuales destacan:
- GF_SERVER_ROOT_URL: Se configura para apuntar a la URL pública del servicio.
- GF_AUTH_DISABLE_LOGIN_FORM: Se deshabilita el formulario de login interno para que la autenticación se realice a través de un proxy.
- GF_AUTH_GENERIC_OAUTH_*: Se establecen los parámetros para que Grafana utilice Keycloak como proveedor de identidades (IdP) mediante OpenID Connect, incluyendo el
client_id,client_secret, URLs de autorización, token y usuario, y una expresión para mapear roles.
Esta configuración permite que, en lugar de autenticar al usuario internamente, Grafana reciba la identidad del usuario ya validada y gestionada por componentes externos.
El Papel de Keycloak y OpenID Connect
Keycloak actúa como el centro neurálgico de gestión de identidades en este escenario. Gracias a OpenID Connect, Keycloak se encarga de:
- Autenticar a los usuarios: Mediante un proceso robusto que puede incluir múltiples factores de autenticación.
- Proveer tokens y claims: Tras una autenticación exitosa, Keycloak genera tokens de acceso y refresh, y extrae información del usuario (correo, nombre, roles, etc.) que se inyecta en las cabeceras HTTP.
- Centralizar la gestión de accesos: Con Keycloak se unifican los mecanismos de login, 2FA, integración con otros IdP y políticas de seguridad, lo que aporta mayor robustez y flexibilidad a la solución.
Secuencia del proceso
A continuación se describe la secuencia de 14 pasos del flujo OAuth2 Authorization Code en el que Grafana actúa como cliente OpenID Connect que se comunica directamente con Keycloak:
- Inicio del Acceso del Usuario: El usuario accede a la URL pública de Grafana a través de su navegador. Al llegar, Grafana detecta que no existe una sesión activa.
- Detección de la Falta de Autenticación: Al no contar con una sesión válida (por ejemplo, la cookie de sesión o token de acceso), Grafana inicia el proceso de autenticación mediante OpenID Connect.
- Redirección a Keycloak: Grafana genera una redirección hacia el endpoint de autorización de Keycloak. En esta URL se incluyen parámetros esenciales como el
client_id, elscope(que puede incluir “openid”, “email”, “profile”, etc.) y la URL de redirección (redirect_uri) donde se espera recibir el código de autorización. - Llegada a la Pantalla de Login de Keycloak: El navegador sigue la redirección y llega a Keycloak, donde se presenta la pantalla de login para que el usuario introduzca sus credenciales.
- Ingreso y Validación de Credenciales: El usuario introduce sus datos (nombre de usuario y contraseña) y Keycloak procede a validar las credenciales. En este paso también pueden activarse mecanismos adicionales de seguridad (como autenticación de dos factores).
- Emisión del Código de Autorización: Una vez autenticado correctamente, Keycloak genera un código de autorización temporal y redirige el navegador hacia la URL de redirección definida por Grafana, adjuntando dicho código como parámetro.
- Recepción del Código en Grafana: Grafana recibe la solicitud con el código de autorización en la URL. Este código es la prueba de que el usuario se ha autenticado correctamente en Keycloak.
- Intercambio del Código por Tokens: Con el código en mano, Grafana realiza una solicitud al endpoint de tokens de Keycloak. En esta solicitud se incluyen el
client_id,client_secrety el código recibido, para intercambiarlo por un access token (y, opcionalmente, un refresh token). - Validación y Recepción de Tokens: Keycloak verifica la validez del código de autorización y, de ser correcto, devuelve a Grafana el access token junto con otros tokens relevantes. Estos tokens contienen información (claims) sobre el usuario autenticado.
- Validación Interna en Grafana: Grafana valida el access token recibido, comprobando su firma y vigencia, y extrae los datos de usuario necesarios (correo, nombre, roles, etc.) según la configuración establecida.
- Mapeo de Roles: Utilizando la expresión definida en la variable de entorno
GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH, Grafana interpreta los roles contenidos en el token (por ejemplo, asignando “Admin”, “Editor” o “Viewer” según corresponda). - Establecimiento de la Sesión de Usuario: Con los datos validados, Grafana crea una sesión interna para el usuario y establece las cookies correspondientes, de modo que las solicitudes futuras se consideren autenticadas sin necesidad de repetir el proceso.
- Redirección Final al Dashboard: Una vez establecida la sesión, Grafana redirige al usuario a su página de inicio o dashboard, permitiéndole acceder a las funcionalidades de forma segura y sin interrupciones.
- Mantenimiento de la Sesión y Acceso Continuado: Durante la navegación, Grafana utiliza la sesión establecida (y, en caso de expirar, puede utilizar el refresh token) para mantener la autenticación del usuario. Así, el usuario disfruta de un acceso continuo sin tener que reingresar sus credenciales en cada petición.
Esta secuencia de 14 pasos ilustra cómo Grafana, al utilizar su cliente OpenID Connect, se integra directamente con Keycloak para gestionar la autenticación, delegando en el proveedor de identidad toda la complejidad del proceso y estableciendo una experiencia de usuario fluida y segura.
Configuración
Keycloak

1. Creación del Client




Las credenciales de acceso:
client-id lo hemos introducido al principio del proceso en nuestro caso: grafana y el client-password se puede encontrar aquí:
2. Creación de los roles
Hay que crear los tres roles que tiene Grafana: admin, editor y viewer.

3. Role mapper:
Queremos que cuando se devuelva la información del usuario durante la emisión del Access Token se envie también la información de los roles que hemos creado.



4. Creación de usuario y asignación del role





Hay que escoger alguno de los tres roles que pone
grafana: admin, editor o viewer. el otro role (uma_protection) esta solución no nos aporta nada. Si se escoge más de un role es muy probable que no funcione.
Hasta aquí la configuración de Keycloak. Con esto debería ser suficiente para que podamos autenticarnos con el usuario
username01 en el proceso de login al que nos desafiará Grafana cuando intentemos acceder a él.Evidentemente es muy recomendable crear un usuario con permisos de administrador (admin) para que pueda gestionar los items de Grafana.
Grafana
En este fichoer de docker compose que se adjunta hay toda la configuración que le hace falta a Grafana para poder conectarse a Keycloak y delegar la autenticación de los usuarios y su role.
docker-compose.yaml
name: grafana_i40sys
x-logging:
&default-logging
driver: "json-file"
options:
max-size: "10m"
max-file: "1"
services:
grafana:
image: grafana/grafana:latest
restart: unless-stopped
environment:
- GF_LOG_LEVEL=warn
# [server]
- GF_SERVER_ROOT_URL=https://grafana.i40sys.com/
# [dataproxy]
- GF_DATAPROXY_SEND_USER_HEADER=true
# [users]
- GF_USERS_ALLOW_SIGN_UP=false
- GF_USERS_AUTO_ASSIGN_ORG=true
- GF_USERS_AUTO_ASSIGN_ORG_ID=1
- GF_USERS_AUTO_ASSIGN_ORG_ROLE=Admin
# [auth]
- GF_AUTH_DISABLE_LOGIN_FORM=true
- GF_AUTH_SIGNOUT_REDIRECT_URL=https://grafana.i40sys.com/oauth2/sign_out?rd=https://grafana.i40sys.com
# [auth.anonymous]
- GF_AUTH_ANONYMOUS_ENABLED=false
# [auth.generic_oauth]
- GF_AUTH_GENERIC_OAUTH_ENABLED=true
- GF_AUTH_GENERIC_OAUTH_AUTO_LOGIN=true
- GF_AUTH_GENERIC_OAUTH_NAME=Keycloak-OAuth
- GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP=true
- GF_AUTH_GENERIC_OAUTH_CLIENT_ID=grafana
- GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET=UsaoxkLbC1h6tfzxdMrM6ZjfV24ueKtq
- GF_AUTH_GENERIC_OAUTH_SCOPES="openid email profile offline_access roles"
- GF_AUTH_GENERIC_OAUTH_EMAIL_ATTRIBUTE_PATH=email
- GF_AUTH_GENERIC_OAUTH_LOGIN_ATTRIBUTE_PATH=username
- GF_AUTH_GENERIC_OAUTH_NAME_ATTRIBUTE_PATH=full_name
- GF_AUTH_GENERIC_OAUTH_AUTH_URL=https://iam.i40sys.com/realms/observability/protocol/openid-connect/auth
- GF_AUTH_GENERIC_OAUTH_TOKEN_URL=https://iam.i40sys.com/realms/observability/protocol/openid-connect/token
- GF_AUTH_GENERIC_OAUTH_API_URL=https://iam.i40sys.com/realms/observability/protocol/openid-connect/userinfo
- GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH=contains(resource_access.grafana.roles[*], 'admin') && 'Admin' || contains(resource_access.grafana.roles[*], 'editor') && 'Editor' || (contains(resource_access.grafana.roles[*], 'viewer') && 'Viewer')
- GF_AUTH_GENERIC_OAUTH_SIGNOUT_REDIRECT_URL=https://iam.i40sys.com/realms/observability/protocol/openid-connect/logout?post_logout_redirect_uri=https%3A%2F%2Fgrafana.i40sys.com%2Flogin
- GF_AUTH_GENERIC_OAUTH_ALLOW_ASSIGN_GRAFANA_ADMIN=true
- GF_AUTH_GENERIC_OAUTH_USE_REFRESH_TOKEN=true
- GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_STRICT=true
volumes:
- /etc/localtime:/etc/localtime:ro
networks:
- services
logging: *default-logging
networks:
services:
external: true
name: services

Securing Grafana with Keycloak SSO Integration