Skip to content

Commit de5dc7f

Browse files
authored
misc: credentials business metrics (#1442)
1 parent 75e9644 commit de5dc7f

File tree

51 files changed

+680
-220
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+680
-220
lines changed

aws-runtime/aws-config/api/aws-config.api

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,6 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/InvalidSsoTokenExcept
9797
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
9898
}
9999

100-
public final class aws/sdk/kotlin/runtime/auth/credentials/LazilyInitializedCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CredentialsProvider {
101-
public fun <init> (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
102-
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
103-
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
104-
public fun toString ()Ljava/lang/String;
105-
}
106-
107100
public final class aws/sdk/kotlin/runtime/auth/credentials/ProcessCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CredentialsProvider {
108101
public fun <init> (Ljava/lang/String;Laws/smithy/kotlin/runtime/util/PlatformProvider;JJ)V
109102
public synthetic fun <init> (Ljava/lang/String;Laws/smithy/kotlin/runtime/util/PlatformProvider;JJILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -216,6 +209,17 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredent
216209
public static synthetic fun fromEnvironment-TUY-ock$default (Laws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredentialsProvider$Companion;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JLaws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;ILjava/lang/Object;)Laws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredentialsProvider;
217210
}
218211

212+
public final class aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CloseableCredentialsProvider {
213+
public fun <init> ()V
214+
public fun <init> (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;Ljava/lang/String;)V
215+
public synthetic fun <init> (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
216+
public fun close ()V
217+
public final fun getHttpClient ()Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;
218+
public final fun getPlatformProvider ()Laws/smithy/kotlin/runtime/util/PlatformProvider;
219+
public final fun getRegion ()Ljava/lang/String;
220+
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
221+
}
222+
219223
public final class aws/sdk/kotlin/runtime/auth/credentials/SystemPropertyCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CredentialsProvider {
220224
public fun <init> ()V
221225
public fun <init> (Lkotlin/jvm/functions/Function1;)V

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/DefaultChainCredentialsProvider.kt

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ package aws.sdk.kotlin.runtime.auth.credentials
77

88
import aws.sdk.kotlin.runtime.config.AwsSdkSetting
99
import aws.sdk.kotlin.runtime.config.imds.ImdsClient
10+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric
11+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric
1012
import aws.smithy.kotlin.runtime.auth.awscredentials.*
1113
import aws.smithy.kotlin.runtime.collections.Attributes
1214
import aws.smithy.kotlin.runtime.http.engine.DefaultHttpEngine
@@ -52,14 +54,8 @@ public class DefaultChainCredentialsProvider constructor(
5254
private val chain = CredentialsProviderChain(
5355
SystemPropertyCredentialsProvider(platformProvider::getProperty),
5456
EnvironmentCredentialsProvider(platformProvider::getenv),
55-
LazilyInitializedCredentialsProvider("EnvironmentStsWebIdentityCredentialsProvider") {
56-
// STS web identity provider can be constructed from either the profile OR 100% from the environment
57-
StsWebIdentityCredentialsProvider.fromEnvironment(
58-
platformProvider = platformProvider,
59-
httpClient = httpClient,
60-
region = region,
61-
)
62-
},
57+
// STS web identity provider can be constructed from either the profile OR 100% from the environment
58+
StsWebIdentityProvider(platformProvider = platformProvider, httpClient = engine, region = region),
6359
ProfileCredentialsProvider(profileName = profileName, platformProvider = platformProvider, httpClient = engine, region = region),
6460
EcsCredentialsProvider(platformProvider, engine),
6561
ImdsCredentialsProvider(
@@ -86,3 +82,20 @@ public class DefaultChainCredentialsProvider constructor(
8682

8783
override fun toString(): String = this.simpleClassName + ": " + this.chain
8884
}
85+
86+
/**
87+
* Wrapper around [StsWebIdentityCredentialsProvider] that delays any exceptions until [resolve] is invoked.
88+
* This allows it to be part of the default chain and any failures result in the chain to move onto the next provider.
89+
*/
90+
public class StsWebIdentityProvider(
91+
public val platformProvider: PlatformProvider = PlatformProvider.System,
92+
public val httpClient: HttpClientEngine? = null,
93+
public val region: String? = null,
94+
) : CloseableCredentialsProvider {
95+
override suspend fun resolve(attributes: Attributes): Credentials {
96+
val wrapped = StsWebIdentityCredentialsProvider.fromEnvironment(platformProvider = platformProvider, httpClient = httpClient, region = region)
97+
return wrapped.resolve(attributes).withBusinessMetric(AwsBusinessMetric.Credentials.CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN)
98+
}
99+
100+
override fun close() { }
101+
}

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/EcsCredentialsProvider.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ package aws.sdk.kotlin.runtime.auth.credentials
77

88
import aws.sdk.kotlin.runtime.auth.credentials.internal.credentials
99
import aws.sdk.kotlin.runtime.config.AwsSdkSetting
10+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric
11+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric
1012
import aws.smithy.kotlin.runtime.ErrorMetadata
1113
import aws.smithy.kotlin.runtime.auth.awscredentials.*
1214
import aws.smithy.kotlin.runtime.client.endpoints.Endpoint
@@ -76,6 +78,7 @@ public class EcsCredentialsProvider(
7678

7779
override suspend fun resolve(attributes: Attributes): Credentials {
7880
val logger = coroutineContext.logger<EcsCredentialsProvider>()
81+
7982
val authToken = loadAuthToken()
8083
val relativeUri = AwsSdkSetting.AwsContainerCredentialsRelativeUri.resolve(platformProvider)
8184
val fullUri = AwsSdkSetting.AwsContainerCredentialsFullUri.resolve(platformProvider)
@@ -110,7 +113,7 @@ public class EcsCredentialsProvider(
110113

111114
logger.debug { "obtained credentials from container metadata service; expiration=${creds.expiration?.format(TimestampFormat.ISO_8601)}" }
112115

113-
return creds
116+
return creds.withBusinessMetric(AwsBusinessMetric.Credentials.CREDENTIALS_HTTP)
114117
}
115118

116119
private suspend fun loadAuthToken(): String? {

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/EnvironmentCredentialsProvider.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ package aws.sdk.kotlin.runtime.auth.credentials
77

88
import aws.sdk.kotlin.runtime.auth.credentials.internal.credentials
99
import aws.sdk.kotlin.runtime.config.AwsSdkSetting
10+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric
11+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric
1012
import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
1113
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProvider
1214
import aws.smithy.kotlin.runtime.auth.awscredentials.simpleClassName
@@ -36,13 +38,14 @@ public class EnvironmentCredentialsProvider(
3638
coroutineContext.trace<EnvironmentCredentialsProvider> {
3739
"Attempting to load credentials from env vars $ACCESS_KEY_ID/$SECRET_ACCESS_KEY/$SESSION_TOKEN"
3840
}
41+
3942
return credentials(
4043
accessKeyId = requireEnv(ACCESS_KEY_ID),
4144
secretAccessKey = requireEnv(SECRET_ACCESS_KEY),
4245
sessionToken = getEnv(SESSION_TOKEN),
4346
providerName = PROVIDER_NAME,
4447
accountId = getEnv(ACCOUNT_ID),
45-
)
48+
).withBusinessMetric(AwsBusinessMetric.Credentials.CREDENTIALS_ENV_VARS)
4649
}
4750

4851
override fun toString(): String = this.simpleClassName

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/ImdsCredentialsProvider.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import aws.sdk.kotlin.runtime.config.AwsSdkSetting
99
import aws.sdk.kotlin.runtime.config.imds.EC2MetadataError
1010
import aws.sdk.kotlin.runtime.config.imds.ImdsClient
1111
import aws.sdk.kotlin.runtime.config.imds.InstanceMetadataProvider
12+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric
13+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric
1214
import aws.smithy.kotlin.runtime.auth.awscredentials.*
1315
import aws.smithy.kotlin.runtime.collections.Attributes
1416
import aws.smithy.kotlin.runtime.config.resolve
@@ -106,7 +108,7 @@ public class ImdsCredentialsProvider(
106108
resp.sessionToken,
107109
resp.expiration,
108110
PROVIDER_NAME,
109-
)
111+
).withBusinessMetric(AwsBusinessMetric.Credentials.CREDENTIALS_IMDS)
110112

111113
creds.also {
112114
mu.withLock { previousCredentials = it }

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/LazilyInitializedCredentialsProvider.kt

Lines changed: 0 additions & 24 deletions
This file was deleted.

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/ProcessCredentialsProvider.kt

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
package aws.sdk.kotlin.runtime.auth.credentials
66

77
import aws.sdk.kotlin.runtime.auth.credentials.internal.credentials
8-
import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
9-
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProvider
10-
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProviderException
11-
import aws.smithy.kotlin.runtime.auth.awscredentials.simpleClassName
8+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric
9+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric
10+
import aws.smithy.kotlin.runtime.auth.awscredentials.*
1211
import aws.smithy.kotlin.runtime.collections.Attributes
1312
import aws.smithy.kotlin.runtime.serde.json.JsonDeserializer
1413
import aws.smithy.kotlin.runtime.telemetry.logging.logger
@@ -68,14 +67,16 @@ public class ProcessCredentialsProvider(
6867
val deserializer = JsonDeserializer(payload)
6968

7069
return when (val resp = deserializeJsonProcessCredentials(deserializer)) {
71-
is JsonCredentialsResponse.SessionCredentials -> credentials(
72-
resp.accessKeyId,
73-
resp.secretAccessKey,
74-
resp.sessionToken,
75-
resp.expiration ?: Instant.MAX_VALUE,
76-
PROVIDER_NAME,
77-
resp.accountId,
78-
)
70+
is JsonCredentialsResponse.SessionCredentials -> {
71+
credentials(
72+
resp.accessKeyId,
73+
resp.secretAccessKey,
74+
resp.sessionToken,
75+
resp.expiration ?: Instant.MAX_VALUE,
76+
PROVIDER_NAME,
77+
resp.accountId,
78+
).withBusinessMetric(AwsBusinessMetric.Credentials.CREDENTIALS_PROCESS)
79+
}
7980
else -> throw CredentialsProviderException("Credentials response was not of expected format")
8081
}
8182
}

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/ProfileCredentialsProvider.kt

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@ import aws.sdk.kotlin.runtime.InternalSdkApi
99
import aws.sdk.kotlin.runtime.auth.credentials.profile.LeafProvider
1010
import aws.sdk.kotlin.runtime.auth.credentials.profile.ProfileChain
1111
import aws.sdk.kotlin.runtime.auth.credentials.profile.RoleArn
12+
import aws.sdk.kotlin.runtime.auth.credentials.profile.RoleArnSource
1213
import aws.sdk.kotlin.runtime.client.AwsClientOption
1314
import aws.sdk.kotlin.runtime.config.AwsSdkSetting
1415
import aws.sdk.kotlin.runtime.config.imds.ImdsClient
1516
import aws.sdk.kotlin.runtime.config.profile.AwsConfigurationSource
1617
import aws.sdk.kotlin.runtime.config.profile.loadAwsSharedConfig
18+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric
19+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetrics
1720
import aws.sdk.kotlin.runtime.region.resolveRegion
18-
import aws.smithy.kotlin.runtime.auth.awscredentials.CloseableCredentialsProvider
19-
import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
20-
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProvider
21-
import aws.smithy.kotlin.runtime.auth.awscredentials.simpleClassName
21+
import aws.smithy.kotlin.runtime.auth.awscredentials.*
22+
import aws.smithy.kotlin.runtime.businessmetrics.BusinessMetric
23+
import aws.smithy.kotlin.runtime.businessmetrics.BusinessMetrics
2224
import aws.smithy.kotlin.runtime.collections.Attributes
2325
import aws.smithy.kotlin.runtime.http.engine.HttpClientEngine
2426
import aws.smithy.kotlin.runtime.io.closeIfCloseable
@@ -86,6 +88,7 @@ public class ProfileCredentialsProvider @InternalSdkApi constructor(
8688
public val httpClient: HttpClientEngine? = null,
8789
public val configurationSource: AwsConfigurationSource? = null,
8890
) : CloseableCredentialsProvider {
91+
private val credentialsBusinessMetrics: MutableSet<BusinessMetric> = mutableSetOf()
8992

9093
public constructor(
9194
profileName: String? = null,
@@ -131,12 +134,21 @@ public class ProfileCredentialsProvider @InternalSdkApi constructor(
131134

132135
chain.roles.forEach { roleArn ->
133136
logger.debug { "Assuming role `${roleArn.roleArn}`" }
137+
if (roleArn.source == RoleArnSource.SOURCE_PROFILE) {
138+
credentialsBusinessMetrics.add(AwsBusinessMetric.Credentials.CREDENTIALS_PROFILE_SOURCE_PROFILE)
139+
}
140+
134141
val assumeProvider = roleArn.toCredentialsProvider(creds, region)
142+
143+
creds.attributes.getOrNull(BusinessMetrics)?.forEach { metric ->
144+
credentialsBusinessMetrics.add(metric)
145+
}
146+
135147
creds = assumeProvider.resolve(attributes)
136148
}
137149

138150
logger.debug { "Obtained credentials from profile; expiration=${creds.expiration?.format(TimestampFormat.ISO_8601)}" }
139-
return creds
151+
return creds.withBusinessMetrics(credentialsBusinessMetrics)
140152
}
141153

142154
override fun close() {
@@ -147,10 +159,13 @@ public class ProfileCredentialsProvider @InternalSdkApi constructor(
147159

148160
private suspend fun LeafProvider.toCredentialsProvider(region: LazyAsyncValue<String?>): CredentialsProvider =
149161
when (this) {
150-
is LeafProvider.NamedSource -> namedProviders[name]
151-
?: throw ProviderConfigurationException("unknown credentials source: $name")
162+
is LeafProvider.NamedSource -> namedProviders[name].also {
163+
credentialsBusinessMetrics.add(AwsBusinessMetric.Credentials.CREDENTIALS_PROFILE_NAMED_PROVIDER)
164+
} ?: throw ProviderConfigurationException("unknown credentials source: $name")
152165

153-
is LeafProvider.AccessKey -> StaticCredentialsProvider(credentials)
166+
is LeafProvider.AccessKey -> StaticCredentialsProvider(credentials).also {
167+
credentialsBusinessMetrics.add(AwsBusinessMetric.Credentials.CREDENTIALS_PROFILE)
168+
}
154169

155170
is LeafProvider.WebIdentityTokenRole -> StsWebIdentityCredentialsProvider(
156171
roleArn,
@@ -159,7 +174,9 @@ public class ProfileCredentialsProvider @InternalSdkApi constructor(
159174
roleSessionName = sessionName,
160175
platformProvider = platformProvider,
161176
httpClient = httpClient,
162-
)
177+
).also {
178+
credentialsBusinessMetrics.add(AwsBusinessMetric.Credentials.CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN)
179+
}
163180

164181
is LeafProvider.SsoSession -> SsoCredentialsProvider(
165182
accountId = ssoAccountId,
@@ -169,7 +186,9 @@ public class ProfileCredentialsProvider @InternalSdkApi constructor(
169186
ssoSessionName = ssoSessionName,
170187
httpClient = httpClient,
171188
platformProvider = platformProvider,
172-
)
189+
).also {
190+
credentialsBusinessMetrics.add(AwsBusinessMetric.Credentials.CREDENTIALS_PROFILE_SSO)
191+
}
173192

174193
is LeafProvider.LegacySso -> SsoCredentialsProvider(
175194
accountId = ssoAccountId,
@@ -178,9 +197,13 @@ public class ProfileCredentialsProvider @InternalSdkApi constructor(
178197
ssoRegion = ssoRegion,
179198
httpClient = httpClient,
180199
platformProvider = platformProvider,
181-
)
200+
).also {
201+
credentialsBusinessMetrics.add(AwsBusinessMetric.Credentials.CREDENTIALS_PROFILE_SSO_LEGACY)
202+
}
182203

183-
is LeafProvider.Process -> ProcessCredentialsProvider(command)
204+
is LeafProvider.Process -> ProcessCredentialsProvider(command).also {
205+
credentialsBusinessMetrics.add(AwsBusinessMetric.Credentials.CREDENTIALS_PROFILE_PROCESS)
206+
}
184207
}
185208

186209
private suspend fun RoleArn.toCredentialsProvider(

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/SsoCredentialsProvider.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@ package aws.sdk.kotlin.runtime.auth.credentials
88
import aws.sdk.kotlin.runtime.auth.credentials.internal.credentials
99
import aws.sdk.kotlin.runtime.auth.credentials.internal.sso.SsoClient
1010
import aws.sdk.kotlin.runtime.auth.credentials.internal.sso.getRoleCredentials
11-
import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
12-
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProvider
13-
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProviderException
14-
import aws.smithy.kotlin.runtime.auth.awscredentials.simpleClassName
11+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric
12+
import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric
13+
import aws.smithy.kotlin.runtime.auth.awscredentials.*
1514
import aws.smithy.kotlin.runtime.client.SdkClientOption
1615
import aws.smithy.kotlin.runtime.collections.Attributes
1716
import aws.smithy.kotlin.runtime.http.engine.HttpClientEngine
18-
import aws.smithy.kotlin.runtime.serde.json.*
1917
import aws.smithy.kotlin.runtime.telemetry.logging.logger
2018
import aws.smithy.kotlin.runtime.telemetry.telemetryProvider
2119
import aws.smithy.kotlin.runtime.time.Clock
@@ -121,14 +119,20 @@ public class SsoCredentialsProvider public constructor(
121119

122120
val roleCredentials = resp.roleCredentials ?: throw CredentialsProviderException("Expected SSO roleCredentials to not be null")
123121

124-
return credentials(
122+
val creds = credentials(
125123
accessKeyId = checkNotNull(roleCredentials.accessKeyId) { "Expected accessKeyId in SSO roleCredentials response" },
126124
secretAccessKey = checkNotNull(roleCredentials.secretAccessKey) { "Expected secretAccessKey in SSO roleCredentials response" },
127125
sessionToken = roleCredentials.sessionToken,
128126
expiration = Instant.fromEpochMilliseconds(roleCredentials.expiration),
129127
PROVIDER_NAME,
130128
accountId = accountId,
131129
)
130+
131+
return if (ssoTokenProvider != null) {
132+
creds.withBusinessMetric(AwsBusinessMetric.Credentials.CREDENTIALS_SSO)
133+
} else {
134+
creds.withBusinessMetric(AwsBusinessMetric.Credentials.CREDENTIALS_SSO_LEGACY)
135+
}
132136
}
133137

134138
// non sso-session legacy token flow

0 commit comments

Comments
 (0)