From 05b121809c6a558becbaf95ed77c89e00b0e5801 Mon Sep 17 00:00:00 2001 From: Alexey Artamonov Date: Mon, 14 Sep 2026 17:29:01 +0300 Subject: [PATCH] feat(dashboard): brand the token-proxy login page from the console config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dashboard branding (title, logo) lives in the cozy-dashboard-console-config ConfigMap, which the SPA reaches only through the authenticated kube-api. The token-proxy login page — the first screen an unauthenticated user sees on a non-OIDC cluster — had no access to it and rendered the hardcoded default title and heading, defeating branding for customer-facing deployments. Mount that ConfigMap read-only into the token-proxy container and render its titleText, logoText and logoSvg on the login page, falling back to the historical unbranded page when the file is absent or unreadable so a cluster without branding is unaffected. logoSvg is already base64 in the config — the SPA's Logo.tsx consumes it that way — so it is served verbatim through an data URI, never re-encoded, which keeps any embedded script inert. The OIDC branch is untouched: its login is served by Keycloak, already branded through the realm theme. Signed-off-by: Alexey Artamonov --- .../dashboard/images/token-proxy/main.go | 106 ++++++++++++-- .../dashboard/images/token-proxy/main_test.go | 135 ++++++++++++++++++ .../dashboard/templates/gatekeeper.yaml | 15 ++ .../dashboard/tests/gatekeeper_test.yaml | 35 +++++ 4 files changed, 278 insertions(+), 13 deletions(-) diff --git a/packages/system/dashboard/images/token-proxy/main.go b/packages/system/dashboard/images/token-proxy/main.go index 3fb2ce7a7..caae63ec7 100644 --- a/packages/system/dashboard/images/token-proxy/main.go +++ b/packages/system/dashboard/images/token-proxy/main.go @@ -10,6 +10,7 @@ import ( "flag" "fmt" "html/template" + "io/fs" "log" "net/http" "net/http/httputil" @@ -37,6 +38,7 @@ var ( jwksURL string saTokenPath string saCACertPath string + brandingConfigPath string ) func init() { @@ -51,6 +53,12 @@ func init() { flag.StringVar(&jwksURL, "jwks-url", "https://kubernetes.default.svc/openid/v1/jwks", "JWKS URL for token verification") flag.StringVar(&saTokenPath, "sa-token-path", "/var/run/secrets/kubernetes.io/serviceaccount/token", "Path to service account token") flag.StringVar(&saCACertPath, "sa-ca-cert-path", "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt", "Path to service account CA certificate") + // The dashboard branding lives in the cozy-dashboard-console-config + // ConfigMap, which the SPA reaches only through the authenticated kube-api. + // Mounting the same config.json here gives the pre-auth login page a source + // for the deployment's branding; an absent or unreadable file falls back to + // the unbranded page, so a cluster without branding renders as before. + flag.StringVar(&brandingConfigPath, "branding-config-path", "/etc/cozystack/branding/config.json", "Path to the dashboard branding config.json mounted from the console ConfigMap") } // newJWKCache builds the JWK cache used to verify Kubernetes-issued JWTs. @@ -144,7 +152,7 @@ var loginTmpl = template.Must(template.New("login").Parse(` - Login + {{.Title}}