Skip to content

Keycloak

Keycloak provides the OAuth2 and OIDC functionalities used for this project. The controller module uses Keycloak to authenticate users or clients and to authorize requests. It also uses the Keycloak admin client extension to register clients. Keycloak is deployed inside the cluster/helm/eurodat-cluster Helm Chart, where a basic admin user is configured, requiring only 2 environment variables (which can be written into ones .bashrc). The current default values are:

export KC_ADMIN_USER=<KC_ADMIN_USER>
export KC_ADMIN_PASSWORD=<KC_ADMIN_PASSWORD>

Controller Setup

After the initial deployment is done, a custom realm and a separate client for each (client-) controller (broker, data_provider, data_consumer) is created. The external clients are registered in Keycloak via the controller API. During the client registration, one also needs to provide Keycloak a certificate that is later used to authenticate the respective controllers. All this is currently done dynamically in the CI/CD pipeline (see cluster/helm/.gitlab-ci.yml & cluster/scripts).

Keycloak administration

The registered Keycloak clients are confidential clients with the clientAuthenticatorType set to client-jwt. The client certificate needed by client-jwt is registered with a RS256 algorithm.

The clients can be configured most extensively using Keycloak's admin REST API. There are two possible ways to access the admin REST API, one is by running a bash command inside the Keycloak Kubernetes-pod via exec <pod> -it -- bash -c <command>, which will run the kcadm.sh script inside the /opt/jboss/keycloak/bin folder. The other one is talking to it directly via curl, which requires Keycloak's URL and an initial access token (IAT) inside the header of the request. Currently, we only use the second approach.

Using the Admin REST API

All Keycloak requests are handled by a central script . Run ./kc_do --help to receive more information about it.

  • Get general help
  kubectl -n $NAMESPACE exec $KC_POD_NAME -it -- bash -c "./opt/jboss/keycloak/bin/kcadm.sh help"
  • Get help for any command (eg. "create" = POST)
  kubectl -n $NAMESPACE exec $KC_POD_NAME -it -- bash -c "./opt/jboss/keycloak/bin/kcadm.sh create --help"

Using the Keycloak UI

First deploy the eurodat-cluster Helm Chart.

Register Client

  • Generate an Initial Access Token

    • Forward Keycloak port:
      kubectl port-forward -n <namespace> <pod> <local_port>:8080
    
    • Go to Realm Settings > Client Registration > Initial Access Token > Create
    • Insert values and click on Save
  • Send a POST Request with the Initial Access Token inside the header and clientID in the body

    • CURL:
      curl -X POST -d '{ "clientId": "ID" }' \
      -H "Content-Type:application/json"
      -H "Authorization: bearer $TOKEN
    

Other Problems

  • Do not use password made out of only numbers
    Keycloak seems to think that those are integers, leading the following error:
  Error: StatefulSet in version "v1" cannot be handled as a StatefulSet: v1.StatefulSet.Spec: v1.StatefulSetSpec.Template: v1.PodTemplateSpec.Spec: v1.PodSpec.Containers: []v1.Container: v1.Container.Env: []v1.EnvVar: v1.EnvVar.Value: ReadString: expects " or n, but found 1, error found in #10 byte of ...|,"value":YOUR_NUMBER_PASSWORD}]...
  • Pod name Problems
    Keycloak's Helm Chart comes with the option to edit its pod and service name with the fullnameOverride variable. However, there is a 23-character limit which, if exceeded, will lead to this being ignored.

  • Client-Role mapping
    Currently, we register a user for each realm who, after creation, requires an additional role-mapping to allow him to register clients inside the realm. This is done the Admin Rest API, but can also be done manually via the UI:

  Users > <User> > "Role Mappings" > "Client Roles" > "realm-management" > select "manage-clients" > "Add selected"

NOTE that the correct client role is NOT create-client.

  • Client-ID and Client's ID
    Keycloak's clients have 2 IDs inside their ClientRepresentation , a ClientId which is basically the "username" of the client and the only ID you see in Keycloak's UI; the other one is the client's Id which, if not specified is set to a random UUID. Keycloak refers to the first as client-id. The client's Id is only needed when performing a GET or PUT request to Keycloak's Admin Rest API.
    We set both of those IDs, where the Id is a combination of the clientId-realmName. This is necessary because of a bug which does not allow any client to share the same Id, even those that are not in the same realm.
  • User-ID
    Although Keycloak's API now allows to specify an Id in the request body for the user creation , it actually is ignored when set and a random UUID is used in its place.