Skip to content

Latest commit

 

History

History
642 lines (459 loc) · 29.6 KB

File metadata and controls

642 lines (459 loc) · 29.6 KB

Configuration of ODM with Keycloak

Introduction

In the context of the Operational Decision Manager (ODM) on Certified Kubernetes offering, ODM for production can be configured with an external OpenID Connect server (OIDC provider), such as the Keycloak cloud service.

This tutorial shows how to integrate ODM with Keycloak to manage classic authentication and authorization. Another tutorial explains how to manage fine grain permission with Decision Center by using a Keycloak SCIM Server.

What is Keycloak?

Keycloak is an open source enterprise identity service that provides single sign-on, user federation, identity brokering and social login. The Keycloak SSO OpenID Connect capability is the service that we use in this article.

About this task

You need to create a number of secrets before you can install an ODM instance with an external OIDC provider such as the Keycloak service, and use web application single sign-on (SSO). The following diagram shows the ODM services with an external OIDC provider after a successful installation.

ODM web application SSO

The following procedure describes how to manually configure ODM with a Keycloak service.

ODM OpenID flows

OpenID Connect is an authentication standard built on top of OAuth 2.0. It adds a token called an ID token.

Terminology:

  • The OpenID provider — The authorization server that issues the ID token. In this case, Keycloak is the OpenID provider.
  • The end user — The end user whose information is contained in the ID token.
  • The relying party — The client application that requests the ID token from Keycloak.
  • The ID token — The token that is issued by the OpenID provider and contains information about the end user in the form of claims.
  • A claim — A piece of information about the end user.

The Authorization Code flow is best used by server-side apps where the source code is not publicly exposed. The apps must be server-side because the request that exchanges the authorization code for a token requires a client secret, which has to be stored in your client. However, the server-side app requires an end user because it relies on interactions with the end user's web browser, which redirects the user and then receives the authorization code.

Authentication flow (© Okta)

The Client Credentials flow is intended for server-side (AKA "confidential") client applications with no end user, which normally describes machine-to-machine communication. The application must be server-side because it must be trusted with the client secret, and since the credentials are hard-coded, it cannot be used by an actual end user. It involves a single, authenticated request to the token endpoint, which returns an access token.

Client Credential Flow (© Okta)

The resource owner password flow allows an application to sign in a user by directly handling their password. It is not recommended to use this flow. In most scenarios, more secure alternatives are available and recommended. This flow requires a very high degree of trust in the application, and carries risks which are not present in other flows. You should only use this flow when other more secure flows cannot be used.

Password Flow (© Okta)

Prerequisites

You need the following elements:

  • Helm v3
  • Kubectl
  • Access to an Operational Decision Manager product
  • Access to a CNCF Kubernetes cluster
  • A Keycloak Instance

Install a Keycloak instance

This tutorial has been tested with a Keycloak instance version 26.0.5 installed on Openshift. The installation procedure can be found at Get started with Keycloak on Openshift. If you already have an Openshift cluster, you can skip the section Before you start and use the following steps:

  • oc login to your cluster

  • Create a namespace "keycloak":

    oc new-project keycloak
  • To install Keycloak on Openshift, continue from the section Start Keycloak.

  • If you want to install Keycloak on another Kubernetes platform than Openshift, follow these instructions: Get started with Keycloak on Kubernetes.

Configure a Keycloak instance for ODM (Part 1)

In this section, you will:

  • Log into the Keycloak Admin Console
  • Create a dedicated odm realm
  • Manage roles, groups, and users
  • Set up an application
  • Configure the default Authorization server

Log into the Keycloak Admin Console

If you have deployed Keycloak on OpenShift, you may use the script below to get the URL of the Keycloak Admin Console:

KEYCLOAK_URL=https://$(oc get route keycloak --template='{{ .spec.host }}') &&
echo "" &&
echo "Keycloak Admin Console:   $KEYCLOAK_URL/admin" &&
echo ""

You can log in using the credentials:

  • username = admin
  • password = admin

The configurations that follow take place in this Keycloak Admin Console.

Create a dedicated odm realm

This step is not compulsory as you can perform the following tasks in the default master realm. But to avoid getting mixing up with existing configurations, it is preferable to create a dedicated odm realm.

  1. Create a new realm named odm

    On the Main page, click Master:

    • Click Create Realm
      • Realm Name: odm
      • Enabled: On
      • Click Create

    Create Realm

Manage roles, groups, and users

As explained in Keycloak documentation, groups and roles enables to give users access and permissions to use applications. Groups are collections of users to which you apply roles and attributes. Roles define specific application permissions and access control. To manage permissions inside the ODM application, the ID token and access token contain a property (aka claim) named 'groups' listing all the roles granted to the identified user. You can create roles and grant these roles directly to an individual user, or even better to a group. This way, all the users of the group are granted the roles of the group.

1. Create a role for ODM administrators.

In the Menu Manage / Realm roles:

  • Click Create role

    • Role name: rtsAdministrators
    • Click Save

    Create Roles

    Do the same for the other ODM J2EE roles:

    • rtsConfigManagers
    • rtsInstallers
    • rtsUsers
    • resAdministrators
    • resMonitors
    • resDeployers
    • resExecutors

    For more information about ODM groups and roles, refer to the ODM on Kubernetes documentation.

2. Create a group for ODM administrators.

In the Menu Manage / Groups:

  • Click Create group

  • Name: odm-admin

    Create Group

    In the Menu Manage / Groups:

    • Click odm-admin to edit the new group
    • Click the Role mapping tab
      • Click Assign role
        • Select Filter by realm roles
        • Tick all previously created ODM roles
        • Click Assign

    Assign Roles

3. Create at least one user that belongs to this new group.

In the Menu Manage / Users:

  • Click Create new user (or Add user)

    • Required user actions: leave the field blank
    • Email verified: On
    • Username: johndoe@mynicecompany.com
    • Email: johndoe@mynicecompany.com
    • First name: John
    • Last name: Doe
    • Groups : Click Join Groups , tick odm-admin, and click Join
    • Click Create

    Create User

  • In User Details, select the Credentials tab

  • Click Set password

    • Fill the Password and Password confirmation fields with johndoe
    • Temporary: Off
    • Click Save
    • Click Save password to confirm
  • Click the Details tab

  • Click Save

(Optional) Every user is created with a predefined role named default-roles-. This role is not useful for this tutorial. Here is the way to unassign this role.

  • In User Details, select the Role mapping tab

    • Tick default-roles-odm
    • Click Unassign
    • Click Remove to confirm

    Unassign default role

  • Click the Details tab

  • Make sure the toggle Enabled is On

  • Click Save

Repeat those steps for each user you want to add.

Set up the client

1. Create the ODM client.

In the Menu Manage / Clients, click Create client:

  • Client type: OpenID Connect

  • Client ID: odm

  • Name: ODM Application

  • Always display in UI: On

  • Click Next

    Create Client 1

    • Client Authentication: On
    • Authorization: On
    • Click Next (or Save)

    Create Client 2

    • Newer versions of Keycloak display the additional Login settings page below. If you can see it, just click Save.

    Create Client 3

    • Click the Credentials tab
    • Take a note of the Client secret value. It will be referenced as CLIENT_SECRET in the next steps.

    Get Client Secret

    • Click the Service accounts roles tab
    • Click the Assign role button.
    • Select Filter by realm roles
    • Tick all res* and rts* roles in the list and click the Assign button.

    Set Service Account Roles

2. Add the groups predefined mapper to the Roles client scope

  • Select the Manage / Client scopes menu

    • Search for the scope : roles
    • click the roles scope
  • Select the Mappers tab

  • Click Add mapper > From predefined mappers

    • Search for mapper : groups
    • Tick groups
    • Click Add

    Add group mapper

3. Retrieve the Keycloak Server URL

In the Menu Configure / Realm settings,

  • Select the General tab,
    • Click the OpenID Endpoint Configuration link (at the bottom of the page).
    • Take note of the issuer URL. It will be referenced as KEYCLOAK_SERVER_URL in the next steps.

4. Check the configuration

Download the keycloak-odm-script.zip file to your machine and unzip it in your working directory. This .zip file contains scripts and templates to verify and set up ODM.

4.1 Verify the Client Credentials Token

You can request an access token using the Client-Credentials flow to verify the format of the token. This token is used for the deployment of rulesets from the Business Console:

./get-client-credential-token.sh -i $CLIENT_ID -x $CLIENT_SECRET -n $KEYCLOAK_SERVER_URL

Where:

  • CLIENT_ID is your ODM Application (odm if you followed the instructions). You can find it in the Manage / Clients menu.
  • CLIENT_SECRET is the secret for your ODM Application. You can find it in the Credentials tab.
  • KEYCLOAK_SERVER_URL is the issuer that can be retrieved using the OpenID Endpoint Configuration link of the General tab in the Configure/Realm settings menu

If you decode the access_token (or id_token) value with a JWT decoder tool, you should get:

{
  ..
  "iss": "<KEYCLOAK_SERVER_URL>",
....
  "preferred_username": "service-account-<CLIENT_ID>",
  ...
}

4.2 Verify the Client Password Token

You can request an access token using the Password flow to verify the format of the token. This token is used for the invocation of the ODM components like the Decision Center, Decision Server console, and the invocation of the Decision Server Runtime REST API.

./get-user-password-token.sh -i $CLIENT_ID -x $CLIENT_SECRET -n $KEYCLOAK_SERVER_URL -u johndoe@mynicecompany.com -p johndoe

Where:

  • CLIENT_ID is your ODM Application (odm if you followed the instructions). You can find it in the Manage / Clients menu.
  • CLIENT_SECRET is the secret for your ODM Application. You can find it in the Credentials tab.
  • KEYCLOAK_SERVER_URL is the issuer that can be retrieved using the OpenID Endpoint Configuration link of the General tab in the Configure/Realm settings menu
  • The credentials used are from the section 3. Create at least one user that belongs to this new group.

By introspecting the id_token value with a JWT decoder tool, you should get:

{
  ..
  "iss": "<KEYCLOAK_SERVER_URL>",
  ....
  "preferred_username": "<USERNAME>",
  "groups": [
    "rtsAdministrators",
    "rtsInstallers",
    "rtsConfigManagers",
    "rtsUsers",
    "resAdministrators",
    "resDeployers",
    "resMonitors",
    "resExecutors"
  ],
  ...
}

Deploy ODM on a container configured with Keycloak (Part 2)

Prepare your environment for the ODM installation

Create a secret to use the Entitled Registry

  1. To get your entitlement key, log in to MyIBM Container Software Library with the IBMid and password that are associated with the entitled software.

    In the Container software library tile, verify your entitlement on the View library page, and then go to Get entitlement key to retrieve the key.

  2. Create a pull secret by running a kubectl create secret command.

    kubectl create secret docker-registry ibm-entitlement-key \
        --docker-server=cp.icr.io \
        --docker-username=cp \
        --docker-password="<API_KEY_GENERATED>" \
        --docker-email=<USER_EMAIL>

    Where:

    • API_KEY_GENERATED is the entitlement key from the previous step. Make sure you enclose the key in double-quotes.
    • USER_EMAIL is the email address associated with your IBMid.

    Note:

    1. The cp.icr.io value for the docker-server parameter is the only registry domain name that contains the images. You MUST set the docker-username to cp to use an entitlement key as docker-password.
    2. The ibm-entitlement-key secret name will be used for the image.pullSecrets parameter when you run a Helm install of your containers. The image.repository parameter is also set by default to cp.icr.io/cp/cp4a/odm.

Create secrets to configure ODM with Keycloak

  1. Create a secret for the Keycloak Server certificate.

    To allow ODM services to access the Keycloak Server, it is mandatory to provide the Keycloak Server certificate. You can create the secret as follows:

    export KEYCLOAK_SERVER_URL_WITHOUT_HTTPS=${KEYCLOAK_SERVER_URL#https://}
    keytool -printcert -sslserver ${KEYCLOAK_SERVER_URL_WITHOUT_HTTPS} -rfc > keycloak.crt
    kubectl create secret generic keycloak-secret --from-file=tls.crt=keycloak.crt

    Where:

    • KEYCLOAK_SERVER_URL_WITHOUT_HTTPS is KEYCLOAK_SERVER_URL without the leading https://
  2. Generate the ODM configuration file for Keycloak.

    If you have not done it yet, download the keycloak-odm-script.zip file to your machine. This .zip file contains the script and the content of the templates directory. The script allows you to generate the necessary configuration files.

    Generate the files with the following command:

    ./generateTemplate.sh -i $CLIENT_ID -x $CLIENT_SECRET -n $KEYCLOAK_SERVER_URL [-r $REALM_NAME -u $USERID_CLAIM]

    Where:

    • CLIENT_SECRET can be found in your ODM Application, section General / Client Credentials
    • REALM_NAME is optional (odm** by default)
    • USERID_CLAIM is optional (preferred_username by default). This is the name of the claim (ie. parameter) in the token that holds the name of the user.

    The following files are generated into the output directory:

    • webSecurity.xml contains the mapping between Liberty J2EE ODM roles and Keycloak groups and users:
      • the rtsAdministrators/resAdministrators/resExecutors ODM roles are granted to
        • the service account service-account-odm for the client-credentials flow
        • the basic registry group basicAdministrators (that contains only the user odmAdmin)
      • each J2EE ODM role is mapped to its related role in Keycloak
    • openIdWebSecurity.xml contains two openIdConnectClient Liberty configurations:
      • the first for web access to Decision Center and Decision Server consoles with the Authorization Code flow
      • the second for the rest-api calls with the client-credentials flow
    • openIdParameters.properties configures several features like allowed domains, logout, and some internal ODM openid features
    • ldap-configurations.xml contains LDAP configuration for How to import Keycloak Groups and Users using SCIM
  3. Create the Keycloak authentication secret using webSecurity.xml, openIdWebSecurity.xml and openIdParameters.properties files.

    kubectl create secret generic keycloak-auth-secret \
        --from-file=openIdParameters.properties=./output/openIdParameters.properties \
        --from-file=openIdWebSecurity.xml=./output/openIdWebSecurity.xml \
        --from-file=webSecurity.xml=./output/webSecurity.xml

Install your ODM Helm release

1. Add the public IBM Helm charts repository

helm repo add ibm-helm https://raw.githubusercontent.com/IBM/charts/master/repo/ibm-helm
helm repo update

2. Check that you can access the ODM chart

helm search repo ibm-odm-prod

The output should look like:

NAME                      CHART VERSION  APP VERSION  DESCRIPTION
ibm-helm/ibm-odm-prod     26.0.0         9.6.0.0      IBM Operational Decision Manager

3. Run the helm install command

You can now install the product. We will use the PostgreSQL internal database and disable data persistence (internalDatabase.persistence.enabled=false) to avoid any platform complexity with persistent volume allocation.

Note:
The following command installs the latest available version of the chart.
If you want to install a specific version, add the --version option:

helm install my-odm-release ibm-helm/ibm-odm-prod --version <version> -f keycloak-nginx-values.yaml

You can list all available versions using:

helm search repo ibm-helm/ibm-odm-prod -l

a. Installation on OpenShift using Routes

See the Preparing to install documentation for more information. Inspect keycloak-values.yaml for the parameters that have been defined for this installation.

helm install my-odm-release ibm-helm/ibm-odm-prod -f keycloak-values.yaml

b. Installation using Ingress

Refer to the following documentation to install an NGINX Ingress Controller on:

When the NGINX Ingress Controller is ready, you can install the ODM release using keycloak-nginx-values.yaml. Take note of the service.ingress.annotations values that have been defined in this file.

helm install my-odm-release ibm-helm/ibm-odm-prod -f keycloak-nginx-values.yaml

Complete post-deployment tasks

Register the ODM redirect URL

  1. Get the ODM endpoints. Refer to this documentation to retrieve the endpoints. For example, on OpenShift you can get the route names and hosts with:

    kubectl get routes --no-headers --output custom-columns=":metadata.name,:spec.host"

    You get the following hosts:

    my-odm-release-odm-dc-route           <DC_HOST>
    my-odm-release-odm-dr-route           <DR_HOST>
    my-odm-release-odm-ds-console-route   <DS_CONSOLE_HOST>
    my-odm-release-odm-ds-runtime-route   <DS_RUNTIME_HOST>
    

    Using an Ingress, the endpoint is the address of the ODM ingress and is the same for all components. You can get it with:

    kubectl get ingress my-odm-release-odm-ingress

    You get the following ingress address:

    NAME                       CLASS    HOSTS   ADDRESS          PORTS   AGE
    my-odm-release-odm-ingress <none>   *       <INGRESS_ADDRESS>   80    1d
    
  2. Register the redirect URIs into your Keycloak application.

    The redirect URIs are built in the following way:

    Using Routes:

    • Decision Center redirect URI: https://<DC_HOST>/decisioncenter/openid/redirect/odm
    • Decision Runner redirect URI: https://<DR_HOST>/DecisionRunner/openid/redirect/odm
    • Decision Server Console redirect URI: https://<DS_CONSOLE_HOST>/res/openid/redirect/odm
    • Decision Server Runtime redirect URI: https://<DS_RUNTIME_HOST>/DecisionService/openid/redirect/odm
    • Rule Designer redirect URI: https://127.0.0.1:9081/oidcCallback

    Using Ingress:

    • Decision Center redirect URI: https://<INGRESS_ADDRESS>/decisioncenter/openid/redirect/odm
    • Decision Runner redirect URI: https://<INGRESS_ADDRESS>/DecisionRunner/openid/redirect/odm
    • Decision Server Console redirect URI: https://<INGRESS_ADDRESS>/res/openid/redirect/odm
    • Decision Server Runtime redirect URI: https://<INGRESS_ADDRESS>/DecisionService/openid/redirect/odm
    • Rule Designer redirect URI: https://127.0.0.1:9081/oidcCallback

    From the Keycloak admin console, in Manage / Clients

    • Click the odm client

    • In the tab Settings

      • Add the redirect URIs in the Valid redirect URIs field for each component.

      For example, add the Decision Center redirect URI that you got earlier (https://<DC_HOST>/decisioncenter/openid/redirect/odm -- do not forget to replace <DC_HOST> with your actual host name!)

    • Click Save at the bottom of the page.

    Add URI

Access the ODM services

Well done! You can now connect to ODM using the endpoints you got earlier and log in as an ODM admin with the account you created in the first step (e.g. johndoe@mynicecompany.com / johndoe).

Set up Rule Designer

First set up Rule Designer following these instructions.

To be able to securely connect your Rule Designer to the Decision Server and Decision Center services that are running in Certified Kubernetes, you need to establish a TLS connection through a security certificate in addition to the OpenID configuration.

  1. Get the following configuration files.

    • https://<DC_HOST>/decisioncenter/assets/truststore.jks
    • https://<DC_HOST>/decisioncenter/assets/OdmOidcProvidersRD.json where DC_HOST is the Decision Center endpoint.
  2. Copy the truststore.jks and OdmOidcProvidersRD.json files to your Rule Designer installation directory next to the eclipse.ini file.

  3. Edit your eclipse.ini file and add the following lines at the end.

    -Djavax.net.ssl.trustStore=<ECLIPSEINITDIR>/truststore.jks
    -Djavax.net.ssl.trustStorePassword=changeme
    -Dcom.ibm.rules.authentication.oidcconfig=<ECLIPSEINITDIR>/OdmOidcProvidersRD.json
    

    Where:

    • changeme is the fixed password to be used for the default truststore.jks file.
    • ECLIPSEINITDIR is the Rule Designer installation directory where the eclipse.ini file is.
  4. Restart Rule Designer.

For more information, refer to this documentation.

Getting Started with IBM Operational Decision Manager for Containers

Get hands-on experience with IBM Operational Decision Manager in a container environment by following this Getting started tutorial.

Calling the ODM Runtime Service

Log in the Business Console as John Doe (johndoe@mynicecompany.com / johndoe).

Import the Decision Service named Loan Validation Service if it is not already there.

Import project

Deploy the Loan Validation Service production_deployment ruleapp using the production deployment deployment configuration in the Deployments>Configurations tab.

Deploy project

You can retrieve the payload.json from the ODM Decision Server Console or use the provided payload.

As explained in the ODM on Certified Kubernetes documentation Configuring user access with OpenID, we advise you to use basic authentication for the ODM runtime call for better performance and to avoid token expiration and revocation.

You perform a basic authentication ODM runtime call in the following way:

curl -H "Content-Type: application/json" -k --data @payload.json \
      -H "Authorization: Basic b2RtQWRtaW46b2RtQWRtaW4=" \
     https://<DS_RUNTIME_HOST>/DecisionService/rest/production_deployment/1.0/loan_validation_production/1.0

Where b2RtQWRtaW46b2RtQWRtaW4= is the base64 encoding of the current username:password odmAdmin:odmAdmin

If you want to perform a bearer authentication ODM runtime call using the Client Credentials flow, you must get a bearer access token:

curl -k -X POST -H "Content-Type: application/x-www-form-urlencoded" \
     -d "client_id=${CLIENT_ID}&scope=openid&client_secret=${CLIENT_SECRET}&grant_type=client_credentials" \
     "${KEYCLOAK_SERVER_URL}/protocol/openid-connect/token"

And use the retrieved access token in the following way:

curl -H "Content-Type: application/json" -k --data @payload.json \
     -H "Authorization: Bearer <ACCESS_TOKEN>" \
     https://<DS_RUNTIME_HOST>/DecisionService/rest/production_deployment/1.0/loan_validation_production/1.0

Troubleshooting

If you encounter any issue, have a look at the OpenID Connect troubleshooting Tips

License

Apache 2.0