tchiotludo / akhq

Kafka GUI for Apache Kafka to manage topics, topics data, consumers group, schema registry, connect and more...
https://akhq.io/
Apache License 2.0
3.41k stars 660 forks source link

Couldn't view topic and connect after upgrading to 0.25 #1805

Open VisionaryAries opened 5 months ago

VisionaryAries commented 5 months ago

Couldn't view topic and connect after upgrading to 0.25, the topic and connect page are display loading, the log shows below error.

2024-06-04 15:48:04,649 ERROR io-executor-thread-8 o.akhq.controllers.ErrorController Cannot invoke "java.util.List.stream()" because the return value of "java.util.Map.get(Object)" is null
java.lang.NullPointerException: Cannot invoke "java.util.List.stream()" because the return value of "java.util.Map.get(Object)" is null
        at org.akhq.controllers.AbstractController.lambda$buildUserBasedResourceFilters$5(AbstractController.java:100)
        at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
        at org.akhq.controllers.AbstractController.buildUserBasedResourceFilters(AbstractController.java:110)
        at org.akhq.controllers.TopicController.list(TopicController.java:111)
        at org.akhq.controllers.$TopicController$Definition$Exec.dispatch(Unknown Source)
        at io.micronaut.context.AbstractExecutableMethodsDefinition$DispatchedExecutableMethod.invokeUnsafe(AbstractExecutableMethodsDefinition.java:461)
        at io.micronaut.context.DefaultBeanContext$BeanContextUnsafeExecutionHandle.invokeUnsafe(DefaultBeanContext.java:4276)
        at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:271)
        at io.micronaut.http.server.RouteExecutor.executeRouteAndConvertBody(RouteExecutor.java:488)
        at io.micronaut.http.server.RouteExecutor.lambda$callRoute$6(RouteExecutor.java:465)
        at io.micronaut.core.execution.ExecutionFlow.lambda$async$1(ExecutionFlow.java:87)
        at io.micronaut.core.propagation.PropagatedContext.lambda$wrap$3(PropagatedContext.java:211)
image
AlexisSouquiere commented 5 months ago

Please check the documentation after the new RBAC release to take into account the breaking changes https://akhq.io/docs/configuration/authentifications/groups.html

dheeg commented 5 months ago

@AlexisSouquiere Hi we updated as well and see the error above.

Authentication is done via oauth2. Our setup:

akhq.security.groups: []
akhq.security.roles:
    node-read:
      - resources: [ "NODE" ]
        actions: [ "READ", "READ_CONFIG" ]
    node-admin:
      - resources: [ "NODE" ]
        actions: [ "READ", "READ_CONFIG", "ALTER_CONFIG" ]
    topic-read:
      - resources: [ "TOPIC", "TOPIC_DATA" ]
        actions: [ "READ" ]
      - resources: [ "TOPIC" ]
        actions: [ "READ_CONFIG" ]
    topic-admin:
      - resources: [ "TOPIC", "TOPIC_DATA" ]
        actions: [ "READ", "CREATE", "DELETE" ]
      - resources: [ "TOPIC" ]
        actions: [ "UPDATE", "READ_CONFIG", "ALTER_CONFIG" ]
    connect-read:
      - resources: [ "CONNECTOR" ]
        actions: [ "READ" ]
    connect-rw:
      - resources: [ "CONNECTOR" ]
        actions: [ "READ", "CREATE", "UPDATE_STATE" ]
    connect-admin:
      - resources: [ "CONNECTOR" ]
        actions: [ "READ", "CREATE", "UPDATE_STATE", "DELETE" ]
    registry-read:
      - resources: [ "SCHEMA" ]
        actions: [ "READ" ]
    registry-admin:
      - resources: [ "SCHEMA" ]
        actions: [ "READ", "CREATE", "UPDATE", "DELETE", "DELETE_VERSION" ]
    group-read:
      - resources: [ "CONSUMER_GROUP" ]
        actions: [ "READ" ]
    connect-cluster-read:
      - resources: [ "CONNECT_CLUSTER" ]
        actions: [ "READ" ]
    ksqldb-admin:
      - resources: [ "KSQLDB" ]
        actions: [ "READ", "EXECUTE" ]

We use the external EXTERNAL_REST_URL as per https://akhq.io/docs/configuration/authentifications/external.html. The following document is returned for the example user which results in the error above:

{"groups": {"generated": [{"role": "node-admin", "patterns": [".*"], "clusters": [".*"]}, {"role": "topic-admin", "patterns": [".*"], "clusters": [".*"]}, {"role": "connect-admin", "patterns": [".*"], "clusters": [".*"]}, {"role": "registry-admin", "patterns": [".*"], "clusters": [".*"]}, {"role": "group-read", "patterns": [".*"], "clusters": [".*"]}, {"role": "connect-cluster-read", "patterns": [".*"], "clusters": [".*"]}, {"role": "ksqldb-admin", "patterns": [".*"], "clusters": [".*"]}]}}

From my understanding of the documentation I would expect that the group with the name "generated" refers to the roles in the configuration and access to topics should be possible for the user. The /api/me endpoint after login does not reflect that, it shows a configuration I'm not sure were it comes from, but even this configuration should allow topic access?

{
"logged": true,
"username": "xyz",
"roles": [
{
"resources": [
"NODE"
],
"actions": [
"READ",
"READ_CONFIG",
"ALTER_CONFIG"
],
"patterns": [
".*"
],
"clusters": [
".*"
]
},
{
"resources": [
"TOPIC",
"TOPIC_DATA"
],
"actions": [
"READ",
"CREATE",
"UPDATE",
"DELETE",
"READ_CONFIG",
"ALTER_CONFIG"
],
"patterns": [
".*"
],
"clusters": [
".*"
]
},
{
"resources": [
"KSQLDB"
],
"actions": [
"READ",
"EXECUTE"
],
"patterns": [
".*"
],
"clusters": [
".*"
]
}
]
}
VisionaryAries commented 5 months ago

Please check the documentation after the new RBAC release to take into account the breaking changes https://akhq.io/docs/configuration/authentifications/groups.html

@AlexisSouquiere Thanks a lot, the issue is solved after applying the latest configuration about RBAC.

AlexisSouquiere commented 5 months ago

@dheeg /api/me returns all your permissions flattened (resources, actions, patterns and clusters) without any references to the roles name. In any case, the response should match (in terms of resources, actions, patterns and clusters) the response of your external claim provider.

For me there is an inconsistency between the external claim provider response and the /api/me response. group-read and connect-cluster-read permissions are missing from the /api/me response.

Please increase log level by adding

logger:
  levels:
    io.micronaut.security: TRACE

And put the log to see the authentication flow execution. In my company we are using the external claim provider too (with LDAP auth) so I think something is missing in the configuration

VictorEmmanuelPadelBell commented 4 months ago

@AlexisSouquiere looks like we are having a similar issue on our side (we get the same error message). We refactored our entire ACLs but something is not working at all. We tried to enable the logs as you suggested but couldn't find anything helpful in them.

We are using ldap for authentication.

Here are our ACLs roles (taken from the AKHQ doc):

akhq: 
  security:
    roles:
      acl:
        - resources: ["ACL"]
          actions: [ "READ" ]
      node-read:
        - resources: [ "NODE" ]
          actions: [ "READ", "READ_CONFIG" ]
      node-admin:
        - resources: [ "NODE" ]
          actions: [ "READ", "READ_CONFIG", "ALTER_CONFIG" ]
      topic-read:
        - resources: [ "TOPIC", "TOPIC_DATA" ]
          actions: [ "READ" ]
        - resources: [ "TOPIC" ]
          actions: [ "READ_CONFIG" ]
      topic-admin:
        - resources: [ "TOPIC", "TOPIC_DATA" ]
          actions: [ "READ", "CREATE", "DELETE" ]
        - resources: [ "TOPIC" ]
          actions: [ "UPDATE", "READ_CONFIG", "ALTER_CONFIG" ]
      connect-rw:
        - resources: [ "CONNECTOR" ]
          actions: [ "READ", "CREATE", "UPDATE_STATE" ]
      connect-admin:
        - resources: [ "CONNECTOR" ]
          actions: [ "READ", "CREATE", "UPDATE_STATE", "DELETE" ]
      registry-read:
        - resources: [ "SCHEMA" ]
          actions: [ "READ" ]
      registry-admin:
        - resources: [ "SCHEMA" ]
          actions: [ "READ", "CREATE", "UPDATE", "DELETE", "DELETE_VERSION" ]
      group-admin:
        - resources: [ "CONSUMER_GROUP" ]
          actions: [ "READ", "UPDATE_OFFSET", "DELETE_OFFSET" ]
      connect-cluster-read:
        - resources: [ "CONNECT_CLUSTER" ]
          actions: [ "READ" ]

Here are our groups and ldap configuration:

    groups:
        developer:
          - role: topic-admin
            patterns: "^(?!_).*"
          - role: group-admin
            patterns: "^(?!_).*"
          - role: node-read
            patterns: "^(?!_).*"
          - role: registry-admin
            patterns: "^(?!_).*"
          - role: connect-admin
            patterns: "^(?!_).*"
        kafka_admin:
          - role: topic-admin
            patterns: ".*"
          - role: node-admin
            patterns: ".*"
          - role: group-admin
            patterns: ".*"
          - role: admin
            patterns: ".*"
          - role: registry-admin
            patterns: ".*"
          - role: acl
            patterns: ".*"
          - role: connect-admin
            patterns: ".*"
    ldap:
      groups:
         - name: kafka_admin
            groups:
              - admin
              - kafka_admin
         - name: kafka_cluster_a_dev
           groups:
              - developer
         - name: kafka_cluster_b_dev
           groups:
             - developer

And here is our LDAP micronaut config:

micronaut:
  server:
    context-path: /akhq-{{ stability_level }}
  security:
    enabled: true
    ldap:
      default:
        enabled: true
        context:
          server: 'ldaps://ldaps.our.company.com:636'
          managerDn: "CN={{ username }},OU=Company Users,OU=Company,OU=Business Units,DC=company,DC=corp,DC=comp,DC=com"
          managerPassword: "{{ password }}"
        search:
          base: "OU=Business Units,DC=company,DC=corp,DC=comp,DC=com"
          subtree: true
          filter: "(sAMAccountName={0})"
        groups:
          enabled: true
          base: "OU=Business Units,DC=company,DC=corp,DC=comp,DC=com"
          subtree: true
          filter: "member={0}"
    token:
      jwt:
        signatures:
          secret:
            generator:
              secret: {{ jwt_encryption_key }}

Do you see anything that could cause that issue?

Thank you in advance for your help!