Skip to content

Commit c63cf83

Browse files
committed
Presigned URL checksums
1 parent b2e6f61 commit c63cf83

File tree

10 files changed

+63
-9
lines changed

10 files changed

+63
-9
lines changed

codegen/smithy-kotlin-codegen/src/main/kotlin/software/amazon/smithy/kotlin/codegen/core/RuntimeTypes.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ object RuntimeTypes {
106106
val TimestampFormat = symbol("TimestampFormat", "time")
107107
val ClientException = symbol("ClientException")
108108
val SdkDsl = symbol("SdkDsl")
109+
val IllegalStateException = symbol("IllegalStateException")
109110

110111
object BusinessMetrics : RuntimeTypePackage(KotlinDependency.CORE, "businessmetrics") {
111112
val AccountIdBasedEndpointAccountId = symbol("AccountIdBasedEndpointAccountId")
@@ -170,6 +171,8 @@ object RuntimeTypes {
170171

171172
object Hashing : RuntimeTypePackage(KotlinDependency.CORE, "hashing") {
172173
val Sha256 = symbol("Sha256")
174+
val toHashFunctionOrThrow = symbol("toHashFunctionOrThrow")
175+
val isSupportedForFlexibleChecksums = symbol("isSupportedForFlexibleChecksums")
173176
}
174177

175178
object IO : RuntimeTypePackage(KotlinDependency.CORE, "io") {
@@ -180,6 +183,7 @@ object RuntimeTypes {
180183
}
181184

182185
object Text : RuntimeTypePackage(KotlinDependency.CORE, "text") {
186+
val lowercase = symbol("lowercase")
183187
object Encoding : RuntimeTypePackage(KotlinDependency.CORE, "text.encoding") {
184188
val decodeBase64 = symbol("decodeBase64")
185189
val decodeBase64Bytes = symbol("decodeBase64Bytes")
@@ -199,6 +203,7 @@ object RuntimeTypes {
199203
val toNumber = symbol("toNumber")
200204
val type = symbol("type")
201205
val PlatformProvider = symbol("PlatformProvider")
206+
val runBlocking = symbol("runBlocking")
202207
}
203208

204209
object Net : RuntimeTypePackage(KotlinDependency.CORE, "net") {
@@ -397,6 +402,7 @@ object RuntimeTypes {
397402
val TelemetryContextElement = symbol("TelemetryContextElement", "context")
398403
val TraceSpan = symbol("TraceSpan", "trace")
399404
val withSpan = symbol("withSpan", "trace")
405+
val warn = symbol("warn", "logging")
400406
}
401407
object TelemetryDefaults : RuntimeTypePackage(KotlinDependency.TELEMETRY_DEFAULTS) {
402408
val Global = symbol("Global")

runtime/auth/aws-signing-common/api/aws-signing-common.api

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public final class aws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig {
7171
public static final field Companion Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig$Companion;
7272
public fun <init> (Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig$Builder;)V
7373
public final fun getAlgorithm ()Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningAlgorithm;
74+
public final fun getChecksum ()Lkotlin/Pair;
7475
public final fun getCredentials ()Laws/smithy/kotlin/runtime/auth/awscredentials/Credentials;
7576
public final fun getExpiresAfter-FghU774 ()Lkotlin/time/Duration;
7677
public final fun getHashSpecification ()Laws/smithy/kotlin/runtime/auth/awssigning/HashSpecification;
@@ -91,6 +92,7 @@ public final class aws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig$Bu
9192
public fun <init> ()V
9293
public final fun build ()Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig;
9394
public final fun getAlgorithm ()Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningAlgorithm;
95+
public final fun getChecksum ()Lkotlin/Pair;
9496
public final fun getCredentials ()Laws/smithy/kotlin/runtime/auth/awscredentials/Credentials;
9597
public final fun getExpiresAfter-FghU774 ()Lkotlin/time/Duration;
9698
public final fun getHashSpecification ()Laws/smithy/kotlin/runtime/auth/awssigning/HashSpecification;
@@ -105,6 +107,7 @@ public final class aws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig$Bu
105107
public final fun getSigningDate ()Laws/smithy/kotlin/runtime/time/Instant;
106108
public final fun getUseDoubleUriEncode ()Z
107109
public final fun setAlgorithm (Laws/smithy/kotlin/runtime/auth/awssigning/AwsSigningAlgorithm;)V
110+
public final fun setChecksum (Lkotlin/Pair;)V
108111
public final fun setCredentials (Laws/smithy/kotlin/runtime/auth/awscredentials/Credentials;)V
109112
public final fun setExpiresAfter-BwNAW2A (Lkotlin/time/Duration;)V
110113
public final fun setHashSpecification (Laws/smithy/kotlin/runtime/auth/awssigning/HashSpecification;)V

runtime/auth/aws-signing-common/common/src/aws/smithy/kotlin/runtime/auth/awssigning/AwsSigningConfig.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ public class AwsSigningConfig(builder: Builder) {
172172
*/
173173
public val logRequest: Boolean = builder.logRequest
174174

175+
/**
176+
* Determines the checksum to add to the canonical request query parameters before signing.
177+
*/
178+
public val checksum: Pair<String, String>? = builder.checksum
179+
175180
public fun toBuilder(): Builder = Builder().also {
176181
it.region = region
177182
it.service = service
@@ -187,6 +192,7 @@ public class AwsSigningConfig(builder: Builder) {
187192
it.credentials = credentials
188193
it.expiresAfter = expiresAfter
189194
it.logRequest = logRequest
195+
it.checksum = checksum
190196
}
191197

192198
public class Builder {
@@ -204,6 +210,7 @@ public class AwsSigningConfig(builder: Builder) {
204210
public var credentials: Credentials? = null
205211
public var expiresAfter: Duration? = null
206212
public var logRequest: Boolean = false
213+
public var checksum: Pair<String, String>? = null
207214

208215
public fun build(): AwsSigningConfig = AwsSigningConfig(this)
209216
}

runtime/auth/aws-signing-default/common/src/aws/smithy/kotlin/runtime/auth/awssigning/Canonicalizer.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ internal class DefaultCanonicalizer(private val sha256Supplier: HashSupplier = :
120120
param("X-Amz-Expires", config.expiresAfter?.inWholeSeconds?.toString(), signViaQueryParams)
121121
param("X-Amz-Security-Token", sessionToken, !config.omitSessionToken) // Add pre-sig if omitSessionToken=false
122122

123+
// Add checksum as query param
124+
if (config.signatureType == AwsSignatureType.HTTP_REQUEST_VIA_QUERY_PARAMS && config.checksum != null) {
125+
param(config.checksum!!.first, config.checksum!!.second)
126+
}
127+
123128
val headers = builder
124129
.headers
125130
.entries()

runtime/protocol/http-client/common/src/aws/smithy/kotlin/runtime/http/interceptors/FlexibleChecksumsRequestInterceptor.kt

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public class FlexibleChecksumsRequestInterceptor<I>(
8181

8282
private val checksumAlgorithm = requestChecksumAlgorithm
8383
?.toHashFunctionOrThrow()
84-
?.takeIf { it.isSupported }
84+
?.takeIf { it.isSupportedForFlexibleChecksums }
8585
?: (Crc32().takeIf { requestChecksumRequired || requestChecksumCalculation == HttpChecksumConfigOption.WHEN_SUPPORTED })
8686

8787
// TODO: Remove in next minor version bump
@@ -169,14 +169,6 @@ public class FlexibleChecksumsRequestInterceptor<I>(
169169
contentLength != null &&
170170
(isOneShot || contentLength!! > 65536 * 16)
171171

172-
/**
173-
* @return if the [HashFunction] is supported by flexible checksums
174-
*/
175-
private val HashFunction.isSupported: Boolean get() = when (this) {
176-
is Crc32, is Crc32c, is Sha256, is Sha1 -> true
177-
else -> false
178-
}
179-
180172
/**
181173
* Removes all checksum headers except [headerName]
182174
* @param headerName the checksum header name to keep

runtime/runtime-core/api/runtime-core.api

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ public final class aws/smithy/kotlin/runtime/ErrorMetadata$Companion {
2121
public abstract interface annotation class aws/smithy/kotlin/runtime/ExperimentalApi : java/lang/annotation/Annotation {
2222
}
2323

24+
public final class aws/smithy/kotlin/runtime/IllegalStateException : java/lang/IllegalStateException {
25+
public fun <init> (Ljava/lang/String;)V
26+
}
27+
2428
public abstract interface annotation class aws/smithy/kotlin/runtime/InternalApi : java/lang/annotation/Annotation {
2529
}
2630

@@ -695,6 +699,7 @@ public final class aws/smithy/kotlin/runtime/hashing/HashFunction$DefaultImpls {
695699
public final class aws/smithy/kotlin/runtime/hashing/HashFunctionKt {
696700
public static final fun hash ([BLaws/smithy/kotlin/runtime/hashing/HashFunction;)[B
697701
public static final fun hash ([BLkotlin/jvm/functions/Function0;)[B
702+
public static final fun isSupportedForFlexibleChecksums (Laws/smithy/kotlin/runtime/hashing/HashFunction;)Z
698703
public static final fun toHashFunction (Ljava/lang/String;)Laws/smithy/kotlin/runtime/hashing/HashFunction;
699704
public static final fun toHashFunctionOrThrow (Ljava/lang/String;)Laws/smithy/kotlin/runtime/hashing/HashFunction;
700705
}
@@ -2083,6 +2088,7 @@ public final class aws/smithy/kotlin/runtime/text/Scanner {
20832088
public final class aws/smithy/kotlin/runtime/text/TextKt {
20842089
public static final fun ensurePrefix (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
20852090
public static final fun ensureSuffix (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
2091+
public static final fun lowercase (Ljava/lang/String;)Ljava/lang/String;
20862092
}
20872093

20882094
public final class aws/smithy/kotlin/runtime/text/Utf8Kt {
@@ -2261,6 +2267,10 @@ public abstract interface class aws/smithy/kotlin/runtime/util/CanDeepCopy {
22612267
public abstract fun deepCopy ()Ljava/lang/Object;
22622268
}
22632269

2270+
public final class aws/smithy/kotlin/runtime/util/ConcurrencyKt {
2271+
public static final fun runBlocking (Lkotlin/jvm/functions/Function1;)V
2272+
}
2273+
22642274
public final class aws/smithy/kotlin/runtime/util/CoroutineUtilsKt {
22652275
public static final fun derivedName (Lkotlin/coroutines/CoroutineContext;Ljava/lang/String;)Lkotlinx/coroutines/CoroutineName;
22662276
}

runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/Exceptions.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package aws.smithy.kotlin.runtime
77
import aws.smithy.kotlin.runtime.collections.AttributeKey
88
import aws.smithy.kotlin.runtime.collections.MutableAttributes
99
import aws.smithy.kotlin.runtime.collections.mutableAttributes
10+
import kotlin.IllegalStateException
1011

1112
/**
1213
* Additional metadata about an error
@@ -174,3 +175,9 @@ public open class ServiceException : SdkBaseException {
174175

175176
override val sdkErrorMetadata: ServiceErrorMetadata = ServiceErrorMetadata()
176177
}
178+
179+
/**
180+
* Runtime accessible version of the [IllegalStateException]
181+
*/
182+
@InternalApi
183+
public class IllegalStateException(message: String) : IllegalStateException(message)

runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/hashing/HashFunction.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,12 @@ public fun String.toHashFunction(): HashFunction? = when (this.lowercase()) {
7878
@InternalApi
7979
public fun String.toHashFunctionOrThrow(): HashFunction =
8080
toHashFunction() ?: throw ClientException("Checksum algorithm '$this' is not supported")
81+
82+
/**
83+
* @return if the [HashFunction] is supported by flexible checksums
84+
*/
85+
@InternalApi
86+
public val HashFunction.isSupportedForFlexibleChecksums: Boolean get() = when (this) {
87+
is Crc32, is Crc32c, is Sha256, is Sha1 -> true
88+
else -> false
89+
}

runtime/runtime-core/common/src/aws/smithy/kotlin/runtime/text/Text.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
package aws.smithy.kotlin.runtime.text
77

88
import aws.smithy.kotlin.runtime.InternalApi
9+
import java.util.*
910

1011
@InternalApi
1112
public fun String.ensurePrefix(prefix: String): String = if (startsWith(prefix)) this else prefix + this
1213

1314
@InternalApi
1415
public fun String.ensureSuffix(suffix: String): String = if (endsWith(suffix)) this else plus(suffix)
16+
17+
@InternalApi
18+
public fun String.lowercase(): String = this.lowercase(Locale.getDefault())
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package aws.smithy.kotlin.runtime.util
2+
3+
import aws.smithy.kotlin.runtime.InternalApi
4+
import kotlinx.coroutines.runBlocking
5+
6+
@InternalApi
7+
public fun runBlocking(block: suspend () -> Unit) {
8+
runBlocking {
9+
block()
10+
}
11+
}

0 commit comments

Comments
 (0)