Skip to content

KAFKA-14062: OAuth client token refresh fails with SASL extensions#12398

Merged
omkreddy merged 3 commits intoapache:trunkfrom
kirktrue:kafka-14062-fix-oauth-refresh
Jul 12, 2022
Merged

KAFKA-14062: OAuth client token refresh fails with SASL extensions#12398
omkreddy merged 3 commits intoapache:trunkfrom
kirktrue:kafka-14062-fix-oauth-refresh

Conversation

@kirktrue
Copy link
Copy Markdown
Contributor

@kirktrue kirktrue commented Jul 9, 2022

Authored by @emissionnebula

What

Kafka client is adding and removing the SASL extensions alternatively at the time of token refresh. During the window when the extensions are not present in the subject. If a connection to a broker is reattempted, it fails with the error that the extensions are missing.

See KAFKA-14062 for more information.

Why

In clients, a Subject object is maintained which contains two sets each for Private and Public Credentials. Public Credentials includes the extensions. These values are stored in a SaslExtensions object which internally maintains these in a HashMap.

At the time of token refresh, a SaslExtensions object with these extensions is added to the public credentials set. As a next step, the refresh thread tries to logout the client for the older credentials. So it tries to remove the older token (private credential) and older SaslExtensions object (public credential) from the sets maintained in the Subject object.

SaslExtensions Class overrides the equals and hashcode functions and directly calls the equals and hashcode functions of HashMap. So at the time refresh when a new SaslExtensions object is added, because the extension values don't change, it results in a no-op because the hashes of the existing SaslExtensions object and the new object will be equals. But in the logout step, the only SaslExtensions object present in the set gets removed.

After removing the extensions in 1st refresh, the extensions will get added again at the time of 2nd refresh. So, this addition and removal keep happening alternatively.

The addition and removal of private credentials (tokens) from Subject work just fine because the tokens are always different.

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

… methods

Different objects should be considered unique even with same content to support logout
@kirktrue kirktrue changed the title KAFKA-14062: Remove SaslExtensions overridden equals() and hashCode() methods KAFKA-14062: OAuth client token refresh fails with SASL extensions Jul 9, 2022
@kirktrue
Copy link
Copy Markdown
Contributor Author

kirktrue commented Jul 9, 2022

@dajac
Copy link
Copy Markdown
Member

dajac commented Jul 9, 2022

Could we add a unit test?

@kirktrue
Copy link
Copy Markdown
Contributor Author

kirktrue commented Jul 9, 2022

Thanks for the feedback, @dajac! 😄

Could we add a unit test?

Yes, I'd like to see that too.

@emissionnebula: has the testing for this been mostly manual up to this point?

I am willing to try to come up with one or more tests around this, but I can't commit to it.

Also swapped out the use of mocks in exchange for *real*
SaslExtensions so that we exercise the use of default equals()
and hashCode() methods.
@kirktrue
Copy link
Copy Markdown
Contributor Author

I've modified some existing unit tests in OAuthBearerLoginModuleTest that appear to exercise/mimic the refresh logic.

If the equals and hashCode method implementations in the SaslExtensions class are left in, the tests fail. When I remove the methods (as per @emissionnebula's change), the unit tests pass as expected.

@kirktrue
Copy link
Copy Markdown
Contributor Author

kirktrue commented Jul 11, 2022

The issue really does seem to boil down to how the Subject class implicitly expects the objects in its public credentials set to behave. They seem to really be expected to be unique. I'm not sure if we're violating some assumption or tenet in OAuthBearerLoginModule, SaslExtensions, or not.

I don't see a way to change OAuthBearerLoginModule to account for the case when two instances in the set evaluated to being equal.

@kirktrue
Copy link
Copy Markdown
Contributor Author

cc @rondagostino

@kirktrue
Copy link
Copy Markdown
Contributor Author

kirktrue commented Jul 11, 2022

Looking at this a little more, I see multiple classes (OAuthBearerLoginModule, OAuthBearerRefreshingLogin, ExpiringCredentialRefreshingLogin, etc.) that seem to play a part in the login process. Given that there is a dedicated refresh thread that modifies the Subject, I'm still wondering if there's some kind of race condition here 🤔

Copy link
Copy Markdown
Contributor

@omkreddy omkreddy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kirktrue Thanks for the PR. LGTM

@omkreddy omkreddy merged commit d3130f2 into apache:trunk Jul 12, 2022
omkreddy pushed a commit that referenced this pull request Jul 12, 2022
…12398)

- Different objects should be considered unique even with same content to support logout
- Added comments for SaslExtension re: removal of equals and hashCode
- Also swapped out the use of mocks in exchange for *real* SaslExtensions so that we exercise the use of default equals() and hashCode() methods.
- Updates to implement equals and hashCode and add tests in SaslExtensionsTest to confirm

Co-authored-by: Purshotam Chauhan <pchauhan@confluent.io>

Reviewers: Manikumar Reddy <manikumar.reddy@gmail.com>
omkreddy pushed a commit that referenced this pull request Jul 12, 2022
…12398)

- Different objects should be considered unique even with same content to support logout
- Added comments for SaslExtension re: removal of equals and hashCode
- Also swapped out the use of mocks in exchange for *real* SaslExtensions so that we exercise the use of default equals() and hashCode() methods.
- Updates to implement equals and hashCode and add tests in SaslExtensionsTest to confirm

Co-authored-by: Purshotam Chauhan <pchauhan@confluent.io>

Reviewers: Manikumar Reddy <manikumar.reddy@gmail.com>
omkreddy pushed a commit that referenced this pull request Jul 12, 2022
…12398)

- Different objects should be considered unique even with same content to support logout
- Added comments for SaslExtension re: removal of equals and hashCode
- Also swapped out the use of mocks in exchange for *real* SaslExtensions so that we exercise the use of default equals() and hashCode() methods.
- Updates to implement equals and hashCode and add tests in SaslExtensionsTest to confirm

Co-authored-by: Purshotam Chauhan <pchauhan@confluent.io>

Reviewers: Manikumar Reddy <manikumar.reddy@gmail.com>
fmin added a commit to confluentinc/kafka that referenced this pull request Sep 14, 2022
…1-14-SEP-2022

* apache-kafka/3.1: (17 commits)
  MINOR: Update 3.1 branch version to 3.1.3-SNAPSHOT
  Upgrade Netty and Jackson versions for CVE fixes [KAFKA-14044] (apache#12376)
  Bump version to 3.1.2
  MINOR: Update LICENSE-binary
  MINOR: Bump version in upgrade guide to 3.1.2
  MINOR: Add configurable max receive size for SASL authentication requests
  MINOR: Add more validation during KRPC deserialization
  MINOR: Add note on IDEMPOTENT_WRITE ACL to notable changes (apache#12260)
  KAFKA-14107: Upgrade Jetty version for CVE fixes (apache#12440)
  KAFKA-14062: OAuth client token refresh fails with SASL extensions (apache#12398)
  ...
@kirktrue kirktrue deleted the kafka-14062-fix-oauth-refresh branch October 25, 2023 00:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants