Skip to content

Commit a77e559

Browse files
committed
Feature IDs implem for SSO Creds
1 parent 685e7ac commit a77e559

5 files changed

Lines changed: 60 additions & 27 deletions

File tree

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ private AwsCredentialsProvider roleAndSourceProfileBasedProfileCredentialsProvid
261261
.credentialsProvider(children))
262262
.orElseThrow(this::noSourceCredentialsException);
263263

264-
return stsCredentialsProviderFactory().create(sourceCredentialsProvider, profile);
264+
String source = BusinessMetricFeatureId.CREDENTIALS_PROFILE_SOURCE_PROFILE.value();
265+
return stsCredentialsProviderFactory().create(sourceCredentialsProvider, profile, source);
265266
}
266267

267268
/**

services/sso/src/main/java/software/amazon/awssdk/services/sso/auth/SsoCredentialsProvider.java

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@
2525
import software.amazon.awssdk.auth.credentials.AwsCredentials;
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.sso.SsoClient;
2930
import software.amazon.awssdk.services.sso.internal.SessionCredentialsHolder;
3031
import software.amazon.awssdk.services.sso.model.GetRoleCredentialsRequest;
3132
import software.amazon.awssdk.services.sso.model.RoleCredentials;
3233
import software.amazon.awssdk.utils.SdkAutoCloseable;
34+
import software.amazon.awssdk.utils.StringUtils;
3335
import software.amazon.awssdk.utils.builder.CopyableBuilder;
3436
import software.amazon.awssdk.utils.builder.ToCopyableBuilder;
3537
import software.amazon.awssdk.utils.cache.CachedSupplier;
@@ -51,14 +53,15 @@
5153
@SdkPublicApi
5254
public final class SsoCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable,
5355
ToCopyableBuilder<SsoCredentialsProvider.Builder, SsoCredentialsProvider> {
54-
private static final String PROVIDER_NAME = "SsoCredentialsProvider";
56+
private static final String PROVIDER_NAME = BusinessMetricFeatureId.CREDENTIALS_SSO.value();
5557

5658
private static final Duration DEFAULT_STALE_TIME = Duration.ofMinutes(1);
5759
private static final Duration DEFAULT_PREFETCH_TIME = Duration.ofMinutes(5);
5860

5961
private static final String ASYNC_THREAD_NAME = "sdk-sso-credentials-provider";
6062

6163
private final Supplier<GetRoleCredentialsRequest> getRoleCredentialsRequestSupplier;
64+
private final String source;
6265

6366
private final SsoClient ssoClient;
6467
private final Duration staleTime;
@@ -77,6 +80,7 @@ private SsoCredentialsProvider(BuilderImpl builder) {
7780

7881
this.staleTime = Optional.ofNullable(builder.staleTime).orElse(DEFAULT_STALE_TIME);
7982
this.prefetchTime = Optional.ofNullable(builder.prefetchTime).orElse(DEFAULT_PREFETCH_TIME);
83+
this.source = builder.source;
8084

8185
this.asyncCredentialUpdateEnabled = builder.asyncCredentialUpdateEnabled;
8286
CachedSupplier.Builder<SessionCredentialsHolder> cacheBuilder =
@@ -95,11 +99,11 @@ private SsoCredentialsProvider(BuilderImpl builder) {
9599
*/
96100
private RefreshResult<SessionCredentialsHolder> updateSsoCredentials() {
97101
SessionCredentialsHolder credentials = getUpdatedCredentials(ssoClient);
98-
Instant acutalTokenExpiration = credentials.sessionCredentialsExpiration();
102+
Instant actualTokenExpiration = credentials.sessionCredentialsExpiration();
99103

100104
return RefreshResult.builder(credentials)
101-
.staleTime(acutalTokenExpiration.minus(staleTime))
102-
.prefetchTime(acutalTokenExpiration.minus(prefetchTime))
105+
.staleTime(actualTokenExpiration.minus(staleTime))
106+
.prefetchTime(actualTokenExpiration.minus(prefetchTime))
103107
.build();
104108
}
105109

@@ -112,11 +116,19 @@ private SessionCredentialsHolder getUpdatedCredentials(SsoClient ssoClient) {
112116
.secretAccessKey(roleCredentials.secretAccessKey())
113117
.sessionToken(roleCredentials.sessionToken())
114118
.accountId(request.accountId())
115-
.providerName(PROVIDER_NAME)
119+
.providerName(providerName())
116120
.build();
117121
return new SessionCredentialsHolder(sessionCredentials, Instant.ofEpochMilli(roleCredentials.expiration()));
118122
}
119123

124+
private String providerName() {
125+
String providerName = PROVIDER_NAME;
126+
if (!StringUtils.isEmpty(this.source)) {
127+
providerName = String.format("%s,%s", this.source, providerName);
128+
}
129+
return providerName;
130+
}
131+
120132
/**
121133
* The amount of time, relative to session token expiration, that the cached credentials are considered stale and
122134
* should no longer be used. All threads will block until the value is updated.
@@ -206,6 +218,12 @@ public interface Builder extends CopyableBuilder<Builder, SsoCredentialsProvider
206218
*/
207219
Builder refreshRequest(Supplier<GetRoleCredentialsRequest> getRoleCredentialsRequestSupplier);
208220

221+
/**
222+
* An optional string list of {@link software.amazon.awssdk.core.useragent.BusinessMetricFeatureId} denoting previous
223+
* credentials providers that are chained with this one.
224+
*/
225+
Builder source(String source);
226+
209227
/**
210228
* Create a {@link SsoCredentialsProvider} using the configuration applied to this builder.
211229
* @return
@@ -220,6 +238,7 @@ protected static final class BuilderImpl implements Builder {
220238
private Duration staleTime;
221239
private Duration prefetchTime;
222240
private Supplier<GetRoleCredentialsRequest> getRoleCredentialsRequestSupplier;
241+
private String source;
223242

224243
BuilderImpl() {
225244

@@ -231,6 +250,7 @@ public BuilderImpl(SsoCredentialsProvider provider) {
231250
this.staleTime = provider.staleTime;
232251
this.prefetchTime = provider.prefetchTime;
233252
this.getRoleCredentialsRequestSupplier = provider.getRoleCredentialsRequestSupplier;
253+
this.source = provider.source;
234254
}
235255

236256
@Override
@@ -268,6 +288,12 @@ public Builder refreshRequest(Supplier<GetRoleCredentialsRequest> getRoleCredent
268288
return this;
269289
}
270290

291+
@Override
292+
public Builder source(String source) {
293+
this.source = source;
294+
return this;
295+
}
296+
271297
@Override
272298
public SsoCredentialsProvider build() {
273299
return new SsoCredentialsProvider(this);

services/sso/src/main/java/software/amazon/awssdk/services/sso/auth/SsoProfileCredentialsProviderFactory.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,37 +63,35 @@ public class SsoProfileCredentialsProviderFactory implements ProfileCredentialsP
6363
*/
6464
@Override
6565
public AwsCredentialsProvider create(ProfileProviderCredentialsContext credentialsContext) {
66-
return new SsoProfileCredentialsProvider(credentialsContext.profile(),
67-
credentialsContext.profileFile(),
68-
sdkTokenProvider(credentialsContext.profile(),
69-
credentialsContext.profileFile()));
66+
return new SsoProfileCredentialsProvider(credentialsContext, sdkTokenProvider(credentialsContext));
7067
}
7168

7269
/**
7370
* Alternative method to create the {@link SsoProfileCredentialsProvider} with a customized {@link SsoAccessTokenProvider}.
7471
* This method is only used for testing.
7572
*/
7673
@SdkTestInternalApi
77-
public AwsCredentialsProvider create(Profile profile, ProfileFile profileFile,
74+
public AwsCredentialsProvider create(ProfileProviderCredentialsContext credentialsContext,
7875
SdkTokenProvider tokenProvider) {
79-
return new SsoProfileCredentialsProvider(profile, profileFile, tokenProvider);
76+
return new SsoProfileCredentialsProvider(credentialsContext, tokenProvider);
8077
}
8178

8279
/**
8380
* A wrapper for a {@link SsoCredentialsProvider} that is returned by this factory when {@link
84-
* #create(ProfileProviderCredentialsContext)} * or {@link #create(Profile, ProfileFile, SdkTokenProvider)} is invoked. This
85-
* wrapper is important because it ensures * the parent credentials provider is closed when the sso credentials provider is no
86-
* longer needed.
81+
* #create(ProfileProviderCredentialsContext)} * or {@link #create(ProfileProviderCredentialsContext, SdkTokenProvider)}
82+
* is invoked. This wrapper is important because it ensures * the parent credentials provider is closed when the sso
83+
* credentials provider is no longer needed.
8784
*/
8885
private static final class SsoProfileCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable {
8986
private final SsoClient ssoClient;
9087
private final SsoCredentialsProvider credentialsProvider;
9188

92-
private SsoProfileCredentialsProvider(Profile profile, ProfileFile profileFile,
89+
private SsoProfileCredentialsProvider(ProfileProviderCredentialsContext credentialsContext,
9390
SdkTokenProvider tokenProvider) {
91+
Profile profile = credentialsContext.profile();
9492
String ssoAccountId = profile.properties().get(ProfileProperty.SSO_ACCOUNT_ID);
9593
String ssoRoleName = profile.properties().get(ProfileProperty.SSO_ROLE_NAME);
96-
String ssoRegion = regionFromProfileOrSession(profile, profileFile);
94+
String ssoRegion = regionFromProfileOrSession(profile, credentialsContext.profileFile());
9795

9896
this.ssoClient = SsoClient.builder()
9997
.credentialsProvider(AnonymousCredentialsProvider.create())
@@ -114,6 +112,7 @@ private SsoProfileCredentialsProvider(Profile profile, ProfileFile profileFile,
114112
this.credentialsProvider = SsoCredentialsProvider.builder()
115113
.ssoClient(ssoClient)
116114
.refreshRequest(supplier)
115+
.source(credentialsContext.source())
117116
.build();
118117
}
119118

@@ -157,7 +156,9 @@ private static Profile ssoSessionInProfile(String sessionName, ProfileFile profi
157156
return ssoProfile;
158157
}
159158

160-
private static SdkTokenProvider sdkTokenProvider(Profile profile, ProfileFile profileFile) {
159+
private static SdkTokenProvider sdkTokenProvider(ProfileProviderCredentialsContext credentialsContext) {
160+
Profile profile = credentialsContext.profile();
161+
ProfileFile profileFile = credentialsContext.profileFile();
161162
Optional<String> ssoSession = profile.property(ProfileSection.SSO_SESSION.getPropertyKeyName());
162163

163164

@@ -172,11 +173,9 @@ private static SdkTokenProvider sdkTokenProvider(Profile profile, ProfileFile pr
172173
.profileFile(() -> profileFile)
173174
.profileName(profile.name())
174175
.build());
175-
} else {
176-
return new SsoAccessTokenProvider(generateCachedTokenPath(
177-
profile.properties().get(ProfileProperty.SSO_START_URL), TOKEN_DIRECTORY));
178-
179176
}
177+
return new SsoAccessTokenProvider(generateCachedTokenPath(profile.properties().get(ProfileProperty.SSO_START_URL),
178+
TOKEN_DIRECTORY));
180179
}
181180

182181
private static void validateCommonProfileProperties(Profile profile, Profile ssoSessionProfileFile, String propertyName) {

services/sso/src/test/java/software/amazon/awssdk/services/sso/auth/SsoCredentialsProviderTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.junit.jupiter.api.Test;
2828
import org.mockito.Mockito;
2929
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials;
30+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
3031
import software.amazon.awssdk.services.sso.SsoClient;
3132
import software.amazon.awssdk.services.sso.model.GetRoleCredentialsRequest;
3233
import software.amazon.awssdk.services.sso.model.GetRoleCredentialsResponse;
@@ -136,7 +137,7 @@ private void callClientWithCredentialsProvider(Instant credentialsExpirationDate
136137
assertThat(actualCredentials.accessKeyId()).isEqualTo("a");
137138
assertThat(actualCredentials.secretAccessKey()).isEqualTo("b");
138139
assertThat(actualCredentials.sessionToken()).isEqualTo("c");
139-
assertThat(actualCredentials.providerName()).isPresent().contains("SsoCredentialsProvider");
140+
assertThat(actualCredentials.providerName()).isPresent().contains(BusinessMetricFeatureId.CREDENTIALS_SSO.value());
140141
assertThat(actualCredentials.accountId()).isPresent().contains("123456789");
141142
}
142143
}

services/sso/src/test/java/software/amazon/awssdk/services/sso/auth/SsoProfileCredentialsProviderFactoryTest.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,12 @@ public void createSsoCredentialsProviderWithFactorySucceed() throws IOException
7979
cachedTokenFilePath);
8080

8181
SsoProfileCredentialsProviderFactory factory = new SsoProfileCredentialsProviderFactory();
82-
assertThat(factory.create(profileFile.profile("foo").get(),
83-
profileFile,
84-
tokenProvider)).isInstanceOf(AwsCredentialsProvider.class);
82+
assertThat(factory.create(ProfileProviderCredentialsContext.builder()
83+
.profile(profileFile.profile("foo").get())
84+
.profileFile(profileFile)
85+
.build(),
86+
tokenProvider))
87+
.isInstanceOf(AwsCredentialsProvider.class);
8588
}
8689

8790
private Path prepareTestCachedTokenFile(String tokenFileContent, String generatedTokenFileName) throws IOException {
@@ -169,7 +172,10 @@ public void tokenResolvedFromTokenProvider(@Mock SdkTokenProvider sdkTokenProvid
169172
"sso_start_url=https//d-abc123.awsapps.com/start");
170173
SsoProfileCredentialsProviderFactory factory = new SsoProfileCredentialsProviderFactory();
171174
when(sdkTokenProvider.resolveToken()).thenReturn(SsoAccessToken.builder().accessToken("sample").expiresAt(Instant.now()).build());
172-
AwsCredentialsProvider credentialsProvider = factory.create(profileFile.profile("test").get(), profileFile, sdkTokenProvider);
175+
AwsCredentialsProvider credentialsProvider = factory.create(ProfileProviderCredentialsContext.builder()
176+
.profile(profileFile.profile("test").get())
177+
.profileFile(profileFile)
178+
.build(), sdkTokenProvider);
173179
try {
174180
credentialsProvider.resolveCredentials();
175181
} catch (Exception e) {

0 commit comments

Comments
 (0)