Skip to content

Commit 278791f

Browse files
committed
Address PR feedback
1 parent fbeb0ae commit 278791f

File tree

8 files changed

+142
-92
lines changed

8 files changed

+142
-92
lines changed

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

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
* provider via the 'software.amazon.awssdk.services.sts.internal.StsProfileCredentialsProviderFactory', assuming STS is on the
2626
* classpath.
2727
*/
28-
@FunctionalInterface
2928
@SdkProtectedApi
3029
public interface ChildProfileCredentialsProviderFactory {
3130
/**
@@ -41,7 +40,10 @@ public interface ChildProfileCredentialsProviderFactory {
4140
* @return The credentials provider with permissions derived from the source credentials provider and profile.
4241
*/
4342
default AwsCredentialsProvider create(AwsCredentialsProvider sourceCredentialsProvider, Profile profile) {
44-
ChildProfileCredentialsRequest request = new ChildProfileCredentialsRequest(sourceCredentialsProvider, profile, null);
43+
ChildProfileCredentialsRequest request = ChildProfileCredentialsRequest.builder()
44+
.sourceCredentialsProvider(sourceCredentialsProvider)
45+
.profile(profile)
46+
.build();
4547
return create(request);
4648
}
4749

@@ -54,19 +56,23 @@ default AwsCredentialsProvider create(AwsCredentialsProvider sourceCredentialsPr
5456
* @param request The request containing all parameters needed to create the child credentials provider.
5557
* @return The credentials provider with permissions derived from the request parameters.
5658
*/
57-
AwsCredentialsProvider create(ChildProfileCredentialsRequest request);
59+
default AwsCredentialsProvider create(ChildProfileCredentialsRequest request) {
60+
throw new UnsupportedOperationException();
61+
}
5862

5963
final class ChildProfileCredentialsRequest {
6064
private final AwsCredentialsProvider sourceCredentialsProvider;
6165
private final Profile profile;
6266
private final String sourceFeatureId;
6367

64-
public ChildProfileCredentialsRequest(AwsCredentialsProvider sourceCredentialsProvider,
65-
Profile profile,
66-
String sourceFeatureId) {
67-
this.sourceCredentialsProvider = sourceCredentialsProvider;
68-
this.profile = profile;
69-
this.sourceFeatureId = sourceFeatureId;
68+
private ChildProfileCredentialsRequest(Builder builder) {
69+
this.sourceCredentialsProvider = builder.sourceCredentialsProvider;
70+
this.profile = builder.profile;
71+
this.sourceFeatureId = builder.sourceFeatureId;
72+
}
73+
74+
public static Builder builder() {
75+
return new Builder();
7076
}
7177

7278
public AwsCredentialsProvider sourceCredentialsProvider() {
@@ -80,5 +86,30 @@ public Profile profile() {
8086
public String sourceFeatureId() {
8187
return sourceFeatureId;
8288
}
89+
90+
public static final class Builder {
91+
private AwsCredentialsProvider sourceCredentialsProvider;
92+
private Profile profile;
93+
private String sourceFeatureId;
94+
95+
public Builder sourceCredentialsProvider(AwsCredentialsProvider sourceCredentialsProvider) {
96+
this.sourceCredentialsProvider = sourceCredentialsProvider;
97+
return this;
98+
}
99+
100+
public Builder profile(Profile profile) {
101+
this.profile = profile;
102+
return this;
103+
}
104+
105+
public Builder sourceFeatureId(String sourceFeatureId) {
106+
this.sourceFeatureId = sourceFeatureId;
107+
return this;
108+
}
109+
110+
public ChildProfileCredentialsRequest build() {
111+
return new ChildProfileCredentialsRequest(this);
112+
}
113+
}
83114
}
84115
}

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ private ContainerCredentialsProvider(BuilderImpl builder) {
106106
this.providerName = StringUtils.isEmpty(builder.sourceFeatureId)
107107
? PROVIDER_NAME
108108
: builder.sourceFeatureId + "," + PROVIDER_NAME;
109-
this.httpCredentialsLoader = HttpCredentialsLoader.create(providerName());
109+
this.httpCredentialsLoader = HttpCredentialsLoader.create(this.providerName);
110110

111111
if (Boolean.TRUE.equals(builder.asyncCredentialUpdateEnabled)) {
112112
Validate.paramNotBlank(builder.asyncThreadName, "asyncThreadName");
@@ -168,10 +168,6 @@ private Instant prefetchTime(Instant expiration) {
168168
return ComparableUtils.minimum(oneHourFromNow, fifteenMinutesBeforeExpiration);
169169
}
170170

171-
private String providerName() {
172-
return this.providerName;
173-
}
174-
175171
@Override
176172
public AwsCredentials resolveCredentials() {
177173
return credentialsCache.get();

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

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

1818
import software.amazon.awssdk.annotations.SdkPublicApi;
19-
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
2019
import software.amazon.awssdk.utils.SdkAutoCloseable;
2120

2221
/**
@@ -50,8 +49,7 @@ interface Builder<TypeToBuildT extends HttpCredentialsProvider, BuilderT extends
5049
BuilderT endpoint(String endpoint);
5150

5251
/**
53-
* An optional string list of {@link BusinessMetricFeatureId} denoting previous credentials providers
54-
* that are chained with this one.
52+
* An optional string denoting previous credentials providers that are chained with this one.
5553
* <p><b>Note:</b> This method is primarily intended for use by AWS SDK internal components
5654
* and should not be used directly by external users.</p>
5755
*/

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private InstanceProfileCredentialsProvider(BuilderImpl builder) {
113113
? PROVIDER_NAME
114114
: builder.sourceFeatureId + "," + PROVIDER_NAME;
115115

116-
this.httpCredentialsLoader = HttpCredentialsLoader.create(providerName());
116+
this.httpCredentialsLoader = HttpCredentialsLoader.create(this.providerName);
117117
this.configProvider =
118118
Ec2MetadataConfigProvider.builder()
119119
.profileFile(profileFile)
@@ -212,10 +212,6 @@ public void close() {
212212
credentialsCache.close();
213213
}
214214

215-
private String providerName() {
216-
return this.providerName;
217-
}
218-
219215
@Override
220216
public String toString() {
221217
return ToString.create(CLASS_NAME);

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,6 @@ private JsonNode parseProcessOutput(String processOutput) {
181181
return credentialsJson;
182182
}
183183

184-
private String providerName() {
185-
return this.providerName;
186-
}
187-
188184
/**
189185
* Parse the process output to retrieve the credentials.
190186
*/
@@ -206,13 +202,13 @@ private AwsCredentials credentials(JsonNode credentialsJson) {
206202
.sessionToken(sessionToken)
207203
.expirationTime(credentialExpirationTime(credentialsJson))
208204
.accountId(resolvedAccountId)
209-
.providerName(providerName())
205+
.providerName(this.providerName)
210206
.build() :
211207
AwsBasicCredentials.builder()
212208
.accessKeyId(accessKeyId)
213209
.secretAccessKey(secretAccessKey)
214210
.accountId(resolvedAccountId)
215-
.providerName(providerName())
211+
.providerName(this.providerName)
216212
.build();
217213
}
218214

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

Lines changed: 87 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,27 @@ public Optional<AwsCredentialsProvider> credentialsProvider() {
109109
* @param children The child profiles that source credentials from this profile.
110110
*/
111111
private Optional<AwsCredentialsProvider> credentialsProvider(Set<String> children) {
112+
return credentialsProviderWithMetrics(children).map(ProviderWithMetrics::provider);
113+
}
114+
115+
/**
116+
* Internal method that returns both the credentials provider and its business metrics.
117+
*/
118+
private Optional<ProviderWithMetrics> credentialsProviderWithMetrics(Set<String> children) {
112119
if (properties.containsKey(ProfileProperty.ROLE_ARN) && properties.containsKey(ProfileProperty.WEB_IDENTITY_TOKEN_FILE)) {
113-
return Optional.ofNullable(roleAndWebIdentityTokenProfileCredentialsProvider());
120+
return Optional.of(new ProviderWithMetrics(roleAndWebIdentityTokenProfileCredentialsProvider(),
121+
BusinessMetricFeatureId.CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN.value()));
114122
}
115123

116124
if (properties.containsKey(ProfileProperty.SSO_ROLE_NAME)
117125
|| properties.containsKey(ProfileProperty.SSO_ACCOUNT_ID)
118126
|| properties.containsKey(ProfileProperty.SSO_REGION)
119127
|| properties.containsKey(ProfileProperty.SSO_START_URL)
120128
|| properties.containsKey(ProfileSection.SSO_SESSION.getPropertyKeyName())) {
121-
return Optional.ofNullable(ssoProfileCredentialsProvider());
129+
boolean isLegacy = isLegacySsoConfiguration();
130+
String featureId = isLegacy ? BusinessMetricFeatureId.CREDENTIALS_PROFILE_SSO_LEGACY.value()
131+
: BusinessMetricFeatureId.CREDENTIALS_PROFILE_SSO.value();
132+
return Optional.of(new ProviderWithMetrics(ssoProfileCredentialsProvider(), featureId));
122133
}
123134

124135
if (properties.containsKey(ProfileProperty.ROLE_ARN)) {
@@ -138,15 +149,18 @@ private Optional<AwsCredentialsProvider> credentialsProvider(Set<String> childre
138149
}
139150

140151
if (properties.containsKey(ProfileProperty.CREDENTIAL_PROCESS)) {
141-
return Optional.ofNullable(credentialProcessCredentialsProvider());
152+
return Optional.of(new ProviderWithMetrics(credentialProcessCredentialsProvider(),
153+
BusinessMetricFeatureId.CREDENTIALS_PROFILE_PROCESS.value()));
142154
}
143155

144156
if (properties.containsKey(ProfileProperty.AWS_SESSION_TOKEN)) {
145-
return Optional.of(sessionProfileCredentialsProvider());
157+
return Optional.of(new ProviderWithMetrics(sessionProfileCredentialsProvider(),
158+
BusinessMetricFeatureId.CREDENTIALS_PROFILE.value()));
146159
}
147160

148161
if (properties.containsKey(ProfileProperty.AWS_ACCESS_KEY_ID)) {
149-
return Optional.of(basicProfileCredentialsProvider());
162+
return Optional.of(new ProviderWithMetrics(basicProfileCredentialsProvider(),
163+
BusinessMetricFeatureId.CREDENTIALS_PROFILE.value()));
150164
}
151165

152166
return Optional.empty();
@@ -250,53 +264,84 @@ private AwsCredentialsProvider roleAndWebIdentityTokenProfileCredentialsProvider
250264
*
251265
* @param children The child profiles that source credentials from this profile.
252266
*/
253-
private AwsCredentialsProvider roleAndSourceProfileBasedProfileCredentialsProvider(Set<String> children) {
267+
private ProviderWithMetrics roleAndSourceProfileBasedProfileCredentialsProvider(Set<String> children) {
254268
requireProperties(ProfileProperty.SOURCE_PROFILE);
255269

256270
Validate.validState(!children.contains(name),
257271
"Invalid profile file: Circular relationship detected with profiles %s.", children);
258272
Validate.validState(credentialsSourceResolver != null,
259-
"The profile '%s' must be configured with a source profile in order to use assumed roles.", name);
273+
"The profile '%s' must be configured with a source profile in order to use assumed roles.",
274+
name);
260275

261276
children.add(name);
262-
AwsCredentialsProvider sourceCredentialsProvider =
263-
credentialsSourceResolver.apply(properties.get(ProfileProperty.SOURCE_PROFILE))
264-
.flatMap(p -> new ProfileCredentialsUtils(profileFile, p, credentialsSourceResolver)
265-
.credentialsProvider(children))
266-
.orElseThrow(this::noSourceCredentialsException);
267-
268-
String sourceFeatureId = BusinessMetricFeatureId.CREDENTIALS_PROFILE_SOURCE_PROFILE.value();
269-
return createStsCredentialsProviderWithMetrics(sourceCredentialsProvider, sourceFeatureId);
277+
Optional<ProviderWithMetrics> sourceResult = credentialsSourceResolver
278+
.apply(properties.get(ProfileProperty.SOURCE_PROFILE))
279+
.flatMap(p -> new ProfileCredentialsUtils(profileFile, p, credentialsSourceResolver)
280+
.credentialsProviderWithMetrics(children));
281+
282+
if (!sourceResult.isPresent()) {
283+
throw noSourceCredentialsException();
284+
}
285+
286+
ProviderWithMetrics source = sourceResult.get();
287+
String profileMetric = BusinessMetricFeatureId.CREDENTIALS_PROFILE_SOURCE_PROFILE.value();
288+
String combinedMetrics = profileMetric + "," + source.metrics();
289+
290+
AwsCredentialsProvider stsProvider = createStsCredentialsProviderWithMetrics(source.provider(), combinedMetrics);
291+
return new ProviderWithMetrics(stsProvider, combinedMetrics);
270292
}
271293

272294
/**
273295
* Load an assumed-role credentials provider that has been configured in this profile. This will attempt to locate the STS
274296
* module in order to generate the credentials provider. If it's not available, an illegal state exception will be raised.
275297
*/
276-
private AwsCredentialsProvider roleAndCredentialSourceBasedProfileCredentialsProvider() {
298+
private ProviderWithMetrics roleAndCredentialSourceBasedProfileCredentialsProvider() {
277299
requireProperties(ProfileProperty.CREDENTIAL_SOURCE);
278300

279301
CredentialSourceType credentialSource = CredentialSourceType.parse(properties.get(ProfileProperty.CREDENTIAL_SOURCE));
280-
String profileSource = BusinessMetricFeatureId.CREDENTIALS_PROFILE_NAMED_PROVIDER.value();
281-
AwsCredentialsProvider credentialsProvider = credentialSourceCredentialProvider(credentialSource);
302+
String profileMetric = BusinessMetricFeatureId.CREDENTIALS_PROFILE_NAMED_PROVIDER.value();
303+
ProviderWithMetrics sourceResult = credentialSourceCredentialProviderWithMetrics(credentialSource);
304+
305+
String combinedMetrics = profileMetric + "," + sourceResult.metrics();
306+
AwsCredentialsProvider stsProvider = createStsCredentialsProviderWithMetrics(sourceResult.provider(), combinedMetrics);
307+
return new ProviderWithMetrics(stsProvider, combinedMetrics);
308+
}
282309

283-
return createStsCredentialsProviderWithMetrics(credentialsProvider, profileSource);
310+
/**
311+
* Helper method to create STS credentials provider with business metrics.
312+
*/
313+
private AwsCredentialsProvider createStsCredentialsProviderWithMetrics(AwsCredentialsProvider sourceProvider,
314+
String combinedMetrics) {
315+
ChildProfileCredentialsProviderFactory.ChildProfileCredentialsRequest request =
316+
ChildProfileCredentialsProviderFactory.ChildProfileCredentialsRequest.builder()
317+
.sourceCredentialsProvider(sourceProvider)
318+
.profile(profile)
319+
.sourceFeatureId(combinedMetrics)
320+
.build();
321+
322+
return stsCredentialsProviderFactory().create(request);
284323
}
285324

286-
private AwsCredentialsProvider credentialSourceCredentialProvider(CredentialSourceType credentialSource) {
325+
private ProviderWithMetrics credentialSourceCredentialProviderWithMetrics(CredentialSourceType credentialSource) {
287326
switch (credentialSource) {
288327
case ECS_CONTAINER:
289-
return ContainerCredentialsProvider.builder().build();
328+
return new ProviderWithMetrics(
329+
ContainerCredentialsProvider.builder().build(),
330+
BusinessMetricFeatureId.CREDENTIALS_HTTP.value());
290331
case EC2_INSTANCE_METADATA:
291-
return InstanceProfileCredentialsProvider.builder()
292-
.profileFile(profileFile)
293-
.profileName(name)
294-
.build();
332+
return new ProviderWithMetrics(
333+
InstanceProfileCredentialsProvider.builder()
334+
.profileFile(profileFile)
335+
.profileName(name)
336+
.build(),
337+
BusinessMetricFeatureId.CREDENTIALS_IMDS.value());
295338
case ENVIRONMENT:
296-
return AwsCredentialsProviderChain.builder()
297-
.addCredentialsProvider(SystemPropertyCredentialsProvider.create())
298-
.addCredentialsProvider(EnvironmentVariableCredentialsProvider.create())
299-
.build();
339+
return new ProviderWithMetrics(
340+
AwsCredentialsProviderChain.builder()
341+
.addCredentialsProvider(SystemPropertyCredentialsProvider.create())
342+
.addCredentialsProvider(EnvironmentVariableCredentialsProvider.create())
343+
.build(),
344+
BusinessMetricFeatureId.CREDENTIALS_ENV_VARS.value());
300345
default:
301346
throw noSourceCredentialsException();
302347
}
@@ -318,36 +363,24 @@ private IllegalStateException noSourceCredentialsException() {
318363
}
319364

320365
/**
321-
* Extract business metrics from a credentials provider by resolving credentials and checking the provider name.
322-
* This is used to propagate business metrics from source credentials to assume role operations.
366+
* Simple data class to hold both a credentials provider and its business metrics.
323367
*/
324-
private String extractBusinessMetricsFromProvider(AwsCredentialsProvider credentialsProvider) {
325-
try {
326-
AwsCredentials credentials = credentialsProvider.resolveCredentials();
327-
return credentials.providerName().orElse(null);
328-
} catch (Exception e) {
329-
return null;
330-
}
331-
}
368+
private static final class ProviderWithMetrics {
369+
private final AwsCredentialsProvider provider;
370+
private final String metrics;
332371

333-
/**
334-
* Helper method to create STS credentials provider with business metrics propagation.
335-
* This method extracts business metrics from the source credentials provider and combines them
336-
* with the profile-level business metrics before creating the STS credentials provider.
337-
*/
338-
private AwsCredentialsProvider createStsCredentialsProviderWithMetrics(AwsCredentialsProvider sourceCredentialsProvider,
339-
String profileMetric) {
340-
String sourceMetrics = extractBusinessMetricsFromProvider(sourceCredentialsProvider);
372+
ProviderWithMetrics(AwsCredentialsProvider provider, String metrics) {
373+
this.provider = provider;
374+
this.metrics = metrics;
375+
}
341376

342-
String combinedSource = profileMetric;
343-
if (sourceMetrics != null && !sourceMetrics.isEmpty()) {
344-
combinedSource = profileMetric + "," + sourceMetrics;
377+
AwsCredentialsProvider provider() {
378+
return provider;
345379
}
346380

347-
ChildProfileCredentialsProviderFactory.ChildProfileCredentialsRequest request =
348-
new ChildProfileCredentialsProviderFactory
349-
.ChildProfileCredentialsRequest(sourceCredentialsProvider, profile, combinedSource);
350-
return stsCredentialsProviderFactory().create(request);
381+
String metrics() {
382+
return metrics;
383+
}
351384
}
352385

353386
/**

0 commit comments

Comments
 (0)