@@ -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