Skip to content

Commit dad80ac

Browse files
committed
- release drafter
- make config builders generic - force refresh with managedidentity - skipcache with confidentialclientapp - add builder cloners
1 parent 3860b95 commit dad80ac

File tree

7 files changed

+85
-47
lines changed

7 files changed

+85
-47
lines changed

.github/workflows/release-drafter.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ on:
55
# branches to consider in the event; optional, defaults to all
66
branches:
77
- master
8-
8+
workflow_dispatch:
9+
910
jobs:
1011
update_release_draft:
1112
runs-on: ubuntu-latest

core/src/main/java/redis/clients/authentication/core/TokenAuthConfig.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,42 +23,42 @@ public static Builder builder() {
2323
return new Builder();
2424
}
2525

26-
public static class Builder {
26+
public static class Builder<T extends Builder<T>> {
2727
private IdentityProviderConfig identityProviderConfig;
2828
private int lowerRefreshBoundMillis;
2929
private float expirationRefreshRatio;
3030
private int tokenRequestExecTimeoutInMs;
3131
private int maxAttemptsToRetry;
3232
private int delayInMsToRetry;
3333

34-
public Builder expirationRefreshRatio(float expirationRefreshRatio) {
34+
public T expirationRefreshRatio(float expirationRefreshRatio) {
3535
this.expirationRefreshRatio = expirationRefreshRatio;
36-
return this;
36+
return (T) this;
3737
}
3838

39-
public Builder lowerRefreshBoundMillis(int lowerRefreshBoundMillis) {
39+
public T lowerRefreshBoundMillis(int lowerRefreshBoundMillis) {
4040
this.lowerRefreshBoundMillis = lowerRefreshBoundMillis;
41-
return this;
41+
return (T) this;
4242
}
4343

44-
public Builder tokenRequestExecTimeoutInMs(int tokenRequestExecTimeoutInMs) {
44+
public T tokenRequestExecTimeoutInMs(int tokenRequestExecTimeoutInMs) {
4545
this.tokenRequestExecTimeoutInMs = tokenRequestExecTimeoutInMs;
46-
return this;
46+
return (T) this;
4747
}
4848

49-
public Builder maxAttemptsToRetry(int maxAttemptsToRetry) {
49+
public T maxAttemptsToRetry(int maxAttemptsToRetry) {
5050
this.maxAttemptsToRetry = maxAttemptsToRetry;
51-
return this;
51+
return (T) this;
5252
}
5353

54-
public Builder delayInMsToRetry(int delayInMsToRetry) {
54+
public T delayInMsToRetry(int delayInMsToRetry) {
5555
this.delayInMsToRetry = delayInMsToRetry;
56-
return this;
56+
return (T) this;
5757
}
5858

59-
public Builder identityProviderConfig(IdentityProviderConfig identityProviderConfig) {
59+
public T identityProviderConfig(IdentityProviderConfig identityProviderConfig) {
6060
this.identityProviderConfig = identityProviderConfig;
61-
return this;
61+
return (T) this;
6262
}
6363

6464
public TokenAuthConfig build() {
@@ -67,5 +67,14 @@ public TokenAuthConfig build() {
6767
new TokenManagerConfig.RetryPolicy(maxAttemptsToRetry, delayInMsToRetry)),
6868
identityProviderConfig);
6969
}
70+
71+
public static Builder from(Builder sample) {
72+
return new Builder().expirationRefreshRatio(sample.expirationRefreshRatio)
73+
.lowerRefreshBoundMillis(sample.lowerRefreshBoundMillis)
74+
.tokenRequestExecTimeoutInMs(sample.tokenRequestExecTimeoutInMs)
75+
.maxAttemptsToRetry(sample.maxAttemptsToRetry)
76+
.delayInMsToRetry(sample.delayInMsToRetry)
77+
.identityProviderConfig(sample.identityProviderConfig);
78+
}
7079
}
7180
}

core/src/main/java/redis/clients/authentication/core/TokenManager.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.concurrent.ScheduledFuture;
99
import java.util.concurrent.TimeUnit;
1010
import java.util.concurrent.atomic.AtomicBoolean;
11+
import java.util.concurrent.atomic.AtomicInteger;
1112

1213
import org.slf4j.Logger;
1314
import org.slf4j.LoggerFactory;
@@ -18,12 +19,10 @@ public class TokenManager {
1819
private IdentityProvider identityProvider;
1920
private TokenListener listener;
2021
private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
21-
22-
// TODO: manage thread pool to avoid blocking on IDP hangs
2322
private ExecutorService executor = Executors.newFixedThreadPool(2);
2423
private boolean stopped = false;
2524
private ScheduledFuture<?> scheduledTask;
26-
private int numberOfRetries = 0;
25+
private AtomicInteger numberOfRetries = new AtomicInteger(0);
2726
private Exception lastException;
2827
private Logger logger = LoggerFactory.getLogger(getClass());
2928
private Token currentToken = null;
@@ -86,8 +85,8 @@ protected Token renewToken() {
8685
listener.onTokenRenewed(newToken);
8786
return newToken;
8887
} catch (Exception e) {
89-
if (numberOfRetries < tokenManagerConfig.getRetryPolicy().getMaxAttempts()) {
90-
numberOfRetries++;
88+
if (numberOfRetries.getAndIncrement() < tokenManagerConfig.getRetryPolicy()
89+
.getMaxAttempts()) {
9190
scheduledTask = scheduleNext(tokenManagerConfig.getRetryPolicy().getdelayInMs());
9291
} else {
9392
TokenRequestException tre = new TokenRequestException(unwrap(e), lastException);

entraid/src/main/java/redis/clients/authentication/entraid/EntraIDIdentityProvider.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ public final class EntraIDIdentityProvider implements IdentityProvider {
2020

2121
private Supplier<IAuthenticationResult> resultSupplier;
2222

23-
public EntraIDIdentityProvider(ServicePrincipalInfo servicePrincipalInfo, Set<String> scopes) {
23+
public EntraIDIdentityProvider(ServicePrincipalInfo servicePrincipalInfo, Set<String> scopes,
24+
int timeout) {
2425
IClientCredential credential = getClientCredential(servicePrincipalInfo);
2526
ConfidentialClientApplication app;
2627

@@ -30,20 +31,22 @@ public EntraIDIdentityProvider(ServicePrincipalInfo servicePrincipalInfo, Set<St
3031
: authority;
3132
app = ConfidentialClientApplication
3233
.builder(servicePrincipalInfo.getClientId(), credential).authority(authority)
33-
.build();
34+
.readTimeoutForDefaultHttpClient(timeout).build();
3435
} catch (MalformedURLException e) {
3536
throw new RedisEntraIDException("Failed to init EntraID client!", e);
3637
}
37-
ClientCredentialParameters params = ClientCredentialParameters.builder(scopes).build();
38+
ClientCredentialParameters params = ClientCredentialParameters.builder(scopes)
39+
.skipCache(true).build();
3840

3941
resultSupplier = () -> supplierForConfidentialApp(app, params);
4042
}
4143

42-
public EntraIDIdentityProvider(ManagedIdentityInfo info, Set<String> scopes) {
43-
ManagedIdentityApplication app = ManagedIdentityApplication.builder(info.getId()).build();
44+
public EntraIDIdentityProvider(ManagedIdentityInfo info, Set<String> scopes, int timeout) {
45+
ManagedIdentityApplication app = ManagedIdentityApplication.builder(info.getId())
46+
.readTimeoutForDefaultHttpClient(timeout).build();
4447

4548
ManagedIdentityParameters params = ManagedIdentityParameters
46-
.builder(scopes.iterator().next()).build();
49+
.builder(scopes.iterator().next()).forceRefresh(true).build();
4750
resultSupplier = () -> supplierForManagedIdentityApp(app, params);
4851
}
4952

entraid/src/main/java/redis/clients/authentication/entraid/EntraIDIdentityProviderConfig.java

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88
import redis.clients.authentication.core.IdentityProvider;
99
import redis.clients.authentication.core.IdentityProviderConfig;
1010

11-
public final class EntraIDIdentityProviderConfig implements IdentityProviderConfig, AutoCloseable {
11+
public final class EntraIDIdentityProviderConfig implements IdentityProviderConfig {
1212

13-
private Supplier<IdentityProvider> providerSupplier;
13+
private final Supplier<IdentityProvider> providerSupplier;
1414

15-
public EntraIDIdentityProviderConfig(ServicePrincipalInfo info, Set<String> scopes) {
16-
providerSupplier = () -> new EntraIDIdentityProvider(info, scopes);
15+
public EntraIDIdentityProviderConfig(ServicePrincipalInfo info, Set<String> scopes, int timeout) {
16+
providerSupplier = () -> new EntraIDIdentityProvider(info, scopes, timeout);
1717
}
1818

19-
public EntraIDIdentityProviderConfig(ManagedIdentityInfo info, Set<String> scopes) {
20-
providerSupplier = () -> new EntraIDIdentityProvider(info, scopes);
19+
public EntraIDIdentityProviderConfig(ManagedIdentityInfo info, Set<String> scopes, int timeout) {
20+
providerSupplier = () -> new EntraIDIdentityProvider(info, scopes, timeout);
2121
}
2222

2323
public EntraIDIdentityProviderConfig(
@@ -28,16 +28,6 @@ public EntraIDIdentityProviderConfig(
2828
@Override
2929
public IdentityProvider getProvider() {
3030
IdentityProvider identityProvider = providerSupplier.get();
31-
clear();
3231
return identityProvider;
3332
}
34-
35-
@Override
36-
public void close() throws Exception {
37-
clear();
38-
}
39-
40-
private void clear() {
41-
providerSupplier = null;
42-
}
4333
}

entraid/src/main/java/redis/clients/authentication/entraid/EntraIDTokenAuthConfigBuilder.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
import com.microsoft.aad.msal4j.IAuthenticationResult;
99

1010
import redis.clients.authentication.core.TokenAuthConfig;
11+
import redis.clients.authentication.core.TokenManagerConfig;
1112
import redis.clients.authentication.entraid.ManagedIdentityInfo.UserManagedIdentityType;
1213
import redis.clients.authentication.entraid.ServicePrincipalInfo.ServicePrincipalAccess;
1314

14-
public class EntraIDTokenAuthConfigBuilder extends TokenAuthConfig.Builder
15-
implements AutoCloseable {
15+
public class EntraIDTokenAuthConfigBuilder
16+
extends TokenAuthConfig.Builder<EntraIDTokenAuthConfigBuilder> implements AutoCloseable {
1617
public static final float DEFAULT_EXPIRATION_REFRESH_RATIO = 0.8F;
1718
public static final int DEFAULT_LOWER_REFRESH_BOUND_MILLIS = 2 * 60 * 1000;
1819
public static final int DEFAULT_TOKEN_REQUEST_EXECUTION_TIMEOUT_IN_MS = 1000;
@@ -27,6 +28,7 @@ public class EntraIDTokenAuthConfigBuilder extends TokenAuthConfig.Builder
2728
private Set<String> scopes;
2829
private ServicePrincipalAccess accessWith;
2930
private ManagedIdentityInfo mii;
31+
private int tokenRequestExecTimeoutInMs;
3032
private Supplier<IAuthenticationResult> customEntraIdAuthenticationSupplier;
3133

3234
public EntraIDTokenAuthConfigBuilder() {
@@ -82,6 +84,14 @@ public EntraIDTokenAuthConfigBuilder scopes(Set<String> scopes) {
8284
return this;
8385
}
8486

87+
@Override
88+
public EntraIDTokenAuthConfigBuilder tokenRequestExecTimeoutInMs(
89+
int tokenRequestExecTimeoutInMs) {
90+
super.tokenRequestExecTimeoutInMs(tokenRequestExecTimeoutInMs);
91+
this.tokenRequestExecTimeoutInMs = tokenRequestExecTimeoutInMs;
92+
return this;
93+
}
94+
8595
public TokenAuthConfig build() {
8696
ServicePrincipalInfo spi = null;
8797
if (key != null || cert != null || secret != null) {
@@ -103,10 +113,12 @@ public TokenAuthConfig build() {
103113
"Cannot have both customEntraIdAuthenticationSupplier and ServicePrincipal/ManagedIdentity!");
104114
}
105115
if (spi != null) {
106-
super.identityProviderConfig(new EntraIDIdentityProviderConfig(spi, scopes));
116+
super.identityProviderConfig(
117+
new EntraIDIdentityProviderConfig(spi, scopes, tokenRequestExecTimeoutInMs));
107118
}
108119
if (mii != null) {
109-
super.identityProviderConfig(new EntraIDIdentityProviderConfig(mii, scopes));
120+
super.identityProviderConfig(
121+
new EntraIDIdentityProviderConfig(mii, scopes, tokenRequestExecTimeoutInMs));
110122
}
111123
if (customEntraIdAuthenticationSupplier != null) {
112124
super.identityProviderConfig(
@@ -129,4 +141,28 @@ public void close() throws Exception {
129141
public static EntraIDTokenAuthConfigBuilder builder() {
130142
return new EntraIDTokenAuthConfigBuilder();
131143
}
144+
145+
public static EntraIDTokenAuthConfigBuilder from(EntraIDTokenAuthConfigBuilder sample) {
146+
TokenAuthConfig tokenAuthConfig = TokenAuthConfig.Builder.from(sample).build();
147+
TokenManagerConfig tokenManagerConfig = tokenAuthConfig.getTokenManagerConfig();
148+
149+
EntraIDTokenAuthConfigBuilder builder = (EntraIDTokenAuthConfigBuilder) new EntraIDTokenAuthConfigBuilder()
150+
.expirationRefreshRatio(tokenManagerConfig.getExpirationRefreshRatio())
151+
.lowerRefreshBoundMillis(tokenManagerConfig.getLowerRefreshBoundMillis())
152+
.tokenRequestExecTimeoutInMs(tokenManagerConfig.getTokenRequestExecTimeoutInMs())
153+
.maxAttemptsToRetry(tokenManagerConfig.getRetryPolicy().getMaxAttempts())
154+
.delayInMsToRetry(tokenManagerConfig.getRetryPolicy().getdelayInMs())
155+
.identityProviderConfig(tokenAuthConfig.getIdentityProviderConfig());
156+
157+
builder.accessWith = sample.accessWith;
158+
builder.authority = sample.authority;
159+
builder.cert = sample.cert;
160+
builder.clientId = sample.clientId;
161+
builder.customEntraIdAuthenticationSupplier = sample.customEntraIdAuthenticationSupplier;
162+
builder.key = sample.key;
163+
builder.mii = sample.mii;
164+
builder.scopes = sample.scopes;
165+
builder.secret = sample.secret;
166+
return builder;
167+
}
132168
}

entraid/src/test/java/redis/clients/authentication/EntraIDIntegrationTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public void requestTokenWithSecret() throws MalformedURLException {
1717
testCtx.getClientId(), testCtx.getClientSecret(),
1818
testCtx.getAuthority());
1919
Token token = new EntraIDIdentityProvider(servicePrincipalInfo,
20-
testCtx.getRedisScopes()).requestToken();
20+
testCtx.getRedisScopes(),1000).requestToken();
2121

2222
assertNotNull(token.getValue());
2323
}
@@ -29,7 +29,7 @@ public void requestTokenWithCert() throws MalformedURLException {
2929
testCtx.getClientId(), testCtx.getPrivateKey(), testCtx.getCert(),
3030
testCtx.getAuthority());
3131
Token token = new EntraIDIdentityProvider(servicePrincipalInfo,
32-
testCtx.getRedisScopes()).requestToken();
32+
testCtx.getRedisScopes(),1000).requestToken();
3333
assertNotNull(token.getValue());
3434
}
3535

0 commit comments

Comments
 (0)