Skip to content

Commit f3a111d

Browse files
authored
Merge credentials reloading feature branch to mainline (#3712)
* ProfileCredentialsProvider can now reload credentials when profile files change (#3487) * ProfileFile can update if disk changed, reload as new instance * ProfileCredentialsProvider reloads credentials if profile file has changes * Created class ProfileFileRefresher * Created ReloadingProfileCredentialsProvider; moved new logic in ProfileFile to ProfileFileRefresher * Fix ReloadingProfileCredentialsBehavior when missing ProfileFile Supplier or Predicate, and dealing with defaults * Consolidated ReloadingProfileCredentialsProvider functionality into ProfileCredentialsProvider * Fix behavior when dealing with defaults * Created ProfileFileSupplier interface; refactored * Misc fixes * Created package-private ProfileFileSupplierBuilder; ProfileFileSupplier now extends Supplier; Fixed Javadoc * Fixed unit tests for default credentials file * Removed ProfileFileSupplier.Builder interface * Code cleanup * ProfileFileSupplier API changes, aggregating (#3558) * Added methods for aggregating ProfileFile objects * Removed redundant logic, changelog entry * Removed redundant methods * Use compare and set to make thread safe * DefaultCredentialsProvider reload profile (#3580) * Misc fixes * Reload credentials by DefaultCredentialsProvider; pass supplier to InstanceProfileCredentialsProvider * Fix code alignment * Update public APIs to Supplier<ProfileFile> instead of ProfileFileSupplier (#3607) * ProfileTokenProvider Reload ProfileFile (#3608) * Updated ProfileTokenProvider * Updated tests, do not explicitly swallow exceptions * ProfileTokenProviderLoader can use Supplier<Profilefile> internally * Simplified ProfileTokenProviderLoader API; implemented synchronized block * Use synchronized block (#3646) * S3 support classes take Supplier<ProfileFile> (#3653) * S3 support classes take Supplier<ProfileFile> * Review comments * Presigners, other Support classes take Supplier<ProfileFile> (#3677) * Presigners, other Support classes take Supplier<ProfileFile> * Split new ProfileFile tests from existing parameterized tests * Improved tests readability * ProfileFile updates to BaseClientBuilderClass, other S3 classes (#3685) * Leverage SdkClientOption and SdkExecutionAttributes; fallback to simp… (#3692) * Leverage SdkClientOption and SdkExecutionAttributes; fallback to simple ProfileFile * Addressed review comments * Updated changelog entry (#3699) * Fixed review comments * Removed unnecessary logic * Deprecated SdkClientOption PROFILE_FILE * Deprecated SdkExecutionAttribute PROFILE_FILE * Updated changelog entry
1 parent 970cbd8 commit f3a111d

File tree

64 files changed

+2844
-291
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2844
-291
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": "- ProfileCredentialsProvider and ProfileTokenProvider can reload credentials when disk profile changes\n- Updated DefaultCredentialsProvider chain for reloading credentials\n- Service support classes store ProfileFile as a Supplier interface\n- SdkClientOption and SdkExecutionAttributes constants for PROFILE_FILE have been deprecated in favor of PROFILE_FILE_SUPPLIER"
6+
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -362,15 +362,13 @@ private MethodSpec finalizeServiceConfigurationMethod() {
362362

363363
private void mergeServiceConfiguration(MethodSpec.Builder builder, String clientConfigClassName) {
364364
ClassName clientConfigClass = ClassName.bestGuess(clientConfigClassName);
365-
builder.addCode("$1T.Builder serviceConfigBuilder = (($1T) config.option($2T.SERVICE_CONFIGURATION)).toBuilder();" +
366-
"serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFile() "
367-
+ "!= null ? serviceConfigBuilder.profileFile() : config.option($2T.PROFILE_FILE));" +
368-
"serviceConfigBuilder.profileName(serviceConfigBuilder.profileName() "
365+
builder.addCode("$1T.Builder serviceConfigBuilder = (($1T) config.option($2T.SERVICE_CONFIGURATION)).toBuilder();"
366+
+ "serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFileSupplier() != null ? "
367+
+ "serviceConfigBuilder.profileFileSupplier() : config.option($2T.PROFILE_FILE_SUPPLIER));"
368+
+ "serviceConfigBuilder.profileName(serviceConfigBuilder.profileName() "
369369
+ "!= null ? serviceConfigBuilder.profileName() : config.option($2T.PROFILE_NAME));",
370370
clientConfigClass, SdkClientOption.class);
371371

372-
373-
374372
if (model.getCustomizationConfig().getServiceConfig().hasDualstackProperty()) {
375373
builder.addCode("if (serviceConfigBuilder.dualstackEnabled() != null) {")
376374
.addCode(" $T.validState(config.option($T.DUALSTACK_ENDPOINT_ENABLED) == null, \"Dualstack has been "

codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-class.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon
6868
interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS));
6969
ServiceConfiguration.Builder serviceConfigBuilder = ((ServiceConfiguration) config
7070
.option(SdkClientOption.SERVICE_CONFIGURATION)).toBuilder();
71-
serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFile() != null ? serviceConfigBuilder.profileFile() : config
72-
.option(SdkClientOption.PROFILE_FILE));
71+
serviceConfigBuilder.profileFile(serviceConfigBuilder.profileFileSupplier() != null ?
72+
serviceConfigBuilder.profileFileSupplier() :
73+
config.option(SdkClientOption.PROFILE_FILE_SUPPLIER));
7374
serviceConfigBuilder.profileName(serviceConfigBuilder.profileName() != null ? serviceConfigBuilder.profileName() : config
7475
.option(SdkClientOption.PROFILE_NAME));
7576
if (serviceConfigBuilder.dualstackEnabled() != null) {

core/auth/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@
152152
<artifactId>commons-lang3</artifactId>
153153
<scope>test</scope>
154154
</dependency>
155+
<dependency>
156+
<groupId>com.google.jimfs</groupId>
157+
<artifactId>jimfs</artifactId>
158+
<version>${jimfs.version}</version>
159+
<scope>test</scope>
160+
</dependency>
155161
</dependencies>
156162
<build>
157163
<plugins>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
public interface AwsCredentialsProvider {
3131
/**
3232
* Returns {@link AwsCredentials} that can be used to authorize an AWS request. Each implementation of AWSCredentialsProvider
33-
* can chose its own strategy for loading credentials. For example, an implementation might load credentials from an existing
33+
* can choose its own strategy for loading credentials. For example, an implementation might load credentials from an existing
3434
* key management system, or load new credentials when credentials are rotated.
3535
*
3636
* <p>If an error occurs during the loading of credentials or credentials could not be found, a runtime exception will be

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

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515

1616
package software.amazon.awssdk.auth.credentials;
1717

18+
import java.util.Optional;
19+
import java.util.function.Supplier;
1820
import software.amazon.awssdk.annotations.SdkPublicApi;
1921
import software.amazon.awssdk.auth.credentials.internal.LazyAwsCredentialsProvider;
2022
import software.amazon.awssdk.profiles.ProfileFile;
23+
import software.amazon.awssdk.profiles.ProfileFileSupplier;
2124
import software.amazon.awssdk.utils.SdkAutoCloseable;
2225
import software.amazon.awssdk.utils.ToString;
2326
import software.amazon.awssdk.utils.builder.CopyableBuilder;
@@ -26,8 +29,8 @@
2629
/**
2730
* AWS credentials provider chain that looks for credentials in this order:
2831
* <ol>
29-
* <li>Java System Properties - <code>aws.accessKeyId</code> and <code>aws.secretAccessKey</code></li>
30-
* <li>Environment Variables - <code>AWS_ACCESS_KEY_ID</code> and <code>AWS_SECRET_ACCESS_KEY</code></li>
32+
* <li>Java System Properties - {@code aws.accessKeyId} and {@code aws.secretAccessKey}</li>
33+
* <li>Environment Variables - {@code AWS_ACCESS_KEY_ID} and {@code AWS_SECRET_ACCESS_KEY}</li>
3134
* <li>Web Identity Token credentials from system properties or environment variables</li>
3235
* <li>Credential profiles file at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI</li>
3336
* <li>Credentials delivered through the Amazon EC2 container service if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" environment
@@ -51,7 +54,7 @@ public final class DefaultCredentialsProvider
5154

5255
private final LazyAwsCredentialsProvider providerChain;
5356

54-
private final ProfileFile profileFile;
57+
private final Supplier<ProfileFile> profileFile;
5558

5659
private final String profileName;
5760

@@ -87,21 +90,21 @@ private static LazyAwsCredentialsProvider createChain(Builder builder) {
8790

8891
return LazyAwsCredentialsProvider.create(() -> {
8992
AwsCredentialsProvider[] credentialsProviders = new AwsCredentialsProvider[] {
90-
SystemPropertyCredentialsProvider.create(),
91-
EnvironmentVariableCredentialsProvider.create(),
92-
WebIdentityTokenFileCredentialsProvider.create(),
93-
ProfileCredentialsProvider.builder()
94-
.profileFile(builder.profileFile)
95-
.profileName(builder.profileName)
96-
.build(),
97-
ContainerCredentialsProvider.builder()
98-
.asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled)
99-
.build(),
100-
InstanceProfileCredentialsProvider.builder()
101-
.asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled)
102-
.profileFile(builder.profileFile)
103-
.profileName(builder.profileName)
104-
.build()
93+
SystemPropertyCredentialsProvider.create(),
94+
EnvironmentVariableCredentialsProvider.create(),
95+
WebIdentityTokenFileCredentialsProvider.create(),
96+
ProfileCredentialsProvider.builder()
97+
.profileFile(builder.profileFile)
98+
.profileName(builder.profileName)
99+
.build(),
100+
ContainerCredentialsProvider.builder()
101+
.asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled)
102+
.build(),
103+
InstanceProfileCredentialsProvider.builder()
104+
.asyncCredentialUpdateEnabled(asyncCredentialUpdateEnabled)
105+
.profileFile(builder.profileFile)
106+
.profileName(builder.profileName)
107+
.build()
105108
};
106109

107110
return AwsCredentialsProviderChain.builder()
@@ -144,7 +147,7 @@ public Builder toBuilder() {
144147
* Configuration that defines the {@link DefaultCredentialsProvider}'s behavior.
145148
*/
146149
public static final class Builder implements CopyableBuilder<Builder, DefaultCredentialsProvider> {
147-
private ProfileFile profileFile;
150+
private Supplier<ProfileFile> profileFile;
148151
private String profileName;
149152
private Boolean reuseLastProviderEnabled = true;
150153
private Boolean asyncCredentialUpdateEnabled = false;
@@ -163,7 +166,13 @@ private Builder(DefaultCredentialsProvider credentialsProvider) {
163166
}
164167

165168
public Builder profileFile(ProfileFile profileFile) {
166-
this.profileFile = profileFile;
169+
return profileFile(Optional.ofNullable(profileFile)
170+
.map(ProfileFileSupplier::fixedProfileFile)
171+
.orElse(null));
172+
}
173+
174+
public Builder profileFile(Supplier<ProfileFile> profileFileSupplier) {
175+
this.profileFile = profileFileSupplier;
167176
return this;
168177
}
169178

@@ -198,6 +207,7 @@ public Builder asyncCredentialUpdateEnabled(Boolean asyncCredentialUpdateEnabled
198207
/**
199208
* Create a {@link DefaultCredentialsProvider} using the configuration defined in this builder.
200209
*/
210+
@Override
201211
public DefaultCredentialsProvider build() {
202212
return new DefaultCredentialsProvider(this);
203213
}

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

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.time.Instant;
2727
import java.util.Collections;
2828
import java.util.Map;
29+
import java.util.Optional;
30+
import java.util.function.Supplier;
2931
import software.amazon.awssdk.annotations.SdkPublicApi;
3032
import software.amazon.awssdk.annotations.SdkTestInternalApi;
3133
import software.amazon.awssdk.auth.credentials.internal.Ec2MetadataConfigProvider;
@@ -36,6 +38,7 @@
3638
import software.amazon.awssdk.core.exception.SdkClientException;
3739
import software.amazon.awssdk.core.exception.SdkServiceException;
3840
import software.amazon.awssdk.profiles.ProfileFile;
41+
import software.amazon.awssdk.profiles.ProfileFileSupplier;
3942
import software.amazon.awssdk.profiles.ProfileFileSystemSetting;
4043
import software.amazon.awssdk.regions.util.HttpResourcesUtils;
4144
import software.amazon.awssdk.regions.util.ResourcesEndpointProvider;
@@ -77,7 +80,7 @@ public final class InstanceProfileCredentialsProvider
7780

7881
private final String asyncThreadName;
7982

80-
private final ProfileFile profileFile;
83+
private final Supplier<ProfileFile> profileFile;
8184

8285
private final String profileName;
8386

@@ -95,8 +98,8 @@ private InstanceProfileCredentialsProvider(BuilderImpl builder) {
9598
this.httpCredentialsLoader = HttpCredentialsLoader.create();
9699
this.configProvider =
97100
Ec2MetadataConfigProvider.builder()
98-
.profileFile(builder.profileFile == null ? null : () -> builder.profileFile)
99-
.profileName(builder.profileName == null ? null : builder.profileName)
101+
.profileFile(builder.profileFile)
102+
.profileName(builder.profileName)
100103
.build();
101104

102105
if (Boolean.TRUE.equals(builder.asyncCredentialUpdateEnabled)) {
@@ -279,9 +282,19 @@ public interface Builder extends HttpCredentialsProvider.Builder<InstanceProfile
279282
* Configure the profile file used for loading IMDS-related configuration, like the endpoint mode (IPv4 vs IPv6).
280283
*
281284
* <p>By default, {@link ProfileFile#defaultProfileFile()} is used.
285+
*
286+
* @see #profileFile(Supplier)
282287
*/
283288
Builder profileFile(ProfileFile profileFile);
284289

290+
/**
291+
* Define the mechanism for loading profile files.
292+
*
293+
* @param profileFileSupplier Supplier interface for generating a ProfileFile instance.
294+
* @see #profileFile(ProfileFile)
295+
*/
296+
Builder profileFile(Supplier<ProfileFile> profileFileSupplier);
297+
285298
/**
286299
* Configure the profile name used for loading IMDS-related configuration, like the endpoint mode (IPv4 vs IPv6).
287300
*
@@ -292,6 +305,7 @@ public interface Builder extends HttpCredentialsProvider.Builder<InstanceProfile
292305
/**
293306
* Build a {@link InstanceProfileCredentialsProvider} from the provided configuration.
294307
*/
308+
@Override
295309
InstanceProfileCredentialsProvider build();
296310
}
297311

@@ -301,7 +315,7 @@ static final class BuilderImpl implements Builder {
301315
private String endpoint;
302316
private Boolean asyncCredentialUpdateEnabled;
303317
private String asyncThreadName;
304-
private ProfileFile profileFile;
318+
private Supplier<ProfileFile> profileFile;
305319
private String profileName;
306320

307321
private BuilderImpl() {
@@ -354,14 +368,25 @@ public void setAsyncThreadName(String asyncThreadName) {
354368

355369
@Override
356370
public Builder profileFile(ProfileFile profileFile) {
357-
this.profileFile = profileFile;
358-
return this;
371+
return profileFile(Optional.ofNullable(profileFile)
372+
.map(ProfileFileSupplier::fixedProfileFile)
373+
.orElse(null));
359374
}
360375

361376
public void setProfileFile(ProfileFile profileFile) {
362377
profileFile(profileFile);
363378
}
364379

380+
@Override
381+
public Builder profileFile(Supplier<ProfileFile> profileFileSupplier) {
382+
this.profileFile = profileFileSupplier;
383+
return this;
384+
}
385+
386+
public void setProfileFile(Supplier<ProfileFile> profileFileSupplier) {
387+
profileFile(profileFileSupplier);
388+
}
389+
365390
@Override
366391
public Builder profileName(String profileName) {
367392
this.profileName = profileName;

0 commit comments

Comments
 (0)