Skip to content

Commit 077e209

Browse files
committed
Feature IDs implementation for STS credentials
1 parent 7c78438 commit 077e209

23 files changed

+1228
-39
lines changed

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,23 @@ 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+
return create(sourceCredentialsProvider, profile, null);
45+
}
46+
47+
/**
48+
* Create a credentials provider for the provided profile, using the provided source credentials provider to authenticate
49+
* with AWS. In the case of STS, the returned credentials provider is for a role that has been assumed, and the provided
50+
* source credentials provider is the credentials that should be used to authenticate that the user is allowed to assume
51+
* that role.
52+
*
53+
* @param sourceCredentialsProvider The credentials provider that should be used to authenticate the child credentials
54+
* provider. This credentials provider should be closed when it is no longer used.
55+
* @param profile The profile that should be used to load the configuration necessary to create the child credentials
56+
* provider.
57+
* @param source A string list of {@link software.amazon.awssdk.core.useragent.BusinessMetricFeatureId} denoting
58+
* previous credentials providers that are chained with this one.
59+
* @return The credentials provider with permissions derived from the source credentials provider and profile.
60+
*/
61+
AwsCredentialsProvider create(AwsCredentialsProvider sourceCredentialsProvider, Profile profile, String source);
4462
}

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/internal/ProfileCredentialsUtils.java

Lines changed: 20 additions & 6 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,28 +190,36 @@ 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

193197
/**
194198
* Create the SSO credentials provider based on the related profile properties.
195199
*/
196200
private AwsCredentialsProvider ssoProfileCredentialsProvider() {
197-
validateRequiredPropertiesForSsoCredentialsProvider();
201+
boolean isLegacy = validateRequiredPropertiesForSsoCredentialsProvider();
202+
String source = isLegacy ?
203+
BusinessMetricFeatureId.CREDENTIALS_PROFILE_SSO_LEGACY.value() :
204+
BusinessMetricFeatureId.CREDENTIALS_PROFILE_SSO.value();
205+
198206
return ssoCredentialsProviderFactory().create(
199207
ProfileProviderCredentialsContext.builder()
200208
.profile(profile)
201209
.profileFile(profileFile)
210+
.source(source)
202211
.build());
203212
}
204213

205-
private void validateRequiredPropertiesForSsoCredentialsProvider() {
214+
private boolean validateRequiredPropertiesForSsoCredentialsProvider() {
206215
requireProperties(ProfileProperty.SSO_ACCOUNT_ID,
207216
ProfileProperty.SSO_ROLE_NAME);
208217

209218
if (!properties.containsKey(ProfileSection.SSO_SESSION.getPropertyKeyName())) {
210219
requireProperties(ProfileProperty.SSO_REGION, ProfileProperty.SSO_START_URL);
220+
return true;
211221
}
222+
return false;
212223
}
213224

214225
private AwsCredentialsProvider roleAndWebIdentityTokenProfileCredentialsProvider() {
@@ -223,6 +234,7 @@ private AwsCredentialsProvider roleAndWebIdentityTokenProfileCredentialsProvider
223234
.roleArn(roleArn)
224235
.roleSessionName(roleSessionName)
225236
.webIdentityTokenFile(webIdentityTokenFile)
237+
.source(BusinessMetricFeatureId.CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN.value())
226238
.build();
227239

228240
return WebIdentityCredentialsUtils.factory().create(credentialProperties);
@@ -260,18 +272,20 @@ private AwsCredentialsProvider roleAndCredentialSourceBasedProfileCredentialsPro
260272
requireProperties(ProfileProperty.CREDENTIAL_SOURCE);
261273

262274
CredentialSourceType credentialSource = CredentialSourceType.parse(properties.get(ProfileProperty.CREDENTIAL_SOURCE));
263-
AwsCredentialsProvider credentialsProvider = credentialSourceCredentialProvider(credentialSource);
264-
return stsCredentialsProviderFactory().create(credentialsProvider, profile);
275+
String source = BusinessMetricFeatureId.CREDENTIALS_PROFILE_NAMED_PROVIDER.value();
276+
AwsCredentialsProvider credentialsProvider = credentialSourceCredentialProvider(credentialSource, source);
277+
return stsCredentialsProviderFactory().create(credentialsProvider, profile, source);
265278
}
266279

267-
private AwsCredentialsProvider credentialSourceCredentialProvider(CredentialSourceType credentialSource) {
280+
private AwsCredentialsProvider credentialSourceCredentialProvider(CredentialSourceType credentialSource, String source) {
268281
switch (credentialSource) {
269282
case ECS_CONTAINER:
270-
return ContainerCredentialsProvider.builder().build();
283+
return ContainerCredentialsProvider.builder().source(source).build();
271284
case EC2_INSTANCE_METADATA:
272285
return InstanceProfileCredentialsProvider.builder()
273286
.profileFile(profileFile)
274287
.profileName(name)
288+
.source(source)
275289
.build();
276290
case ENVIRONMENT:
277291
return AwsCredentialsProviderChain.builder()

services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsAssumeRoleCredentialsProvider.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
import software.amazon.awssdk.annotations.ThreadSafe;
2626
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
2727
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
28+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
2829
import software.amazon.awssdk.services.sts.StsClient;
2930
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;
3031
import software.amazon.awssdk.services.sts.model.AssumeRoleResponse;
32+
import software.amazon.awssdk.utils.StringUtils;
3133
import software.amazon.awssdk.utils.ToString;
3234
import software.amazon.awssdk.utils.Validate;
3335
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
@@ -49,8 +51,9 @@
4951
public final class StsAssumeRoleCredentialsProvider
5052
extends StsCredentialsProvider
5153
implements ToCopyableBuilder<StsAssumeRoleCredentialsProvider.Builder, StsAssumeRoleCredentialsProvider> {
52-
private static final String PROVIDER_NAME = "StsAssumeRoleCredentialsProvider";
54+
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_STS_ASSUME_ROLE.value();
5355
private final Supplier<AssumeRoleRequest> assumeRoleRequestSupplier;
56+
private final String source;
5457

5558
/**
5659
* @see #builder()
@@ -60,6 +63,7 @@ private StsAssumeRoleCredentialsProvider(Builder builder) {
6063
Validate.notNull(builder.assumeRoleRequestSupplier, "Assume role request must not be null.");
6164

6265
this.assumeRoleRequestSupplier = builder.assumeRoleRequestSupplier;
66+
this.source = builder.source;
6367
}
6468

6569
/**
@@ -75,7 +79,7 @@ protected AwsSessionCredentials getUpdatedCredentials(StsClient stsClient) {
7579
Validate.notNull(assumeRoleRequest, "Assume role request must not be null.");
7680
AssumeRoleResponse assumeRoleResponse = stsClient.assumeRole(assumeRoleRequest);
7781
return fromStsCredentials(assumeRoleResponse.credentials(),
78-
PROVIDER_NAME,
82+
providerName(),
7983
accountIdFromArn(assumeRoleResponse.assumedRoleUser()));
8084
}
8185

@@ -93,7 +97,11 @@ public Builder toBuilder() {
9397

9498
@Override
9599
String providerName() {
96-
return PROVIDER_NAME;
100+
String providerName = PROVIDER_NAME;
101+
if (!StringUtils.isEmpty(this.source)) {
102+
providerName = String.format("%s,%s", this.source, providerName);
103+
}
104+
return providerName;
97105
}
98106

99107
/**
@@ -103,6 +111,7 @@ String providerName() {
103111
@NotThreadSafe
104112
public static final class Builder extends BaseBuilder<Builder, StsAssumeRoleCredentialsProvider> {
105113
private Supplier<AssumeRoleRequest> assumeRoleRequestSupplier;
114+
private String source;
106115

107116
private Builder() {
108117
super(StsAssumeRoleCredentialsProvider::new);
@@ -111,6 +120,7 @@ private Builder() {
111120
private Builder(StsAssumeRoleCredentialsProvider provider) {
112121
super(StsAssumeRoleCredentialsProvider::new, provider);
113122
this.assumeRoleRequestSupplier = provider.assumeRoleRequestSupplier;
123+
this.source = provider.source;
114124
}
115125

116126
/**
@@ -145,6 +155,15 @@ public Builder refreshRequest(Consumer<AssumeRoleRequest.Builder> assumeRoleRequ
145155
return refreshRequest(AssumeRoleRequest.builder().applyMutation(assumeRoleRequest).build());
146156
}
147157

158+
/**
159+
* An optional string list of {@link BusinessMetricFeatureId} denoting previous credentials providers
160+
* that are chained with this one.
161+
*/
162+
public Builder source(String source) {
163+
this.source = source;
164+
return this;
165+
}
166+
148167
@Override
149168
public StsAssumeRoleCredentialsProvider build() {
150169
return super.build();

services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsAssumeRoleWithSamlCredentialsProvider.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
import software.amazon.awssdk.annotations.ThreadSafe;
2626
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
2727
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
28+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
2829
import software.amazon.awssdk.services.sts.StsClient;
2930
import software.amazon.awssdk.services.sts.model.AssumeRoleWithSamlRequest;
3031
import software.amazon.awssdk.services.sts.model.AssumeRoleWithSamlResponse;
32+
import software.amazon.awssdk.utils.StringUtils;
3133
import software.amazon.awssdk.utils.Validate;
3234
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
3335

@@ -48,8 +50,9 @@
4850
public final class StsAssumeRoleWithSamlCredentialsProvider
4951
extends StsCredentialsProvider
5052
implements ToCopyableBuilder<StsAssumeRoleWithSamlCredentialsProvider.Builder, StsAssumeRoleWithSamlCredentialsProvider> {
51-
private static final String PROVIDER_NAME = "StsAssumeRoleWithSamlCredentialsProvider";
53+
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_STS_ASSUME_ROLE_SAML.value();
5254
private final Supplier<AssumeRoleWithSamlRequest> assumeRoleWithSamlRequestSupplier;
55+
private final String source;
5356

5457

5558
/**
@@ -60,6 +63,7 @@ private StsAssumeRoleWithSamlCredentialsProvider(Builder builder) {
6063
Validate.notNull(builder.assumeRoleWithSamlRequestSupplier, "Assume role with SAML request must not be null.");
6164

6265
this.assumeRoleWithSamlRequestSupplier = builder.assumeRoleWithSamlRequestSupplier;
66+
this.source = builder.source;
6367
}
6468

6569
/**
@@ -75,7 +79,7 @@ protected AwsSessionCredentials getUpdatedCredentials(StsClient stsClient) {
7579
Validate.notNull(assumeRoleWithSamlRequest, "Assume role with saml request must not be null.");
7680
AssumeRoleWithSamlResponse assumeRoleResponse = stsClient.assumeRoleWithSAML(assumeRoleWithSamlRequest);
7781
return fromStsCredentials(assumeRoleResponse.credentials(),
78-
PROVIDER_NAME,
82+
providerName(),
7983
accountIdFromArn(assumeRoleResponse.assumedRoleUser()));
8084
}
8185

@@ -86,7 +90,11 @@ public Builder toBuilder() {
8690

8791
@Override
8892
String providerName() {
89-
return PROVIDER_NAME;
93+
String providerName = PROVIDER_NAME;
94+
if (!StringUtils.isEmpty(this.source)) {
95+
providerName = String.format("%s,%s", this.source, providerName);
96+
}
97+
return providerName;
9098
}
9199

92100
/**
@@ -96,6 +104,7 @@ String providerName() {
96104
@NotThreadSafe
97105
public static final class Builder extends BaseBuilder<Builder, StsAssumeRoleWithSamlCredentialsProvider> {
98106
private Supplier<AssumeRoleWithSamlRequest> assumeRoleWithSamlRequestSupplier;
107+
private String source;
99108

100109
private Builder() {
101110
super(StsAssumeRoleWithSamlCredentialsProvider::new);
@@ -104,6 +113,7 @@ private Builder() {
104113
public Builder(StsAssumeRoleWithSamlCredentialsProvider provider) {
105114
super(StsAssumeRoleWithSamlCredentialsProvider::new, provider);
106115
this.assumeRoleWithSamlRequestSupplier = provider.assumeRoleWithSamlRequestSupplier;
116+
this.source = provider.source;
107117
}
108118

109119
/**
@@ -138,6 +148,18 @@ public Builder refreshRequest(Consumer<AssumeRoleWithSamlRequest.Builder> assume
138148
return refreshRequest(AssumeRoleWithSamlRequest.builder().applyMutation(assumeRoleWithSamlRequest).build());
139149
}
140150

151+
/**
152+
* Configure the source of this credentials provider. This is used for business metrics tracking
153+
* to identify the credential provider chain.
154+
*
155+
* @param source The source identifier for business metrics tracking.
156+
* @return This object for chained calls.
157+
*/
158+
public Builder source(String source) {
159+
this.source = source;
160+
return this;
161+
}
162+
141163
@Override
142164
public StsAssumeRoleWithSamlCredentialsProvider build() {
143165
return super.build();

0 commit comments

Comments
 (0)