Skip to content

Commit b2f84a9

Browse files
authored
Millem/web identity token file stale duration config (#4191)
Allowing configuring the prefetchTime and staleTime on WebIdentityTokenFileCredentialsProvider and session duration
1 parent 157f9eb commit b2f84a9

File tree

5 files changed

+179
-23
lines changed

5 files changed

+179
-23
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"category": "AWS SDK for Java v2",
3+
"contributor": "",
4+
"type": "feature",
5+
"description": "Allowing configuring the prefetchTime and staleTime on WebIdentityTokenFileCredentialsProvider"
6+
}

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/WebIdentityTokenFileCredentialsProvider.java

Lines changed: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.nio.file.Path;
2121
import java.nio.file.Paths;
22+
import java.time.Duration;
2223
import software.amazon.awssdk.annotations.SdkPublicApi;
2324
import software.amazon.awssdk.auth.credentials.internal.WebIdentityCredentialsUtils;
2425
import software.amazon.awssdk.auth.credentials.internal.WebIdentityTokenCredentialProperties;
@@ -31,18 +32,19 @@
3132
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
3233

3334
/**
34-
* A credential provider that will read web identity token file path, aws role arn
35-
* and aws session name from system properties or environment variables for using
36-
* web identity token credentials with STS.
35+
* A credential provider that will read web identity token file path, aws role arn and aws session name from system properties or
36+
* environment variables for using web identity token credentials with STS.
3737
* <p>
38-
* Use of this credentials provider requires the 'sts' module to be on the classpath.
38+
* Use of this credentials provider requires the 'sts' module to be on the classpath.
3939
* </p>
4040
* <p>
41-
* StsWebIdentityTokenFileCredentialsProvider in sts package can be used instead of this class if any one of following is required
42-
*<ul>
41+
* StsWebIdentityTokenFileCredentialsProvider in sts package can be used instead of this class if any one of following is
42+
* required
43+
* <ul>
4344
* <li>Pass a custom StsClient to the provider. </li>
4445
* <li>Periodically update credentials </li>
45-
*</ul>
46+
* </ul>
47+
*
4648
* @see AwsCredentialsProvider
4749
*/
4850
@SdkPublicApi
@@ -62,13 +64,22 @@ public class WebIdentityTokenFileCredentialsProvider
6264

6365
private final Boolean asyncCredentialUpdateEnabled;
6466

67+
private final Duration prefetchTime;
68+
69+
private final Duration staleTime;
70+
71+
private final Duration roleSessionDuration;
72+
6573
private WebIdentityTokenFileCredentialsProvider(BuilderImpl builder) {
6674
AwsCredentialsProvider credentialsProvider = null;
6775
RuntimeException loadException = null;
6876
String roleArn = null;
6977
String roleSessionName = null;
7078
Path webIdentityTokenFile = null;
7179
Boolean asyncCredentialUpdateEnabled = null;
80+
Duration prefetchTime = null;
81+
Duration staleTime = null;
82+
Duration roleSessionDuration = null;
7283

7384
try {
7485
webIdentityTokenFile =
@@ -77,7 +88,7 @@ private WebIdentityTokenFileCredentialsProvider(BuilderImpl builder) {
7788
.getStringValueOrThrow()));
7889

7990
roleArn = builder.roleArn != null ? builder.roleArn
80-
: trim(SdkSystemSetting.AWS_ROLE_ARN.getStringValueOrThrow());
91+
: trim(SdkSystemSetting.AWS_ROLE_ARN.getStringValueOrThrow());
8192

8293
roleSessionName =
8394
builder.roleSessionName != null ? builder.roleSessionName
@@ -86,12 +97,19 @@ private WebIdentityTokenFileCredentialsProvider(BuilderImpl builder) {
8697
asyncCredentialUpdateEnabled =
8798
builder.asyncCredentialUpdateEnabled != null ? builder.asyncCredentialUpdateEnabled : false;
8899

100+
prefetchTime = builder.prefetchTime;
101+
staleTime = builder.staleTime;
102+
roleSessionDuration = builder.roleSessionDuration;
103+
89104
WebIdentityTokenCredentialProperties credentialProperties =
90105
WebIdentityTokenCredentialProperties.builder()
91106
.roleArn(roleArn)
92107
.roleSessionName(roleSessionName)
93108
.webIdentityTokenFile(webIdentityTokenFile)
94109
.asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled)
110+
.prefetchTime(prefetchTime)
111+
.staleTime(staleTime)
112+
.roleSessionDuration(roleSessionDuration)
95113
.build();
96114

97115
credentialsProvider = WebIdentityCredentialsUtils.factory().create(credentialProperties);
@@ -108,10 +126,12 @@ private WebIdentityTokenFileCredentialsProvider(BuilderImpl builder) {
108126
this.roleSessionName = roleSessionName;
109127
this.webIdentityTokenFile = webIdentityTokenFile;
110128
this.asyncCredentialUpdateEnabled = asyncCredentialUpdateEnabled;
129+
this.prefetchTime = prefetchTime;
130+
this.staleTime = staleTime;
131+
this.roleSessionDuration = roleSessionDuration;
111132
}
112133

113134
public static WebIdentityTokenFileCredentialsProvider create() {
114-
115135
return WebIdentityTokenFileCredentialsProvider.builder().build();
116136
}
117137

@@ -165,9 +185,33 @@ public interface Builder extends CopyableBuilder<Builder, WebIdentityTokenFileCr
165185
/**
166186
* Define whether the provider should fetch credentials asynchronously in the background.
167187
*/
168-
169188
Builder asyncCredentialUpdateEnabled(Boolean asyncCredentialUpdateEnabled);
170189

190+
/**
191+
* Configure the amount of time, relative to STS token expiration, that the cached credentials are considered close to
192+
* stale and should be updated.
193+
*
194+
* <p>Prefetch updates will occur between the specified time and the stale time of the provider. Prefetch
195+
* updates may be asynchronous. See {@link #asyncCredentialUpdateEnabled}.
196+
*
197+
* <p>By default, this is 5 minutes.
198+
*/
199+
Builder prefetchTime(Duration prefetchTime);
200+
201+
/**
202+
* Configure the amount of time, relative to STS token expiration, that the cached credentials are considered stale and
203+
* must be updated. All threads will block until the value is updated.
204+
*
205+
* <p>By default, this is 1 minute.
206+
*/
207+
Builder staleTime(Duration staleTime);
208+
209+
/**
210+
* @param sessionDuration
211+
* @return
212+
*/
213+
Builder roleSessionDuration(Duration sessionDuration);
214+
171215
/**
172216
* Create a {@link WebIdentityTokenFileCredentialsProvider} using the configuration applied to this builder.
173217
*/
@@ -179,6 +223,9 @@ static final class BuilderImpl implements Builder {
179223
private String roleSessionName;
180224
private Path webIdentityTokenFile;
181225
private Boolean asyncCredentialUpdateEnabled;
226+
private Duration prefetchTime;
227+
private Duration staleTime;
228+
private Duration roleSessionDuration;
182229

183230
BuilderImpl() {
184231
}
@@ -188,6 +235,9 @@ private BuilderImpl(WebIdentityTokenFileCredentialsProvider provider) {
188235
this.roleSessionName = provider.roleSessionName;
189236
this.webIdentityTokenFile = provider.webIdentityTokenFile;
190237
this.asyncCredentialUpdateEnabled = provider.asyncCredentialUpdateEnabled;
238+
this.prefetchTime = provider.prefetchTime;
239+
this.staleTime = provider.staleTime;
240+
this.roleSessionDuration = provider.roleSessionDuration;
191241
}
192242

193243
@Override
@@ -230,6 +280,36 @@ public void setAsyncCredentialUpdateEnabled(Boolean asyncCredentialUpdateEnabled
230280
asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled);
231281
}
232282

283+
@Override
284+
public Builder prefetchTime(Duration prefetchTime) {
285+
this.prefetchTime = prefetchTime;
286+
return this;
287+
}
288+
289+
public void setPrefetchTime(Duration prefetchTime) {
290+
prefetchTime(prefetchTime);
291+
}
292+
293+
@Override
294+
public Builder staleTime(Duration staleTime) {
295+
this.staleTime = staleTime;
296+
return this;
297+
}
298+
299+
public void setStaleTime(Duration staleTime) {
300+
staleTime(staleTime);
301+
}
302+
303+
@Override
304+
public Builder roleSessionDuration(Duration sessionDuration) {
305+
this.roleSessionDuration = sessionDuration;
306+
return this;
307+
}
308+
309+
public void setRoleSessionDuration(Duration roleSessionDuration) {
310+
roleSessionDuration(roleSessionDuration);
311+
}
312+
233313
@Override
234314
public WebIdentityTokenFileCredentialsProvider build() {
235315
return new WebIdentityTokenFileCredentialsProvider(this);

core/auth/src/main/java/software/amazon/awssdk/auth/credentials/internal/WebIdentityTokenCredentialProperties.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package software.amazon.awssdk.auth.credentials.internal;
1717

1818
import java.nio.file.Path;
19+
import java.time.Duration;
1920
import software.amazon.awssdk.annotations.SdkProtectedApi;
2021

2122
/**
@@ -28,12 +29,18 @@ public class WebIdentityTokenCredentialProperties {
2829
private final String roleSessionName;
2930
private final Path webIdentityTokenFile;
3031
private final Boolean asyncCredentialUpdateEnabled;
32+
private final Duration prefetchTime;
33+
private final Duration staleTime;
34+
private final Duration roleSessionDuration;
3135

3236
private WebIdentityTokenCredentialProperties(Builder builder) {
3337
this.roleArn = builder.roleArn;
3438
this.roleSessionName = builder.roleSessionName;
3539
this.webIdentityTokenFile = builder.webIdentityTokenFile;
3640
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
41+
this.prefetchTime = builder.prefetchTime;
42+
this.staleTime = builder.staleTime;
43+
this.roleSessionDuration = builder.roleSessionDuration;
3744
}
3845

3946
public String roleArn() {
@@ -52,6 +59,18 @@ public Boolean asyncCredentialUpdateEnabled() {
5259
return asyncCredentialUpdateEnabled;
5360
}
5461

62+
public Duration prefetchTime() {
63+
return prefetchTime;
64+
}
65+
66+
public Duration staleTime() {
67+
return staleTime;
68+
}
69+
70+
public Duration roleSessionDuration() {
71+
return this.roleSessionDuration;
72+
}
73+
5574
public static Builder builder() {
5675
return new Builder();
5776
}
@@ -61,6 +80,9 @@ public static final class Builder {
6180
private String roleSessionName;
6281
private Path webIdentityTokenFile;
6382
private Boolean asyncCredentialUpdateEnabled;
83+
private Duration prefetchTime;
84+
private Duration staleTime;
85+
private Duration roleSessionDuration;
6486

6587
public Builder roleArn(String roleArn) {
6688
this.roleArn = roleArn;
@@ -82,6 +104,21 @@ public Builder asyncCredentialUpdateEnabled(Boolean asyncCredentialUpdateEnabled
82104
return this;
83105
}
84106

107+
public Builder prefetchTime(Duration prefetchTime) {
108+
this.prefetchTime = prefetchTime;
109+
return this;
110+
}
111+
112+
public Builder staleTime(Duration staleTime) {
113+
this.staleTime = staleTime;
114+
return this;
115+
}
116+
117+
public Builder roleSessionDuration(Duration roleSessionDuration) {
118+
this.roleSessionDuration = roleSessionDuration;
119+
return this;
120+
}
121+
85122
public WebIdentityTokenCredentialProperties build() {
86123
return new WebIdentityTokenCredentialProperties(this);
87124
}

services/sts/src/main/java/software/amazon/awssdk/services/sts/internal/StsWebIdentityCredentialsProviderFactory.java

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,12 @@
3333
import software.amazon.awssdk.services.sts.model.AssumeRoleWithWebIdentityRequest;
3434
import software.amazon.awssdk.services.sts.model.IdpCommunicationErrorException;
3535
import software.amazon.awssdk.utils.IoUtils;
36+
import software.amazon.awssdk.utils.NumericUtils;
3637
import software.amazon.awssdk.utils.SdkAutoCloseable;
3738

3839
/**
39-
* An implementation of {@link WebIdentityTokenCredentialsProviderFactory} that allows users to assume a role
40-
* using a web identity token file specified in either a {@link Profile} or environment variables.
40+
* An implementation of {@link WebIdentityTokenCredentialsProviderFactory} that allows users to assume a role using a web identity
41+
* token file specified in either a {@link Profile} or environment variables.
4142
*/
4243
@SdkProtectedApi
4344
public final class StsWebIdentityCredentialsProviderFactory implements WebIdentityTokenCredentialsProviderFactory {
@@ -72,23 +73,35 @@ private StsWebIdentityCredentialsProvider(WebIdentityTokenCredentialProperties c
7273
.overrideConfiguration(o -> o.retryPolicy(r -> r.retryCondition(retryCondition)))
7374
.build();
7475

75-
AssumeRoleWithWebIdentityRequest request = AssumeRoleWithWebIdentityRequest.builder()
76-
.roleArn(credentialProperties.roleArn())
77-
.roleSessionName(sessionName)
78-
.build();
76+
AssumeRoleWithWebIdentityRequest.Builder requestBuilder = AssumeRoleWithWebIdentityRequest
77+
.builder()
78+
.roleArn(credentialProperties.roleArn())
79+
.roleSessionName(sessionName);
80+
81+
if (credentialProperties.roleSessionDuration() != null) {
82+
requestBuilder.durationSeconds(NumericUtils.saturatedCast(
83+
credentialProperties.roleSessionDuration().getSeconds()));
84+
}
7985

8086
AssumeRoleWithWebIdentityRequestSupplier supplier =
8187
AssumeRoleWithWebIdentityRequestSupplier.builder()
82-
.assumeRoleWithWebIdentityRequest(request)
88+
.assumeRoleWithWebIdentityRequest(requestBuilder.build())
8389
.webIdentityTokenFile(credentialProperties.webIdentityTokenFile())
8490
.build();
8591

86-
this.credentialsProvider =
92+
StsAssumeRoleWithWebIdentityCredentialsProvider.Builder builder =
8793
StsAssumeRoleWithWebIdentityCredentialsProvider.builder()
8894
.asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled)
8995
.stsClient(stsClient)
90-
.refreshRequest(supplier)
91-
.build();
96+
.refreshRequest(supplier);
97+
98+
if (credentialProperties.prefetchTime() != null) {
99+
builder.prefetchTime(credentialProperties.prefetchTime());
100+
}
101+
if (credentialProperties.staleTime() != null) {
102+
builder.staleTime(credentialProperties.staleTime());
103+
}
104+
this.credentialsProvider = builder.build();
92105
}
93106

94107
@Override

services/sts/src/test/java/software/amazon/awssdk/services/sts/internal/StsWebIdentityCredentialsProviderFactoryTest.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,37 @@
1717

1818
import static org.junit.jupiter.api.Assertions.assertNotNull;
1919

20+
import java.nio.file.Paths;
21+
import java.time.Duration;
2022
import org.junit.jupiter.api.Test;
23+
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
2124
import software.amazon.awssdk.auth.credentials.WebIdentityTokenCredentialsProviderFactory;
2225
import software.amazon.awssdk.auth.credentials.internal.WebIdentityCredentialsUtils;
26+
import software.amazon.awssdk.auth.credentials.internal.WebIdentityTokenCredentialProperties;
2327

24-
public class StsWebIdentityCredentialsProviderFactoryTest {
25-
28+
class StsWebIdentityCredentialsProviderFactoryTest {
2629

2730
@Test
28-
public void stsWebIdentityCredentialsProviderFactory_with_webIdentityCredentialsUtils() {
31+
void stsWebIdentityCredentialsProviderFactory_with_webIdentityCredentialsUtils() {
2932
WebIdentityTokenCredentialsProviderFactory factory = WebIdentityCredentialsUtils.factory();
3033
assertNotNull(factory);
3134
}
3235

36+
@Test
37+
void stsWebIdentityCredentialsProviderFactory_withWebIdentityTokenCredentialProperties() {
38+
WebIdentityTokenCredentialsProviderFactory factory = new StsWebIdentityCredentialsProviderFactory();
39+
AwsCredentialsProvider provider = factory.create(
40+
WebIdentityTokenCredentialProperties.builder()
41+
.asyncCredentialUpdateEnabled(true)
42+
.prefetchTime(Duration.ofMinutes(5))
43+
.staleTime(Duration.ofMinutes(15))
44+
.roleArn("role-arn")
45+
.webIdentityTokenFile(Paths.get("/path/to/file"))
46+
.roleSessionName("session-name")
47+
.roleSessionDuration(Duration.ofMinutes(60))
48+
.build());
49+
assertNotNull(provider);
50+
51+
}
52+
3353
}

0 commit comments

Comments
 (0)