From 4c38871e3f1304ab20b08c0f243cfe95e2e6f9cf Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Tue, 30 Dec 2025 10:39:02 -0800 Subject: [PATCH 1/7] Fix sts web identity provider not respecting prefetch time and stale time --- ...bIdentityTokenFileCredentialsProvider.java | 13 ++-- ...ebIdentityTokenCredentialProviderTest.java | 67 +++++++++++++++++++ 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java index cf853fd9a5bf..bba0c7d89a5c 100644 --- a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java +++ b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java @@ -106,11 +106,16 @@ private StsWebIdentityTokenFileCredentialsProvider(Builder builder) { .assumeRoleWithWebIdentityRequest(assumeRoleWithWebIdentityRequest.get()) .webIdentityTokenFile(credentialProperties.webIdentityTokenFile()) .build(); - credentialsProviderLocal = + + StsAssumeRoleWithWebIdentityCredentialsProvider.Builder internalBuilder = StsAssumeRoleWithWebIdentityCredentialsProvider.builder() .stsClient(builder.stsClient) - .refreshRequest(supplier) - .build(); + .refreshRequest(supplier); + + internalBuilder.staleTime(this.staleTime()) + .prefetchTime(this.prefetchTime()); + + credentialsProviderLocal = internalBuilder.build(); } catch (RuntimeException e) { // If we couldn't load the credentials provider for some reason, save an exception describing why. This exception // will only be raised on calls to getCredentials. We don't want to raise an exception here because it may be @@ -181,7 +186,7 @@ private Builder() { } private Builder(StsWebIdentityTokenFileCredentialsProvider provider) { - super(StsWebIdentityTokenFileCredentialsProvider::new); + super(StsWebIdentityTokenFileCredentialsProvider::new, provider); this.roleArn = provider.roleArn; this.roleSessionName = provider.roleSessionName; this.webIdentityTokenFile = provider.webIdentityTokenFile; diff --git a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java index adfa9e4a8fd9..0dc2d777f3d4 100644 --- a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java +++ b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java @@ -30,10 +30,12 @@ import software.amazon.awssdk.services.sts.model.Credentials; import java.nio.file.Paths; +import java.time.Duration; import java.time.Instant; import software.amazon.awssdk.testutils.EnvironmentVariableHelper; import static org.mockito.Mockito.when; +import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(MockitoExtension.class) class StsWebIdentityTokenCredentialProviderTest { @@ -57,6 +59,18 @@ public void cleanUp(){ ENVIRONMENT_VARIABLE_HELPER.reset(); } + private void mockStsClientResponse(Instant expiration) { + when(stsClient.assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class))) + .thenReturn(AssumeRoleWithWebIdentityResponse.builder() + .credentials(Credentials.builder() + .accessKeyId("key") + .expiration(expiration) + .sessionToken("session") + .secretAccessKey("secret") + .build()) + .build()); + } + @Test void createAssumeRoleWithWebIdentityTokenCredentialsProviderWithoutStsClient_throws_Exception() { @@ -111,4 +125,57 @@ void createAssumeRoleWithWebIdentityTokenCredentialsProvider_raisesInResolveCred // exception should be raised lazily when resolving credentials, not at creation time. Assert.assertThrows(IllegalStateException.class, provider::resolveCredentials); } + + @Test + void prefetchTimeAndStaleTime_withCustomConfiguration_shouldReturnConfiguredValues() { + mockStsClientResponse(Instant.now().plusSeconds(3600)); + + StsWebIdentityTokenFileCredentialsProvider provider = + StsWebIdentityTokenFileCredentialsProvider.builder() + .stsClient(stsClient) + .prefetchTime(Duration.ofMinutes(10)) + .staleTime(Duration.ofMinutes(2)) + .build(); + + provider.resolveCredentials(); + + assertThat(provider.prefetchTime()).isEqualTo(Duration.ofMinutes(10)); + assertThat(provider.staleTime()).isEqualTo(Duration.ofMinutes(2)); + + } + + @Test + void prefetchTimeAndStaleTime_withoutConfiguration_shouldReturnDefaultValues() { + mockStsClientResponse(Instant.now().plusSeconds(3600)); + + StsWebIdentityTokenFileCredentialsProvider provider = + StsWebIdentityTokenFileCredentialsProvider.builder() + .stsClient(stsClient) + .build(); + + + provider.resolveCredentials(); + + assertThat(provider.prefetchTime()).isEqualTo(Duration.ofMinutes(5)); + assertThat(provider.staleTime()).isEqualTo(Duration.ofMinutes(1)); + } + + @Test + void toBuilder_withTimingConfiguration_shouldPreserveConfiguration() { + mockStsClientResponse(Instant.now().plusSeconds(3600)); + StsWebIdentityTokenFileCredentialsProvider originalProvider = + StsWebIdentityTokenFileCredentialsProvider.builder() + .stsClient(stsClient) + .prefetchTime(Duration.ofMinutes(8)) + .staleTime(Duration.ofMinutes(3)) + .build(); + + + StsWebIdentityTokenFileCredentialsProvider copiedProvider = originalProvider.toBuilder().build(); + + copiedProvider.resolveCredentials(); + + assertThat(copiedProvider.prefetchTime()).isEqualTo(Duration.ofMinutes(8)); + assertThat(copiedProvider.staleTime()).isEqualTo(Duration.ofMinutes(3)); + } } \ No newline at end of file From e6441349c373eb8dce1a49b92b1a22cd5a47f711 Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Wed, 31 Dec 2025 09:33:20 -0800 Subject: [PATCH 2/7] Adding additional tests --- .../sts/auth/StsCredentialsProvider.java | 7 ++ ...bIdentityTokenFileCredentialsProvider.java | 3 +- ...ebIdentityTokenCredentialProviderTest.java | 104 +++++++++++++----- 3 files changed, 86 insertions(+), 28 deletions(-) diff --git a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java index e19a6bf4b9f6..0fbb873968b7 100644 --- a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java +++ b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java @@ -131,6 +131,13 @@ public Duration prefetchTime() { return prefetchTime; } + /** + * Whether the provider should fetch credentials asynchronously in the background. + */ + public Boolean asyncCredentialUpdateEnabled() { + return asyncCredentialUpdateEnabled; + } + @Override public String toString() { return ToString.create(providerName()); diff --git a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java index bba0c7d89a5c..effaa2215da5 100644 --- a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java +++ b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java @@ -113,7 +113,8 @@ private StsWebIdentityTokenFileCredentialsProvider(Builder builder) { .refreshRequest(supplier); internalBuilder.staleTime(this.staleTime()) - .prefetchTime(this.prefetchTime()); + .prefetchTime(this.prefetchTime()) + .asyncCredentialUpdateEnabled(this.asyncCredentialUpdateEnabled()); credentialsProviderLocal = internalBuilder.build(); } catch (RuntimeException e) { diff --git a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java index 0dc2d777f3d4..c8098cb1aaaf 100644 --- a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java +++ b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java @@ -27,6 +27,7 @@ import software.amazon.awssdk.services.sts.StsClient; import software.amazon.awssdk.services.sts.model.AssumeRoleWithWebIdentityRequest; import software.amazon.awssdk.services.sts.model.AssumeRoleWithWebIdentityResponse; +import software.amazon.awssdk.services.sts.model.AssumedRoleUser; import software.amazon.awssdk.services.sts.model.Credentials; import java.nio.file.Paths; @@ -127,55 +128,104 @@ void createAssumeRoleWithWebIdentityTokenCredentialsProvider_raisesInResolveCred } @Test - void prefetchTimeAndStaleTime_withCustomConfiguration_shouldReturnConfiguredValues() { - mockStsClientResponse(Instant.now().plusSeconds(3600)); + void customPrefetchTime_actuallyTriggersRefreshEarly() throws InterruptedException { + Instant tokenExpiration = Instant.now().plusSeconds(8); + Duration customPrefetchTime = Duration.ofSeconds(2); + Duration customStaleTime = Duration.ofSeconds(1); + + when(stsClient.assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class))) + .thenReturn(AssumeRoleWithWebIdentityResponse.builder() + .credentials(Credentials.builder() + .accessKeyId("key1") + .secretAccessKey("secret1") + .sessionToken("session1") + .expiration(tokenExpiration) + .build()) + .assumedRoleUser(AssumedRoleUser.builder() + .arn("arn:aws:iam::123456789012:role/test-role") + .assumedRoleId("role:session") + .build()) + .build()) + + .thenReturn(AssumeRoleWithWebIdentityResponse.builder() + .credentials(Credentials.builder() + .accessKeyId("key2") + .secretAccessKey("secret2") + .sessionToken("session2") + .expiration(Instant.now().plusSeconds(8)) + .build()) + .assumedRoleUser(AssumedRoleUser.builder() + .arn("arn:aws:iam::123456789012:role/test-role") + .assumedRoleId("role:session") + .build()) + .build()); + StsWebIdentityTokenFileCredentialsProvider provider = StsWebIdentityTokenFileCredentialsProvider.builder() .stsClient(stsClient) - .prefetchTime(Duration.ofMinutes(10)) - .staleTime(Duration.ofMinutes(2)) + .asyncCredentialUpdateEnabled(true) + .prefetchTime(customPrefetchTime) + .staleTime(customStaleTime) .build(); - provider.resolveCredentials(); - - assertThat(provider.prefetchTime()).isEqualTo(Duration.ofMinutes(10)); - assertThat(provider.staleTime()).isEqualTo(Duration.ofMinutes(2)); + try { + assertThat(provider.prefetchTime()).isEqualTo(customPrefetchTime); + assertThat(provider.staleTime()).isEqualTo(customStaleTime); + + provider.resolveCredentials(); + Mockito.verify(stsClient, Mockito.times(1)).assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class)); + + // Wait 7 seconds to ensure prefetch completes + Thread.sleep(7_000); + Mockito.verify(stsClient, Mockito.times(2)).assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class)); + } finally { + provider.close(); + } } @Test - void prefetchTimeAndStaleTime_withoutConfiguration_shouldReturnDefaultValues() { - mockStsClientResponse(Instant.now().plusSeconds(3600)); - + void defaultTiming_usesStandardValues() { StsWebIdentityTokenFileCredentialsProvider provider = StsWebIdentityTokenFileCredentialsProvider.builder() .stsClient(stsClient) .build(); - - provider.resolveCredentials(); - - assertThat(provider.prefetchTime()).isEqualTo(Duration.ofMinutes(5)); - assertThat(provider.staleTime()).isEqualTo(Duration.ofMinutes(1)); + try { + assertThat(provider.prefetchTime()).isEqualTo(Duration.ofMinutes(5)); + assertThat(provider.staleTime()).isEqualTo(Duration.ofMinutes(1)); + } finally { + provider.close(); + } } @Test - void toBuilder_withTimingConfiguration_shouldPreserveConfiguration() { - mockStsClientResponse(Instant.now().plusSeconds(3600)); + void toBuilder_preservesCustomTimingConfiguration() { + Duration customPrefetch = Duration.ofMinutes(10); + Duration customStale = Duration.ofMinutes(3); + StsWebIdentityTokenFileCredentialsProvider originalProvider = StsWebIdentityTokenFileCredentialsProvider.builder() .stsClient(stsClient) - .prefetchTime(Duration.ofMinutes(8)) - .staleTime(Duration.ofMinutes(3)) + .prefetchTime(customPrefetch) + .staleTime(customStale) .build(); - - StsWebIdentityTokenFileCredentialsProvider copiedProvider = originalProvider.toBuilder().build(); - - copiedProvider.resolveCredentials(); - - assertThat(copiedProvider.prefetchTime()).isEqualTo(Duration.ofMinutes(8)); - assertThat(copiedProvider.staleTime()).isEqualTo(Duration.ofMinutes(3)); + try { + assertThat(originalProvider.prefetchTime()).isEqualTo(customPrefetch); + assertThat(originalProvider.staleTime()).isEqualTo(customStale); + + StsWebIdentityTokenFileCredentialsProvider copiedProvider = originalProvider.toBuilder().build(); + + try { + assertThat(copiedProvider.prefetchTime()).isEqualTo(customPrefetch); + assertThat(copiedProvider.staleTime()).isEqualTo(customStale); + } finally { + copiedProvider.close(); + } + } finally { + originalProvider.close(); + } } } \ No newline at end of file From b1e090952ffbae28eee5c82a9b7a636c4302392d Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Wed, 31 Dec 2025 09:51:13 -0800 Subject: [PATCH 3/7] Fix failed test --- ...WebIdentityTokenCredentialProviderTest.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java index c8098cb1aaaf..45915a11ec7c 100644 --- a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java +++ b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java @@ -60,18 +60,6 @@ public void cleanUp(){ ENVIRONMENT_VARIABLE_HELPER.reset(); } - private void mockStsClientResponse(Instant expiration) { - when(stsClient.assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class))) - .thenReturn(AssumeRoleWithWebIdentityResponse.builder() - .credentials(Credentials.builder() - .accessKeyId("key") - .expiration(expiration) - .sessionToken("session") - .secretAccessKey("secret") - .build()) - .build()); - } - @Test void createAssumeRoleWithWebIdentityTokenCredentialsProviderWithoutStsClient_throws_Exception() { @@ -100,9 +88,9 @@ void createAssumeRoleWithWebIdentityTokenCredentialsProviderStsClientBuilder() { StsWebIdentityTokenFileCredentialsProvider provider = StsWebIdentityTokenFileCredentialsProvider.builder().stsClient(stsClient) .refreshRequest(r -> r.build()) - .roleArn("someRole") + .roleArn("someTestRole") .webIdentityTokenFile(Paths.get(webIdentityTokenPath)) - .roleSessionName("tempRoleSession") + .roleSessionName("RoleSessionTemp") .build(); when(stsClient.assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class))) .thenReturn(AssumeRoleWithWebIdentityResponse.builder() @@ -129,6 +117,8 @@ void createAssumeRoleWithWebIdentityTokenCredentialsProvider_raisesInResolveCred @Test void customPrefetchTime_actuallyTriggersRefreshEarly() throws InterruptedException { + Mockito.reset(stsClient); + Instant tokenExpiration = Instant.now().plusSeconds(8); Duration customPrefetchTime = Duration.ofSeconds(2); Duration customStaleTime = Duration.ofSeconds(1); From da8fed47fecaa1f80d0bd3b175710c9b2b0df898 Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Wed, 31 Dec 2025 10:17:09 -0800 Subject: [PATCH 4/7] Add changelog --- .changes/next-release/bugfix-AWSSTS-bc7dfee.json | 6 ++++++ .../sts/auth/StsWebIdentityTokenCredentialProviderTest.java | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 .changes/next-release/bugfix-AWSSTS-bc7dfee.json diff --git a/.changes/next-release/bugfix-AWSSTS-bc7dfee.json b/.changes/next-release/bugfix-AWSSTS-bc7dfee.json new file mode 100644 index 000000000000..a13984403e22 --- /dev/null +++ b/.changes/next-release/bugfix-AWSSTS-bc7dfee.json @@ -0,0 +1,6 @@ +{ + "type": "bugfix", + "category": "AWS STS", + "contributor": "", + "description": "Fix `StsWebIdentityTokenFileCredentialsProvider` not respecting custom `prefetchTime` and `staleTime` configurations." +} diff --git a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java index 45915a11ec7c..8fad12f25b90 100644 --- a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java +++ b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java @@ -88,9 +88,9 @@ void createAssumeRoleWithWebIdentityTokenCredentialsProviderStsClientBuilder() { StsWebIdentityTokenFileCredentialsProvider provider = StsWebIdentityTokenFileCredentialsProvider.builder().stsClient(stsClient) .refreshRequest(r -> r.build()) - .roleArn("someTestRole") + .roleArn("someRole") .webIdentityTokenFile(Paths.get(webIdentityTokenPath)) - .roleSessionName("RoleSessionTemp") + .roleSessionName("tempRoleSession") .build(); when(stsClient.assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class))) .thenReturn(AssumeRoleWithWebIdentityResponse.builder() From ef70dc60af91a00f4bb6e6e984dd31a421cb8fc9 Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Wed, 31 Dec 2025 12:06:23 -0800 Subject: [PATCH 5/7] Address PR feedback --- .../services/sts/auth/StsCredentialsProvider.java | 1 + ...StsWebIdentityTokenFileCredentialsProvider.java | 14 ++++++-------- .../StsWebIdentityTokenCredentialProviderTest.java | 6 +++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java index 0fbb873968b7..636f97ff6b63 100644 --- a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java +++ b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java @@ -133,6 +133,7 @@ public Duration prefetchTime() { /** * Whether the provider should fetch credentials asynchronously in the background. + *

By default, this is false.

*/ public Boolean asyncCredentialUpdateEnabled() { return asyncCredentialUpdateEnabled; diff --git a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java index effaa2215da5..07ffe290c7bc 100644 --- a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java +++ b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java @@ -107,16 +107,14 @@ private StsWebIdentityTokenFileCredentialsProvider(Builder builder) { .webIdentityTokenFile(credentialProperties.webIdentityTokenFile()) .build(); - StsAssumeRoleWithWebIdentityCredentialsProvider.Builder internalBuilder = + credentialsProviderLocal = StsAssumeRoleWithWebIdentityCredentialsProvider.builder() .stsClient(builder.stsClient) - .refreshRequest(supplier); - - internalBuilder.staleTime(this.staleTime()) - .prefetchTime(this.prefetchTime()) - .asyncCredentialUpdateEnabled(this.asyncCredentialUpdateEnabled()); - - credentialsProviderLocal = internalBuilder.build(); + .refreshRequest(supplier) + .staleTime(this.staleTime()) + .prefetchTime(this.prefetchTime()) + .asyncCredentialUpdateEnabled(this.asyncCredentialUpdateEnabled()) + .build(); } catch (RuntimeException e) { // If we couldn't load the credentials provider for some reason, save an exception describing why. This exception // will only be raised on calls to getCredentials. We don't want to raise an exception here because it may be diff --git a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java index 8fad12f25b90..dcbbcd6b8ab4 100644 --- a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java +++ b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java @@ -119,7 +119,7 @@ void createAssumeRoleWithWebIdentityTokenCredentialsProvider_raisesInResolveCred void customPrefetchTime_actuallyTriggersRefreshEarly() throws InterruptedException { Mockito.reset(stsClient); - Instant tokenExpiration = Instant.now().plusSeconds(8); + Instant tokenExpiration = Instant.now().plusSeconds(5); Duration customPrefetchTime = Duration.ofSeconds(2); Duration customStaleTime = Duration.ofSeconds(1); @@ -166,8 +166,8 @@ void customPrefetchTime_actuallyTriggersRefreshEarly() throws InterruptedExcepti provider.resolveCredentials(); Mockito.verify(stsClient, Mockito.times(1)).assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class)); - // Wait 7 seconds to ensure prefetch completes - Thread.sleep(7_000); + // Wait 4 seconds to ensure prefetch completes + Thread.sleep(4_000); Mockito.verify(stsClient, Mockito.times(2)).assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class)); } finally { From ae5ff205c9ff15b134a80811794b58ba69c2c13b Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Mon, 5 Jan 2026 14:12:15 -0800 Subject: [PATCH 6/7] Change wait buffer to to reduce test flakiness --- .../sts/auth/StsWebIdentityTokenCredentialProviderTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java index dcbbcd6b8ab4..058eff163eff 100644 --- a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java +++ b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenCredentialProviderTest.java @@ -166,8 +166,8 @@ void customPrefetchTime_actuallyTriggersRefreshEarly() throws InterruptedExcepti provider.resolveCredentials(); Mockito.verify(stsClient, Mockito.times(1)).assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class)); - // Wait 4 seconds to ensure prefetch completes - Thread.sleep(4_000); + // Wait 5 seconds to ensure prefetch completes + Thread.sleep(5_000); Mockito.verify(stsClient, Mockito.times(2)).assumeRoleWithWebIdentity(Mockito.any(AssumeRoleWithWebIdentityRequest.class)); } finally { From 913f6c041be8124fce1c38f1adb25e7e7f294bea Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Fri, 9 Jan 2026 10:24:41 -0800 Subject: [PATCH 7/7] Add asyncCredentialUpdateEnabled getter in builder --- .../sts/auth/StsCredentialsProvider.java | 16 ++++++++-------- ...sWebIdentityTokenFileCredentialsProvider.java | 12 ++++++++---- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java index 636f97ff6b63..74ebc39c664e 100644 --- a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java +++ b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProvider.java @@ -131,14 +131,6 @@ public Duration prefetchTime() { return prefetchTime; } - /** - * Whether the provider should fetch credentials asynchronously in the background. - *

By default, this is false.

- */ - public Boolean asyncCredentialUpdateEnabled() { - return asyncCredentialUpdateEnabled; - } - @Override public String toString() { return ToString.create(providerName()); @@ -238,5 +230,13 @@ public B prefetchTime(Duration prefetchTime) { public T build() { return providerConstructor.apply((B) this); } + + /** + * Whether the provider should fetch credentials asynchronously in the background. + *

By default, this is false.

+ */ + Boolean asyncCredentialUpdateEnabled() { + return asyncCredentialUpdateEnabled; + } } } diff --git a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java index 07ffe290c7bc..389f4415bdd9 100644 --- a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java +++ b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsWebIdentityTokenFileCredentialsProvider.java @@ -107,14 +107,18 @@ private StsWebIdentityTokenFileCredentialsProvider(Builder builder) { .webIdentityTokenFile(credentialProperties.webIdentityTokenFile()) .build(); - credentialsProviderLocal = + StsAssumeRoleWithWebIdentityCredentialsProvider.Builder providerBuilder = StsAssumeRoleWithWebIdentityCredentialsProvider.builder() .stsClient(builder.stsClient) .refreshRequest(supplier) .staleTime(this.staleTime()) - .prefetchTime(this.prefetchTime()) - .asyncCredentialUpdateEnabled(this.asyncCredentialUpdateEnabled()) - .build(); + .prefetchTime(this.prefetchTime()); + + if (builder.asyncCredentialUpdateEnabled() != null) { + providerBuilder.asyncCredentialUpdateEnabled(builder.asyncCredentialUpdateEnabled()); + } + + credentialsProviderLocal = providerBuilder.build(); } catch (RuntimeException e) { // If we couldn't load the credentials provider for some reason, save an exception describing why. This exception // will only be raised on calls to getCredentials. We don't want to raise an exception here because it may be