Managing user roles

After configuring access to your Event Processing instance, you must specify roles for your users to determine their permissions.

Event Processing supports the user role with complete access to the Event Processing UI.

Note: You must assign this role to each user.

You can set up authorization in one of the following ways:

  1. Assign each user their roles individually.
  2. If using an OIDC provider for authentication, define mappings to custom roles in your OIDC provider.

Assigning roles to users

Users are assigned roles in Event Processing through user mapping, where an identifier for the user or a group of users is mapped to a role or set of roles. The mappings are defined in a configuration file that is exposed through the Kubernetes secret <custom-resource-name>-ibm-ep-user-roles. By default, this file requires separate mapping information for each user.

The following example shows a user mappings file:

{
  "mappings": [
    {
      "id": "user1",
      "roles": [
        "user"
      ]
    }
  ]
}

Using OpenShift Container Platform web console

  1. Log in to the OpenShift Container Platform web console using your login credentials.
  2. Expand Workloads in the navigation on the left and click Secrets. This lists the secrets available in this project (namespace).
  3. To edit the secret <custom-resource-name>-ibm-ep-user-roles with your role mappings, go to Actions, and click Edit Secret.
  4. Edit the mappings, as described in the setting up roles per user or setting up roles by using a custom identifier sections depending on your use case.
  5. Click Save.

Using the CLI

  1. Log in to your Kubernetes cluster as a cluster administrator by setting your kubectl context.
  2. Create a JSON file called myroles.json that contains the user role mappings for your Event Processing instance as described in the setting up roles per user or setting up roles by using a custom identifier sections depending on your use case.

  3. Obtain the Base64-encoded string representing the file content. For example, you can run the following command to obtain the string:

    cat myroles.json | base64
    
  4. Patch the <custom-resource-name>-ibm-ep-user-roles secret with the local user credentials by running the following command:

    kubectl patch secret <custom-resource-name>-ibm-ep-user-roles --type='json' -p='[{"op" : "replace" ,"path" : "/data/user-mapping.json" ,"value" : "<your-base64-value>"}]'
    

    Where:

    • <custom-resource-name> is the name of your Event Processing instance.
    • <your-base64-value> is the Base64-encoded string returned from the previous command.

    For example:

    kubectl patch secret quick-start-ep-ibm-ep-user-roles --type='json' -p='[{"op" : "replace" ,"path" : "/data/user-mapping.json" ,"value" : "ewogICJtYXBwaW5ncyI6IFsKICAgIHsKICAgICAgImlkIjogImF1dGhvcjEiLAogICAgICAicm9sZXMiOiBbCiAgICAgICAgImF1dGhvciIKICAgICAgXQogICAgfSwKICAgIHsKICAgICAgImlkIjogInZpZXdlcjEiLAogICAgICAicm9sZXMiOiBbCiAgICAgICAgInZpZXdlciIKICAgICAgXQogICAgfQogIF0KfQo="}]'
    

    Note: Alternatively, edit the secret directly and replace the Base64 value associated with data.user-mapping.json. To edit the secret directly, run the following command:

    kubectl edit secret/<custom-resource-name>-ibm-ep-user-roles -o json
    
  5. Important: For security reasons, delete the local file you created.

Note: The changed configuration file is automatically picked up by the Event Processing instance after a few minutes.

Setting up roles per user

This is the default set up, where the id in the mappings file is the unique identifier of the user:

  • When using local authentication, it is the username for the user as set in the <custom-resource-name>-ibm-ep-user-credentials secret (for more information, see managing access).

  • When using OIDC-based authentication, it is the user’s subject. You can retrieve this either directly from your OIDC provider, or by logging in to the Event Processing UI and setting the path to /auth/protected/userinfo in the URL.

The following example shows a user mappings file:

{
  "mappings": [
    {
      "id": "<user_subject_1>",
      "roles": [
        "user"
      ]
    }
  ]
}

Setting up roles by using a custom identifier

Using a custom identifier is a more advanced configuration only available with OIDC-based authentication. It means you can map users to their roles through a custom property (claim) associated with the user in the configured OIDC provider.

To use a custom identifier, you must configure your Event Processing instance to set where it can find the property to use for the mapping. During log in, Event Processing checks for the configured property in the user information received from the OIDC provider in the following order:

  1. ID token
  2. Access Token
  3. User Info

Note: If the property is not found, Event Processing will attempt to map the user directly by using their subject (as mentioned in setting up roles per user).

To configure the custom property (claim) to use, set the authorizationClaimPointer and the additionalScopes fields in the spec.authoring.authConfig.oidcConfig section of your EventProcessing custom resource:

apiVersion: events.ibm.com/v1beta1
kind: EventProcessing
# ...
spec:
  # ...
  authoring:
    authConfig:
      authType: OIDC
      oidcConfig:
     # ...
        authorizationClaimPointer: <required "/" separated JSON path to the location of the required property>
        additionalScopes: <optional additional scopes to be requested during OIDC-based authentication to retrieve additional properties>
#...

Note: The property being mapped must either be a string or a list of strings.

Example configuration

The following example describes how to set up roles for a custom identifier called developer.

An OIDC provider always provides an ID token, but you might receive additional data from the provider, and you can use this data for mapping user roles to the roles in Event Processing.

The OIDC provider might store additional user information that can be returned to the client (in this case, Event Processing) if the client asks for it by requesting the appropriate scope.

For example, the provider supports a data scope which returns the following additional user information when requested:

{
  "data": {
    "group": "test",
    "roles": ["developer", "tester"]
  }
}

With a single mapping in the user mappings file, you can assign user access to Event Processing for all users that have the developer role (the custom identifier as listed in the roles field of the updated ID token).

Complete the following steps to assign access:

  1. Configure Event Processing to request this additional user information by adding the mentioned data scope to the additionalScopes field in your EventProcessing custom resource:

    additionalScopes: ["data"]
    

    This setting means that the next time the user logs in, their ID token will also include the additional information from data:

    {
      "sub": "user-xyz-123",
      "name": "xyz-123",
      "data": {
        "group": "test",
        "roles": ["developer", "tester"]
    },
    ...
    "exp": 123456
    }
    
  2. Add the path to the required property (in this example, /data/roles) to the authorizationClaimPointer field in the EventProcessing custom resource as follows:

    authorizationClaimPointer: /data/roles
    
  3. Update the role mappings file as follows to map the developer role as an id to have the Event Processing user role:

    {
      "mappings": [
        {
          "id": "developer",
          "roles": [
            "user"
          ]
        }
      ]
    }
    

    This instructs Event Processing to look inside the ID token for the value at /data/roles, and it will then be able to map the developer role in the OIDC provider to the user role in Event Processing by using the mappings file.

    This means that any user who is known to the OIDC provider and has the developer role will be able to use Event Processing.

Note: Event Processing checks multiple sources for the configured property. If it does not find the /data/roles field in the ID token, it will check for it next in the Access Token, then finally it will check in the response to the User Info API, which is available in all OIDC providers. Event Processing uses the value from the first match. If no match is found, it defaults to checking for the user’s subject directly in the mappings file.