Skip to content

Commit a74743c

Browse files
authored
Merge branch 'master' into otel
2 parents c10ba5c + a7772e4 commit a74743c

36 files changed

+1305
-153
lines changed

.github/wordlist.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,12 @@ RedisGears
6565
RedisTimeseries
6666
RediSearch
6767
RawResult
68-
RawVal
68+
RawVal
69+
entra
70+
EntraID
71+
Entra
72+
OAuth
73+
Azure
74+
StreamingCredentialsProvider
75+
oauth
76+
entraid

.github/workflows/spellcheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
- name: Checkout
99
uses: actions/checkout@v4
1010
- name: Check Spelling
11-
uses: rojopolis/spellcheck-github-actions@0.48.0
11+
uses: rojopolis/spellcheck-github-actions@0.49.0
1212
with:
1313
config_path: .github/spellcheck-settings.yml
1414
task_name: Markdown

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ testdata/*
77
redis8tests.sh
88
coverage.txt
99
**/coverage.txt
10-
.vscode
10+
.vscode
11+
tmp/*

README.md

Lines changed: 113 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ key value NoSQL database that uses RocksDB as storage engine and is compatible w
6868

6969
- Redis commands except QUIT and SYNC.
7070
- Automatic connection pooling.
71+
- [StreamingCredentialsProvider (e.g. entra id, oauth)](#1-streaming-credentials-provider-highest-priority) (experimental)
7172
- [Pub/Sub](https://redis.uptrace.dev/guide/go-redis-pubsub.html).
7273
- [Pipelines and transactions](https://redis.uptrace.dev/guide/go-redis-pipelines.html).
7374
- [Scripting](https://redis.uptrace.dev/guide/lua-scripting.html).
@@ -136,17 +137,121 @@ func ExampleClient() {
136137
}
137138
```
138139

139-
The above can be modified to specify the version of the RESP protocol by adding the `protocol`
140-
option to the `Options` struct:
140+
### Authentication
141+
142+
The Redis client supports multiple ways to provide authentication credentials, with a clear priority order. Here are the available options:
143+
144+
#### 1. Streaming Credentials Provider (Highest Priority) - Experimental feature
145+
146+
The streaming credentials provider allows for dynamic credential updates during the connection lifetime. This is particularly useful for managed identity services and token-based authentication.
141147

142148
```go
143-
rdb := redis.NewClient(&redis.Options{
144-
Addr: "localhost:6379",
145-
Password: "", // no password set
146-
DB: 0, // use default DB
147-
Protocol: 3, // specify 2 for RESP 2 or 3 for RESP 3
148-
})
149+
type StreamingCredentialsProvider interface {
150+
Subscribe(listener CredentialsListener) (Credentials, UnsubscribeFunc, error)
151+
}
152+
153+
type CredentialsListener interface {
154+
OnNext(credentials Credentials) // Called when credentials are updated
155+
OnError(err error) // Called when an error occurs
156+
}
157+
158+
type Credentials interface {
159+
BasicAuth() (username string, password string)
160+
RawCredentials() string
161+
}
162+
```
163+
164+
Example usage:
165+
```go
166+
rdb := redis.NewClient(&redis.Options{
167+
Addr: "localhost:6379",
168+
StreamingCredentialsProvider: &MyCredentialsProvider{},
169+
})
170+
```
171+
172+
**Note:** The streaming credentials provider can be used with [go-redis-entraid](https://github.com/redis/go-redis-entraid) to enable Entra ID (formerly Azure AD) authentication. This allows for seamless integration with Azure's managed identity services and token-based authentication.
173+
174+
Example with Entra ID:
175+
```go
176+
import (
177+
"github.com/redis/go-redis/v9"
178+
"github.com/redis/go-redis-entraid"
179+
)
180+
181+
// Create an Entra ID credentials provider
182+
provider := entraid.NewDefaultAzureIdentityProvider()
183+
184+
// Configure Redis client with Entra ID authentication
185+
rdb := redis.NewClient(&redis.Options{
186+
Addr: "your-redis-server.redis.cache.windows.net:6380",
187+
StreamingCredentialsProvider: provider,
188+
TLSConfig: &tls.Config{
189+
MinVersion: tls.VersionTLS12,
190+
},
191+
})
192+
```
149193

194+
#### 2. Context-based Credentials Provider
195+
196+
The context-based provider allows credentials to be determined at the time of each operation, using the context.
197+
198+
```go
199+
rdb := redis.NewClient(&redis.Options{
200+
Addr: "localhost:6379",
201+
CredentialsProviderContext: func(ctx context.Context) (string, string, error) {
202+
// Return username, password, and any error
203+
return "user", "pass", nil
204+
},
205+
})
206+
```
207+
208+
#### 3. Regular Credentials Provider
209+
210+
A simple function-based provider that returns static credentials.
211+
212+
```go
213+
rdb := redis.NewClient(&redis.Options{
214+
Addr: "localhost:6379",
215+
CredentialsProvider: func() (string, string) {
216+
// Return username and password
217+
return "user", "pass"
218+
},
219+
})
220+
```
221+
222+
#### 4. Username/Password Fields (Lowest Priority)
223+
224+
The most basic way to provide credentials is through the `Username` and `Password` fields in the options.
225+
226+
```go
227+
rdb := redis.NewClient(&redis.Options{
228+
Addr: "localhost:6379",
229+
Username: "user",
230+
Password: "pass",
231+
})
232+
```
233+
234+
#### Priority Order
235+
236+
The client will use credentials in the following priority order:
237+
1. Streaming Credentials Provider (if set)
238+
2. Context-based Credentials Provider (if set)
239+
3. Regular Credentials Provider (if set)
240+
4. Username/Password fields (if set)
241+
242+
If none of these are set, the client will attempt to connect without authentication.
243+
244+
### Protocol Version
245+
246+
The client supports both RESP2 and RESP3 protocols. You can specify the protocol version in the options:
247+
248+
```go
249+
rdb := redis.NewClient(&redis.Options{
250+
Addr: "localhost:6379",
251+
Password: "", // no password set
252+
DB: 0, // use default DB
253+
Protocol: 3, // specify 2 for RESP 2 or 3 for RESP 3
254+
})
150255
```
151256

152257
### Connecting via a redis url

RELEASE-NOTES.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,62 @@
11
# Release Notes
22

3+
# 9.9.0 (2025-05-27)
4+
5+
## 🚀 Highlights
6+
- **Token-based Authentication**: Added `StreamingCredentialsProvider` for dynamic credential updates (experimental)
7+
- Can be used with [go-redis-entraid](https://github.com/redis/go-redis-entraid) for Azure AD authentication
8+
- **Connection Statistics**: Added connection waiting statistics for better monitoring
9+
- **Failover Improvements**: Added `ParseFailoverURL` for easier failover configuration
10+
- **Ring Client Enhancements**: Added shard access methods for better Pub/Sub management
11+
12+
## ✨ New Features
13+
- Added `StreamingCredentialsProvider` for token-based authentication ([#3320](https://github.com/redis/go-redis/pull/3320))
14+
- Supports dynamic credential updates
15+
- Includes connection close hooks
16+
- Note: Currently marked as experimental
17+
- Added `ParseFailoverURL` for parsing failover URLs ([#3362](https://github.com/redis/go-redis/pull/3362))
18+
- Added connection waiting statistics ([#2804](https://github.com/redis/go-redis/pull/2804))
19+
- Added new utility functions:
20+
- `ParseFloat` and `MustParseFloat` in public utils package ([#3371](https://github.com/redis/go-redis/pull/3371))
21+
- Unit tests for `Atoi`, `ParseInt`, `ParseUint`, and `ParseFloat` ([#3377](https://github.com/redis/go-redis/pull/3377))
22+
- Added Ring client shard access methods:
23+
- `GetShardClients()` to retrieve all active shard clients
24+
- `GetShardClientForKey(key string)` to get the shard client for a specific key ([#3388](https://github.com/redis/go-redis/pull/3388))
25+
26+
## 🐛 Bug Fixes
27+
- Fixed routing reads to loading slave nodes ([#3370](https://github.com/redis/go-redis/pull/3370))
28+
- Added support for nil lag in XINFO GROUPS ([#3369](https://github.com/redis/go-redis/pull/3369))
29+
- Fixed pool acquisition timeout issues ([#3381](https://github.com/redis/go-redis/pull/3381))
30+
- Optimized unnecessary copy operations ([#3376](https://github.com/redis/go-redis/pull/3376))
31+
32+
## 📚 Documentation
33+
- Updated documentation for XINFO GROUPS with nil lag support ([#3369](https://github.com/redis/go-redis/pull/3369))
34+
- Added package-level comments for new features
35+
36+
## ⚡ Performance and Reliability
37+
- Optimized `ReplaceSpaces` function ([#3383](https://github.com/redis/go-redis/pull/3383))
38+
- Set default value for `Options.Protocol` in `init()` ([#3387](https://github.com/redis/go-redis/pull/3387))
39+
- Exported pool errors for public consumption ([#3380](https://github.com/redis/go-redis/pull/3380))
40+
41+
## 🔧 Dependencies and Infrastructure
42+
- Updated Redis CI to version 8.0.1 ([#3372](https://github.com/redis/go-redis/pull/3372))
43+
- Updated spellcheck GitHub Actions ([#3389](https://github.com/redis/go-redis/pull/3389))
44+
- Removed unused parameters ([#3382](https://github.com/redis/go-redis/pull/3382), [#3384](https://github.com/redis/go-redis/pull/3384))
45+
46+
## 🧪 Testing
47+
- Added unit tests for pool acquisition timeout ([#3381](https://github.com/redis/go-redis/pull/3381))
48+
- Added unit tests for utility functions ([#3377](https://github.com/redis/go-redis/pull/3377))
49+
50+
## 👥 Contributors
51+
52+
We would like to thank all the contributors who made this release possible:
53+
54+
[@ndyakov](https://github.com/ndyakov), [@ofekshenawa](https://github.com/ofekshenawa), [@LINKIWI](https://github.com/LINKIWI), [@iamamirsalehi](https://github.com/iamamirsalehi), [@fukua95](https://github.com/fukua95), [@lzakharov](https://github.com/lzakharov), [@DengY11](https://github.com/DengY11)
55+
56+
## 📝 Changelog
57+
58+
For a complete list of changes, see the [full changelog](https://github.com/redis/go-redis/compare/v9.8.0...v9.9.0).
59+
360
# 9.8.0 (2025-04-30)
461

562
## 🚀 Highlights

auth/auth.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Package auth package provides authentication-related interfaces and types.
2+
// It also includes a basic implementation of credentials using username and password.
3+
package auth
4+
5+
// StreamingCredentialsProvider is an interface that defines the methods for a streaming credentials provider.
6+
// It is used to provide credentials for authentication.
7+
// The CredentialsListener is used to receive updates when the credentials change.
8+
type StreamingCredentialsProvider interface {
9+
// Subscribe subscribes to the credentials provider for updates.
10+
// It returns the current credentials, a cancel function to unsubscribe from the provider,
11+
// and an error if any.
12+
// TODO(ndyakov): Should we add context to the Subscribe method?
13+
Subscribe(listener CredentialsListener) (Credentials, UnsubscribeFunc, error)
14+
}
15+
16+
// UnsubscribeFunc is a function that is used to cancel the subscription to the credentials provider.
17+
// It is used to unsubscribe from the provider when the credentials are no longer needed.
18+
type UnsubscribeFunc func() error
19+
20+
// CredentialsListener is an interface that defines the methods for a credentials listener.
21+
// It is used to receive updates when the credentials change.
22+
// The OnNext method is called when the credentials change.
23+
// The OnError method is called when an error occurs while requesting the credentials.
24+
type CredentialsListener interface {
25+
OnNext(credentials Credentials)
26+
OnError(err error)
27+
}
28+
29+
// Credentials is an interface that defines the methods for credentials.
30+
// It is used to provide the credentials for authentication.
31+
type Credentials interface {
32+
// BasicAuth returns the username and password for basic authentication.
33+
BasicAuth() (username string, password string)
34+
// RawCredentials returns the raw credentials as a string.
35+
// This can be used to extract the username and password from the raw credentials or
36+
// additional information if present in the token.
37+
RawCredentials() string
38+
}
39+
40+
type basicAuth struct {
41+
username string
42+
password string
43+
}
44+
45+
// RawCredentials returns the raw credentials as a string.
46+
func (b *basicAuth) RawCredentials() string {
47+
return b.username + ":" + b.password
48+
}
49+
50+
// BasicAuth returns the username and password for basic authentication.
51+
func (b *basicAuth) BasicAuth() (username string, password string) {
52+
return b.username, b.password
53+
}
54+
55+
// NewBasicCredentials creates a new Credentials object from the given username and password.
56+
func NewBasicCredentials(username, password string) Credentials {
57+
return &basicAuth{
58+
username: username,
59+
password: password,
60+
}
61+
}

0 commit comments

Comments
 (0)