Skip to content

dotcomrow/keycloak-image

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

49 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Keycloak with Dynamic IdP Membership Providers (Provable CI)

This repo builds a Keycloak image that bakes in custom Authenticator + Realm Resource SPIs for dynamic role resolution from identity-provider membership.

CI proves providers load and can be attached to a flow via kcadm.sh before pushing the image.

Quick start (locally)

# build the image locally (build-time args are required)
docker build \
  --build-arg KEYCLOAK_VERSION=26.5.1 \
  --build-arg KC_FEATURES=token-exchange-standard,token-exchange-external-internal \
  --build-arg KC_HTTP_RELATIVE_PATH=/ \
  --build-arg KC_TRANSACTION_XA_ENABLED=false \
  -t keycloak/github-team-admin:dev .

# run with a local Postgres
docker network create kc-net || true
docker run -d --rm --name kc-db --network kc-net   -e POSTGRES_USER=keycloak -e POSTGRES_PASSWORD=keycloak -e POSTGRES_DB=keycloak   -p 5432:5432 postgres:15

# wait for db then run keycloak
docker run -d --rm --name kc --network kc-net -p 8080:8080   -e KC_DB=postgres   -e KC_DB_URL=jdbc:postgresql://kc-db:5432/keycloak   -e KC_DB_USERNAME=keycloak   -e KC_DB_PASSWORD=keycloak   -e KC_DB_SCHEMA=public   keycloak/github-team-admin:dev

# health check
curl -fsS http://localhost:8080/health/ready

GitHub Actions

  • Builds the provider jar against the same Keycloak version as the runtime image.
  • Boots Postgres + the built Keycloak image.
  • Uses kcadm.sh to verify the provider appears and can be attached to a flow.
  • Only pushes if proof passes and the event is not a PR.

Tags produced (on main)

  • latest
  • ${KEYCLOAK_VERSION} (e.g. 26.5.1)
  • ${KEYCLOAK_VERSION}-sha-${{ github.sha }}
  • sha-${{ github.sha }} (from metadata-action)
  • ${{ inputs.image_version }} if provided via workflow_dispatch input (e.g. 1.0.3)

Set the repository variable IMAGE_REPO to your destination, e.g.:

  • ghcr.io/your-org/keycloak-github-admin
  • docker.io/youruser/keycloak-github-admin

For Docker Hub (or another registry), add secrets:

  • REGISTRY_USERNAME
  • REGISTRY_PASSWORD

Provider IDs

  • Authenticator: github-team-admin
  • Authenticator: google-groups-authenticator
  • Realm endpoint provider: suncoast-memberships

GitHub Membership Resolver behavior

  • Looks up user teams from GitHub (org/team keys from /user/teams).
  • Derives role names directly from team slug (team segment after org/), e.g.
    • dotcomrow/openwebui_access -> openwebui_access
  • Does not create/grant/revoke Keycloak role mappings.
  • Optional env:
    • GITHUB_MEMBERSHIP_ENABLED (default true)
    • GITHUB_API_VERSION (optional, forwarded as X-GitHub-Api-Version)
    • GITHUB_USER_AGENT (optional, default keycloak-github-membership-resolver/1.0)

Google Membership Resolver behavior

Fetches Cloud Identity / Google Workspace group membership at login using a service account with domain-wide delegation.

Required env

  • GOOGLE_ADMIN_EMAIL (or GOOGLE_DELEGATED_ADMIN) — delegated admin to impersonate
  • GOOGLE_SA_JSON_PATH or GOOGLE_SA_JSON — service account JSON

Behavior

  • Lists groups for the logged-in user via Directory API groups.list?userKey=<email>.
  • Derives role names directly from group key, e.g. openwebui_access@yourdomain.com -> openwebui_access.
  • Does not create/grant/revoke Keycloak role mappings.
  • Optional env:
    • GOOGLE_MEMBERSHIP_ENABLED (default true)

Admin SDK scopes

Ensure the service account is authorized for:

  • https://www.googleapis.com/auth/admin.directory.group.readonly
  • https://www.googleapis.com/auth/admin.directory.group.member.readonly

Membership Endpoint

This image exposes:

  • GET /realms/{realm}/suncoast-memberships/me

It returns:

  • effective role list resolved from current IdP membership
  • per-source diagnostics (github, google) with membership keys and derived roles

Authentication supports either:

  • bearer token, or
  • Keycloak identity cookie session

Membership Token Mapper

Provider ID:

  • suncoast-membership-roles-mapper

Behavior:

  • Emits normalized IdP membership roles into an OIDC claim, usually suncoast_roles.
  • Uses cached user attributes populated by the GitHub/Google authenticators.
  • Refreshes the cached GitHub/Google membership during token issuance when the cache is stale.
  • Default cache TTL is 300 seconds and can be overridden by mapper config cache.ttl.seconds or SUNCOAST_MEMBERSHIP_TOKEN_CACHE_TTL_SECONDS.
  • Does not read or emit Keycloak realm role mappings, so stale direct Keycloak roles do not grant app/page/MFE access through this claim.

About

Keycloak image build with auth services baked in

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors