Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kafka SASL GSSAPI exception #20088

Closed
irenakezic opened this issue Sep 13, 2021 · 16 comments · Fixed by #20416
Closed

Kafka SASL GSSAPI exception #20088

irenakezic opened this issue Sep 13, 2021 · 16 comments · Fixed by #20416
Assignees
Labels
area/kafka kind/bug Something isn't working
Milestone

Comments

@irenakezic
Copy link
Contributor

Describe the bug

Connecting to a Kafka broker using SASL GSSAPI works fine without the quarkus-infinispan-client extension. However, when quarkus-infinispan-client extension is added as a dependency the exception occurs when connecting to Kafka.

Expected behavior

Kafka connection is sucessful.

Actual behavior

The following exception occurs:

Caused by: javax.security.sasl.SaslException: ELY05108: Unable to create response token [Caused by javax.security.sasl.SaslException: ELY05127: No security layer supported by server but maximum message size received: "65536"]
	at org.wildfly.security.sasl.gssapi.GssapiClient.evaluateMessage(GssapiClient.java:313)
	at org.wildfly.security.sasl.util.AbstractSaslParticipant.evaluateMessage(AbstractSaslParticipant.java:219)
	at org.wildfly.security.sasl.gssapi.GssapiClient.evaluateChallenge(GssapiClient.java:218)
	at org.apache.kafka.common.security.authenticator.SaslClientAuthenticator.lambda$createSaslToken$1(SaslClientAuthenticator.java:524)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/javax.security.auth.Subject.doAs(Subject.java:423)
	at org.apache.kafka.common.security.authenticator.SaslClientAuthenticator.createSaslToken(SaslClientAuthenticator.java:524)
	at org.apache.kafka.common.security.authenticator.SaslClientAuthenticator.sendSaslClientToken(SaslClientAuthenticator.java:431)
	at org.apache.kafka.common.security.authenticator.SaslClientAuthenticator.authenticate(SaslClientAuthenticator.java:301)
	at org.apache.kafka.common.network.KafkaChannel.prepare(KafkaChannel.java:176)
	at org.apache.kafka.common.network.Selector.pollSelectionKeys(Selector.java:543)
	at org.apache.kafka.common.network.Selector.poll(Selector.java:481)
	at org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:563)
	at org.apache.kafka.clients.admin.KafkaAdminClient$AdminClientRunnable.processRequests(KafkaAdminClient.java:1329)
	at org.apache.kafka.clients.admin.KafkaAdminClient$AdminClientRunnable.run(KafkaAdminClient.java:1260)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: javax.security.sasl.SaslException: ELY05127: No security layer supported by server but maximum message size received: "65536"
	at org.wildfly.security.sasl.gssapi.GssapiClient.evaluateMessage(GssapiClient.java:281)
	... 15 more
java.security.PrivilegedActionException: javax.security.sasl.SaslException: ELY05108: Unable to create response token [Caused by javax.security.sasl.SaslException: ELY05127: No security layer supported by server but maximum message size received: "65536"] occurred when evaluating SASL token received from the Kafka Broker. Kafka Client will go to AUTHENTICATION_FAILED state.

How to Reproduce?

Reproducer:
https://github.com/irenakezic/kafka-sasl.git

Steps to reproduce:

  1. Build project using "mvn clean package -Djava.security.krb5.conf=src/test/resources/krb5.conf"
  2. Build should be successful and tests should run with no errors
  3. Uncomment infinispan client extension dependency in pom.xml (you can also uncomment InfinispanBean code and infinispan config in application.properties though uncommenting the dependency in pom.xml is enough)
  4. Test should fail with exception stated above

Please note that Kafka testcontainer in the example provided runs on port 9092 and container will not start properly if port is already taken on your localhost.

The reproducer is created using version 2.2.2.Final as it is the latest one but I need a fix for 1.11.7.Final-redhat-00009 if possible.

Output of uname -a or ver

No response

Output of java -version

No response

GraalVM version (if different from Java)

No response

Quarkus version or git rev

1.11.7.Final-redhat-00009

Build tool (ie. output of mvnw --version or gradlew --version)

No response

Additional information

The reason is wildfly.elytron.sasl.gssapi dependency that comes along with quarkus-infinispan-client. It seems that elytron GSSAPI implementation has more restrictive checks than default one.
Noticed that wildfly uses "wildfly.sasl.relax-compliance" config property to relax security checks for elytron gssapi. I wonder if there an option to add something similar in Quarkus?

@irenakezic irenakezic added the kind/bug Something isn't working label Sep 13, 2021
@quarkus-bot
Copy link

quarkus-bot bot commented Sep 13, 2021

/cc @cescoffier, @ozangunalp

@cescoffier
Copy link
Member

I guess we will have to relax some checks.

@cescoffier
Copy link
Member

@sberyozkin any advice?

@cescoffier
Copy link
Member

@sberyozkin by any chance, you have an idea where this "wildfly.sasl.relax-compliance" property is managed in wildfly? I would like to see what it is actually doing.

@cescoffier
Copy link
Member

@cescoffier cescoffier self-assigned this Sep 26, 2021
@cescoffier
Copy link
Member

cescoffier commented Sep 27, 2021

The wildfly.sasl.relax-compliance property can be passed in the channel configuration or even as a global configuration, but as it contains a - it gets replaced by wildfly.sasl.relax.compliance. This is something we can fix in reactive messaging.

The property gets replaced by wildfly.sasl.relax.compliance by the default configuration mapping (in Quarkus), which means, it cannot be found.

@cescoffier
Copy link
Member

Workaround 1: Add mp.messaging.connector.smallrye-kafka.wildfly.sasl.relax-compliance=true to the configuration
Workaround 2: Add:

  • mp.messaging.outgoing.out.wildfly.sasl.relax-compliance=true
  • mp.messaging.incoming.in.wildfly.sasl.relax-compliance=true

The question is whether we want to automatically detect that Elytron is on the classpath and inject the configuration automatically.

@Ladicek @ozangunalp WDYT?

@Ladicek
Copy link
Contributor

Ladicek commented Sep 27, 2021

I don't really have an opinion, but I guess adding this property unconditionally for the Kafka connector can't hurt? :-)

@ozangunalp
Copy link
Contributor

We can add the wildfly.sasl.relax-compliance property on kafka-client extension instead of smallrye-reactive-messaging-kafka no?

@cescoffier
Copy link
Member

Yes, it would be in the kafka-client extension. Most probably injected directly in the global config map.

@irenakezic
Copy link
Contributor Author

Hi @cescoffier,
thx for the workaround!
It works fine for Quarkus 2.2.2.Final. However, for Quarkus 1.11.7.Final-redhat-00009 (this the one I need to use for now) I get the following exceptuion:
2021-09-27 16:12:55,886 WARN [org.apa.kaf.cli.NetworkClient] (kafka-producer-network-thread | kafka-producer-out) [Producer clientId=kafka-producer-out] Error connecting to node localhost:9092 (id: -1 rack: null): java.io.IOException: Channel could not be created for socket java.nio.channels.SocketChannel[closed] at org.apache.kafka.common.network.Selector.buildAndAttachKafkaChannel(Selector.java:348) at org.apache.kafka.common.network.Selector.registerChannel(Selector.java:329) at org.apache.kafka.common.network.Selector.connect(Selector.java:256) at org.apache.kafka.clients.NetworkClient.initiateConnect(NetworkClient.java:1006) at org.apache.kafka.clients.NetworkClient.access$600(NetworkClient.java:75) at org.apache.kafka.clients.NetworkClient$DefaultMetadataUpdater.maybeUpdate(NetworkClient.java:1177) at org.apache.kafka.clients.NetworkClient$DefaultMetadataUpdater.maybeUpdate(NetworkClient.java:1065) at org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:561) at org.apache.kafka.clients.producer.internals.Sender.runOnce(Sender.java:325) at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:240) at java.base/java.lang.Thread.run(Thread.java:834) Caused by: org.apache.kafka.common.KafkaException: org.apache.kafka.common.errors.SaslAuthenticationException: Failed to configure SaslClientAuthenticator at org.apache.kafka.common.network.SaslChannelBuilder.buildChannel(SaslChannelBuilder.java:228) at org.apache.kafka.common.network.Selector.buildAndAttachKafkaChannel(Selector.java:338) ... 10 more Caused by: org.apache.kafka.common.errors.SaslAuthenticationException: Failed to configure SaslClientAuthenticator Caused by: java.lang.ClassCastException: class java.lang.Boolean cannot be cast to class java.lang.String (java.lang.Boolean and java.lang.String are in module java.base of loader 'bootstrap') at org.wildfly.security.sasl.gssapi.AbstractGssapiMechanism.<init>(AbstractGssapiMechanism.java:76) at org.wildfly.security.sasl.gssapi.GssapiClient.<init>(GssapiClient.java:66) at org.wildfly.security.sasl.gssapi.GssapiClientFactory.createSaslClient(GssapiClientFactory.java:42) at java.security.sasl/javax.security.sasl.Sasl.createSaslClient(Sasl.java:433) at org.apache.kafka.common.security.authenticator.SaslClientAuthenticator.lambda$createSaslClient$0(SaslClientAuthenticator.java:217) at java.base/java.security.AccessController.doPrivileged(Native Method) at java.base/javax.security.auth.Subject.doAs(Subject.java:423) at org.apache.kafka.common.security.authenticator.SaslClientAuthenticator.createSaslClient(SaslClientAuthenticator.java:213) at org.apache.kafka.common.security.authenticator.SaslClientAuthenticator.<init>(SaslClientAuthenticator.java:204) at org.apache.kafka.common.network.SaslChannelBuilder.buildClientAuthenticator(SaslChannelBuilder.java:275) at org.apache.kafka.common.network.SaslChannelBuilder.lambda$buildChannel$1(SaslChannelBuilder.java:216) at org.apache.kafka.common.network.KafkaChannel.<init>(KafkaChannel.java:142) at org.apache.kafka.common.network.SaslChannelBuilder.buildChannel(SaslChannelBuilder.java:224) at org.apache.kafka.common.network.Selector.buildAndAttachKafkaChannel(Selector.java:338) at org.apache.kafka.common.network.Selector.registerChannel(Selector.java:329) at org.apache.kafka.common.network.Selector.connect(Selector.java:256) at org.apache.kafka.clients.NetworkClient.initiateConnect(NetworkClient.java:1006) at org.apache.kafka.clients.NetworkClient.access$600(NetworkClient.java:75) at org.apache.kafka.clients.NetworkClient$DefaultMetadataUpdater.maybeUpdate(NetworkClient.java:1177) at org.apache.kafka.clients.NetworkClient$DefaultMetadataUpdater.maybeUpdate(NetworkClient.java:1065) at org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:561) at org.apache.kafka.clients.producer.internals.Sender.runOnce(Sender.java:325) at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:240) at java.base/java.lang.Thread.run(Thread.java:834)

Do you have any suggestions on how to workaround this one?

@cescoffier
Copy link
Member

Did you try both workarounds?

The problem is that it sees "true", and transforms it to a boolean in 1.11, but AbstractGssapiMechanism wants it as a String.

@irenakezic
Copy link
Contributor Author

@cescoffier I did try both options :(

cescoffier added a commit to cescoffier/quarkus that referenced this issue Sep 27, 2021
When you use Infinispan and Kafka at the same time and you connect to a Kafka broker with SASL, the SASL client uses Elytron.
However, Elytron SASL implementation is stricter than what Kafka expects.

This commit relaxes Elytron checks for Kafka.
@cescoffier
Copy link
Member

Unfortunately, there is nothing we can do. How Elytron is configured is not really "Kafka-friendly" ("-" instead of ".", String value instead of object)...

@irenakezic
Copy link
Contributor Author

@cescoffier thx, I guess we will need to migrate to a more recent version than.

@quarkus-bot quarkus-bot bot added this to the 2.4 - main milestone Sep 28, 2021
@geoand geoand modified the milestones: 2.4 - main, 2.3.0.Final Sep 28, 2021
geoand pushed a commit to geoand/quarkus that referenced this issue Sep 28, 2021
When you use Infinispan and Kafka at the same time and you connect to a Kafka broker with SASL, the SASL client uses Elytron.
However, Elytron SASL implementation is stricter than what Kafka expects.

This commit relaxes Elytron checks for Kafka.

(cherry picked from commit c17f875)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/kafka kind/bug Something isn't working
Projects
None yet
5 participants