Skip to content

Commit 192c33f

Browse files
committed
Cleanups and fixes
1 parent bc4ac1e commit 192c33f

22 files changed

Lines changed: 492 additions & 1095 deletions

File tree

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,11 @@ public AwsCredentials resolveCredentials() {
132132
}
133133

134134
@Override
135-
@SuppressWarnings("unchecked")
136135
public CompletableFuture<Void> invalidate(AwsCredentialsIdentity identity) {
137136
CompletableFuture<?>[] futures = credentialsProviders.stream()
138137
.map(provider -> {
139138
try {
140-
return ((IdentityProvider<AwsCredentialsIdentity>) provider)
141-
.invalidate(identity)
139+
return invalidateProvider(provider, identity)
142140
.exceptionally(e -> {
143141
log.debug(() -> "Failed to invalidate provider " + provider + ": " + e.getMessage(), e);
144142
return null;
@@ -152,6 +150,17 @@ public CompletableFuture<Void> invalidate(AwsCredentialsIdentity identity) {
152150
return CompletableFuture.allOf(futures);
153151
}
154152

153+
/**
154+
* Helper to call invalidate with proper type capture, avoiding unchecked casts.
155+
* The identity is always an {@code AwsCredentialsIdentity}, and all providers in this chain
156+
* are {@code IdentityProvider<? extends AwsCredentialsIdentity>}, so the cast is safe.
157+
*/
158+
@SuppressWarnings("unchecked")
159+
private static <T extends AwsCredentialsIdentity> CompletableFuture<Void> invalidateProvider(
160+
IdentityProvider<T> provider, AwsCredentialsIdentity identity) {
161+
return provider.invalidate((T) identity);
162+
}
163+
155164
@Override
156165
public void close() {
157166
credentialsProviders.forEach(c -> IoUtils.closeIfCloseable(c, null));

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import java.util.function.Predicate;
3939
import software.amazon.awssdk.annotations.SdkPublicApi;
4040
import software.amazon.awssdk.auth.credentials.internal.ContainerCredentialsRetryPolicy;
41-
import software.amazon.awssdk.auth.credentials.internal.CredentialsInvalidationUtils;
4241
import software.amazon.awssdk.auth.credentials.internal.HttpCredentialsLoader;
4342
import software.amazon.awssdk.auth.credentials.internal.HttpCredentialsLoader.LoadedCredentials;
4443
import software.amazon.awssdk.core.SdkSystemSetting;
@@ -191,8 +190,10 @@ public AwsCredentials resolveCredentials() {
191190

192191
@Override
193192
public CompletableFuture<Void> invalidate(AwsCredentialsIdentity identity) {
194-
return CredentialsInvalidationUtils.invalidateCredentialsCache(
195-
identity, credentialsCache, AwsCredentialsIdentity::accessKeyId);
193+
String rejectedAccessKeyId = identity.accessKeyId();
194+
return CompletableFuture.runAsync(() ->
195+
credentialsCache.invalidate(cachedCreds -> rejectedAccessKeyId.equals(cachedCreds.accessKeyId()))
196+
);
196197
}
197198

198199
@Override

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import java.util.function.Supplier;
3131
import software.amazon.awssdk.annotations.SdkPublicApi;
3232
import software.amazon.awssdk.annotations.SdkTestInternalApi;
33-
import software.amazon.awssdk.auth.credentials.internal.CredentialsInvalidationUtils;
3433
import software.amazon.awssdk.auth.credentials.internal.Ec2MetadataConfigProvider;
3534
import software.amazon.awssdk.auth.credentials.internal.HttpCredentialsLoader;
3635
import software.amazon.awssdk.auth.credentials.internal.HttpCredentialsLoader.LoadedCredentials;
@@ -172,8 +171,10 @@ public AwsCredentials resolveCredentials() {
172171

173172
@Override
174173
public CompletableFuture<Void> invalidate(AwsCredentialsIdentity identity) {
175-
return CredentialsInvalidationUtils.invalidateCredentialsCache(
176-
identity, credentialsCache, AwsCredentialsIdentity::accessKeyId);
174+
String rejectedAccessKeyId = identity.accessKeyId();
175+
return CompletableFuture.runAsync(() ->
176+
credentialsCache.invalidate(cachedCreds -> rejectedAccessKeyId.equals(cachedCreds.accessKeyId()))
177+
);
177178
}
178179

179180
private RefreshResult<AwsCredentials> refreshCredentials() {

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.util.Optional;
2828
import java.util.concurrent.CompletableFuture;
2929
import software.amazon.awssdk.annotations.SdkPublicApi;
30-
import software.amazon.awssdk.auth.credentials.internal.CredentialsInvalidationUtils;
3130
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
3231
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
3332
import software.amazon.awssdk.protocols.jsoncore.JsonNode;
@@ -171,8 +170,10 @@ public AwsCredentials resolveCredentials() {
171170

172171
@Override
173172
public CompletableFuture<Void> invalidate(AwsCredentialsIdentity identity) {
174-
return CredentialsInvalidationUtils.invalidateCredentialsCache(
175-
identity, processCredentialCache, AwsCredentialsIdentity::accessKeyId);
173+
String rejectedAccessKeyId = identity.accessKeyId();
174+
return CompletableFuture.runAsync(() ->
175+
processCredentialCache.invalidate(cachedCreds -> rejectedAccessKeyId.equals(cachedCreds.accessKeyId()))
176+
);
176177
}
177178

178179
private RefreshResult<AwsCredentials> refreshCredentials() {

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

Lines changed: 0 additions & 71 deletions
This file was deleted.

core/auth/src/test/java/software/amazon/awssdk/auth/credentials/AwsCredentialsProviderChainTest.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@
1818
import static org.assertj.core.api.Assertions.assertThat;
1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020
import static org.junit.jupiter.api.Assertions.assertThrows;
21+
import static org.mockito.ArgumentMatchers.any;
22+
import static org.mockito.Mockito.doThrow;
23+
import static org.mockito.Mockito.mock;
24+
import static org.mockito.Mockito.times;
25+
import static org.mockito.Mockito.verify;
2126

2227
import java.util.Arrays;
28+
import java.util.concurrent.CompletableFuture;
2329
import org.junit.Test;
2430
import org.junit.jupiter.api.function.Executable;
2531
import software.amazon.awssdk.core.exception.SdkClientException;
@@ -172,6 +178,65 @@ private static void assertChainResolvesCorrectly(AwsCredentialsProviderChain cha
172178
assertThat(credentials.secretAccessKey()).isEqualTo("secretKey");
173179
}
174180

181+
@Test
182+
public void invalidate_propagatesToAllChildren() {
183+
TrackingCredentialsProvider provider1 = new TrackingCredentialsProvider("key1", "secret1");
184+
TrackingCredentialsProvider provider2 = new TrackingCredentialsProvider("key2", "secret2");
185+
TrackingCredentialsProvider provider3 = new TrackingCredentialsProvider("key3", "secret3");
186+
187+
AwsCredentialsProviderChain chain = AwsCredentialsProviderChain.builder()
188+
.credentialsProviders(provider1, provider2, provider3)
189+
.build();
190+
191+
AwsCredentialsIdentity identity = AwsBasicCredentials.create("key1", "secret1");
192+
chain.invalidate(identity).join();
193+
194+
assertThat(provider1.invalidateCallCount).isEqualTo(1);
195+
assertThat(provider2.invalidateCallCount).isEqualTo(1);
196+
assertThat(provider3.invalidateCallCount).isEqualTo(1);
197+
}
198+
199+
@SuppressWarnings("unchecked")
200+
@Test
201+
public void invalidate_doesNotShortCircuit_whenChildThrows() {
202+
AwsCredentialsProvider mockProvider1 = mock(AwsCredentialsProvider.class);
203+
AwsCredentialsProvider mockProvider2 = mock(AwsCredentialsProvider.class);
204+
AwsCredentialsProvider mockProvider3 = mock(AwsCredentialsProvider.class);
205+
206+
doThrow(new RuntimeException("Provider 1 failed")).when(mockProvider1).invalidate(any());
207+
208+
AwsCredentialsProviderChain chain = AwsCredentialsProviderChain.builder()
209+
.credentialsProviders(mockProvider1, mockProvider2, mockProvider3)
210+
.build();
211+
212+
AwsCredentialsIdentity identity = AwsBasicCredentials.create("key1", "secret1");
213+
chain.invalidate(identity).join();
214+
215+
verify(mockProvider1, times(1)).invalidate(identity);
216+
verify(mockProvider2, times(1)).invalidate(identity);
217+
verify(mockProvider3, times(1)).invalidate(identity);
218+
}
219+
220+
private static final class TrackingCredentialsProvider implements AwsCredentialsProvider {
221+
private final AwsBasicCredentials credentials;
222+
int invalidateCallCount = 0;
223+
224+
TrackingCredentialsProvider(String accessKeyId, String secretAccessKey) {
225+
this.credentials = AwsBasicCredentials.create(accessKeyId, secretAccessKey);
226+
}
227+
228+
@Override
229+
public AwsCredentials resolveCredentials() {
230+
return credentials;
231+
}
232+
233+
@Override
234+
public CompletableFuture<Void> invalidate(AwsCredentialsIdentity identity) {
235+
invalidateCallCount++;
236+
return CompletableFuture.completedFuture(null);
237+
}
238+
}
239+
175240
private static final class MockCredentialsProvider implements AwsCredentialsProvider {
176241
private final StaticCredentialsProvider staticCredentialsProvider;
177242
private final String exceptionMessage;

0 commit comments

Comments
 (0)