Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/awslabs/aws-sdk-kotlin into…
Browse files Browse the repository at this point in the history
… missing-content-type
  • Loading branch information
0marperez committed Oct 25, 2023
2 parents 82a9155 + e9a321e commit 5df01d8
Show file tree
Hide file tree
Showing 91 changed files with 1,446 additions and 502 deletions.
5 changes: 5 additions & 0 deletions .changes/07646ee7-9b1a-4d59-b298-ab1740caf763.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"id": "07646ee7-9b1a-4d59-b298-ab1740caf763",
"type": "misc",
"description": "Upgrade Kotlin to 1.9.10"
}
5 changes: 5 additions & 0 deletions .changes/1691b2fe-15ba-4bf8-8f27-382b59c792c8.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"id": "1691b2fe-15ba-4bf8-8f27-382b59c792c8",
"type": "bugfix",
"description": "Ignore empty environment variable and system property strings when evaluating AWS credentials"
}
5 changes: 5 additions & 0 deletions .changes/3b368bab-1a77-400c-9777-be183dbe9bdc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"id": "3b368bab-1a77-400c-9777-be183dbe9bdc",
"type": "misc",
"description": "Upgrade Dokka to 1.9.0"
}
9 changes: 9 additions & 0 deletions .changes/703da74b-6f77-4555-b129-295486571361.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"id": "703da74b-6f77-4555-b129-295486571361",
"type": "feature",
"description": "Publish a BOM and a Version Catalog",
"issues": [
"awslabs/aws-sdk-kotlin#605",
"awslabs/aws-sdk-kotlin#805"
]
}
5 changes: 5 additions & 0 deletions .changes/80721b55-6e70-4bfe-a6b3-8806605c079e.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"id": "80721b55-6e70-4bfe-a6b3-8806605c079e",
"type": "misc",
"description": "Add skeleton implementation of a second KMP target"
}
5 changes: 5 additions & 0 deletions .changes/8665c18c-d742-4212-b920-6fea43f70c2c.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"id": "8665c18c-d742-4212-b920-6fea43f70c2c",
"type": "feature",
"description": "Detect and automatically correct clock skew to prevent signing errors"
}
5 changes: 5 additions & 0 deletions .changes/e965338d-28c5-41e2-b585-121d9d56393f.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"id": "e965338d-28c5-41e2-b585-121d9d56393f",
"type": "misc",
"description": "**BREAKING**: Remove `smithy.client.request.size`, `smithy.client.response.size`, `smithy.client.retries` metrics. Rename all `smithy.client.*` metrics to `smithy.client.call.*`."
}
4 changes: 2 additions & 2 deletions .github/workflows/codebuild-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
Expand All @@ -45,7 +45,7 @@ jobs:
- name: Checkout sources
uses: actions/checkout@v2
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CI_AWS_ROLE_ARN }}
aws-region: us-west-2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
pwd
./gradlew publishToMavenLocal
./gradlew apiCheck
./gradlew test allTests
./gradlew test jvmTest
./gradlew testAllProtocols
- name: Save Test Reports
if: failure()
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Release Checks
on:
pull_request:
types: [ opened, synchronize, reopened ]
branches: [ main ]
branches: [ main, release ]

# Allow one instance of this workflow per pull request, and cancel older runs when new changes are pushed
concurrency:
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## [0.32.5-beta] - 10/12/2023

### Features
* [#945](https://github.com/awslabs/aws-sdk-kotlin/issues/945) Add new sources for User-Agent app id

### Miscellaneous
* Sync to the latest versions of **smithy-kotlin** and AWS service models

## [0.32.4-beta] - 10/06/2023

### Miscellaneous
Expand Down
4 changes: 4 additions & 0 deletions aws-runtime/aws-config/api/aws-config.api
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ public final class aws/sdk/kotlin/runtime/config/imds/EndpointMode : java/lang/E
public static final field Companion Laws/sdk/kotlin/runtime/config/imds/EndpointMode$Companion;
public static final field IPv4 Laws/sdk/kotlin/runtime/config/imds/EndpointMode;
public static final field IPv6 Laws/sdk/kotlin/runtime/config/imds/EndpointMode;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Laws/sdk/kotlin/runtime/config/imds/EndpointMode;
public static fun values ()[Laws/sdk/kotlin/runtime/config/imds/EndpointMode;
}
Expand Down Expand Up @@ -315,6 +316,9 @@ public final class aws/sdk/kotlin/runtime/config/profile/AwsSharedConfigKt {
public final class aws/sdk/kotlin/runtime/config/retries/ResolveRetryStrategyKt {
}

public final class aws/sdk/kotlin/runtime/config/useragent/ResolveUserAgentKt {
}

public abstract interface class aws/sdk/kotlin/runtime/region/RegionProvider {
public abstract fun getRegion (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
Expand Down
12 changes: 10 additions & 2 deletions aws-runtime/aws-config/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ kotlin {

// additional dependencies required by generated sts provider
implementation(libs.smithy.kotlin.serde.xml)
implementation(libs.smithy.kotlin.serde.formurl)
implementation(libs.smithy.kotlin.serde.form.url)
implementation(libs.smithy.kotlin.aws.xml.protocols)

// additional dependencies required by generated sso provider(s)
Expand All @@ -53,11 +53,11 @@ kotlin {
implementation(libs.kotlinx.coroutines.test)
implementation(libs.smithy.kotlin.http.test)
implementation(libs.kotlinx.serialization.json)
implementation(libs.mockk)
}
}
jvmTest {
dependencies {
implementation(libs.mockk)
implementation(libs.kotest.runner.junit5)
}
}
Expand Down Expand Up @@ -192,6 +192,9 @@ NOTE: We need the following tasks to depend on codegen for gradle caching/up-to-
* `compileKotlinJvm` (Type=KotlinCompile)
* `compileKotlinMetadata` (Type=KotlinCompileCommon)
* `sourcesJar` and `jvmSourcesJar` (Type=org.gradle.jvm.tasks.Jar)
*
* For Kotlin/Native, an additional dependency is introduced:
* `compileKotlin<Platform>` (Type=KotlinNativeCompile) (e.g. compileKotlinLinuxX64)
*/
val codegenTask = tasks.named("generateSmithyProjections")
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
Expand All @@ -201,6 +204,11 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.allWarningsAsErrors = false
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile> {
dependsOn(codegenTask)
kotlinOptions.allWarningsAsErrors = false
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon> {
dependsOn(codegenTask)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class EnvironmentCredentialsProvider(
) : CredentialsProvider {

private fun requireEnv(variable: String): String =
getEnv(variable) ?: throw ProviderConfigurationException("Missing value for environment variable `$variable`")
getEnv(variable)?.takeIf(String::isNotBlank) ?: throw ProviderConfigurationException("Missing value for environment variable `$variable`")

override suspend fun resolve(attributes: Attributes): Credentials {
coroutineContext.trace<EnvironmentCredentialsProvider> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProviderExceptio
import aws.smithy.kotlin.runtime.auth.awscredentials.DEFAULT_CREDENTIALS_REFRESH_SECONDS
import aws.smithy.kotlin.runtime.config.resolve
import aws.smithy.kotlin.runtime.http.HttpStatusCode
import aws.smithy.kotlin.runtime.io.IOException
import aws.smithy.kotlin.runtime.serde.json.JsonDeserializer
import aws.smithy.kotlin.runtime.telemetry.logging.info
import aws.smithy.kotlin.runtime.telemetry.logging.warn
Expand All @@ -33,8 +34,6 @@ private const val CREDENTIALS_BASE_PATH: String = "/latest/meta-data/iam/securit
private const val CODE_ASSUME_ROLE_UNAUTHORIZED_ACCESS: String = "AssumeRoleUnauthorizedAccess"
private const val PROVIDER_NAME = "IMDSv2"

internal expect class SdkIOException : Exception // FIXME move this to the proper place when we do the larger KMP Exception refactor

/**
* [CredentialsProvider] that uses EC2 instance metadata service (IMDS) to provide credentials information.
* This provider requires that the EC2 instance has an [instance profile](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#ec2-instance-profile)
Expand Down Expand Up @@ -145,7 +144,7 @@ public class ImdsCredentialsProvider(
}

private suspend fun useCachedCredentials(ex: Exception): Credentials? = when {
ex is SdkIOException || ex is EC2MetadataError && ex.statusCode == HttpStatusCode.InternalServerError.value -> {
ex is IOException || ex is EC2MetadataError && ex.statusCode == HttpStatusCode.InternalServerError.value -> {
mu.withLock {
previousCredentials?.apply { nextRefresh = clock.now() + DEFAULT_CREDENTIALS_REFRESH_SECONDS.seconds }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class SystemPropertyCredentialsProvider(
) : CredentialsProvider {

private fun requireProperty(variable: String): String =
getProperty(variable) ?: throw ProviderConfigurationException("Missing value for system property `$variable`")
getProperty(variable)?.takeIf(String::isNotBlank) ?: throw ProviderConfigurationException("Missing value for system property `$variable`")

override suspend fun resolve(attributes: Attributes): Credentials {
coroutineContext.trace<SystemPropertyCredentialsProvider> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import aws.sdk.kotlin.runtime.config.endpoints.resolveUseFips
import aws.sdk.kotlin.runtime.config.profile.AwsSharedConfig
import aws.sdk.kotlin.runtime.config.profile.loadAwsSharedConfig
import aws.sdk.kotlin.runtime.config.retries.resolveRetryStrategy
import aws.sdk.kotlin.runtime.config.useragent.resolveUserAgentAppId
import aws.sdk.kotlin.runtime.region.resolveRegion
import aws.smithy.kotlin.runtime.ExperimentalApi
import aws.smithy.kotlin.runtime.client.RetryStrategyClientConfig
Expand Down Expand Up @@ -57,7 +58,8 @@ public abstract class AbstractAwsSdkClientFactory<
val tracer = telemetryProvider.tracerProvider.getOrCreateTracer("AwsSdkClientFactory")

tracer.withSpan("fromEnvironment") {
val sharedConfig = asyncLazy { loadAwsSharedConfig(PlatformProvider.System) }
val platform = PlatformProvider.System
val sharedConfig = asyncLazy { loadAwsSharedConfig(platform) }
val profile = asyncLazy { sharedConfig.get().activeProfile }

// As a DslBuilderProperty, the value of retryStrategy cannot be checked for nullability because it may have
Expand All @@ -68,10 +70,12 @@ public abstract class AbstractAwsSdkClientFactory<

block?.let(config::apply)

config.logMode = config.logMode ?: ClientSettings.LogMode.resolve(platform = PlatformProvider.System)
config.logMode = config.logMode ?: ClientSettings.LogMode.resolve(platform = platform)
config.region = config.region ?: resolveRegion(profile = profile)
config.useFips = config.useFips ?: resolveUseFips(profile = profile)
config.useDualStack = config.useDualStack ?: resolveUseDualStack(profile = profile)
config.applicationId = config.applicationId ?: resolveUserAgentAppId(platform, profile)

finalizeConfig(builder, sharedConfig)
}
return builder.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package aws.sdk.kotlin.runtime.config

import aws.sdk.kotlin.runtime.InternalSdkApi
import aws.sdk.kotlin.runtime.http.AWS_APP_ID_ENV
import aws.sdk.kotlin.runtime.http.AWS_APP_ID_PROP
import aws.smithy.kotlin.runtime.client.config.RetryMode
import aws.smithy.kotlin.runtime.config.*
import aws.smithy.kotlin.runtime.net.Url
Expand Down Expand Up @@ -45,6 +47,11 @@ public object AwsSdkSetting {
*/
public val AwsRegion: EnvironmentSetting<String> = strEnvSetting("aws.region", "AWS_REGION")

/**
* Configure the user agent app ID
*/
public val AwsAppId: EnvironmentSetting<String> = strEnvSetting(AWS_APP_ID_PROP, AWS_APP_ID_ENV)

/**
* Configure the default path to the shared config file.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ public val AwsProfile.ignoreEndpointUrls: Boolean?
public val AwsProfile.servicesSection: String?
get() = getOrNull("services")

/**
* The SDK user agent app ID used to identify applications.
*/
@InternalSdkApi
public val AwsProfile.sdkUserAgentAppId: String?
get() = getOrNull("sdk_ua_app_id")

/**
* Parse a config value as a boolean, ignoring case.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package aws.sdk.kotlin.runtime.config.useragent

import aws.sdk.kotlin.runtime.InternalSdkApi
import aws.sdk.kotlin.runtime.config.AwsSdkSetting
import aws.sdk.kotlin.runtime.config.profile.AwsProfile
import aws.sdk.kotlin.runtime.config.profile.sdkUserAgentAppId
import aws.smithy.kotlin.runtime.config.resolve
import aws.smithy.kotlin.runtime.util.LazyAsyncValue
import aws.smithy.kotlin.runtime.util.PlatformProvider

/**
* Attempts to resolve user agent from specified sources.
* @return The user agent app id if found, null if not
*/
@InternalSdkApi
public suspend fun resolveUserAgentAppId(platform: PlatformProvider = PlatformProvider.System, profile: LazyAsyncValue<AwsProfile>): String? =
AwsSdkSetting.AwsAppId.resolve(platform) ?: profile.get().sdkUserAgentAppId
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class EnvironmentCredentialsProviderTest {
private fun provider(vararg vars: Pair<String, String>) = EnvironmentCredentialsProvider((vars.toMap())::get)

@Test
fun `it should read from environment variables (incl session token)`() = runTest {
fun testReadFromEnvironmentIncludingSessionToken() = runTest {
val provider = provider(
AwsSdkSetting.AwsAccessKeyId.envVar to "abc",
AwsSdkSetting.AwsSecretAccessKey.envVar to "def",
Expand All @@ -27,7 +27,7 @@ class EnvironmentCredentialsProviderTest {
}

@Test
fun `it should read from environment variables (excl session token)`() = runTest {
fun testReadFromEnvironmentExcludingSessionToken() = runTest {
val provider = provider(
AwsSdkSetting.AwsAccessKeyId.envVar to "abc",
AwsSdkSetting.AwsSecretAccessKey.envVar to "def",
Expand All @@ -36,16 +36,36 @@ class EnvironmentCredentialsProviderTest {
}

@Test
fun `it should throw an exception on missing access key`() = runTest {
fun testThrowsWhenMissingAccessKey() = runTest {
assertFailsWith<ProviderConfigurationException> {
provider(AwsSdkSetting.AwsSecretAccessKey.envVar to "def").resolve()
}.message.shouldContain("Missing value for environment variable `AWS_ACCESS_KEY_ID`")
}

@Test
fun `it should throw an exception on missing secret key`() = runTest {
fun testThrowsWhenMissingSecretKey() = runTest {
assertFailsWith<ProviderConfigurationException> {
provider(AwsSdkSetting.AwsAccessKeyId.envVar to "abc").resolve()
}.message.shouldContain("Missing value for environment variable `AWS_SECRET_ACCESS_KEY`")
}

@Test
fun testIgnoresEmptyAccessKey() = runTest {
assertFailsWith<ProviderConfigurationException> {
provider(
AwsSdkSetting.AwsAccessKeyId.envVar to "",
AwsSdkSetting.AwsSecretAccessKey.envVar to "abc",
).resolve()
}.message.shouldContain("Missing value for environment variable `AWS_ACCESS_KEY_ID`")
}

@Test
fun testIgnoresEmptySecretKey() = runTest {
assertFailsWith<ProviderConfigurationException> {
provider(
AwsSdkSetting.AwsAccessKeyId.envVar to "abc",
AwsSdkSetting.AwsSecretAccessKey.envVar to "",
).resolve()
}.message.shouldContain("Missing value for environment variable `AWS_SECRET_ACCESS_KEY`")
}
}
Loading

0 comments on commit 5df01d8

Please sign in to comment.