Skip to content

Commit e20c919

Browse files
committed
Merge remote-tracking branch 'origin/feature/master/feature-ids-implementation' into feature/master/feature-ids-implementation
2 parents cb6f5b4 + 36324ae commit e20c919

File tree

32 files changed

+793
-226
lines changed

32 files changed

+793
-226
lines changed

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

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,45 @@ public interface ChildProfileCredentialsProviderFactory {
4040
* provider.
4141
* @return The credentials provider with permissions derived from the source credentials provider and profile.
4242
*/
43-
AwsCredentialsProvider create(AwsCredentialsProvider sourceCredentialsProvider, Profile profile);
43+
default AwsCredentialsProvider create(AwsCredentialsProvider sourceCredentialsProvider, Profile profile) {
44+
ChildProfileCredentialsRequest request = new ChildProfileCredentialsRequest(sourceCredentialsProvider, profile, null);
45+
return create(request);
46+
}
47+
48+
/**
49+
* Create a credentials provider for the provided profile, using the provided source credentials provider to authenticate
50+
* with AWS. In the case of STS, the returned credentials provider is for a role that has been assumed, and the provided
51+
* source credentials provider is the credentials that should be used to authenticate that the user is allowed to assume
52+
* that role.
53+
*
54+
* @param request The request containing all parameters needed to create the child credentials provider.
55+
* @return The credentials provider with permissions derived from the request parameters.
56+
*/
57+
AwsCredentialsProvider create(ChildProfileCredentialsRequest request);
58+
59+
final class ChildProfileCredentialsRequest {
60+
private final AwsCredentialsProvider sourceCredentialsProvider;
61+
private final Profile profile;
62+
private final String source;
63+
64+
public ChildProfileCredentialsRequest(AwsCredentialsProvider sourceCredentialsProvider,
65+
Profile profile,
66+
String source) {
67+
this.sourceCredentialsProvider = sourceCredentialsProvider;
68+
this.profile = profile;
69+
this.source = source;
70+
}
71+
72+
public AwsCredentialsProvider sourceCredentialsProvider() {
73+
return sourceCredentialsProvider;
74+
}
75+
76+
public Profile profile() {
77+
return profile;
78+
}
79+
80+
public String source() {
81+
return source;
82+
}
83+
}
4484
}

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public final class ContainerCredentialsProvider
9393

9494
private final String asyncThreadName;
9595
private final String source;
96+
private final String providerName;
9697

9798
/**
9899
* @see #builder()
@@ -102,6 +103,9 @@ private ContainerCredentialsProvider(BuilderImpl builder) {
102103
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
103104
this.asyncThreadName = builder.asyncThreadName;
104105
this.source = builder.source;
106+
this.providerName = StringUtils.isEmpty(builder.source)
107+
? PROVIDER_NAME
108+
: builder.source + "," + PROVIDER_NAME;
105109
this.httpCredentialsLoader = HttpCredentialsLoader.create(providerName());
106110

107111
if (Boolean.TRUE.equals(builder.asyncCredentialUpdateEnabled)) {
@@ -165,11 +169,7 @@ private Instant prefetchTime(Instant expiration) {
165169
}
166170

167171
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;
172+
return this.providerName;
173173
}
174174

175175
@Override

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package software.amazon.awssdk.auth.credentials;
1717

1818
import software.amazon.awssdk.annotations.SdkPublicApi;
19+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
1920
import software.amazon.awssdk.utils.SdkAutoCloseable;
2021

2122
/**
@@ -49,7 +50,8 @@ interface Builder<TypeToBuildT extends HttpCredentialsProvider, BuilderT extends
4950
BuilderT endpoint(String endpoint);
5051

5152
/**
52-
* Configure the source of this credentials provider. This is used for business metrics tracking.
53+
* An optional string list of {@link BusinessMetricFeatureId} denoting previous credentials providers
54+
* that are chained with this one.
5355
*/
5456
default BuilderT source(String source) {
5557
throw new UnsupportedOperationException();

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import software.amazon.awssdk.regions.util.HttpResourcesUtils;
4646
import software.amazon.awssdk.regions.util.ResourcesEndpointProvider;
4747
import software.amazon.awssdk.utils.Logger;
48+
import software.amazon.awssdk.utils.StringUtils;
4849
import software.amazon.awssdk.utils.ToString;
4950
import software.amazon.awssdk.utils.Validate;
5051
import software.amazon.awssdk.utils.builder.CopyableBuilder;
@@ -93,6 +94,7 @@ public final class InstanceProfileCredentialsProvider
9394
private final Duration staleTime;
9495

9596
private final String source;
97+
private final String providerName;
9698

9799
/**
98100
* @see #builder()
@@ -107,6 +109,9 @@ private InstanceProfileCredentialsProvider(BuilderImpl builder) {
107109
this.profileName = Optional.ofNullable(builder.profileName)
108110
.orElseGet(ProfileFileSystemSetting.AWS_PROFILE::getStringValueOrThrow);
109111
this.source = builder.source;
112+
this.providerName = StringUtils.isEmpty(builder.source)
113+
? PROVIDER_NAME
114+
: builder.source + "," + PROVIDER_NAME;
110115

111116
this.httpCredentialsLoader = HttpCredentialsLoader.create(providerName());
112117
this.configProvider =
@@ -208,11 +213,7 @@ public void close() {
208213
}
209214

210215
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+
return this.providerName;
216217
}
217218

218219
@Override

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import software.amazon.awssdk.utils.IoUtils;
3333
import software.amazon.awssdk.utils.Platform;
3434
import software.amazon.awssdk.utils.SdkAutoCloseable;
35+
import software.amazon.awssdk.utils.StringUtils;
3536
import software.amazon.awssdk.utils.ToString;
3637
import software.amazon.awssdk.utils.Validate;
3738
import software.amazon.awssdk.utils.builder.CopyableBuilder;
@@ -85,6 +86,7 @@ public final class ProcessCredentialsProvider
8586
private final Boolean asyncCredentialUpdateEnabled;
8687

8788
private final String source;
89+
private final String providerName;
8890

8991
/**
9092
* @see #builder()
@@ -98,6 +100,9 @@ private ProcessCredentialsProvider(Builder builder) {
98100
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
99101
this.staticAccountId = builder.staticAccountId;
100102
this.source = builder.source;
103+
this.providerName = StringUtils.isEmpty(builder.source)
104+
? PROVIDER_NAME
105+
: builder.source + "," + PROVIDER_NAME;
101106

102107
CachedSupplier.Builder<AwsCredentials> cacheBuilder = CachedSupplier.builder(this::refreshCredentials)
103108
.cachedValueName(toString());
@@ -177,11 +182,7 @@ private JsonNode parseProcessOutput(String processOutput) {
177182
}
178183

179184
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+
return this.providerName;
185186
}
186187

187188
/**

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,22 @@ private StaticCredentialsProvider(AwsCredentials credentials) {
3535

3636
private AwsCredentials withProviderName(AwsCredentials credentials) {
3737
if (credentials instanceof AwsBasicCredentials) {
38-
return ((AwsBasicCredentials) credentials).copy(c -> c.providerName(PROVIDER_NAME));
38+
AwsBasicCredentials basicCreds = (AwsBasicCredentials) credentials;
39+
if (basicCreds.providerName()
40+
.map(BusinessMetricFeatureId.CREDENTIALS_PROFILE.value()::equals)
41+
.orElse(false)) {
42+
return basicCreds;
43+
}
44+
return basicCreds.copy(c -> c.providerName(PROVIDER_NAME));
3945
}
4046
if (credentials instanceof AwsSessionCredentials) {
41-
return ((AwsSessionCredentials) credentials).copy(c -> c.providerName(PROVIDER_NAME));
47+
AwsSessionCredentials sessionCreds = (AwsSessionCredentials) credentials;
48+
if (sessionCreds.providerName()
49+
.map(BusinessMetricFeatureId.CREDENTIALS_PROFILE.value()::equals)
50+
.orElse(false)) {
51+
return sessionCreds;
52+
}
53+
return sessionCreds.copy(c -> c.providerName(PROVIDER_NAME));
4254
}
4355
return credentials;
4456
}

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

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
4141
import software.amazon.awssdk.auth.credentials.SystemPropertyCredentialsProvider;
4242
import software.amazon.awssdk.core.internal.util.ClassLoaderHelper;
43+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
4344
import software.amazon.awssdk.profiles.Profile;
4445
import software.amazon.awssdk.profiles.ProfileFile;
4546
import software.amazon.awssdk.profiles.ProfileProperty;
@@ -161,6 +162,7 @@ private AwsCredentialsProvider basicProfileCredentialsProvider() {
161162
.accessKeyId(properties.get(ProfileProperty.AWS_ACCESS_KEY_ID))
162163
.secretAccessKey(properties.get(ProfileProperty.AWS_SECRET_ACCESS_KEY))
163164
.accountId(properties.get(ProfileProperty.AWS_ACCOUNT_ID))
165+
.providerName(BusinessMetricFeatureId.CREDENTIALS_PROFILE.value())
164166
.build();
165167
return StaticCredentialsProvider.create(credentials);
166168
}
@@ -177,6 +179,7 @@ private AwsCredentialsProvider sessionProfileCredentialsProvider() {
177179
.secretAccessKey(properties.get(ProfileProperty.AWS_SECRET_ACCESS_KEY))
178180
.sessionToken(properties.get(ProfileProperty.AWS_SESSION_TOKEN))
179181
.accountId(properties.get(ProfileProperty.AWS_ACCOUNT_ID))
182+
.providerName(BusinessMetricFeatureId.CREDENTIALS_PROFILE.value())
180183
.build();
181184
return StaticCredentialsProvider.create(credentials);
182185
}
@@ -187,6 +190,7 @@ private AwsCredentialsProvider credentialProcessCredentialsProvider() {
187190
return ProcessCredentialsProvider.builder()
188191
.command(properties.get(ProfileProperty.CREDENTIAL_PROCESS))
189192
.staticAccountId(properties.get(ProfileProperty.AWS_ACCOUNT_ID))
193+
.source(BusinessMetricFeatureId.CREDENTIALS_PROFILE_PROCESS.value())
190194
.build();
191195
}
192196

@@ -195,10 +199,16 @@ private AwsCredentialsProvider credentialProcessCredentialsProvider() {
195199
*/
196200
private AwsCredentialsProvider ssoProfileCredentialsProvider() {
197201
validateRequiredPropertiesForSsoCredentialsProvider();
202+
boolean isLegacy = isLegacySsoConfiguration();
203+
String sourceFeatureId = isLegacy ?
204+
BusinessMetricFeatureId.CREDENTIALS_PROFILE_SSO_LEGACY.value() :
205+
BusinessMetricFeatureId.CREDENTIALS_PROFILE_SSO.value();
206+
198207
return ssoCredentialsProviderFactory().create(
199208
ProfileProviderCredentialsContext.builder()
200209
.profile(profile)
201210
.profileFile(profileFile)
211+
.source(sourceFeatureId)
202212
.build());
203213
}
204214

@@ -211,6 +221,10 @@ private void validateRequiredPropertiesForSsoCredentialsProvider() {
211221
}
212222
}
213223

224+
private boolean isLegacySsoConfiguration() {
225+
return !properties.containsKey(ProfileSection.SSO_SESSION.getPropertyKeyName());
226+
}
227+
214228
private AwsCredentialsProvider roleAndWebIdentityTokenProfileCredentialsProvider() {
215229
requireProperties(ProfileProperty.ROLE_ARN, ProfileProperty.WEB_IDENTITY_TOKEN_FILE);
216230

@@ -223,6 +237,7 @@ private AwsCredentialsProvider roleAndWebIdentityTokenProfileCredentialsProvider
223237
.roleArn(roleArn)
224238
.roleSessionName(roleSessionName)
225239
.webIdentityTokenFile(webIdentityTokenFile)
240+
.source(BusinessMetricFeatureId.CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN.value())
226241
.build();
227242

228243
return WebIdentityCredentialsUtils.factory().create(credentialProperties);
@@ -249,7 +264,8 @@ private AwsCredentialsProvider roleAndSourceProfileBasedProfileCredentialsProvid
249264
.credentialsProvider(children))
250265
.orElseThrow(this::noSourceCredentialsException);
251266

252-
return stsCredentialsProviderFactory().create(sourceCredentialsProvider, profile);
267+
String sourceFeatureId = BusinessMetricFeatureId.CREDENTIALS_PROFILE_SOURCE_PROFILE.value();
268+
return createStsCredentialsProviderWithMetrics(sourceCredentialsProvider, sourceFeatureId);
253269
}
254270

255271
/**
@@ -260,8 +276,10 @@ private AwsCredentialsProvider roleAndCredentialSourceBasedProfileCredentialsPro
260276
requireProperties(ProfileProperty.CREDENTIAL_SOURCE);
261277

262278
CredentialSourceType credentialSource = CredentialSourceType.parse(properties.get(ProfileProperty.CREDENTIAL_SOURCE));
279+
String profileSource = BusinessMetricFeatureId.CREDENTIALS_PROFILE_NAMED_PROVIDER.value();
263280
AwsCredentialsProvider credentialsProvider = credentialSourceCredentialProvider(credentialSource);
264-
return stsCredentialsProviderFactory().create(credentialsProvider, profile);
281+
282+
return createStsCredentialsProviderWithMetrics(credentialsProvider, profileSource);
265283
}
266284

267285
private AwsCredentialsProvider credentialSourceCredentialProvider(CredentialSourceType credentialSource) {
@@ -298,6 +316,39 @@ private IllegalStateException noSourceCredentialsException() {
298316
return new IllegalStateException(error);
299317
}
300318

319+
/**
320+
* Extract business metrics from a credentials provider by resolving credentials and checking the provider name.
321+
* This is used to propagate business metrics from source credentials to assume role operations.
322+
*/
323+
private String extractBusinessMetricsFromProvider(AwsCredentialsProvider credentialsProvider) {
324+
try {
325+
AwsCredentials credentials = credentialsProvider.resolveCredentials();
326+
return credentials.providerName().orElse(null);
327+
} catch (Exception e) {
328+
return null;
329+
}
330+
}
331+
332+
/**
333+
* Helper method to create STS credentials provider with business metrics propagation.
334+
* This method extracts business metrics from the source credentials provider and combines them
335+
* with the profile-level business metrics before creating the STS credentials provider.
336+
*/
337+
private AwsCredentialsProvider createStsCredentialsProviderWithMetrics(AwsCredentialsProvider sourceCredentialsProvider,
338+
String profileMetric) {
339+
String sourceMetrics = extractBusinessMetricsFromProvider(sourceCredentialsProvider);
340+
341+
String combinedSource = profileMetric;
342+
if (sourceMetrics != null && !sourceMetrics.isEmpty()) {
343+
combinedSource = profileMetric + "," + sourceMetrics;
344+
}
345+
346+
ChildProfileCredentialsProviderFactory.ChildProfileCredentialsRequest request =
347+
new ChildProfileCredentialsProviderFactory
348+
.ChildProfileCredentialsRequest(sourceCredentialsProvider, profile, combinedSource);
349+
return stsCredentialsProviderFactory().create(request);
350+
}
351+
301352
/**
302353
* Load the factory that can be used to create the STS credentials provider, assuming it is on the classpath.
303354
*/

0 commit comments

Comments
 (0)