-
Notifications
You must be signed in to change notification settings - Fork 103
Description
Description
Hello,
I am deploying a strimzi cluster that use strimzi-kafka-oauth for the user authentication and configuring kubernetes as authorization server to use service account token to extract information about the user.
Here is the configuration I used for my listener:
- name: oauth
port: 9094
tls: false
type: internal
authentication:
type: custom
sasl: true
listenerConfig:
connections.max.reauth.ms: 3600000
sasl.enabled.mechanisms: OAUTHBEARER
oauthbearer.sasl.server.callback.handler.class: io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler
principal.builder.class: io.strimzi.kafka.oauth.server.OAuthKafkaPrincipalBuilder
oauthbearer.sasl.jaas.config: >
org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required
unsecuredLoginStringClaim_sub="useless"
oauth.valid.issuer.uri="<clusterIssuerUri>"
oauth.jwks.endpoint.uri="https://kubernetes.default.svc.cluster.local/openid/v1/jwks"
oauth.server.bearer.token.location="/var/run/secrets/kubernetes.io/serviceaccount/token"
oauth.username.claim="<usernameClaim>"
oauth.check.access.token.type="false"
oauth.include.accept.header="false"
oauth.ssl.truststore.location="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
oauth.ssl.truststore.type="PEM";
And here is an example of kubernetes token:
{
"aud": [
"<audience>"
],
"exp": 1798103464,
"iat": 1766567464,
"iss": "<iss>",
"jti": "<jti>",
"kubernetes.io": {
"namespace": "default",
"node": {
"name": "<nodeName>",
"uid": "<uid>"
},
"pod": {
"name": "<podName>",
"uid": "<uid>"
},
"serviceaccount": {
"name": "my-service-account",
"uid": "<uid>"
},
"warnafter": 1766571071
},
"nbf": 1766567464,
"sub": "system:serviceaccount:default:my-service-account"
}
What is working well for the oauth.username.claim property is to set it to ['kubernetes.io']['serviceaccount']['name'], it allows to retrieve the name of the service account and to bind it to an existing KafkaUser.
But with this solution we miss the binding of the namespace and the service account name.
I saw that you are using the JsonPath library to extract information from JWT token. In their documentation they mention function can be used in path expression: https://github.com/json-path/JsonPath/tree/json-path-2.10.0?tab=readme-ov-file#functions
I tried this solution in a java project to ensure they work with JsonPath library:
String result = JsonPath.read(token, "concat($.['kubernetes.io']['namespace'], \"-\", $.['kubernetes.io']['serviceaccount']['name'])");
But when using this expression in the property oauth.username.claim it does not work.
It gives me this kind of error
io.strimzi.kafka.oauth.validator.ValidationException: Failed to extract principal - check usernameClaim, fallbackUsernameClaim configuration
at io.strimzi.kafka.oauth.validator.JWTSignatureValidator.extractPrincipal(JWTSignatureValidator.java:509) ~[kafka-oauth-common-0.17.1.jar:?]
at io.strimzi.kafka.oauth.validator.JWTSignatureValidator.validate(JWTSignatureValidator.java:493) ~[kafka-oauth-common-0.17.1.jar:?]
at io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler.validateToken(JaasServerOauthValidatorCallbackHandler.java:739) [kafka-oauth-server-0.17.1.jar:?]
at io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler.handleCallback(JaasServerOauthValidatorCallbackHandler.java:681) [kafka-oauth-server-0.17.1.jar:?]
at io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler.delegatedHandle(JaasServerOauthValidatorCallbackHandler.java:664) [kafka-oauth-server-0.17.1.jar:?]
at io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler.handle(JaasServerOauthValidatorCallbackHandler.java:643) [kafka-oauth-server-0.17.1.jar:?]
at org.apache.kafka.common.security.oauthbearer.internals.OAuthBearerSaslServer.process(OAuthBearerSaslServer.java:156) [kafka-clients-4.1.1.jar:?]
at org.apache.kafka.common.security.oauthbearer.internals.OAuthBearerSaslServer.evaluateResponse(OAuthBearerSaslServer.java:101) [kafka-clients-4.1.1.jar:?]
at org.apache.kafka.common.security.authenticator.SaslServerAuthenticator.handleSaslToken(SaslServerAuthenticator.java:461) [kafka-clients-4.1.1.jar:?]
at org.apache.kafka.common.security.authenticator.SaslServerAuthenticator.authenticate(SaslServerAuthenticator.java:286) [kafka-clients-4.1.1.jar:?]
at org.apache.kafka.common.network.KafkaChannel.prepare(KafkaChannel.java:181) [kafka-clients-4.1.1.jar:?]
at org.apache.kafka.common.network.Selector.pollSelectionKeys(Selector.java:548) [kafka-clients-4.1.1.jar:?]
at org.apache.kafka.common.network.Selector.poll(Selector.java:486) [kafka-clients-4.1.1.jar:?]
at kafka.network.Processor.poll(SocketServer.scala:1010) [kafka_2.13-4.1.1.jar:?]
at kafka.network.Processor.run(SocketServer.scala:914) [kafka_2.13-4.1.1.jar:?]
at java.base/java.lang.Thread.run(Thread.java:840) [?:?]
Did someone already tried it or is there a documentation about how to make it work with strimzi-kafka-oauth ?
Environment
- Strimzi version: 0.49.1
- Kafka version: 4.1.1
- Auth provider: kubernetes