From d8ee88e4876bca5661979f5207643bc15f9e5732 Mon Sep 17 00:00:00 2001 From: jochens Date: Wed, 30 Sep 2026 00:39:16 +0200 Subject: [PATCH] grafana: log in through keycloak's oidc-client provision HAL's grafana logged in through a hand-made Keycloak client whose secret sat in its .env. Requiring oidc-client gives it a client the mesh makes and keeps: the id and URLs come from the binding, the secret arrives as a file grafana reads itself (__FILE), and the callback it contributes is what keycloak registers as its redirect. GF_SERVER_ROOT_URL is still a literal: a module cannot yet learn the public name the mesh composes for its own endpoint (hq issue 122), and without it grafana sends a redirect Keycloak refuses. --- modules/grafana/module.json | 41 +++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/modules/grafana/module.json b/modules/grafana/module.json index b5a7458..0cd6f36 100644 --- a/modules/grafana/module.json +++ b/modules/grafana/module.json @@ -47,6 +47,21 @@ "owner": "472:472", "content": "${secret:admin}" }, + { + "id": "oidc-secret", + "type": "file", + "path": "${dir:state}/oidc-client.secret", + "mode": "0400", + "owner": "472:472", + "content": "${secret:oidc-client}" + }, + { + "id": "oidc-env", + "type": "file", + "path": "${dir:state}/oidc.env", + "mode": "0644", + "content": "GF_SERVER_ROOT_URL=https://grafana.zurag.be\nGF_AUTH_GENERIC_OAUTH_ENABLED=true\nGF_AUTH_GENERIC_OAUTH_NAME=Keycloak\nGF_AUTH_GENERIC_OAUTH_CLIENT_ID=${bound:oidc-client:as}\nGF_AUTH_GENERIC_OAUTH_CLIENT_SECRET__FILE=/run/secrets/oidc-client\nGF_AUTH_GENERIC_OAUTH_SCOPES=openid email profile roles\nGF_AUTH_GENERIC_OAUTH_AUTH_URL=${bound:oidc-client:issuer}${bound:oidc-client:authorization-path}\nGF_AUTH_GENERIC_OAUTH_TOKEN_URL=${bound:oidc-client:issuer}${bound:oidc-client:token-path}\nGF_AUTH_GENERIC_OAUTH_API_URL=${bound:oidc-client:issuer}${bound:oidc-client:userinfo-path}\nGF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH=contains(roles[*], 'admin') && 'Admin' || contains(realm_access.roles[*], 'admin') && 'Admin' || 'Viewer'\nGF_AUTH_GENERIC_OAUTH_USE_PKCE=true\nGF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP=true\nGF_AUTH_GENERIC_OAUTH_ALLOW_ASSIGN_GRAFANA_ADMIN=true\n" + }, { "id": "server", "type": "container", @@ -57,11 +72,19 @@ ], "volumes": [ "${dir:data}:/var/lib/grafana", - "${dir:state}/admin.secret:/run/secrets/admin:ro" + "${dir:state}/admin.secret:/run/secrets/admin:ro", + "${dir:state}/oidc-client.secret:/run/secrets/oidc-client:ro" ], "env": { "GF_SECURITY_ADMIN_PASSWORD__FILE": "/run/secrets/admin" - } + }, + "env-file": [ + "${dir:state}/oidc.env" + ], + "restart-on": [ + "oidc-env", + "oidc-secret" + ] }, { "id": "runtime-config", @@ -92,16 +115,26 @@ } ], "requires": [ - "route" + "route", + "oidc-client" ], "contributes": { "route": { "label": "grafana", "endpoint": "web" + }, + "oidc-client": { + "label": "grafana", + "endpoint": "web", + "callback": "/login/generic_oauth" } }, "binds": { - "route": "${dir:state}/route.json" + "route": "${dir:state}/route.json", + "oidc-client": "${dir:state}/oidc.json" + }, + "secrets": { + "oidc-client": "/var/lib/mesh/grafana/oidc-client" }, "build": { "on": [