Skip to content

Commit 4d290a5

Browse files
authored
Profile Auth Support JVM system property and Environment Variables #297 (#312)
1 parent 7aa183e commit 4d290a5

File tree

7 files changed

+105
-17
lines changed

7 files changed

+105
-17
lines changed

.github/workflows/lint.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ on:
55
branches:
66
- '*'
77
- '!main'
8+
pull_request:
9+
branches: [ main ]
810
workflow_dispatch:
911

1012
env:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ local.properties
1515
# ignore generated files
1616
services/*/generated-src
1717
services/*/build.gradle.kts
18+
.kotest/

aws-runtime/auth/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extra["displayName"] = "Software :: AWS :: Kotlin SDK :: Auth"
88
extra["moduleName"] = "aws.sdk.kotlin.runtime.auth"
99

1010
val smithyKotlinVersion: String by project
11+
val kotestVersion: String by project
1112

1213
kotlin {
1314
sourceSets {
@@ -26,5 +27,10 @@ kotlin {
2627
implementation(project(":aws-runtime:testing"))
2728
}
2829
}
30+
jvmTest {
31+
dependencies {
32+
implementation("io.kotest:kotest-runner-junit5:$kotestVersion")
33+
}
34+
}
2935
}
3036
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,16 @@ public class ProfileCredentialsProvider public constructor(
2525
override val crtProvider: ProfileCredentialsProviderCrt = ProfileCredentialsProviderCrt.build {
2626
clientBootstrap = SdkDefaultIO.ClientBootstrap
2727
tlsContext = SdkDefaultIO.TlsContext
28-
this.profileName = profileName
28+
this.profileName = profileName ?: loadProfileName()
2929
this.configFileName = configFileName
3030
this.credentialsFileName = credentialsFileName
3131
}
3232
}
33+
34+
/**
35+
* Attempts to load profile name using the following priority,
36+
* if neither are available, profileName will remain blank.
37+
* 1. JVM System Property
38+
* 2. Environment Variable
39+
*/
40+
internal expect fun loadProfileName(): String?
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
6+
package aws.sdk.kotlin.runtime.auth
7+
8+
import aws.sdk.kotlin.runtime.AwsSdkSetting
9+
10+
/**
11+
* Attempts to load profile name using the following priority,
12+
* if neither are available, profileName will remain blank.
13+
* 1. JVM System Property
14+
* 2. Environment Variable
15+
*/
16+
internal actual fun loadProfileName(): String? {
17+
val profileSysPropOverride = System.getProperty(AwsSdkSetting.AwsProfile.jvmProperty, "")
18+
return profileSysPropOverride.ifEmpty {
19+
System.getenv().getOrDefault(AwsSdkSetting.AwsProfile.environmentVariable, null)
20+
}
21+
}

aws-runtime/auth/jvm/test/aws/sdk/kotlin/runtime/auth/ProfileCredentialsProviderTest.kt

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,80 @@
55

66
package aws.sdk.kotlin.runtime.auth
77

8+
import aws.sdk.kotlin.runtime.AwsSdkSetting
9+
import io.kotest.extensions.system.withEnvironment
810
import kotlinx.coroutines.runBlocking
11+
import org.junit.jupiter.api.AfterAll
12+
import org.junit.jupiter.api.BeforeAll
913
import java.nio.file.Files
14+
import java.nio.file.Path
1015
import kotlin.test.Test
1116
import kotlin.test.assertEquals
1217

1318
class ProfileCredentialsProviderTest {
1419
companion object {
15-
private const val ID = "abcd"
16-
private const val KEY = "efgh"
17-
private val EXPECTED_CREDS = Credentials(ID, KEY, null)
20+
private const val DEFAULT_ID = "defaultId"
21+
private const val DEFAULT_KEY = "defaultKey"
22+
private val EXPECTED_DEFAULT_CREDS = Credentials(DEFAULT_ID, DEFAULT_KEY, null)
23+
24+
private const val PROFILE_ID = "profileId"
25+
private const val PROFILE_KEY = "profileKey"
26+
private val EXPECTED_PROFILE_CREDS = Credentials(PROFILE_ID, PROFILE_KEY, null)
27+
28+
private lateinit var credsPath: Path
29+
30+
@BeforeAll
31+
@JvmStatic
32+
fun setup() {
33+
credsPath = Files.createTempFile("ProfileCredentialsProviderTest_creds", "")
34+
credsPath.toFile().writeText(
35+
"""
36+
[default]
37+
aws_access_key_id = $DEFAULT_ID
38+
aws_secret_access_key = $DEFAULT_KEY
39+
40+
[unique-profile-name]
41+
aws_access_key_id = $PROFILE_ID
42+
aws_secret_access_key = $PROFILE_KEY
43+
""".trimIndent()
44+
)
45+
}
46+
47+
@AfterAll
48+
@JvmStatic
49+
fun teardown() {
50+
Files.deleteIfExists(credsPath)
51+
}
1852
}
1953

2054
@Test
21-
fun `it should create a provider for a valid profile`() = runBlocking {
22-
val credsPath = Files.createTempFile("ProfileCredentialsProviderTest_creds", "")
23-
credsPath.toFile().writeText(
24-
"""
25-
[default]
26-
aws_access_key_id = $ID
27-
aws_secret_access_key = $KEY
28-
""".trimIndent()
29-
)
55+
fun `it should create a provider for a default profile`() = runBlocking {
56+
val provider = ProfileCredentialsProvider(credentialsFileName = credsPath.toString())
57+
val actual = provider.getCredentials()
58+
assertEquals(EXPECTED_DEFAULT_CREDS, actual)
59+
}
3060

31-
try {
61+
@Test
62+
fun `it should create a provider for a unique profile specified in constructor`() = runBlocking {
63+
val provider = ProfileCredentialsProvider(profileName = "unique-profile-name", credentialsFileName = credsPath.toString())
64+
val actual = provider.getCredentials()
65+
assertEquals(EXPECTED_PROFILE_CREDS, actual)
66+
}
67+
68+
@Test
69+
fun `it should create a provider for a unique profile specified from JVM Property`() = runBlocking {
70+
System.setProperty(AwsSdkSetting.AwsProfile.jvmProperty, "unique-profile-name")
71+
val provider = ProfileCredentialsProvider(credentialsFileName = credsPath.toString())
72+
val actual = provider.getCredentials()
73+
assertEquals(EXPECTED_PROFILE_CREDS, actual)
74+
}
75+
76+
@Test
77+
fun `it should create a provider for a unique profile specified from Environment Variable`() = runBlocking {
78+
withEnvironment(AwsSdkSetting.AwsProfile.environmentVariable, "unique-profile-name") {
3279
val provider = ProfileCredentialsProvider(credentialsFileName = credsPath.toString())
3380
val actual = provider.getCredentials()
34-
assertEquals(EXPECTED_CREDS, actual)
35-
} finally {
36-
Files.deleteIfExists(credsPath)
81+
assertEquals(EXPECTED_PROFILE_CREDS, actual)
3782
}
3883
}
3984
}

aws-runtime/aws-core/common/src/aws/sdk/kotlin/runtime/AwsSdkSetting.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,9 @@ public sealed class AwsSdkSetting<T> (
5757
* For example, AWS Lambda will automatically specify a runtime indicating that the SDK is being used within Lambda.
5858
*/
5959
public object AwsExecutionEnv : AwsSdkSetting<String>("AWS_EXECUTION_ENV", "aws.executionEnvironment")
60+
61+
/**
62+
* The name of the default profile that should be loaded from config
63+
*/
64+
public object AwsProfile : AwsSdkSetting<String>("AWS_PROFILE", "aws.profile", "default")
6065
}

0 commit comments

Comments
 (0)