Description
Issue submitter TODO list
- I've looked up my issue in FAQ
- I've searched for an already existing issues here
- I've tried running
main
-labeled docker image and the issue still persists there - I'm running a supported version of the application which is listed here
Describe the bug (actual behavior)
After upgrading to Kafbat 1.2.0 via Helm Chart 1.4.12, it is expected that we have support for using regex to identify subjects for roles when configuring RBAC permissions. We use Microsoft Entra ID as a generic OAuth2 Provider, with custom-params
configured to set the roles-field
to roles
, which allows us to utilise App Roles within EntraID to assign our users to the subjects Kafbat is configured to read.
Our redacted OAuth configuration is this:
type: OAUTH2
oauth2:
client:
azure:
clientId: <redacted>
clientSecret: <redacted>
scope: openid
client-name: azure
provider: azure
issuer-uri: <redacted>
jwk-set-uri: <redacted>
user-name-attribute: email
custom-params:
type: oauth
roles-field: roles
Our RBAC is configured like this:
rbac:
roles:
- name: "readonly-global"
clusters:
- dev
subjects:
- provider: oauth
type: role
value: ".*-ADMIN"
isRegex: true
permissions:
- resource: clusterconfig
actions: [ "view" ]
- resource: topic
value: ".*"
actions:
- VIEW
- resource: consumer
value: ".*"
actions: [ view ]
- resource: schema
value: ".*"
actions: [ view ]
- resource: connect
value: ".*"
actions: [ view ]
- resource: acl
actions: [ view ]
- name: "readdelete-testrole"
clusters:
- dev
subjects:
- provider: oauth
type: role
value: "dev.engsoft.user"
permissions:
- resource: topic
value: mgp.engsoft\..*
actions:
- MESSAGES_READ
- MESSAGES_DELETE
Within Azure, I have two roles assigned: dev.engsoft.user
via a group assignment and KAFBAT-ADMIN
via direct assignment. Both groups are present in the token sent to Kafbat, which can be seen in the logs, however, Kafbat does not respect the regex assignment of .*-ADMIN
and only assigns roles that exactly match, regardless of the isRegex
field value.
Here are logs of this with the above configuration:
2025-03-25 16:30:04,457 TRACE [reactor-http-epoll-9] i.k.u.s.r.e.OauthAuthorityExtractor: Extracting OAuth2 user authorities
2025-03-25 16:30:04,458 DEBUG [reactor-http-epoll-9] i.k.u.s.r.e.OauthAuthorityExtractor: Principal name is: [<redacted email>]
2025-03-25 16:30:04,459 DEBUG [reactor-http-epoll-9] i.k.u.s.r.e.OauthAuthorityExtractor: Matched roles by username: []
2025-03-25 16:30:04,459 TRACE [reactor-http-epoll-9] i.k.u.s.r.e.OauthAuthorityExtractor: The field is either a set or a list, returning as is
2025-03-25 16:30:04,459 DEBUG [reactor-http-epoll-9] i.k.u.s.r.e.OauthAuthorityExtractor: Token's groups: [KAFBAT-ADMIN,dev.engsoft.user]
2025-03-25 16:30:04,459 DEBUG [reactor-http-epoll-9] i.k.u.s.r.e.OauthAuthorityExtractor: Matched group roles: [readdelete-testrole]
Setting the subject to the following shows the permission successfully assigns:
subjects:
- provider: oauth
type: role
value: "KAFBAT-ADMIN"
isRegex: true
2025-03-25 16:56:18,855 TRACE [reactor-http-epoll-8] i.k.u.s.r.e.OauthAuthorityExtractor: Extracting OAuth2 user authorities
2025-03-25 16:56:18,855 DEBUG [reactor-http-epoll-8] i.k.u.s.r.e.OauthAuthorityExtractor: Principal name is: [<redacted email>]
2025-03-25 16:56:18,856 DEBUG [reactor-http-epoll-8] i.k.u.s.r.e.OauthAuthorityExtractor: Matched roles by username: []
2025-03-25 16:56:18,856 TRACE [reactor-http-epoll-8] i.k.u.s.r.e.OauthAuthorityExtractor: The field is either a set or a list, returning as is
2025-03-25 16:56:18,856 DEBUG [reactor-http-epoll-8] i.k.u.s.r.e.OauthAuthorityExtractor: Token's groups: [KAFBAT-ADMIN,dev.engsoft.user]
2025-03-25 16:56:18,857 DEBUG [reactor-http-epoll-8] i.k.u.s.r.e.OauthAuthorityExtractor: Matched group roles: [readonly-global, readdelete-testrole]
It appears that the configuration of isRegex
is ignored entirely. For the record, the regex we use for topic naming permissions within these roles all work as expected, which points directly to the implementation of Subject regex parsing.
Expected behavior
It is expected that for a regex, Kafbat matches any roles that succeed against that regex to the group. The above .*-ADMIN
example is taken directly from the documentation - in reality, we want it to match an even simpler regex of .*
so we can assign any role a set of global default permissions.
Your installation details
We're running:
- App version v1.2.0 3074abc
- Helm chart version 1.4.12
yamlApplicationConfig:
kafka:
internalTopicPrefix: _ui_
clusters:
- name: dev
bootstrapServers: dev-kafka-bootstrap.dev-kafka.svc.cluster.local:9092
schemaRegistry: http://conf-schema-registry:8081
readonly: false
properties:
security:
protocol: SASL_PLAINTEXT
sasl:
mechanism: PLAIN
jaas:
config: org.apache.kafka.common.security.plain.PlainLoginModule required username="<redacted>" password="<redacted>" ;
auth:
type: OAUTH2
oauth2:
client:
azure:
clientId: <redacted>
clientSecret: <redacted>
scope: openid
client-name: azure
provider: azure
issuer-uri: <redacted>
jwk-set-uri: <redacted>
user-name-attribute: email
custom-params:
type: oauth
roles-field: roles
logging:
level:
root: info # trace,debug, info, warn, error. default: info
io.kafbat.ui.service.rbac: TRACE
rbac:
roles:
- name: "readonly-global"
clusters:
- dev
subjects:
- provider: oauth
type: role
value: "KAFBAT-ADMIN"
isRegex: true
permissions:
- resource: clusterconfig
actions: [ "view" ]
- resource: topic
value: ".*"
actions:
- VIEW
- resource: consumer
value: ".*"
actions: [ view ]
- resource: schema
value: ".*"
actions: [ view ]
- resource: connect
value: ".*"
actions: [ view ]
- resource: acl
actions: [ view ]
- name: "readdelete-testrole"
clusters:
- dev
subjects:
- provider: oauth
type: role
value: "dev.engsoft.user"
permissions:
- resource: topic
value: mgp.engsoft\..*
actions:
- MESSAGES_READ
- MESSAGES_DELETE
Steps to reproduce
Deploy Kafbat via chart with the above configuration and correct setup in EntraID and the result is reproducible.
Screenshots
No response
Logs
Additional context
This was discussed in the community Discord. We tried the suggestion of changing isRegex
to isIsRegex
but this didn't work.