Skip to content

Commit 21e7f31

Browse files
Merging main into release
2 parents 08b654a + 1ef81ff commit 21e7f31

File tree

15 files changed

+494
-61
lines changed

15 files changed

+494
-61
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "256a9c00-f658-4ee8-9e02-2cf46b76a900",
3+
"type": "bugfix",
4+
"description": "Add `forcePathStyle` and `enableAccelerate` config properties back to the S3 client.",
5+
"issues": [
6+
"awslabs/aws-sdk-kotlin#1098"
7+
]
8+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": "cfedccd4-4819-4fb7-9570-9db62ef484a8",
3+
"type": "misc",
4+
"description": "Upgrade to the latest version of **smithy-kotlin**"
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": "dc1ee1a2-547e-4caa-8696-2affe5289d42",
3+
"type": "feature",
4+
"description": "Support EKS endpoints and auth token file in container credentials provider."
5+
}

.github/workflows/release-check.yml

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
name: Update release branch
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
commit_message:
7+
description: |
8+
The merge commit message to use for non fast-forward merges.
9+
required: false
10+
type: string
11+
dry_run:
12+
description: Dry runs will only attempt to merge but the result will not be pushed to the release branch
13+
required: true
14+
type: boolean
15+
default: true
16+
17+
concurrency:
18+
group: release-manual-${{ github.ref }}
19+
cancel-in-progress: true
20+
21+
jobs:
22+
update-release:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
with:
27+
ref: 'main'
28+
fetch-depth: 0
29+
token: ${{ secrets.CI_USER_PAT }}
30+
- name: Configure Git
31+
shell: bash
32+
run: |
33+
git config user.name aws-sdk-kotlin-ci
34+
git config user.email "[email protected]"
35+
- name: Configure JDK
36+
uses: actions/setup-java@v3
37+
with:
38+
distribution: 'corretto'
39+
java-version: 17
40+
cache: 'gradle'
41+
- name: Check merge base
42+
shell: bash
43+
run: |
44+
git status
45+
git branch -vv
46+
git fetch
47+
main_sha=$(git rev-parse main)
48+
release_sha=$(git rev-parse origin/release)
49+
echo "main_sha=$main_sha" >> $GITHUB_ENV
50+
echo "release_sha=$release_sha" >> $GITHUB_ENV
51+
if git merge-base --is-ancestor $main_sha $release_sha; then
52+
echo "main@$main_sha already exists in origin/release, nothing to update";
53+
echo "MERGE_NEEDED=false" >> $GITHUB_ENV;
54+
else
55+
echo "MERGE_NEEDED=true" >> $GITHUB_ENV
56+
fi
57+
- name: Release Check - snapshot versions
58+
if: env.MERGE_NEEDED == 'true'
59+
run: |
60+
# We aren't releasable if we (1) directly depend on a snapshot version of a dependency OR (2) can't build the project without unreleased changes
61+
if grep -q -i snapshot ./gradle/libs.versions.toml; then
62+
echo "::error ::found snapshot version in libs.versions.toml"
63+
exit 1
64+
fi
65+
- name: Release Check - build
66+
if: env.MERGE_NEEDED == 'true'
67+
run: |
68+
# Our CI is implemented as a "live at HEAD" model where we build against the latest of all our 1P deps (either
69+
# main branch or matching branch name). Double check that without this "live at HEAD" mode we still build
70+
# successfully (which is how it is built during release).
71+
# This should help prevent the cases where we forgot to bump smithy-kotlin versions and don't catch it
72+
# because CI is masking it
73+
./gradlew -Paws.kotlin.native=false test jvmTest
74+
- name: Merge
75+
if: env.MERGE_NEEDED == 'true'
76+
shell: bash
77+
run: |
78+
echo "merging main @ $main_sha into release @ $release_sha";
79+
git switch release;
80+
input_message=${{ inputs.commit_message }}
81+
message=${input_message:-"Merging main into release"}
82+
echo "message=$message"
83+
git merge -m "$message" main;
84+
if [ "${{ inputs.dry_run }}" == "true" ]; then
85+
echo "dry run, skipping push to remote";
86+
git log -n 10 --oneline;
87+
else
88+
echo "pushing changes to release branch";
89+
git push origin release;
90+
fi

aws-runtime/aws-config/api/aws-config.api

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ public final class aws/sdk/kotlin/runtime/auth/credentials/DefaultChainCredentia
5555

5656
public final class aws/sdk/kotlin/runtime/auth/credentials/EcsCredentialsProvider : aws/smithy/kotlin/runtime/auth/awscredentials/CloseableCredentialsProvider {
5757
public fun <init> ()V
58-
public fun <init> (Laws/smithy/kotlin/runtime/util/PlatformEnvironProvider;Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;)V
59-
public synthetic fun <init> (Laws/smithy/kotlin/runtime/util/PlatformEnvironProvider;Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
58+
public fun <init> (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;)V
59+
public synthetic fun <init> (Laws/smithy/kotlin/runtime/util/PlatformProvider;Laws/smithy/kotlin/runtime/http/engine/HttpClientEngine;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
6060
public fun close ()V
61-
public final fun getPlatformProvider ()Laws/smithy/kotlin/runtime/util/PlatformEnvironProvider;
61+
public final fun getPlatformProvider ()Laws/smithy/kotlin/runtime/util/PlatformProvider;
6262
public fun resolve (Laws/smithy/kotlin/runtime/util/Attributes;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
6363
}
6464

aws-runtime/aws-config/common/src/aws/sdk/kotlin/runtime/auth/credentials/EcsCredentialsProvider.kt

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ import aws.smithy.kotlin.runtime.http.request.HttpRequestBuilder
2323
import aws.smithy.kotlin.runtime.http.request.header
2424
import aws.smithy.kotlin.runtime.http.response.HttpResponse
2525
import aws.smithy.kotlin.runtime.io.closeIfCloseable
26-
import aws.smithy.kotlin.runtime.net.Scheme
27-
import aws.smithy.kotlin.runtime.net.Url
26+
import aws.smithy.kotlin.runtime.net.*
2827
import aws.smithy.kotlin.runtime.operation.ExecutionContext
2928
import aws.smithy.kotlin.runtime.retries.policy.RetryDirective
3029
import aws.smithy.kotlin.runtime.retries.policy.RetryErrorType
@@ -33,7 +32,6 @@ import aws.smithy.kotlin.runtime.serde.json.JsonDeserializer
3332
import aws.smithy.kotlin.runtime.telemetry.logging.logger
3433
import aws.smithy.kotlin.runtime.time.TimestampFormat
3534
import aws.smithy.kotlin.runtime.util.Attributes
36-
import aws.smithy.kotlin.runtime.util.PlatformEnvironProvider
3735
import aws.smithy.kotlin.runtime.util.PlatformProvider
3836
import kotlin.coroutines.coroutineContext
3937

@@ -61,7 +59,7 @@ private const val PROVIDER_NAME = "EcsContainer"
6159
*
6260
*/
6361
public class EcsCredentialsProvider(
64-
public val platformProvider: PlatformEnvironProvider = PlatformProvider.System,
62+
public val platformProvider: PlatformProvider = PlatformProvider.System,
6563
httpClient: HttpClientEngine? = null,
6664
) : CloseableCredentialsProvider {
6765

@@ -70,7 +68,7 @@ public class EcsCredentialsProvider(
7068

7169
override suspend fun resolve(attributes: Attributes): Credentials {
7270
val logger = coroutineContext.logger<EcsCredentialsProvider>()
73-
val authToken = AwsSdkSetting.AwsContainerAuthorizationToken.resolve(platformProvider)
71+
val authToken = loadAuthToken()
7472
val relativeUri = AwsSdkSetting.AwsContainerCredentialsRelativeUri.resolve(platformProvider)
7573
val fullUri = AwsSdkSetting.AwsContainerCredentialsFullUri.resolve(platformProvider)
7674

@@ -107,6 +105,22 @@ public class EcsCredentialsProvider(
107105
return creds
108106
}
109107

108+
private suspend fun loadAuthToken(): String? {
109+
val token = AwsSdkSetting.AwsContainerAuthorizationTokenFile.resolve(platformProvider)?.let { loadAuthTokenFromFile(it) }
110+
?: AwsSdkSetting.AwsContainerAuthorizationToken.resolve(platformProvider)
111+
?: return null
112+
113+
if (token.contains("\r\n")) {
114+
throw CredentialsProviderException("Token contains illegal line break sequence.")
115+
}
116+
117+
return token
118+
}
119+
120+
private suspend fun loadAuthTokenFromFile(path: String): String =
121+
platformProvider.readFileOrNull(path)?.decodeToString()
122+
?: throw CredentialsProviderException("Could not read token file.")
123+
110124
/**
111125
* Validate that the [relativeUri] can be combined with the static ECS endpoint to form a valid URL
112126
*/
@@ -127,7 +141,6 @@ public class EcsCredentialsProvider(
127141
* @return the validated URL
128142
*/
129143
private suspend fun validateFullUri(uri: String): Url {
130-
// full URI requires verification either https OR that the host resolves to loopback device
131144
val url = try {
132145
Url.parse(uri)
133146
} catch (ex: Exception) {
@@ -136,16 +149,22 @@ public class EcsCredentialsProvider(
136149

137150
if (url.scheme == Scheme.HTTPS) return url
138151

139-
// TODO - validate loopback via DNS resolution instead of fixed set. Custom host names (including localhost) that
140-
// resolve to loopback won't work until then. ALL resolved addresses MUST resolve to the loopback device
141-
val allowedHosts = setOf("127.0.0.1", "::1")
152+
when (url.host) {
153+
is Host.IpAddress -> {
154+
if (allowedAddrs.contains((url.host as Host.IpAddress).address)) {
155+
return url
156+
}
142157

143-
if (url.host.toString() !in allowedHosts) {
144-
throw ProviderConfigurationException(
145-
"The container credentials full URI ($uri) has an invalid host. Host can only be one of [${allowedHosts.joinToString()}].",
158+
throw ProviderConfigurationException(
159+
"The container credentials full URI ($uri) has an invalid host. Host can only be one of [${allowedAddrs.joinToString()}].",
160+
)
161+
}
162+
163+
// TODO - resolve hostnames
164+
is Host.Domain -> throw ProviderConfigurationException(
165+
"The container credentials full URI ($uri) is specified via hostname which is not currently supported.",
146166
)
147167
}
148-
return url
149168
}
150169

151170
override fun close() {
@@ -228,3 +247,11 @@ internal class EcsCredentialsRetryPolicy : RetryPolicy<Any?> {
228247
else -> RetryDirective.TerminateAndFail
229248
}
230249
}
250+
251+
private val ecsV4Addr = IpV4Addr(169u, 254u, 170u, 2u)
252+
253+
private val eksV4Addr = IpV4Addr(169u, 254u, 170u, 23u)
254+
255+
private val eksV6Addr = IpV6Addr(0xfd00u, 0xec2u, 0u, 0u, 0u, 0u, 0u, 0x23u)
256+
257+
private val allowedAddrs = setOf(IpV4Addr.LOCALHOST, IpV6Addr.LOCALHOST, ecsV4Addr, eksV4Addr, eksV6Addr)

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ public object AwsSdkSetting {
139139
public val AwsContainerAuthorizationToken: EnvironmentSetting<String> =
140140
strEnvSetting("aws.containerAuthorizationToken", "AWS_CONTAINER_AUTHORIZATION_TOKEN")
141141

142+
/**
143+
* A path to a file which contains an authorization token to pass to a container metadata service.
144+
*/
145+
public val AwsContainerAuthorizationTokenFile: EnvironmentSetting<String> =
146+
strEnvSetting("aws.containerAuthorizationTokenFile", "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE")
147+
142148
/**
143149
* The maximum number of request attempts to perform. This is one more than the number of retries, so
144150
* aws.maxAttempts = 1 will have 0 retries.

0 commit comments

Comments
 (0)