-
Notifications
You must be signed in to change notification settings - Fork 2.4k
feat: Introducing StreamingCredentialsProvider for token based authentication #3320
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
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but I think the PR title is misleading. From what I understand, this PR doesn't provide the possibility for authentication with a StreamingCredentialsProvider
just yet, instead it introduces the necessary interfaces and already prepares the ground by refactoring the basic auth we were using to use the new Credentials interface.
Reverting this back to Draft, will continue working on it before |
Introduces the StreamingCredentialsProvider as the CredentialsProvider with the highest priority. TODO: needs to be tested
Change CancelProviderFunc to UnsubscribeFunc
ff04986
to
44628c5
Compare
8fd3bd5
to
5fac913
Compare
f7770ce
to
036e1ac
Compare
036e1ac
to
7eea9e7
Compare
auth/reauth_credentials_listener.go
Outdated
if c.reAuth != nil { | ||
err := c.reAuth(credentials) | ||
if err != nil { | ||
if c.onErr != nil { | ||
c.onErr(err) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about using early returns here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also instead of doing the c.OnErr != nil
check, can we instead directly call c.OnError
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree on calling c.OnError
. As for early returns - i don't have a preference when the function is as short as this, but makes sense if we are gonna use them elsewhere and would like to be consistent. Thank you for the suggestions!
username, password := "", "" | ||
if c.opt.StreamingCredentialsProvider != nil { | ||
credentials, cancelCredentialsProvider, err := c.opt.StreamingCredentialsProvider. | ||
Subscribe(c.newReAuthCredentialsListener(ctx, conn)) | ||
if err != nil { | ||
return fmt.Errorf("failed to subscribe to streaming credentials: %w", err) | ||
} | ||
c.onClose = c.wrappedOnClose(cancelCredentialsProvider) | ||
username, password = credentials.BasicAuth() | ||
} else if c.opt.CredentialsProviderContext != nil { | ||
username, password, err = c.opt.CredentialsProviderContext(ctx) | ||
if err != nil { | ||
return fmt.Errorf("failed to get credentials from context provider: %w", err) | ||
} | ||
} else if c.opt.CredentialsProvider != nil { | ||
username, password = c.opt.CredentialsProvider() | ||
} else if c.opt.Username != "" || c.opt.Password != "" { | ||
username, password = c.opt.Username, c.opt.Password | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
username, password := "", "" | |
if c.opt.StreamingCredentialsProvider != nil { | |
credentials, cancelCredentialsProvider, err := c.opt.StreamingCredentialsProvider. | |
Subscribe(c.newReAuthCredentialsListener(ctx, conn)) | |
if err != nil { | |
return fmt.Errorf("failed to subscribe to streaming credentials: %w", err) | |
} | |
c.onClose = c.wrappedOnClose(cancelCredentialsProvider) | |
username, password = credentials.BasicAuth() | |
} else if c.opt.CredentialsProviderContext != nil { | |
username, password, err = c.opt.CredentialsProviderContext(ctx) | |
if err != nil { | |
return fmt.Errorf("failed to get credentials from context provider: %w", err) | |
} | |
} else if c.opt.CredentialsProvider != nil { | |
username, password = c.opt.CredentialsProvider() | |
} else if c.opt.Username != "" || c.opt.Password != "" { | |
username, password = c.opt.Username, c.opt.Password | |
} | |
username, password := c.opt.Username, c.opt.Password | |
switch { | |
case c.opt.StreamingCredentialsProvider != nil: | |
credentials, cancelCredentialsProvider, err := c.opt.StreamingCredentialsProvider. | |
Subscribe(c.newReAuthCredentialsListener(ctx, conn)) | |
if err != nil { | |
return fmt.Errorf("failed to subscribe to streaming credentials: %w", err) | |
} | |
c.onClose = c.wrappedOnClose(cancelCredentialsProvider) | |
username, password = credentials.BasicAuth() | |
case c.CredentialsProviderContext != nil: | |
username, password, err = c.opt.CredentialsProviderContext(ctx) | |
if err != nil { | |
return fmt.Errorf("failed to get credentials from context provider: %w", err) | |
} | |
case c.opt.CredentialsProvider != nil: | |
username, password = c.opt.CredentialsProvider() | |
} |
Do you think this will improve the readability?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although both versions are identical, I think the if / else if/ else
makes it easier to follow the priority of the credentials providers. This is a personal preference, let me know if you have strong opinion on the topic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a streaming credentials provider mechanism for token‐based authentication, refactoring connection initialization and hook propagation while also updating tests and documentation for authentication.
- Introduces new types and interfaces in the auth package for dynamic credential updates.
- Refactors core connection initialization to use the streaming provider and re-authentication listener.
- Updates tests and docs (including README and examples) to cover new authentication flows and hook propagation improvements.
Reviewed Changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
tx.go | Moves hooksMixin from Tx struct into baseClient; updates newTx() accordingly. |
sentinel.go | Updates onClose hook assignment using wrappedOnClose. |
ring_test.go | Enhances pipeline hook tests by skipping connection initialization commands. |
redis_test.go | Introduces tests verifying proper priority usage of Streaming, context, regular, and static credentials. |
redis.go | Adds functions to support re-authentication on credentials updates; adjusts error wrapping and hook usage. |
probabilistic_test.go | Modifies expectations to be more flexible about command lengths. |
osscluster*.go | Minor nil-check improvements and injection of streaming authentication options. |
options.go | Updates option comments and adds StreamingCredentialsProvider field. |
internal_test.go, example_instrumentation_test.go, doctests, command_recorder_test.go | Additions and tweaks to tests and examples for improved instrumentation and command recording support. |
auth/* | New auth package files implementing the streaming credentials API and its tests. |
README.md | Updates documentation describing the new authentication priority order and provider usage. |
.github/wordlist.txt | Updates wordlist with new authentication-related keywords. |
Comments suppressed due to low confidence (2)
tx.go:29
- Verify that removing hooksMixin from the Tx struct and relying on baseClient.hooksMixin is an intentional design change to ensure that all hook functionality remains effective.
hooksMixin: c.hooksMixin.clone(),
redis.go:441
- There appears to be a potential naming inconsistency between 'DisableIdentity' and 'DisableIndentity'. Please confirm that the correct option name is used to avoid confusion.
if !c.opt.DisableIdentity && !c.opt.DisableIndentity {
Implementation Details and Key Changes
New Authentication Package
auth
package to hold types related to authenticationauth.Credentials
interface to facilitate integration with external credential sourcesbasicAuth
for username/password credentialsStreaming Credentials Provider
StreamingCredentialsProvider
interface for dynamic credential updatesReAuthCredentialsListener
for handling credential updatesDocumentation Updates
Hooks System Enhancement
hooksMixin
to propagate hooks to child connectionsTesting
Security Considerations
Important Note: The hooksMixin refactor will now propagate hooks to child connections and trigger them prior to the initialization process. This change may have security implications, particularly regarding the visibility of authentication commands. For example, Redis MONITOR doesn't report AUTH commands, and this change could potentially expose sensitive authentication information through hooks. This should be carefully considered and potentially documented for users implementing custom hooks.
Related Issues