From c07dc9c315362a3a77e8d9e1901d6f7200eb2649 Mon Sep 17 00:00:00 2001 From: Matas Lauzadis Date: Thu, 23 Oct 2025 13:36:40 -0400 Subject: [PATCH 1/3] Route `applicationId` through to internal clients --- aws-runtime/aws-config/api/aws-config.api | 5 +++++ .../auth/credentials/SsoCredentialsProvider.kt | 2 ++ .../credentials/StsAssumeRoleCredentialsProvider.kt | 2 ++ .../StsWebIdentityCredentialsProvider.kt | 2 ++ .../sdk/kotlin/runtime/config/AwsSdkClientOption.kt | 13 +++++++++++++ .../aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt | 1 + .../kotlin/codegen/AwsServiceConfigIntegration.kt | 8 ++++++++ 7 files changed, 33 insertions(+) create mode 100644 aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/AwsSdkClientOption.kt diff --git a/aws-runtime/aws-config/api/aws-config.api b/aws-runtime/aws-config/api/aws-config.api index ce35a2d9ef5..9b55244e258 100644 --- a/aws-runtime/aws-config/api/aws-config.api +++ b/aws-runtime/aws-config/api/aws-config.api @@ -265,6 +265,11 @@ public abstract interface class aws/sdk/kotlin/runtime/config/AwsSdkClientConfig public abstract fun setUseFips (Ljava/lang/Boolean;)V } +public final class aws/sdk/kotlin/runtime/config/AwsSdkClientOption { + public static final field INSTANCE Laws/sdk/kotlin/runtime/config/AwsSdkClientOption; + public final fun getApplicationId ()Laws/smithy/kotlin/runtime/collections/AttributeKey; +} + public final class aws/sdk/kotlin/runtime/config/AwsSdkSetting { public static final field INSTANCE Laws/sdk/kotlin/runtime/config/AwsSdkSetting; public final fun getAwsAccessKeyId ()Laws/smithy/kotlin/runtime/config/EnvironmentSetting; diff --git a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/SsoCredentialsProvider.kt b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/SsoCredentialsProvider.kt index 3cb4304b5f8..a8f90cbd508 100644 --- a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/SsoCredentialsProvider.kt +++ b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/SsoCredentialsProvider.kt @@ -8,6 +8,7 @@ package aws.sdk.kotlin.runtime.auth.credentials import aws.sdk.kotlin.runtime.auth.credentials.internal.credentials import aws.sdk.kotlin.runtime.auth.credentials.internal.sso.SsoClient import aws.sdk.kotlin.runtime.auth.credentials.internal.sso.getRoleCredentials +import aws.sdk.kotlin.runtime.config.AwsSdkClientOption import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric import aws.smithy.kotlin.runtime.auth.awscredentials.* @@ -102,6 +103,7 @@ public class SsoCredentialsProvider public constructor( httpClient = this@SsoCredentialsProvider.httpClient telemetryProvider = telemetry logMode = attributes.getOrNull(SdkClientOption.LogMode) + applicationId = attributes.getOrNull(AwsSdkClientOption.ApplicationId) // FIXME - create an anonymous credential provider to explicitly avoid default chain creation (technically the transform should remove need for sigv4 cred provider since it's all anon auth) } diff --git a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/StsAssumeRoleCredentialsProvider.kt b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/StsAssumeRoleCredentialsProvider.kt index e84781e95ea..486f5a98465 100644 --- a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/StsAssumeRoleCredentialsProvider.kt +++ b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/StsAssumeRoleCredentialsProvider.kt @@ -12,6 +12,7 @@ import aws.sdk.kotlin.runtime.auth.credentials.internal.sts.assumeRole import aws.sdk.kotlin.runtime.auth.credentials.internal.sts.model.PolicyDescriptorType import aws.sdk.kotlin.runtime.auth.credentials.internal.sts.model.RegionDisabledException import aws.sdk.kotlin.runtime.auth.credentials.internal.sts.model.Tag +import aws.sdk.kotlin.runtime.config.AwsSdkClientOption import aws.sdk.kotlin.runtime.config.AwsSdkSetting import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric @@ -106,6 +107,7 @@ public class StsAssumeRoleCredentialsProvider( httpClient = provider.httpClient telemetryProvider = telemetry logMode = attributes.getOrNull(SdkClientOption.LogMode) + applicationId = attributes.getOrNull(AwsSdkClientOption.ApplicationId) } val resp = try { diff --git a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredentialsProvider.kt b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredentialsProvider.kt index 3f5147f1968..b13f3ff2d03 100644 --- a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredentialsProvider.kt +++ b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredentialsProvider.kt @@ -10,6 +10,7 @@ import aws.sdk.kotlin.runtime.auth.credentials.internal.credentials import aws.sdk.kotlin.runtime.auth.credentials.internal.sts.StsClient import aws.sdk.kotlin.runtime.auth.credentials.internal.sts.assumeRoleWithWebIdentity import aws.sdk.kotlin.runtime.auth.credentials.internal.sts.model.PolicyDescriptorType +import aws.sdk.kotlin.runtime.config.AwsSdkClientOption import aws.sdk.kotlin.runtime.config.AwsSdkSetting import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.AwsBusinessMetric import aws.sdk.kotlin.runtime.http.interceptors.businessmetrics.withBusinessMetric @@ -122,6 +123,7 @@ public class StsWebIdentityCredentialsProvider( // NOTE: credentials provider not needed for this operation telemetryProvider = telemetry logMode = attributes.getOrNull(SdkClientOption.LogMode) + applicationId = attributes.getOrNull(AwsSdkClientOption.ApplicationId) } val resp = try { diff --git a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/AwsSdkClientOption.kt b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/AwsSdkClientOption.kt new file mode 100644 index 00000000000..d9f012882ad --- /dev/null +++ b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/AwsSdkClientOption.kt @@ -0,0 +1,13 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package aws.sdk.kotlin.runtime.config + +import aws.smithy.kotlin.runtime.collections.AttributeKey + +// AWS-specific version of smithy-kotlin's SdkClientOption +public object AwsSdkClientOption { + public val ApplicationId: AttributeKey = AttributeKey("aws.sdk.kotlin#ApplicationId") +} diff --git a/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt b/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt index 56364a006b2..f5a7c40846d 100644 --- a/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt +++ b/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsRuntimeTypes.kt @@ -38,6 +38,7 @@ object AwsRuntimeTypes { val AbstractAwsSdkClientFactory = symbol("AbstractAwsSdkClientFactory", "config") val AwsSdkClientConfig = symbol("AwsSdkClientConfig", "config") + val AwsSdkClientOption = symbol("AwsSdkClientOption", "config") object Endpoints : RuntimeTypePackage(AwsKotlinDependency.AWS_CONFIG, "config.endpoints") { val AccountIdEndpointMode = symbol("AccountIdEndpointMode") diff --git a/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsServiceConfigIntegration.kt b/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsServiceConfigIntegration.kt index 436a6a5aa8e..999bd8f53c3 100644 --- a/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsServiceConfigIntegration.kt +++ b/codegen/aws-sdk-codegen/src/main/kotlin/aws/sdk/kotlin/codegen/AwsServiceConfigIntegration.kt @@ -5,6 +5,7 @@ package aws.sdk.kotlin.codegen import software.amazon.smithy.kotlin.codegen.core.* +import software.amazon.smithy.kotlin.codegen.integration.AppendingSectionWriter import software.amazon.smithy.kotlin.codegen.integration.KotlinIntegration import software.amazon.smithy.kotlin.codegen.integration.SectionWriterBinding import software.amazon.smithy.kotlin.codegen.lang.KotlinTypes @@ -12,6 +13,7 @@ import software.amazon.smithy.kotlin.codegen.model.asNullable import software.amazon.smithy.kotlin.codegen.model.knowledge.AwsSignatureVersion4 import software.amazon.smithy.kotlin.codegen.model.nullable import software.amazon.smithy.kotlin.codegen.rendering.* +import software.amazon.smithy.kotlin.codegen.rendering.protocol.HttpProtocolClientGenerator import software.amazon.smithy.kotlin.codegen.rendering.util.ConfigProperty import software.amazon.smithy.kotlin.codegen.rendering.util.ConfigPropertyType import software.amazon.smithy.kotlin.codegen.rendering.util.RuntimeConfigProperty @@ -173,6 +175,12 @@ class AwsServiceConfigIntegration : KotlinIntegration { writer.getContextValue(ServiceClientGenerator.Sections.CompanionObject.ServiceSymbol), ) }, + SectionWriterBinding( + HttpProtocolClientGenerator.MergeServiceDefaults, + AppendingSectionWriter { writer -> + writer.write("ctx.#T(#T.ApplicationId, config.#L)", RuntimeTypes.Core.Collections.putIfAbsentNotNull, AwsRuntimeTypes.Config.AwsSdkClientOption, UserAgentAppId.propertyName) + }, + ), ) override fun additionalServiceConfigProps(ctx: CodegenContext): List = buildList { From 20aa781f9e79e7d44c441504d22b0177a48d985b Mon Sep 17 00:00:00 2001 From: Matas Lauzadis Date: Thu, 23 Oct 2025 13:37:33 -0400 Subject: [PATCH 2/3] changelog --- .changes/cae05a44-3c24-4ba3-9a0b-85aaaa7d9f1f.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changes/cae05a44-3c24-4ba3-9a0b-85aaaa7d9f1f.json diff --git a/.changes/cae05a44-3c24-4ba3-9a0b-85aaaa7d9f1f.json b/.changes/cae05a44-3c24-4ba3-9a0b-85aaaa7d9f1f.json new file mode 100644 index 00000000000..d752dc8fa07 --- /dev/null +++ b/.changes/cae05a44-3c24-4ba3-9a0b-85aaaa7d9f1f.json @@ -0,0 +1,8 @@ +{ + "id": "cae05a44-3c24-4ba3-9a0b-85aaaa7d9f1f", + "type": "bugfix", + "description": "Correctly route applicationId to requests made by internal clients", + "issues": [ + "https://github.com/aws/aws-sdk-kotlin/issues/1717" + ] +} \ No newline at end of file From 52b39c69c7b995290f11f19eef1123805af1ee46 Mon Sep 17 00:00:00 2001 From: Matas Lauzadis Date: Thu, 23 Oct 2025 13:52:06 -0400 Subject: [PATCH 3/3] Add KDocs --- .../aws/sdk/kotlin/runtime/config/AwsSdkClientOption.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/AwsSdkClientOption.kt b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/AwsSdkClientOption.kt index d9f012882ad..0defe514643 100644 --- a/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/AwsSdkClientOption.kt +++ b/aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/config/AwsSdkClientOption.kt @@ -7,7 +7,14 @@ package aws.sdk.kotlin.runtime.config import aws.smithy.kotlin.runtime.collections.AttributeKey -// AWS-specific version of smithy-kotlin's SdkClientOption +/** + * Common client execution options. + * AWS-specific version of [aws.smithy.kotlin.runtime.client.SdkClientOption] + */ public object AwsSdkClientOption { + /** + * An optional application specific identifier. + * When set it will be appended to the User-Agent header of every request in the form of: `app/{applicationId}`. + */ public val ApplicationId: AttributeKey = AttributeKey("aws.sdk.kotlin#ApplicationId") }