Skip to content

Commit

Permalink
misc: credentials search precedence change (#1434)
Browse files Browse the repository at this point in the history
  • Loading branch information
0marperez authored Nov 4, 2024
1 parent acccef5 commit e297a98
Show file tree
Hide file tree
Showing 55 changed files with 1,055 additions and 237 deletions.
6 changes: 6 additions & 0 deletions .changes/0b5b53ab-70c0-4c1b-a445-8663ae86d6d1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"id": "0b5b53ab-70c0-4c1b-a445-8663ae86d6d1",
"type": "misc",
"description": "The order of credentials resolution in config files has been updated to: static credentials, assume role with source profile OR assume role with named provider, web identity token, SSO session, legacy SSO, process",
"requiresMinorVersionBump": true
}
6 changes: 6 additions & 0 deletions .changes/99a099e1-26c1-4ba1-b0d3-435609ea4e94.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"id": "99a099e1-26c1-4ba1-b0d3-435609ea4e94",
"type": "misc",
"description": "The order of credentials resolution in the credentials provider chain has been updated to: system properties, environment variables, web identity tokens, profile, ECS, EC2",
"requiresMinorVersionBump": true
}
111 changes: 111 additions & 0 deletions .changes/announcement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
An upcoming release of the **AWS SDK for Kotlin** will change the order of
credentials resolution for the [default credentials provider chain](https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/credential-providers.html#default-credential-provider-chain)
and the order of credentials resolution for AWS shared config files.

# Release date

This change will be included in the upcoming **v1.4.x** release, expected in the
upcoming months.

# What's changing

The order of credentials resolution for the default credentials provider chain,
and the order of credentials resolution for AWS shared config files (profile chain).

## Default credentials provider chain

The table below outlines the current and new order in which the SDK will
resolve credentials from the default credentials provider chain.

| # | Current Order | New Order |
|---|------------------------------------------------------------------------|------------------------------------------------------------------------|
| 1 | System properties | System properties |
| 2 | Environment variables | Environment variables |
| 3 | **Shared credentials and config files (profile credentials provider)** | **Assume role with web identity token** |
| 4 | **Assume role with web identity token** | **Shared credentials and config files (profile credentials provider)** |
| 5 | Amazon ECS container credentials | Amazon ECS container credentials |
| 6 | Amazon EC2 Instance Metadata Service | Amazon EC2 Instance Metadata Service |

The [default credentials provider chain documentation](https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/credential-providers.html#default-credential-provider-chain)
contains more details on each credential source.

## Profile chain

The table below outlines the current and new order in which the SDK will
resolve credentials from AWS shared config files.

| # | Current Order | New Order |
|---|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
| 1 | **Assume role with source profile OR assume role with named provider (mutually exclusive)** | **Static credentials** |
| 2 | Web identity token | **Assume role with source profile OR assume role with named provider (mutually exclusive)** |
| 3 | SSO session | Web identity token |
| 4 | Legacy SSO | SSO session |
| 5 | Process | Legacy SSO |
| 6 | **Static credentials (moves up to #1 when in a source profile, shifting other credential sources down)** | Process |

# How to migrate

1. Upgrade all of your AWS SDK for Kotlin dependencies to **v.1.4.x**.
2. Verify that the changes to the default credentials provider chain and profile chain do not introduce any issues in your program.
3. If issues arise review the new credentials resolution order, the subsections below, and adjust your configuration as needed.

## Default credentials provider chain

You can preserve the current default credentials provider chain behavior by setting
the credentials provider to a credentials provider chain with the current order, e.g.

```kotlin
S3Client{
credentialsProvider = CredentialsProviderChain(
SystemPropertyCredentialsProvider(),
EnvironmentCredentialsProvider(),
LazilyInitializedCredentialsProvider("EnvironmentStsWebIdentityCredentialsProvider") {
StsWebIdentityCredentialsProvider.fromEnvironment()
},
ProfileCredentialsProvider(),
EcsCredentialsProvider(),
ImdsCredentialsProvider(),
)
}
```

## Profile credentials provider

The order in which credentials are resolved for shared credentials and config
files cannot be customized. If your AWS config file(s) contain multiple valid
credential sources within a single profile, you may need to update them to align
with the new resolution order. For example, config file `A` should be updated to
match config file `B`. This is necessary because static credentials will now
take precedence and be selected before assume role credentials with a source profile.
Similar adjustments to your configuration may be necessary to maintain current
behavior. Use the new order as a guide for any required changes.

Config file `A`
```ini
[default]
role_arn = arn:aws:iam::123456789:role/Role
source_profile = A
aws_access_key_id = 0
aws_secret_access_key = 0

[profile A]
aws_access_key_id = 1
aws_secret_access_key = 2
```

Config file `B`
```ini
[default]
role_arn = arn:aws:iam::123456789:role/Role
source_profile = A

[profile A]
aws_access_key_id = 1
aws_secret_access_key = 2
```

# Feedback

If you have any questions concerning this change, please feel free to engage
with us in this discussion. If you encounter a bug with these changes when
released, please [file an issue](https://github.com/awslabs/aws-sdk-kotlin/issues/new/choose).
22 changes: 22 additions & 0 deletions aws-runtime/aws-config/api/aws-config.api
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/DefaultChainCredentia
public final fun getProfileName ()Ljava/lang/String;
public final fun getRegion ()Ljava/lang/String;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/EcsCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CloseableCredentialsProvider {
Expand All @@ -62,6 +63,7 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/EcsCredentialsProvide
public fun close ()V
public final fun getPlatformProvider ()Laws/smithy/kotlin/runtime/util/PlatformProvider;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/EnvironmentCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CredentialsProvider {
Expand All @@ -70,6 +72,7 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/EnvironmentCredential
public synthetic fun <init> (Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getGetEnv ()Lkotlin/jvm/functions/Function1;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/ImdsCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CloseableCredentialsProvider {
Expand All @@ -81,6 +84,7 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/ImdsCredentialsProvid
public final fun getPlatformProvider ()Laws/smithy/kotlin/runtime/util/PlatformEnvironProvider;
public final fun getProfileOverride ()Ljava/lang/String;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/InvalidJsonCredentialsException : aws/sdk/kotlin/runtime/ClientException {
Expand All @@ -97,6 +101,7 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/ProcessCredentialsPro
public fun <init> (Ljava/lang/String;Laws/smithy/kotlin/runtime/util/PlatformProvider;JJ)V
public synthetic fun <init> (Ljava/lang/String;Laws/smithy/kotlin/runtime/util/PlatformProvider;JJILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/ProfileCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CloseableCredentialsProvider {
Expand All @@ -112,6 +117,7 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/ProfileCredentialsPro
public final fun getProfileName ()Ljava/lang/String;
public final fun getRegion ()Ljava/lang/String;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/ProviderConfigurationException : aws/sdk/kotlin/runtime/ConfigurationException {
Expand All @@ -130,6 +136,7 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/SsoCredentialsProvide
public final fun getSsoSessionName ()Ljava/lang/String;
public final fun getStartUrl ()Ljava/lang/String;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/SsoTokenProvider : aws/smithy/kotlin/runtime/http/auth/BearerTokenProvider {
Expand All @@ -150,6 +157,7 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/StaticCredentialsProv
public fun <init> (Laws/smithy/kotlin/runtime/auth/awscredentials/Credentials;)V
public final fun getCredentials ()Laws/smithy/kotlin/runtime/auth/awscredentials/Credentials;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/StaticCredentialsProvider$Builder {
Expand Down Expand Up @@ -179,6 +187,7 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/StsAssumeRoleCredenti
public final fun getHttpClient ()Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;
public final fun getRegion ()Ljava/lang/String;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CredentialsProvider {
Expand All @@ -192,19 +201,32 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredent
public final fun getRegion ()Ljava/lang/String;
public final fun getWebIdentityParameters ()Laws/sdk/kotlin/runtime/auth/credentials/AssumeRoleWithWebIdentityParameters;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredentialsProvider$Companion {
public final fun fromEnvironment-TUY-ock (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;)Laws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityCredentialsProvider;
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;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/StsWebIdentityProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CloseableCredentialsProvider {
public fun <init> ()V
public fun <init> (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;Ljava/lang/String;)V
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
public fun close ()V
public final fun getHttpClient ()Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;
public final fun getPlatformProvider ()Laws/smithy/kotlin/runtime/util/PlatformProvider;
public final fun getRegion ()Ljava/lang/String;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/SystemPropertyCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CredentialsProvider {
public fun <init> ()V
public fun <init> (Lkotlin/jvm/functions/Function1;)V
public synthetic fun <init> (Lkotlin/jvm/functions/Function1;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getGetProperty ()Lkotlin/jvm/functions/Function1;
public fun resolve (Laws/smithy/kotlin/runtime/collections/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/runtime/auth/credentials/internal/ManagedBearerTokenProviderKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ package aws.sdk.kotlin.runtime.auth.credentials

import aws.sdk.kotlin.runtime.config.AwsSdkSetting
import aws.sdk.kotlin.runtime.config.imds.ImdsClient
import aws.smithy.kotlin.runtime.auth.awscredentials.CachedCredentialsProvider
import aws.smithy.kotlin.runtime.auth.awscredentials.CloseableCredentialsProvider
import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
import aws.smithy.kotlin.runtime.auth.awscredentials.CredentialsProviderChain
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.*
import aws.smithy.kotlin.runtime.collections.Attributes
import aws.smithy.kotlin.runtime.http.engine.DefaultHttpEngine
import aws.smithy.kotlin.runtime.http.engine.HttpClientEngine
Expand All @@ -23,11 +22,12 @@ import aws.smithy.kotlin.runtime.util.PlatformProvider
*
* Resolution order:
*
* 1. Environment variables ([EnvironmentCredentialsProvider])
* 2. Profile ([ProfileCredentialsProvider])
* 1. System properties ([SystemPropertyCredentialsProvider])
* 2. Environment variables ([EnvironmentCredentialsProvider])
* 3. Web Identity Tokens ([StsWebIdentityCredentialsProvider]]
* 4. ECS (IAM roles for tasks) ([EcsCredentialsProvider])
* 5. EC2 Instance Metadata (IMDSv2) ([ImdsCredentialsProvider])
* 4. Profile ([ProfileCredentialsProvider])
* 5. ECS (IAM roles for tasks) ([EcsCredentialsProvider])
* 6. EC2 Instance Metadata (IMDSv2) ([ImdsCredentialsProvider])
*
* The chain is decorated with a [CachedCredentialsProvider].
*
Expand All @@ -54,9 +54,9 @@ public class DefaultChainCredentialsProvider constructor(
private val chain = CredentialsProviderChain(
SystemPropertyCredentialsProvider(platformProvider::getProperty),
EnvironmentCredentialsProvider(platformProvider::getenv),
ProfileCredentialsProvider(profileName = profileName, platformProvider = platformProvider, httpClient = engine, region = region),
// STS web identity provider can be constructed from either the profile OR 100% from the environment
StsWebIdentityProvider(platformProvider = platformProvider, httpClient = engine, region = region),
ProfileCredentialsProvider(profileName = profileName, platformProvider = platformProvider, httpClient = engine, region = region),
EcsCredentialsProvider(platformProvider, engine),
ImdsCredentialsProvider(
client = lazy {
Expand All @@ -79,20 +79,22 @@ public class DefaultChainCredentialsProvider constructor(
engine.closeIfCloseable()
}
}

override fun toString(): String = this.simpleClassName + ": " + this.chain
}

/**
* Wrapper around [StsWebIdentityCredentialsProvider] that delays any exceptions until [resolve] is invoked.
* This allows it to be part of the default chain and any failures result in the chain to move onto the next provider.
*/
private class StsWebIdentityProvider(
val platformProvider: PlatformProvider = PlatformProvider.System,
val httpClient: HttpClientEngine? = null,
val region: String? = null,
public class StsWebIdentityProvider(
public val platformProvider: PlatformProvider = PlatformProvider.System,
public val httpClient: HttpClientEngine? = null,
public val region: String? = null,
) : CloseableCredentialsProvider {
override suspend fun resolve(attributes: Attributes): Credentials {
val wrapped = StsWebIdentityCredentialsProvider.fromEnvironment(platformProvider = platformProvider, httpClient = httpClient, region = region)
return wrapped.resolve(attributes)
return wrapped.resolve(attributes).withBusinessMetric(AwsBusinessMetric.Credentials.CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN)
}

override fun close() { }
Expand Down
Loading

0 comments on commit e297a98

Please sign in to comment.