Keycloak as a sample IdP#
This guide describes how to deploy Keycloak and configure it as the identity provider (IdP) for OSMO. Keycloak acts as an authentication broker, allowing OSMO to authenticate users through various identity providers (LDAP, SAML, social logins) while providing centralized group and role management.
Note
Keycloak is one option for an IdP. OSMO can also connect directly to other providers such as Microsoft Entra ID, Google, or AWS IAM Identity Center without Keycloak. See Identity Provider (IdP) Setup for direct IdP configuration.
When to use Keycloak#
Use Keycloak when:
You want a self-hosted identity broker that can federate multiple upstream identity providers (LDAP, SAML, OIDC) behind a single OIDC interface for OSMO.
You need centralized user, group, and role management in a dedicated admin console.
You want to manage pool access by assigning Keycloak roles to groups rather than configuring each user individually.
If you already have a single IdP (e.g., Microsoft Entra ID) and do not need a broker, connecting OSMO directly to that IdP is simpler. See Identity Provider (IdP) Setup.
Part 1: Deploy Keycloak#
Step 1: Create a Keycloak database#
If you are using an external PostgreSQL instance, create a database for Keycloak. Omit
export OSMO_PGPASSWORD=... and PGPASSWORD=$OSMO_PGPASSWORD if PostgreSQL was configured
without a password.
$ export OSMO_DB_HOST=<your-db-host>
$ export OSMO_PGPASSWORD=<your-postgres-password>
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: osmo-db-ops
spec:
containers:
- name: osmo-db-ops
image: alpine/psql:17.5
command: ["/bin/sh", "-c"]
args:
- "PGPASSWORD=$OSMO_PGPASSWORD psql -U postgres -h $OSMO_DB_HOST -p 5432 -d postgres -c 'CREATE DATABASE keycloak;'"
restartPolicy: Never
EOF
Check that the process Completed with kubectl get pod osmo-db-ops. Then delete the pod with:
$ kubectl delete pod osmo-db-ops
Step 2: Install Keycloak with Helm#
Add the Bitnami Helm repository:
$ helm repo add bitnami https://charts.bitnami.com/bitnami
$ helm repo update
Create a
keycloak-values.yamlfile with the following configuration:
keycloak-values.yaml
global:
security:
allowInsecureImages: true
image:
registry: docker.io
repository: bitnamilegacy/keycloak
tag: 26.1.1-debian-12-r0
# Hostname configuration
hostname: auth-<your-domain>
proxy: edge
# Production mode
production: true
tls:
enabled: true
autoGenerated: true
# Admin user credentials
auth:
adminUser: admin
adminPassword: your-secure-password # Change this!
# Ingress configuration
ingress:
enabled: true
tls: true
ingressClassName: <your-ingress-class> # e.g., nginx, alb
hostname: auth-<your-domain>
annotations:
# Add additional ingress-specific annotations here to match your ingress controller
# Example for AWS ALB:
# alb.ingress.kubernetes.io/target-type: ip
# alb.ingress.kubernetes.io/group.name: osmo
# alb.ingress.kubernetes.io/group.order: "0"
# alb.ingress.kubernetes.io/scheme: internet-facing
# alb.ingress.kubernetes.io/certificate-arn: <your-ssl-cert-arn>
# alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
# alb.ingress.kubernetes.io/ssl-redirect: '443'
path: /
pathType: Prefix
servicePort: 80
# Autoscaling configuration
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 3
targetCPU: 80
targetMemory: 80
# Resource allocation
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2"
memory: "1Gi"
# Database configuration
# Option 1: External Database
postgresql:
enabled: false
externalDatabase:
host: "<your-db-host>"
port: 5432
user: "<your-db-user>"
database: "keycloak"
existingSecret: "keycloak-db-secret"
existingSecretPasswordKey: "postgres-password"
# Option 2: Built-in PostgreSQL (for testing)
# postgresql:
# enabled: true
# Additional environment variables
extraEnvVars:
- name: KC_HOSTNAME_STRICT_HTTPS
value: "true"
- name: KC_PROXY
value: "edge"
Create the namespace for Keycloak:
$ kubectl create namespace keycloak
If you are using an external database, create a secret for the database password:
$ kubectl create secret generic keycloak-db-secret \
--namespace keycloak \
--from-literal=postgres-password='<your-db-password>'
Install Keycloak using Helm:
$ helm install keycloak bitnami/keycloak \
--version 24.4.9 \
--namespace keycloak \
-f keycloak-values.yaml
Verify the installation:
$ kubectl get pods -n keycloak
$ kubectl get ingress -n keycloak
Note
To access the Keycloak instance, configure DNS records to point to your load balancer. For example, create a record for auth-osmo.example.com pointing to the load balancer IP.
If you have DNS configured, access the Keycloak instance at https://auth-osmo.example.com.
If DNS is not configured, use port forwarding:
$ kubectl port-forward service/keycloak 32080:80 -n keycloak
Step 3: Post-installation configuration#
Access your Keycloak instance at
https://auth-osmo.example.comLog in with the admin credentials specified in the values file
Create a new realm for OSMO:
Download the sample realm file:
sample_osmo_realm.jsonClick on the dropdown menu on the top left which says
masterand selectCreate RealmEnter the downloaded realm file in the
Resource filefield and clickCreateYou will be redirected to the
osmorealm
Click on the
Clientstab and for each of theosmo-browser-flowandosmo-deviceclients, update the client settings:Root URL:
https://osmo.example.comHome URL:
https://osmo.example.comAdmin URL:
https://osmo.example.comValid Redirect URIs:
https://osmo.example.com/*Web Origins:
https://osmo.example.com
Note
Replace
osmo.example.comwith your actual OSMO domain name.On the
osmo-browser-flowclient details page, click on theCredentialstab and create and save a client secret. You will need this when configuring OSMO’s OAuth2 Proxy sidecar.
Part 2: Configure OSMO to use Keycloak#
With Keycloak deployed and the osmo realm configured, follow the standard OSMO deployment
steps in Deploy Service, substituting the Keycloak-specific OIDC
endpoints shown below for the generic IdP placeholders.
Keycloak endpoints#
All endpoints are under the osmo realm:
Purpose |
URL |
|---|---|
Token |
|
Authorize |
|
JWKS |
|
Issuer |
|
Device auth |
|
Logout |
|
Create secrets#
Create the OAuth2 Proxy secret using the client secret from Step 3: Post-installation configuration:
$ kubectl create secret generic oauth2-proxy-secrets \
--from-literal=client_secret=<keycloak-client-secret> \
--from-literal=cookie_secret=$(openssl rand -base64 32) \
--namespace osmo
OSMO Helm values for Keycloak#
When preparing the OSMO Helm values (see Step 3: Prepare values), use the Keycloak
endpoints for the auth, oauth2Proxy, and jwt sections. For the full deployment
procedure and all other Helm values, follow Deploy Service.
Below are the Keycloak-specific sections that differ from the generic IdP examples in the
deployment guide. Replace <your-domain> with your actual domain (e.g., osmo.example.com).
Service auth configuration (in osmo_values.yaml):
services:
service:
auth:
enabled: true
device_endpoint: https://auth-<your-domain>/realms/osmo/protocol/openid-connect/device
device_client_id: osmo-device
browser_endpoint: https://auth-<your-domain>/realms/osmo/protocol/openid-connect/auth
browser_client_id: osmo-browser-flow
token_endpoint: https://auth-<your-domain>/realms/osmo/protocol/openid-connect/token
logout_endpoint: https://auth-<your-domain>/realms/osmo/protocol/openid-connect/logout
OAuth2 Proxy sidecar (in osmo_values.yaml):
sidecars:
oauth2Proxy:
enabled: true
provider: oidc
oidcIssuerUrl: https://auth-<your-domain>/realms/osmo
clientId: osmo-browser-flow
cookieDomain: .<your-domain>
scope: "openid email profile"
useKubernetesSecrets: true
secretName: oauth2-proxy-secrets
clientSecretKey: client_secret
cookieSecretKey: cookie_secret
extraArgs:
- --insecure-oidc-allow-unverified-email=true
Note
The --insecure-oidc-allow-unverified-email=true flag is required when using Keycloak
because Keycloak does not set the email_verified claim to true by default. Without
this flag, OAuth2 Proxy will reject logins from users whose email is not marked as verified.
Envoy JWT providers (in osmo_values.yaml):
sidecars:
envoy:
jwt:
user_header: x-osmo-user
providers:
- issuer: https://auth-<your-domain>/realms/osmo
audience: osmo-device
jwks_uri: https://auth-<your-domain>/realms/osmo/protocol/openid-connect/certs
user_claim: preferred_username
cluster: idp
- issuer: https://auth-<your-domain>/realms/osmo
audience: osmo-browser-flow
jwks_uri: https://auth-<your-domain>/realms/osmo/protocol/openid-connect/certs
user_claim: preferred_username
cluster: idp
- issuer: osmo
audience: osmo
jwks_uri: http://localhost:8000/api/auth/keys
user_claim: unique_name
cluster: service
Note
With Keycloak, two IdP JWT providers are configured — one for the osmo-device client (CLI) and one for the osmo-browser-flow client (Web UI) — because each client has its own audience. The third provider is for OSMO-issued JWTs (access tokens).
Apply the same Keycloak endpoints to the router and UI values files. For the complete deployment procedure including all other configuration steps, see Deploy Service.
Part 3: Keycloak Group and Role Management#
OSMO uses Keycloak’s role-based access control to manage permissions for pool access and other resources. The configuration follows a hierarchical structure:
Roles: Represent specific permissions within OSMO (e.g.,
osmo-group1grants permission to submit workflows togroup1-*pools)Groups: Collections of users that share the same access requirements. When a role is assigned to a group, all members inherit the associated permissions
Users: Individual accounts that belong to one or more groups and inherit the roles assigned to those groups
This hierarchical approach simplifies access management by allowing administrators to grant permissions to entire teams at once rather than configuring each user individually.
Configuration Workflow#
The typical workflow for setting up access control is:
Create roles in Keycloak clients (
osmo-browser-flowandosmo-device)Create groups in Keycloak
Assign roles to groups
Add users to groups (manually or via identity provider mappings)
Create matching pools
Verify access
Creating Roles in Keycloak#
Roles must be created in both Keycloak clients that OSMO uses:
Access the Keycloak admin console and select the OSMO realm
Navigate to the “Clients” tab and select the
osmo-browser-flowclientClick on the “Roles” tab, then click “Create Role”
Enter a name for the role following the format
osmo-<pool-group-name>For example:
osmo-group1Click “Save”
Repeat steps 2-5 for the
osmo-deviceclient
Note
The role name is format-sensitive. You must use the exact format osmo-<pool-group-name> for pool access roles.
Creating Groups in Keycloak#
Groups organize users and assign roles to multiple users at once:
In the Keycloak admin console, select the OSMO realm
Navigate to the “Groups” tab and click “Create Group”
Enter a name for the group following the format
OSMO <pool-group-name>For example:
OSMO group1Click “Save”
Assigning Roles to Groups#
After creating the group, assign the appropriate roles:
Click into the group you just created
Select the “Role Mapping” tab
Click “Assign Role”
Click on the filter dropdown and select “Filter by clients”
Search for
osmo-<pool-group-name>(e.g.,osmo-group1)Select both roles (one from
osmo-browser-flowand one fromosmo-deviceclient)Click “Assign”
Note
The osmo-browser-flow client is used for the Web UI and the osmo-device client is used for the CLI.
You must assign roles from both clients for full functionality.
Managing Users in Keycloak#
Adding Users Manually#
To create users directly in the Keycloak admin console:
Go to the “Users” tab
Click “Add User”
Fill in the user details, add the user to the
UserorAdmingroup depending on the role you want to assign, and saveClick on the user’s ID to access their settings. In the “Credentials” tab, enter a password with the temporary password setting enabled
When the temporary password setting is enabled, the user will be forced to change their password upon first login
Note
The Admin group is reserved for administrators with elevated permissions for configuring OSMO and managing users.
The User group is reserved for users with basic permissions for submitting workflows and managing their own workflows.
Adding Users to Groups#
To add existing users to groups:
Navigate to the “Users” tab in the Keycloak admin console
Search for and select the user you want to add
Click on the “Groups” tab
Click “Join Group”
Select the group you want to add the user to
Click “Join”
Configuring Identity Provider Mappings#
Instead of manually adding users to groups, you can configure identity provider mappings to automatically add users to groups based on claims or metadata provided by an upstream identity provider (e.g., LDAP, SAML). For more information, see the Keycloak identity brokering documentation .
See also
Keycloak can be configured to federate login with upstream identity providers. For detailed instructions on configuring SSO with identity providers in Keycloak, refer to the official Keycloak documentation .
Verification and Testing#
Verifying User Access#
To verify that a user has the correct roles:
Have the user log in to OSMO
In the Keycloak admin console, go to “Users” and find the user
Click on the user and select the “Groups” tab
Verify the user is in the expected groups
Select the “Role Mapping” tab and click “View all assigned roles”
Confirm the user has the expected roles (both from
osmo-browser-flowandosmo-device)
Testing Pool Access#
Test that the user can access the pool:
Log in to OSMO as the user
List available pools:
$ osmo pool list
Submit a test workflow to the pool:
$ osmo workflow submit my-workflow.yaml --pool group1-h100-gpu
If successful, the user has proper access
Troubleshooting#
Keycloak Deployment Issues#
Pods not starting: Check pod logs with
kubectl logs -f <keycloak-pod> -n keycloak. Common issues include database connectivity and incorrect secrets.Ingress not accessible: Verify DNS records point to the load balancer and the ingress is configured correctly with
kubectl get ingress -n keycloak.
User Cannot Access Pool#
Symptoms: User receives “Permission denied” or cannot see the pool
Solutions:
Verify Role Policy: Ensure the corresponding role has been created. Follow the steps in Troubleshooting.
Verify Role Names: Pool access roles must start with
osmo-prefix (see Role Naming for Pools). Pool names must match the role suffix. Example: Roleosmo-team1will make pools namedteam1*visible.Check Both Clients: Ensure roles are created in both
osmo-browser-flowandosmo-deviceclients. Both roles must be assigned to the group.Verify Group Membership: In the Keycloak admin console, check if the user appears in the group. If using IdP mappings (see Configuring Identity Provider Mappings):
Verify the mapping configuration
Check IdP logs to ensure claims are being sent
Have the user log out and log back in again. Check Keycloak logs during login and verify that the IdP claim matches the mapper configuration.
Roles Not Appearing in JWT Token#
Symptoms: User can log in but has no permissions
Solutions:
Check Client Scope: Verify that
osmo-browser-flowandosmo-deviceclients have the correct client scopes configured.Review Token: Decode the JWT token to see what roles are included. Use a tool like jwt.io to inspect the token.
Best Practices#
Naming Conventions#
Roles: Use lowercase with hyphens:
osmo-<team>-<purpose>Groups: Use title case:
OSMO <Team> <Purpose>Pools: Match role suffix:
<team>-<resource-type>
- Examples:
Role:
osmo-ml-teamGroup:
OSMO ML TeamPools:
ml-team-training,ml-team-inference
Group Organization#
Use Hierarchy: Create parent groups for departments and child groups for teams
Document Purpose: Add descriptions to groups explaining their purpose
Regular Audits: Periodically review group memberships
Security Considerations#
Principle of Least Privilege: Only grant necessary pool access
Regular Reviews: Audit role assignments quarterly
Offboarding: Remove users from groups when they leave teams
Monitor Access: Review Keycloak audit logs for unusual activity
Test Changes: Always test role/group changes with a test user first
See Also#
Identity Provider (IdP) Setup for direct IdP configuration (without Keycloak)
Roles and Policies for understanding OSMO roles and policies
Authentication Flow for authentication flow details
IdP Role Mapping and Sync Modes for mapping IdP roles to OSMO roles
Deploy Service for the full OSMO deployment guide