diff --git a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/CredentialsProvider.kt b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/CredentialsProvider.kt index 722010fdc3a..ea82222f6a6 100644 --- a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/CredentialsProvider.kt +++ b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/CredentialsProvider.kt @@ -15,5 +15,3 @@ public interface CredentialsProvider { */ public suspend fun getCredentials(): Credentials } - -// TODO - add proxies for all the credentials providers in aws-crt-kotlin diff --git a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/EnvironmentCredentialsProvider.kt b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/EnvironmentCredentialsProvider.kt index d9ea39b3fc1..b6584026310 100644 --- a/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/EnvironmentCredentialsProvider.kt +++ b/aws-runtime/auth/common/src/aws/sdk/kotlin/runtime/auth/EnvironmentCredentialsProvider.kt @@ -5,6 +5,7 @@ package aws.sdk.kotlin.runtime.auth +import aws.sdk.kotlin.runtime.AwsSdkSetting import aws.sdk.kotlin.runtime.ConfigurationException import aws.smithy.kotlin.runtime.util.Platform @@ -13,20 +14,14 @@ import aws.smithy.kotlin.runtime.util.Platform */ public class EnvironmentCredentialsProvider public constructor(private val getEnv: (String) -> String?) : CredentialsProvider { - public companion object { - internal const val ACCESS_KEY_ID: String = "AWS_ACCESS_KEY_ID" - internal const val SECRET_ACCESS_KEY: String = "AWS_SECRET_ACCESS_KEY" - internal const val SESSION_TOKEN: String = "AWS_SESSION_TOKEN" - } - public constructor() : this(Platform::getenv) private fun requireEnv(variable: String): String = getEnv(variable) ?: throw ConfigurationException("Unable to get value from environment variable $variable") override suspend fun getCredentials(): Credentials = Credentials( - accessKeyId = requireEnv(ACCESS_KEY_ID), - secretAccessKey = requireEnv(SECRET_ACCESS_KEY), - sessionToken = getEnv(SESSION_TOKEN), + accessKeyId = requireEnv(AwsSdkSetting.AwsAccessKeyId.environmentVariable), + secretAccessKey = requireEnv(AwsSdkSetting.AwsSecretAccessKey.environmentVariable), + sessionToken = getEnv(AwsSdkSetting.AwsSessionToken.environmentVariable), ) } diff --git a/aws-runtime/auth/common/test/aws/sdk/kotlin/runtime/auth/EnvironmentCredentialsProviderTest.kt b/aws-runtime/auth/common/test/aws/sdk/kotlin/runtime/auth/EnvironmentCredentialsProviderTest.kt index efc5f602764..0a75340ea66 100644 --- a/aws-runtime/auth/common/test/aws/sdk/kotlin/runtime/auth/EnvironmentCredentialsProviderTest.kt +++ b/aws-runtime/auth/common/test/aws/sdk/kotlin/runtime/auth/EnvironmentCredentialsProviderTest.kt @@ -5,6 +5,7 @@ package aws.sdk.kotlin.runtime.auth +import aws.sdk.kotlin.runtime.AwsSdkSetting import aws.sdk.kotlin.runtime.ConfigurationException import aws.sdk.kotlin.runtime.testing.runSuspendTest import kotlin.test.Test @@ -17,9 +18,9 @@ class EnvironmentCredentialsProviderTest { @Test fun `it should read from environment variables (incl session token)`() = runSuspendTest { val provider = provider( - EnvironmentCredentialsProvider.ACCESS_KEY_ID to "abc", - EnvironmentCredentialsProvider.SECRET_ACCESS_KEY to "def", - EnvironmentCredentialsProvider.SESSION_TOKEN to "ghi", + AwsSdkSetting.AwsAccessKeyId.environmentVariable to "abc", + AwsSdkSetting.AwsSecretAccessKey.environmentVariable to "def", + AwsSdkSetting.AwsSessionToken.environmentVariable to "ghi", ) assertEquals(provider.getCredentials(), Credentials("abc", "def", "ghi")) } @@ -27,23 +28,23 @@ class EnvironmentCredentialsProviderTest { @Test fun `it should read from environment variables (excl session token)`() = runSuspendTest { val provider = provider( - EnvironmentCredentialsProvider.ACCESS_KEY_ID to "abc", - EnvironmentCredentialsProvider.SECRET_ACCESS_KEY to "def", + AwsSdkSetting.AwsAccessKeyId.environmentVariable to "abc", + AwsSdkSetting.AwsSecretAccessKey.environmentVariable to "def", ) assertEquals(provider.getCredentials(), Credentials("abc", "def", null)) } @Test - fun `it should throw an exception on missing access key`() = runSuspendTest { + fun `it should throw an exception on missing access key`(): Unit = runSuspendTest { assertFailsWith { - provider(EnvironmentCredentialsProvider.SECRET_ACCESS_KEY to "def").getCredentials() + provider(AwsSdkSetting.AwsSecretAccessKey.environmentVariable to "def").getCredentials() } } @Test - fun `it should throw an exception on missing secret key`() = runSuspendTest { + fun `it should throw an exception on missing secret key`(): Unit = runSuspendTest { assertFailsWith { - provider(EnvironmentCredentialsProvider.ACCESS_KEY_ID to "abc").getCredentials() + provider(AwsSdkSetting.AwsAccessKeyId.environmentVariable to "abc").getCredentials() } } } diff --git a/aws-runtime/aws-core/common/src/aws/sdk/kotlin/runtime/AwsSdkSetting.kt b/aws-runtime/aws-core/common/src/aws/sdk/kotlin/runtime/AwsSdkSetting.kt new file mode 100644 index 00000000000..7943374dc9e --- /dev/null +++ b/aws-runtime/aws-core/common/src/aws/sdk/kotlin/runtime/AwsSdkSetting.kt @@ -0,0 +1,54 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +package aws.sdk.kotlin.runtime + +// NOTE: The JVM property names MUST match the ones defined in the Java SDK for any setting added. +// see: https://github.com/aws/aws-sdk-java-v2/blob/master/core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkSystemSetting.java + +/** + * Settings to configure SDK runtime behavior + */ +@InternalSdkApi +public sealed class AwsSdkSetting ( + /** + * The name of the corresponding environment variable that configures the setting + */ + public val environmentVariable: String, + + /** + * The name of the corresponding JVM system property that configures the setting + */ + public val jvmProperty: String, + + /** + * The default value (if one exists) + */ + public val defaultValue: T? = null +) { + /** + * Configure the AWS access key ID. + * + * This value will not be ignored if the [AwsSecretAccessKey] is not specified. + */ + public object AwsAccessKeyId : AwsSdkSetting("AWS_ACCESS_KEY_ID", "aws.accessKeyId") + + /** + * Configure the AWS secret access key. + * + * This value will not be ignored if the [AwsAccessKeyId] is not specified. + */ + public object AwsSecretAccessKey : AwsSdkSetting("AWS_SECRET_ACCESS_KEY", "aws.secretAccessKey") + + /** + * Configure the AWS session token. + */ + public object AwsSessionToken : AwsSdkSetting("AWS_SESSION_TOKEN", "aws.sessionToken") + + /** + * Configure the default region. + */ + public object AwsRegion : AwsSdkSetting("AWS_REGION", "aws.region") +} diff --git a/aws-runtime/regions/common/src/aws/sdk/kotlin/runtime/regions/providers/DefaultAwsRegionProviderChain.kt b/aws-runtime/regions/common/src/aws/sdk/kotlin/runtime/regions/providers/DefaultAwsRegionProviderChain.kt index 9a43686acec..a94613ba125 100644 --- a/aws-runtime/regions/common/src/aws/sdk/kotlin/runtime/regions/providers/DefaultAwsRegionProviderChain.kt +++ b/aws-runtime/regions/common/src/aws/sdk/kotlin/runtime/regions/providers/DefaultAwsRegionProviderChain.kt @@ -5,15 +5,11 @@ package aws.sdk.kotlin.runtime.regions.providers -// FIXME - this probably needs to be expect/actual to customize the chain per/target platform (and definitely needs per/platform tests) - /** * [AwsRegionProvider] that looks for region in this order: * 1. Check `aws.region` system property (JVM only) - * 2. Check the `AWS_REGION` and `AWS_DEFAULT_REGION` environment variable(s) (JVM, Node, Native) + * 2. Check the `AWS_REGION` environment variable (JVM, Node, Native) * 3. Check the AWS config files/profile for region information * 4. If running on EC2, check the EC2 metadata service for region */ -public class DefaultAwsRegionProviderChain : AwsRegionProviderChain { - public constructor() : super(EnvironmentRegionProvider()) -} +public expect class DefaultAwsRegionProviderChain public constructor() : AwsRegionProvider diff --git a/aws-runtime/regions/common/src/aws/sdk/kotlin/runtime/regions/providers/EnvironmentRegionProvider.kt b/aws-runtime/regions/common/src/aws/sdk/kotlin/runtime/regions/providers/EnvironmentRegionProvider.kt index 12abf09a418..e34bc16fb0e 100644 --- a/aws-runtime/regions/common/src/aws/sdk/kotlin/runtime/regions/providers/EnvironmentRegionProvider.kt +++ b/aws-runtime/regions/common/src/aws/sdk/kotlin/runtime/regions/providers/EnvironmentRegionProvider.kt @@ -5,10 +5,9 @@ package aws.sdk.kotlin.runtime.regions.providers +import aws.sdk.kotlin.runtime.AwsSdkSetting import aws.smithy.kotlin.runtime.util.Platform -private const val AWS_ENVIRON_REGION = "AWS_REGION" - /** * Provide a mapping from key to value */ @@ -17,7 +16,7 @@ public fun interface Environment { } /** - * [AwsRegionProvider] that checks `AWS_REGION` and `AWS_DEFAULT` region environment variables + * [AwsRegionProvider] that checks `AWS_REGION` region environment variable * @param environ the environment mapping to lookup keys in (defaults to the system environment) */ public class EnvironmentRegionProvider( @@ -25,5 +24,5 @@ public class EnvironmentRegionProvider( ) : AwsRegionProvider { public constructor() : this(Platform::getenv) - override suspend fun getRegion(): String? = environ.get(AWS_ENVIRON_REGION) + override suspend fun getRegion(): String? = environ.get(AwsSdkSetting.AwsRegion.environmentVariable) } diff --git a/aws-runtime/regions/jvm/src/aws/sdk/kotlin/runtime/regions/providers/DefaultAwsRegionProviderChainJVM.kt b/aws-runtime/regions/jvm/src/aws/sdk/kotlin/runtime/regions/providers/DefaultAwsRegionProviderChainJVM.kt new file mode 100644 index 00000000000..431810694f3 --- /dev/null +++ b/aws-runtime/regions/jvm/src/aws/sdk/kotlin/runtime/regions/providers/DefaultAwsRegionProviderChainJVM.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.regions.providers + +public actual class DefaultAwsRegionProviderChain public actual constructor() : + AwsRegionProvider, + AwsRegionProviderChain( + JvmSystemPropRegionProvider(), + EnvironmentRegionProvider() + ) diff --git a/aws-runtime/regions/jvm/src/aws/sdk/kotlin/runtime/regions/providers/JvmSystemPropRegionProvider.kt b/aws-runtime/regions/jvm/src/aws/sdk/kotlin/runtime/regions/providers/JvmSystemPropRegionProvider.kt new file mode 100644 index 00000000000..53c1edbc69b --- /dev/null +++ b/aws-runtime/regions/jvm/src/aws/sdk/kotlin/runtime/regions/providers/JvmSystemPropRegionProvider.kt @@ -0,0 +1,15 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +package aws.sdk.kotlin.runtime.regions.providers + +import aws.sdk.kotlin.runtime.AwsSdkSetting + +/** + * [AwsRegionProvider] that checks `aws.region` system property + */ +internal class JvmSystemPropRegionProvider : AwsRegionProvider { + override suspend fun getRegion(): String? = System.getProperty(AwsSdkSetting.AwsRegion.jvmProperty, null) +} diff --git a/aws-runtime/regions/jvm/test/aws/sdk/kotlin/runtime/regions/providers/JvmSystemPropRegionProviderTest.kt b/aws-runtime/regions/jvm/test/aws/sdk/kotlin/runtime/regions/providers/JvmSystemPropRegionProviderTest.kt new file mode 100644 index 00000000000..57b676b1153 --- /dev/null +++ b/aws-runtime/regions/jvm/test/aws/sdk/kotlin/runtime/regions/providers/JvmSystemPropRegionProviderTest.kt @@ -0,0 +1,25 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +package aws.sdk.kotlin.runtime.regions.providers + +import aws.sdk.kotlin.runtime.AwsSdkSetting +import aws.sdk.kotlin.runtime.testing.runSuspendTest +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertNull + +class JvmSystemPropRegionProviderTest { + + @Test + fun testGetRegion() = runSuspendTest { + val provider = JvmSystemPropRegionProvider() + + assertNull(provider.getRegion()) + + System.setProperty(AwsSdkSetting.AwsRegion.jvmProperty, "us-east-1") + assertEquals("us-east-1", provider.getRegion()) + } +}