Skip to content

Instantly share code, notes, and snippets.

@tboerger
Last active October 13, 2025 16:07
Show Gist options
  • Select an option

  • Save tboerger/948e8b771a328abe08927e6d03aeabc3 to your computer and use it in GitHub Desktop.

Select an option

Save tboerger/948e8b771a328abe08927e6d03aeabc3 to your computer and use it in GitHub Desktop.
Authenticate via OIDC to Kubernetes and Headlamp with separate clients on Keycloak
--oidc-issuer-url=https://keycloak.example.com/realms/my-realm
--oidc-client-id=kubernetes
--oidc-groups-claim=groups
--oidc-groups-prefix=oidc:
--oidc-username-claim=preferred_username
--oidc-username-prefix=oidc:
apiVersion: v1
kind: Secret
metadata:
name: headlamp-oidc
namespace: headlamp-system
type: Opaque
stringData:
OIDC_CLIENT_ID: headlamp
OIDC_CLIENT_SECRET: YOUR_SECRET_FOR_THE_CLIENT
OIDC_ISSUER_URL: https://keycloak.example.com/realms/my-realm
OIDC_SCOPES: email,profile
fullnameOverride: headlamp
config:
inCluster: true
watchPlugins: true
oidc:
secret:
create: false
externalSecret:
enabled: true
name: headlamp-oidc
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: headlamp.example.com
paths:
- path: /
type: Prefix
tls:
- secretName: headlamp-tls
hosts:
- headlamp.example.com
annotations:
ingress.kubernetes.io/force-ssl-redirect: "true"
resource "keycloak_group" "headlamp" {
realm_id = keycloak_realm.realm.id
name = "headlamp"
}
resource "keycloak_openid_client" "headlamp" {
realm_id = keycloak_realm.realm.id
client_id = "headlamp"
client_secret = "YOUR_SECRET_FOR_THE_CLIENT"
name = "Headlamp"
enabled = true
access_type = "CONFIDENTIAL"
standard_flow_enabled = true
direct_access_grants_enabled = false
service_accounts_enabled = true
valid_redirect_uris = [
"https://headlamp.example.com/oidc-callback",
]
}
resource "keycloak_openid_audience_protocol_mapper" "headlamp_audience_kubernetes" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.headlamp.id
name = "kubernetes-audience"
included_client_audience = keycloak_openid_client.kubernetes.client_id
add_to_id_token = true
add_to_access_token = true
}
resource "keycloak_openid_client_default_scopes" "headlamp" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.headlamp.id
default_scopes = [
"profile",
"email",
"roles",
keycloak_openid_client_scope.groups.name,
]
}
resource "keycloak_openid_group_membership_protocol_mapper" "headlamp_groups" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.headlamp.id
name = "groups"
claim_name = "groups"
full_path = false
add_to_id_token = true
add_to_access_token = true
add_to_userinfo = true
}
resource "keycloak_openid_user_property_protocol_mapper" "headlamp_username" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.headlamp.id
name = "username"
user_property = "username"
claim_name = "preferred_username"
}
resource "keycloak_openid_user_property_protocol_mapper" "headlamp_email" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.headlamp.id
name = "email"
user_property = "email"
claim_name = "email"
}
resource "keycloak_openid_user_attribute_protocol_mapper" "headlamp_profile" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.headlamp.id
name = "profile"
user_attribute = "profile"
claim_name = "profile"
}
resource "keycloak_openid_client" "kubernetes" {
realm_id = keycloak_realm.realm.id
client_id = "kubernetes"
name = "Kubernetes"
enabled = true
access_type = "PUBLIC"
standard_flow_enabled = true
implicit_flow_enabled = false
direct_access_grants_enabled = false
service_accounts_enabled = false
valid_redirect_uris = [
"http://localhost:8000",
"http://localhost:18000",
]
}
resource "keycloak_openid_client_default_scopes" "kubernetes" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.kubernetes.id
default_scopes = [
"profile",
"email",
"roles",
keycloak_openid_client_scope.groups.name,
]
}
resource "keycloak_openid_group_membership_protocol_mapper" "kubernetes_groups" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.kubernetes.id
name = "groups"
claim_name = "groups"
full_path = false
add_to_id_token = true
add_to_access_token = true
add_to_userinfo = true
}
resource "keycloak_openid_user_property_protocol_mapper" "kubernetes_username" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.kubernetes.id
name = "username"
user_property = "username"
claim_name = "preferred_username"
}
resource "keycloak_openid_user_property_protocol_mapper" "kubernetes_email" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.kubernetes.id
name = "email"
user_property = "email"
claim_name = "email"
}
resource "keycloak_openid_user_attribute_protocol_mapper" "kubernetes_profile" {
realm_id = keycloak_realm.realm.id
client_id = keycloak_openid_client.kubernetes.id
name = "profile"
user_attribute = "profile"
claim_name = "profile"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment