External roles and attributes mapping

If you manage topics (or any other resource) permissions in an external system, you have access to 2 more implementation mechanisms to map your authenticated user (from either Local, Header, LDAP or OIDC) into AKHQ roles and attributes. If you use this approach, keep in mind it will take the local user's groups for local Auth, and the external groups for Header/LDAP/OIDC (ie. this will NOT do the mapping between Header/LDAP/OIDC and local groups).

Default configuration-based This is the current implementation and the default one (doesn't break compatibility)

akhq:
  security:
    default-group: admin
    groups:
      reader:
        - role: reader
        # patterns: [ ".*" ]
        # clusters: [ ".*" ]
    ldap: # LDAP users/groups to AKHQ groups mapping
    oidc: # OIDC users/groups to AKHQ groups mapping
    header-auth: # header authentication users/groups to AKHQ groups mapping

REST API

akhq:
  security:
    default-group: no-roles
    rest:
      enabled: true
      url: https://external.service/get-roles-and-attributes
    groups: # anything set here will not be used

In this mode, AKHQ will send to the akhq.security.rest.url endpoint a POST request with the following JSON :

{
  "providerType": "LDAP or OIDC or BASIC_AUTH or HEADER",
  "providerName": "OIDC provider name (OIDC only)",
  "username": "user",
  "groups": ["LDAP-GROUP-1", "LDAP-GROUP-2", "LDAP-GROUP-3"]
}

and expect the following JSON as response :

{
  "groups": {
    "topic-writer-clusterA-projectA": [
      {
        "role": "topic-reader",
        "patterns": [
          "pub.*"
        ]
      }, {
        "role": "topic-writer",
        "patterns": [
          "projectA.*"
        ],
        "clusters": [
          "clusterA.*"
        ]
      }
    ],
    "acl-reader-clusterA": [
      {
        "role": "acl-reader",
        "clusters": [
          "clusterA.*"
        ]
      }
    ]
  }
}

If you want to send a static authentication token to the external service where it might be public, you can extend the configuration for the rest interface as follows:

akhq:
  security:
    rest:
      enabled: true
      url: https://external.service/get-roles-and-attributes
      headers:
        - name: Authorization
          value: Bearer your-token

Warning

The response must contain the Content-Type: application/json header to prevent any issue when reading the response.

Groovy API

akhq:
  security:
    default-group: no-roles
    groovy:
      enabled: true
      file: |
        package org.akhq.models.security;
        class GroovyCustomClaimProvider implements ClaimProvider {
            @Override
            ClaimResponse generateClaim(ClaimRequest request) {
                String filterRegexp =  request.groups.collect {
                  '^' + it + '\\..*'
                }.join('|')
                def groups = [
                  "reader": [
                    new org.akhq.configs.security.Group(role: "reader", patterns: [filterRegexp]),
                  ]
                ]
                return ClaimResponse.builder().groups(groups).build();
            }
        }
    groups: # anything set here will not be used

akhq.security.groovy.file must be a groovy class that implements the interface ClaimProvider :

package org.akhq.models.securitys;
public interface ClaimProvider {
    ClaimResponse generateClaim(ClaimRequest request);
}

enum ClaimProviderType {
  BASIC_AUTH,
  LDAP,
  OIDC
}

public class ClaimRequest {
  ClaimProvider.ProviderType providerType;
  String providerName;
  String username;
  List<String> groups;
}

public class ClaimResponse {
  private Map<String, List<Group>> groups;
}