Skip to content

Commit 8141a30

Browse files
authored
Feature IDs implementation for credentials (#6415)
* Feature IDs implementation for credentials * Fixing test failure * Adding unit tests
1 parent f8000dd commit 8141a30

26 files changed

+1172
-62
lines changed

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

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import software.amazon.awssdk.auth.credentials.internal.HttpCredentialsLoader.LoadedCredentials;
4040
import software.amazon.awssdk.core.SdkSystemSetting;
4141
import software.amazon.awssdk.core.exception.SdkClientException;
42+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
4243
import software.amazon.awssdk.core.util.SdkUserAgent;
4344
import software.amazon.awssdk.regions.util.ResourcesEndpointProvider;
4445
import software.amazon.awssdk.regions.util.ResourcesEndpointRetryPolicy;
@@ -72,7 +73,8 @@
7273
public final class ContainerCredentialsProvider
7374
implements HttpCredentialsProvider,
7475
ToCopyableBuilder<ContainerCredentialsProvider.Builder, ContainerCredentialsProvider> {
75-
private static final String PROVIDER_NAME = "ContainerCredentialsProvider";
76+
private static final String CLASS_NAME = "ContainerCredentialsProvider";
77+
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_HTTP.value();
7678
private static final Predicate<InetAddress> IS_LOOPBACK_ADDRESS = InetAddress::isLoopbackAddress;
7779
private static final Predicate<InetAddress> ALLOWED_HOSTS_RULES = IS_LOOPBACK_ADDRESS;
7880
private static final String HTTPS = "https";
@@ -90,6 +92,7 @@ public final class ContainerCredentialsProvider
9092
private final Boolean asyncCredentialUpdateEnabled;
9193

9294
private final String asyncThreadName;
95+
private final String source;
9396

9497
/**
9598
* @see #builder()
@@ -98,7 +101,8 @@ private ContainerCredentialsProvider(BuilderImpl builder) {
98101
this.endpoint = builder.endpoint;
99102
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
100103
this.asyncThreadName = builder.asyncThreadName;
101-
this.httpCredentialsLoader = HttpCredentialsLoader.create(PROVIDER_NAME);
104+
this.source = builder.source;
105+
this.httpCredentialsLoader = HttpCredentialsLoader.create(providerName());
102106

103107
if (Boolean.TRUE.equals(builder.asyncCredentialUpdateEnabled)) {
104108
Validate.paramNotBlank(builder.asyncThreadName, "asyncThreadName");
@@ -126,7 +130,7 @@ public static Builder builder() {
126130

127131
@Override
128132
public String toString() {
129-
return ToString.create(PROVIDER_NAME);
133+
return ToString.create(CLASS_NAME);
130134
}
131135

132136
private RefreshResult<AwsCredentials> refreshCredentials() {
@@ -160,6 +164,14 @@ private Instant prefetchTime(Instant expiration) {
160164
return ComparableUtils.minimum(oneHourFromNow, fifteenMinutesBeforeExpiration);
161165
}
162166

167+
private String providerName() {
168+
String providerName = PROVIDER_NAME;
169+
if (source != null && !source.isEmpty()) {
170+
providerName = String.format("%s,%s", source, providerName);
171+
}
172+
return providerName;
173+
}
174+
163175
@Override
164176
public AwsCredentials resolveCredentials() {
165177
return credentialsCache.get();
@@ -318,6 +330,7 @@ private static final class BuilderImpl implements Builder {
318330
private String endpoint;
319331
private Boolean asyncCredentialUpdateEnabled;
320332
private String asyncThreadName;
333+
private String source;
321334

322335
private BuilderImpl() {
323336
asyncThreadName("container-credentials-provider");
@@ -327,6 +340,7 @@ private BuilderImpl(ContainerCredentialsProvider credentialsProvider) {
327340
this.endpoint = credentialsProvider.endpoint;
328341
this.asyncCredentialUpdateEnabled = credentialsProvider.asyncCredentialUpdateEnabled;
329342
this.asyncThreadName = credentialsProvider.asyncThreadName;
343+
this.source = credentialsProvider.source;
330344
}
331345

332346
@Override
@@ -359,6 +373,16 @@ public void setAsyncThreadName(String asyncThreadName) {
359373
asyncThreadName(asyncThreadName);
360374
}
361375

376+
@Override
377+
public Builder source(String source) {
378+
this.source = source;
379+
return this;
380+
}
381+
382+
public void setSource(String source) {
383+
source(source);
384+
}
385+
362386
@Override
363387
public ContainerCredentialsProvider build() {
364388
return new ContainerCredentialsProvider(this);

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.Optional;
1919
import software.amazon.awssdk.annotations.SdkPublicApi;
2020
import software.amazon.awssdk.auth.credentials.internal.SystemSettingsCredentialsProvider;
21+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
2122
import software.amazon.awssdk.utils.SystemSetting;
2223
import software.amazon.awssdk.utils.ToString;
2324

@@ -28,7 +29,8 @@
2829
@SdkPublicApi
2930
public final class EnvironmentVariableCredentialsProvider extends SystemSettingsCredentialsProvider {
3031

31-
private static final String PROVIDER_NAME = "EnvironmentVariableCredentialsProvider";
32+
private static final String CLASS_NAME = "EnvironmentVariableCredentialsProvider";
33+
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_ENV_VARS.value();
3234

3335
private EnvironmentVariableCredentialsProvider() {
3436
}
@@ -52,6 +54,6 @@ protected String provider() {
5254

5355
@Override
5456
public String toString() {
55-
return ToString.create(PROVIDER_NAME);
57+
return ToString.create(CLASS_NAME);
5658
}
5759
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ interface Builder<TypeToBuildT extends HttpCredentialsProvider, BuilderT extends
4848
*/
4949
BuilderT endpoint(String endpoint);
5050

51+
/**
52+
* Configure the source of this credentials provider. This is used for business metrics tracking.
53+
*/
54+
default BuilderT source(String source) {
55+
throw new UnsupportedOperationException();
56+
}
57+
5158
/**
5259
* Build the credentials provider based on the configuration on this builder.
5360
*/

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import software.amazon.awssdk.core.SdkSystemSetting;
3838
import software.amazon.awssdk.core.exception.SdkClientException;
3939
import software.amazon.awssdk.core.exception.SdkServiceException;
40+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
4041
import software.amazon.awssdk.profiles.ProfileFile;
4142
import software.amazon.awssdk.profiles.ProfileFileSupplier;
4243
import software.amazon.awssdk.profiles.ProfileFileSystemSetting;
@@ -67,7 +68,8 @@ public final class InstanceProfileCredentialsProvider
6768
implements HttpCredentialsProvider,
6869
ToCopyableBuilder<InstanceProfileCredentialsProvider.Builder, InstanceProfileCredentialsProvider> {
6970
private static final Logger log = Logger.loggerFor(InstanceProfileCredentialsProvider.class);
70-
private static final String PROVIDER_NAME = "InstanceProfileCredentialsProvider";
71+
private static final String CLASS_NAME = "InstanceProfileCredentialsProvider";
72+
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_IMDS.value();
7173
private static final String EC2_METADATA_TOKEN_HEADER = "x-aws-ec2-metadata-token";
7274
private static final String SECURITY_CREDENTIALS_RESOURCE = "/latest/meta-data/iam/security-credentials/";
7375
private static final String TOKEN_RESOURCE = "/latest/api/token";
@@ -90,6 +92,8 @@ public final class InstanceProfileCredentialsProvider
9092

9193
private final Duration staleTime;
9294

95+
private final String source;
96+
9397
/**
9498
* @see #builder()
9599
*/
@@ -102,8 +106,9 @@ private InstanceProfileCredentialsProvider(BuilderImpl builder) {
102106
.orElseGet(() -> ProfileFileSupplier.fixedProfileFile(ProfileFile.defaultProfileFile()));
103107
this.profileName = Optional.ofNullable(builder.profileName)
104108
.orElseGet(ProfileFileSystemSetting.AWS_PROFILE::getStringValueOrThrow);
109+
this.source = builder.source;
105110

106-
this.httpCredentialsLoader = HttpCredentialsLoader.create(PROVIDER_NAME);
111+
this.httpCredentialsLoader = HttpCredentialsLoader.create(providerName());
107112
this.configProvider =
108113
Ec2MetadataConfigProvider.builder()
109114
.profileFile(profileFile)
@@ -202,9 +207,17 @@ public void close() {
202207
credentialsCache.close();
203208
}
204209

210+
private String providerName() {
211+
String providerName = PROVIDER_NAME;
212+
if (source != null && !source.isEmpty()) {
213+
providerName = String.format("%s,%s", source, providerName);
214+
}
215+
return providerName;
216+
}
217+
205218
@Override
206219
public String toString() {
207-
return ToString.create(PROVIDER_NAME);
220+
return ToString.create(CLASS_NAME);
208221
}
209222

210223
private ResourcesEndpointProvider createEndpointProvider() {
@@ -372,6 +385,7 @@ static final class BuilderImpl implements Builder {
372385
private Supplier<ProfileFile> profileFile;
373386
private String profileName;
374387
private Duration staleTime;
388+
private String source;
375389

376390
private BuilderImpl() {
377391
asyncThreadName("instance-profile-credentials-provider");
@@ -385,6 +399,7 @@ private BuilderImpl(InstanceProfileCredentialsProvider provider) {
385399
this.profileFile = provider.profileFile;
386400
this.profileName = provider.profileName;
387401
this.staleTime = provider.staleTime;
402+
this.source = provider.source;
388403
}
389404

390405
Builder clock(Clock clock) {
@@ -463,6 +478,16 @@ public void setStaleTime(Duration duration) {
463478
staleTime(duration);
464479
}
465480

481+
@Override
482+
public Builder source(String source) {
483+
this.source = source;
484+
return this;
485+
}
486+
487+
public void setSource(String source) {
488+
source(source);
489+
}
490+
466491
@Override
467492
public InstanceProfileCredentialsProvider build() {
468493
return new InstanceProfileCredentialsProvider(this);

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.Collections;
2626
import java.util.List;
2727
import software.amazon.awssdk.annotations.SdkPublicApi;
28+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
2829
import software.amazon.awssdk.protocols.jsoncore.JsonNode;
2930
import software.amazon.awssdk.protocols.jsoncore.JsonNodeParser;
3031
import software.amazon.awssdk.utils.DateUtils;
@@ -64,7 +65,8 @@ public final class ProcessCredentialsProvider
6465
implements AwsCredentialsProvider,
6566
SdkAutoCloseable,
6667
ToCopyableBuilder<ProcessCredentialsProvider.Builder, ProcessCredentialsProvider> {
67-
private static final String PROVIDER_NAME = "ProcessCredentialsProvider";
68+
private static final String CLASS_NAME = "ProcessCredentialsProvider";
69+
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_PROCESS.value();
6870
private static final JsonNodeParser PARSER = JsonNodeParser.builder()
6971
.removeErrorLocations(true)
7072
.build();
@@ -82,6 +84,8 @@ public final class ProcessCredentialsProvider
8284

8385
private final Boolean asyncCredentialUpdateEnabled;
8486

87+
private final String source;
88+
8589
/**
8690
* @see #builder()
8791
*/
@@ -93,6 +97,7 @@ private ProcessCredentialsProvider(Builder builder) {
9397
this.commandAsListOfStringsFromBuilder = builder.commandAsListOfStrings;
9498
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
9599
this.staticAccountId = builder.staticAccountId;
100+
this.source = builder.source;
96101

97102
CachedSupplier.Builder<AwsCredentials> cacheBuilder = CachedSupplier.builder(this::refreshCredentials)
98103
.cachedValueName(toString());
@@ -171,6 +176,14 @@ private JsonNode parseProcessOutput(String processOutput) {
171176
return credentialsJson;
172177
}
173178

179+
private String providerName() {
180+
String providerName = PROVIDER_NAME;
181+
if (source != null && !source.isEmpty()) {
182+
providerName = String.format("%s,%s", source, providerName);
183+
}
184+
return providerName;
185+
}
186+
174187
/**
175188
* Parse the process output to retrieve the credentials.
176189
*/
@@ -192,13 +205,13 @@ private AwsCredentials credentials(JsonNode credentialsJson) {
192205
.sessionToken(sessionToken)
193206
.expirationTime(credentialExpirationTime(credentialsJson))
194207
.accountId(resolvedAccountId)
195-
.providerName(PROVIDER_NAME)
208+
.providerName(providerName())
196209
.build() :
197210
AwsBasicCredentials.builder()
198211
.accessKeyId(accessKeyId)
199212
.secretAccessKey(secretAccessKey)
200213
.accountId(resolvedAccountId)
201-
.providerName(PROVIDER_NAME)
214+
.providerName(providerName())
202215
.build();
203216
}
204217

@@ -270,6 +283,7 @@ public static class Builder implements CopyableBuilder<Builder, ProcessCredentia
270283
private Duration credentialRefreshThreshold = Duration.ofSeconds(15);
271284
private long processOutputLimit = 64000;
272285
private String staticAccountId;
286+
private String source;
273287

274288
/**
275289
* @see #builder()
@@ -284,6 +298,7 @@ private Builder(ProcessCredentialsProvider provider) {
284298
this.credentialRefreshThreshold = provider.credentialRefreshThreshold;
285299
this.processOutputLimit = provider.processOutputLimit;
286300
this.staticAccountId = provider.staticAccountId;
301+
this.source = provider.source;
287302
}
288303

289304
/**
@@ -357,14 +372,22 @@ public Builder staticAccountId(String staticAccountId) {
357372
return this;
358373
}
359374

375+
/**
376+
* Configure the source of this credentials provider. This is used for business metrics tracking.
377+
*/
378+
public Builder source(String source) {
379+
this.source = source;
380+
return this;
381+
}
382+
360383
public ProcessCredentialsProvider build() {
361384
return new ProcessCredentialsProvider(this);
362385
}
363386
}
364387

365388
@Override
366389
public String toString() {
367-
return ToString.builder(PROVIDER_NAME)
390+
return ToString.builder(CLASS_NAME)
368391
.add("cmd", executableCommand)
369392
.build();
370393
}

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

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ public final class ProfileProviderCredentialsContext {
2929

3030
private final Profile profile;
3131
private final ProfileFile profileFile;
32+
private final String source;
3233

33-
private ProfileProviderCredentialsContext(Profile profile, ProfileFile profileFile) {
34-
this.profile = profile;
35-
this.profileFile = profileFile;
34+
private ProfileProviderCredentialsContext(Builder builder) {
35+
this.profile = builder.profile;
36+
this.profileFile = builder.profileFile;
37+
this.source = builder.source;
3638
}
3739

3840
public static Builder builder() {
@@ -55,6 +57,14 @@ public ProfileFile profileFile() {
5557
return profileFile;
5658
}
5759

60+
/**
61+
* An optional string list of {@link software.amazon.awssdk.core.useragent.BusinessMetricFeatureId} denoting previous
62+
* credentials providers that are chained with this one.
63+
*/
64+
public String source() {
65+
return source;
66+
}
67+
5868
@Override
5969
public boolean equals(Object o) {
6070
if (this == o) {
@@ -78,6 +88,7 @@ public int hashCode() {
7888
public static final class Builder {
7989
private Profile profile;
8090
private ProfileFile profileFile;
91+
private String source;
8192

8293
private Builder() {
8394
}
@@ -103,8 +114,19 @@ public Builder profileFile(ProfileFile profileFile) {
103114
return this;
104115
}
105116

117+
/**
118+
* Builder interface to set source.
119+
* @param source An optional string list of {@link software.amazon.awssdk.core.useragent.BusinessMetricFeatureId}
120+
* denoting previous credentials providers that are chained with this one.
121+
* @return Returns a reference to this object so that method calls can be chained together.
122+
*/
123+
public Builder source(String source) {
124+
this.source = source;
125+
return this;
126+
}
127+
106128
public ProfileProviderCredentialsContext build() {
107-
return new ProfileProviderCredentialsContext(profile, profileFile);
129+
return new ProfileProviderCredentialsContext(this);
108130
}
109131
}
110132
}

0 commit comments

Comments
 (0)