Skip to content

Commit 06496ed

Browse files
ggivotishun
andauthored
Readme doc on how to connect to Azure Managed Redis with Entra ID authentication (#3166)
* Readme doc on how to connect to Azure Managed Redis (AMR) and Azure Cache for Redis (ACR) with Entra ID authentication * Spellcheck words list updated * Formating * Update docs/user-guide/connecting-redis.md Co-authored-by: Tihomir Krasimirov Mateev <tihomir.mateev@redis.com> * Apply suggestions from code review Co-authored-by: Tihomir Krasimirov Mateev <tihomir.mateev@redis.com> * Add section for Streaming Credentials * Add section for Streaming Credentials - fix spell check * Apply suggestions from code review Co-authored-by: Tihomir Krasimirov Mateev <tihomir.mateev@redis.com> --------- Co-authored-by: Tihomir Krasimirov Mateev <tihomir.mateev@redis.com>
1 parent fc7bffb commit 06496ed

File tree

2 files changed

+164
-1
lines changed

2 files changed

+164
-1
lines changed

.github/wordlist.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,9 @@ bom
272272
ubuntu
273273
behaviour
274274
databind
275-
jackson
275+
jackson
276+
ACR
277+
AMR
278+
Entra
279+
authx
280+
entraid

docs/user-guide/connecting-redis.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,161 @@ RedisClient client = RedisClient.create(redisUri);
237237
client.shutdown();
238238
```
239239

240+
## Streaming Credentials Provider
241+
[Lettuce 6.6.0](https://github.com/redis/lettuce/releases/tag/6.6.0.RELEASE) extends `RedisCredentialsProvider` to support streaming credentials.
242+
It is useful when you need to refresh credentials periodically. Example use cases include: token expiration, rotating credentials, etc.
243+
Connection configured with `RedisCredentialsProvider` supporting streaming will be re-authenticated automatically when new credentials are emitted and `ReauthenticateBehavior` is set to `ON_NEW_CREDENTIALS`.
244+
245+
### Step 1 - Create a Streaming Credentials Provider
246+
A simple example of a streaming credentials provider that emits new credentials.
247+
```java
248+
public class MyStreamingRedisCredentialsProvider implements RedisCredentialsProvider {
249+
250+
private final Sinks.Many<RedisCredentials> credentialsSink = Sinks.many().replay().latest();
251+
252+
@Override
253+
public boolean supportsStreaming() {
254+
return true;
255+
}
256+
257+
@Override
258+
public Mono<RedisCredentials> resolveCredentials() {
259+
return credentialsSink.asFlux().next();
260+
}
261+
262+
@Override
263+
// Provide a continuous stream of credentials
264+
public Flux<RedisCredentials> credentials() {
265+
return credentialsSink.asFlux().onBackpressureLatest();
266+
}
267+
268+
public void close() {
269+
credentialsSink.tryEmitComplete();
270+
}
271+
// Emit new credentials when needed
272+
public void emitCredentials(String username, char[] password) {
273+
credentialsSink.tryEmitNext(new StaticRedisCredentials(username, password));
274+
}
275+
276+
}
277+
```
278+
### Step 2 - Create a RedisURI with streaming credentials provider
279+
280+
```java
281+
// Create a streaming credentials provider
282+
MyStreamingRedisCredentialsProvider streamingCredentialsProvider = new MyStreamingRedisCredentialsProvider();
283+
284+
// Emit initial credentials
285+
streamingCredentialsProvider.emitCredentials("testuser", "testpass".toCharArray());
286+
287+
// Enable automatic re-authentication
288+
ClientOptions clientOptions = ClientOptions.builder()
289+
// enable automatic re-authentication
290+
.reauthenticateBehavior(ClientOptions.ReauthenticateBehavior.ON_NEW_CREDENTIALS)
291+
.build();
292+
293+
// Create a RedisURI with streaming credentials provider
294+
RedisURI redisURI = RedisURI.builder().withHost(HOST).withPort(PORT)
295+
.withAuthentication(streamingCredentialsProvider)
296+
.build();
297+
298+
// RedisClient
299+
RedisClient redisClient = RedisClient.create(redisURI);
300+
rediscClient.connect().sync().ping();
301+
302+
// ...
303+
// Emit new credentials when needed
304+
streamingCredentialsProvider.emitCredentials("testuser", "password-rotated".toCharArray());
305+
306+
```
307+
308+
## Microsoft Entra ID Authentication
309+
310+
[Lettuce 6.6.0](https://github.com/redis/lettuce/releases/tag/6.6.0.RELEASE) introduces built-in support for authentication with [Azure Managed Redis](https://azure.microsoft.com/en-us/products/managed-redis) and Azure Cache for Redis using Microsoft Entra ID (formerly Azure Active Directory). It enables seamless integration with Azure's Redis services by fetching authentication tokens and managing the token renewal in the background.
311+
Integration is built on top of [redis-authx](https://github.com/redis/jvm-redis-authx-entraid) library, and provides support for:
312+
313+
- System-assigned managed identity
314+
- User-assigned managed identity
315+
- Service principal
316+
317+
You can learn more about managed identities in the [Microsoft Entra ID documentation](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview).
318+
319+
### Basic Usage
320+
321+
#### Pre-requisites
322+
* [register an application and create a service principal](https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals?tabs=browser) in Azure.
323+
* Create a Redis cache in Azure and grant your service principal access: [AMR](https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/managed-redis/managed-redis-entra-for-authentication) or [ACR](https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-azure-active-directory-for-authentication) documentation.
324+
325+
#### Step 1 - Add the dependencies
326+
Lettuce requires [redis-authx-entraid](https://github.com/redis/jvm-redis-authx-entraid/) dependency to provide Microsoft Entra ID authentication support. Make sure to include that dependency on your classpath.
327+
328+
If using Maven, add the following dependency to your `pom.xml`:
329+
330+
``` xml
331+
<dependency>
332+
<groupId>redis.clients.authentication</groupId>
333+
<artifactId>redis-authx-entraid</artifactId>
334+
<version>0.1.1-beta1</version>
335+
</dependency>
336+
```
337+
338+
339+
### Step 2 - Create Entra ID enabled credentials provider
340+
The lifecycle of the credentials provider is not managed by the Lettuce client. You can create it once and reuse it across multiple clients\connections. When no longer needed, you should close the provider to release resources `TokenBasedRedisCredentialsProvider#close`.
341+
342+
#### Create Microsoft Entra ID enabled credentials provider
343+
```java
344+
// Entra ID enabled credentials provider for Service Principle Identity with Client Secret
345+
TokenBasedRedisCredentialsProvider credentialsSP;
346+
try ( EntraIDTokenAuthConfigBuilder builder = EntraIDTokenAuthConfigBuilder.builder()) {
347+
builder.clientId(CLIENT_ID)
348+
.secret(CLIENT_SECRET)
349+
.authority(AUTHORITY) // "https://login.microsoftonline.com/{YOUR_TENANT_ID}";
350+
.scopes(SCOPES); // "https://redis.azure.com/.default";
351+
credentialsSP = TokenBasedRedisCredentialsProvider.create(builder.build());
352+
}
353+
```
354+
355+
You can test the credentials provider by obtaining a token.
356+
357+
```java
358+
// Test Entra ID credentials provider can resolve credentials
359+
credentialsSP.resolveCredentials()
360+
.doOnNext(c-> System.out.println(c.getUsername()))
361+
.block();
362+
```
363+
364+
### Step 3 - Enable automatic re-authentication
365+
Microsoft Entra ID tokens have a limited lifetime. Lettuce provides a mechanism to automatically re-authenticate when new credentials are emitted by a `RedisCredentialsProvider`.
366+
```java
367+
// Enable automatic re-authentication
368+
ClientOptions clientOptions = ClientOptions.builder()
369+
.reauthenticateBehavior(ClientOptions.ReauthenticateBehavior.ON_NEW_CREDENTIALS)
370+
.build();
371+
```
372+
373+
### Step 4 - Connect with Entra ID enabled credentials provider
374+
375+
```java
376+
// Use Entra ID credentials provider
377+
RedisURI redisURI = RedisURI.builder()
378+
.withHost(HOST)
379+
.withPort(PORT)
380+
.withAuthentication(credentialsSP).build();
381+
382+
// RedisClient
383+
RedisClient redisClient = RedisClient.create(redisURI1);
384+
redisClient.setOptions(clientOptions);
385+
386+
try {
387+
redisClient.setOptions(clientOptions);
388+
// Connect with Entra ID credentials provider
389+
try (StatefulRedisConnection<String, String> user1 = redisClient.connect(StringCodec.UTF8)) {
390+
System.out.println("Connected to redis as :" + user1.sync().aclWhoami());
391+
System.out.println("Db size :" + user1.sync().dbsize());
392+
}
393+
} finally {
394+
redisClient.shutdown(); // Shutdown Redis client and close connections
395+
credentialsSP.close(); // Shutdown Entra ID Credentials provider
396+
}
397+
```

0 commit comments

Comments
 (0)