AWS SDK

AWS SDK

rev. d03dc2cbf92e42a76d74caf3e8c12a8b87f47120..7f1eaffcc3edfbcf560e2bf9b488571574fd0992 (ignoring whitespace)

Files changed:

tmp-codegen-diff/services/codebuild/build.gradle.kts

@@ -1,1 +60,60 @@
    1      1   
    2      2   
description = "The AWS SDK for Kotlin client for CodeBuild"
    3      3   
project.ext.set("aws.sdk.id", "CodeBuild")
    4      4   
    5      5   
kotlin {
    6      6   
    sourceSets {
    7      7   
        commonMain {
    8      8   
            dependencies {
    9         -
                implementation("aws.smithy.kotlin:aws-credentials:1.4.10-SNAPSHOT")
           9  +
                implementation("aws.smithy.kotlin:aws-credentials:1.4.4-SNAPSHOT")
   10     10   
                implementation(project(":aws-runtime:aws-http"))
   11         -
                implementation("aws.smithy.kotlin:aws-json-protocols:1.4.10-SNAPSHOT")
   12         -
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.10-SNAPSHOT")
   13         -
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.10-SNAPSHOT")
   14         -
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.10-SNAPSHOT")
   15         -
                implementation("aws.smithy.kotlin:http:1.4.10-SNAPSHOT")
   16         -
                implementation("aws.smithy.kotlin:http-auth:1.4.10-SNAPSHOT")
   17         -
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.10-SNAPSHOT")
   18         -
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.10-SNAPSHOT")
   19         -
                implementation("aws.smithy.kotlin:identity-api:1.4.10-SNAPSHOT")
          11  +
                implementation("aws.smithy.kotlin:aws-json-protocols:1.4.4-SNAPSHOT")
          12  +
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.4-SNAPSHOT")
          13  +
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.4-SNAPSHOT")
          14  +
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.4-SNAPSHOT")
          15  +
                implementation("aws.smithy.kotlin:http:1.4.4-SNAPSHOT")
          16  +
                implementation("aws.smithy.kotlin:http-auth:1.4.4-SNAPSHOT")
          17  +
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.4-SNAPSHOT")
          18  +
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.4-SNAPSHOT")
          19  +
                implementation("aws.smithy.kotlin:identity-api:1.4.4-SNAPSHOT")
   20     20   
                implementation("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
   21         -
                implementation("aws.smithy.kotlin:serde:1.4.10-SNAPSHOT")
   22         -
                implementation("aws.smithy.kotlin:serde-json:1.4.10-SNAPSHOT")
   23         -
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.10-SNAPSHOT")
          21  +
                implementation("aws.smithy.kotlin:serde:1.4.4-SNAPSHOT")
          22  +
                implementation("aws.smithy.kotlin:serde-json:1.4.4-SNAPSHOT")
          23  +
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.4-SNAPSHOT")
   24     24   
                api(project(":aws-runtime:aws-config"))
   25     25   
                api(project(":aws-runtime:aws-core"))
   26     26   
                api(project(":aws-runtime:aws-endpoint"))
   27         -
                api("aws.smithy.kotlin:http-client:1.4.10-SNAPSHOT")
   28         -
                api("aws.smithy.kotlin:runtime-core:1.4.10-SNAPSHOT")
   29         -
                api("aws.smithy.kotlin:smithy-client:1.4.10-SNAPSHOT")
   30         -
                api("aws.smithy.kotlin:telemetry-api:1.4.10-SNAPSHOT")
          27  +
                api("aws.smithy.kotlin:http-client:1.4.4-SNAPSHOT")
          28  +
                api("aws.smithy.kotlin:runtime-core:1.4.4-SNAPSHOT")
          29  +
                api("aws.smithy.kotlin:smithy-client:1.4.4-SNAPSHOT")
          30  +
                api("aws.smithy.kotlin:telemetry-api:1.4.4-SNAPSHOT")
   31     31   
            }
   32     32   
        }
   33     33   
    }
   34     34   
   35     35   
    jvm {
   36     36   
        compilations {
   37     37   
            val mainPath = getByName("main").output.classesDirs
   38     38   
            val testPath = getByName("test").output.classesDirs
   39     39   
            tasks {
   40     40   
                register<Jar>("smokeTestJar") {

tmp-codegen-diff/services/dynamodb/build.gradle.kts

@@ -1,1 +60,60 @@
    1      1   
    2      2   
description = "The AWS SDK for Kotlin client for DynamoDB"
    3      3   
project.ext.set("aws.sdk.id", "DynamoDB")
    4      4   
    5      5   
kotlin {
    6      6   
    sourceSets {
    7      7   
        commonMain {
    8      8   
            dependencies {
    9         -
                implementation("aws.smithy.kotlin:aws-credentials:1.4.10-SNAPSHOT")
           9  +
                implementation("aws.smithy.kotlin:aws-credentials:1.4.4-SNAPSHOT")
   10     10   
                implementation(project(":aws-runtime:aws-http"))
   11         -
                implementation("aws.smithy.kotlin:aws-json-protocols:1.4.10-SNAPSHOT")
   12         -
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.10-SNAPSHOT")
   13         -
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.10-SNAPSHOT")
   14         -
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.10-SNAPSHOT")
   15         -
                implementation("aws.smithy.kotlin:http:1.4.10-SNAPSHOT")
   16         -
                implementation("aws.smithy.kotlin:http-auth:1.4.10-SNAPSHOT")
   17         -
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.10-SNAPSHOT")
   18         -
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.10-SNAPSHOT")
   19         -
                implementation("aws.smithy.kotlin:identity-api:1.4.10-SNAPSHOT")
          11  +
                implementation("aws.smithy.kotlin:aws-json-protocols:1.4.4-SNAPSHOT")
          12  +
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.4-SNAPSHOT")
          13  +
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.4-SNAPSHOT")
          14  +
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.4-SNAPSHOT")
          15  +
                implementation("aws.smithy.kotlin:http:1.4.4-SNAPSHOT")
          16  +
                implementation("aws.smithy.kotlin:http-auth:1.4.4-SNAPSHOT")
          17  +
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.4-SNAPSHOT")
          18  +
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.4-SNAPSHOT")
          19  +
                implementation("aws.smithy.kotlin:identity-api:1.4.4-SNAPSHOT")
   20     20   
                implementation("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
   21         -
                implementation("aws.smithy.kotlin:serde:1.4.10-SNAPSHOT")
   22         -
                implementation("aws.smithy.kotlin:serde-json:1.4.10-SNAPSHOT")
   23         -
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.10-SNAPSHOT")
          21  +
                implementation("aws.smithy.kotlin:serde:1.4.4-SNAPSHOT")
          22  +
                implementation("aws.smithy.kotlin:serde-json:1.4.4-SNAPSHOT")
          23  +
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.4-SNAPSHOT")
   24     24   
                api(project(":aws-runtime:aws-config"))
   25     25   
                api(project(":aws-runtime:aws-core"))
   26     26   
                api(project(":aws-runtime:aws-endpoint"))
   27         -
                api("aws.smithy.kotlin:http-client:1.4.10-SNAPSHOT")
   28         -
                api("aws.smithy.kotlin:runtime-core:1.4.10-SNAPSHOT")
   29         -
                api("aws.smithy.kotlin:smithy-client:1.4.10-SNAPSHOT")
   30         -
                api("aws.smithy.kotlin:telemetry-api:1.4.10-SNAPSHOT")
          27  +
                api("aws.smithy.kotlin:http-client:1.4.4-SNAPSHOT")
          28  +
                api("aws.smithy.kotlin:runtime-core:1.4.4-SNAPSHOT")
          29  +
                api("aws.smithy.kotlin:smithy-client:1.4.4-SNAPSHOT")
          30  +
                api("aws.smithy.kotlin:telemetry-api:1.4.4-SNAPSHOT")
   31     31   
            }
   32     32   
        }
   33     33   
    }
   34     34   
   35     35   
    jvm {
   36     36   
        compilations {
   37     37   
            val mainPath = getByName("main").output.classesDirs
   38     38   
            val testPath = getByName("test").output.classesDirs
   39     39   
            tasks {
   40     40   
                register<Jar>("smokeTestJar") {

tmp-codegen-diff/services/ec2/build.gradle.kts

@@ -1,1 +61,61 @@
    1      1   
    2      2   
description = "The AWS SDK for Kotlin client for EC2"
    3      3   
project.ext.set("aws.sdk.id", "EC2")
    4      4   
    5      5   
kotlin {
    6      6   
    sourceSets {
    7      7   
        commonMain {
    8      8   
            dependencies {
    9         -
                implementation("aws.smithy.kotlin:aws-credentials:1.4.10-SNAPSHOT")
           9  +
                implementation("aws.smithy.kotlin:aws-credentials:1.4.4-SNAPSHOT")
   10     10   
                implementation(project(":aws-runtime:aws-http"))
   11         -
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.10-SNAPSHOT")
   12         -
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.10-SNAPSHOT")
   13         -
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.10-SNAPSHOT")
   14         -
                implementation("aws.smithy.kotlin:aws-xml-protocols:1.4.10-SNAPSHOT")
   15         -
                implementation("aws.smithy.kotlin:http:1.4.10-SNAPSHOT")
   16         -
                implementation("aws.smithy.kotlin:http-auth:1.4.10-SNAPSHOT")
   17         -
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.10-SNAPSHOT")
   18         -
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.10-SNAPSHOT")
   19         -
                implementation("aws.smithy.kotlin:identity-api:1.4.10-SNAPSHOT")
          11  +
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.4-SNAPSHOT")
          12  +
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.4-SNAPSHOT")
          13  +
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.4-SNAPSHOT")
          14  +
                implementation("aws.smithy.kotlin:aws-xml-protocols:1.4.4-SNAPSHOT")
          15  +
                implementation("aws.smithy.kotlin:http:1.4.4-SNAPSHOT")
          16  +
                implementation("aws.smithy.kotlin:http-auth:1.4.4-SNAPSHOT")
          17  +
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.4-SNAPSHOT")
          18  +
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.4-SNAPSHOT")
          19  +
                implementation("aws.smithy.kotlin:identity-api:1.4.4-SNAPSHOT")
   20     20   
                implementation("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
   21         -
                implementation("aws.smithy.kotlin:serde:1.4.10-SNAPSHOT")
   22         -
                implementation("aws.smithy.kotlin:serde-form-url:1.4.10-SNAPSHOT")
   23         -
                implementation("aws.smithy.kotlin:serde-xml:1.4.10-SNAPSHOT")
   24         -
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.10-SNAPSHOT")
          21  +
                implementation("aws.smithy.kotlin:serde:1.4.4-SNAPSHOT")
          22  +
                implementation("aws.smithy.kotlin:serde-form-url:1.4.4-SNAPSHOT")
          23  +
                implementation("aws.smithy.kotlin:serde-xml:1.4.4-SNAPSHOT")
          24  +
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.4-SNAPSHOT")
   25     25   
                api(project(":aws-runtime:aws-config"))
   26     26   
                api(project(":aws-runtime:aws-core"))
   27     27   
                api(project(":aws-runtime:aws-endpoint"))
   28         -
                api("aws.smithy.kotlin:http-client:1.4.10-SNAPSHOT")
   29         -
                api("aws.smithy.kotlin:runtime-core:1.4.10-SNAPSHOT")
   30         -
                api("aws.smithy.kotlin:smithy-client:1.4.10-SNAPSHOT")
   31         -
                api("aws.smithy.kotlin:telemetry-api:1.4.10-SNAPSHOT")
          28  +
                api("aws.smithy.kotlin:http-client:1.4.4-SNAPSHOT")
          29  +
                api("aws.smithy.kotlin:runtime-core:1.4.4-SNAPSHOT")
          30  +
                api("aws.smithy.kotlin:smithy-client:1.4.4-SNAPSHOT")
          31  +
                api("aws.smithy.kotlin:telemetry-api:1.4.4-SNAPSHOT")
   32     32   
            }
   33     33   
        }
   34     34   
    }
   35     35   
   36     36   
    jvm {
   37     37   
        compilations {
   38     38   
            val mainPath = getByName("main").output.classesDirs
   39     39   
            val testPath = getByName("test").output.classesDirs
   40     40   
            tasks {
   41     41   
                register<Jar>("smokeTestJar") {

tmp-codegen-diff/services/polly/build.gradle.kts

@@ -1,1 +60,60 @@
    1      1   
    2      2   
description = "The AWS SDK for Kotlin client for Polly"
    3      3   
project.ext.set("aws.sdk.id", "Polly")
    4      4   
    5      5   
kotlin {
    6      6   
    sourceSets {
    7      7   
        commonMain {
    8      8   
            dependencies {
    9         -
                implementation("aws.smithy.kotlin:aws-credentials:1.4.10-SNAPSHOT")
           9  +
                implementation("aws.smithy.kotlin:aws-credentials:1.4.4-SNAPSHOT")
   10     10   
                implementation(project(":aws-runtime:aws-http"))
   11         -
                implementation("aws.smithy.kotlin:aws-json-protocols:1.4.10-SNAPSHOT")
   12         -
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.10-SNAPSHOT")
   13         -
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.10-SNAPSHOT")
   14         -
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.10-SNAPSHOT")
   15         -
                implementation("aws.smithy.kotlin:http:1.4.10-SNAPSHOT")
   16         -
                implementation("aws.smithy.kotlin:http-auth:1.4.10-SNAPSHOT")
   17         -
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.10-SNAPSHOT")
   18         -
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.10-SNAPSHOT")
   19         -
                implementation("aws.smithy.kotlin:identity-api:1.4.10-SNAPSHOT")
          11  +
                implementation("aws.smithy.kotlin:aws-json-protocols:1.4.4-SNAPSHOT")
          12  +
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.4-SNAPSHOT")
          13  +
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.4-SNAPSHOT")
          14  +
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.4-SNAPSHOT")
          15  +
                implementation("aws.smithy.kotlin:http:1.4.4-SNAPSHOT")
          16  +
                implementation("aws.smithy.kotlin:http-auth:1.4.4-SNAPSHOT")
          17  +
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.4-SNAPSHOT")
          18  +
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.4-SNAPSHOT")
          19  +
                implementation("aws.smithy.kotlin:identity-api:1.4.4-SNAPSHOT")
   20     20   
                implementation("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
   21         -
                implementation("aws.smithy.kotlin:serde:1.4.10-SNAPSHOT")
   22         -
                implementation("aws.smithy.kotlin:serde-json:1.4.10-SNAPSHOT")
   23         -
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.10-SNAPSHOT")
          21  +
                implementation("aws.smithy.kotlin:serde:1.4.4-SNAPSHOT")
          22  +
                implementation("aws.smithy.kotlin:serde-json:1.4.4-SNAPSHOT")
          23  +
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.4-SNAPSHOT")
   24     24   
                api(project(":aws-runtime:aws-config"))
   25     25   
                api(project(":aws-runtime:aws-core"))
   26     26   
                api(project(":aws-runtime:aws-endpoint"))
   27         -
                api("aws.smithy.kotlin:http-client:1.4.10-SNAPSHOT")
   28         -
                api("aws.smithy.kotlin:runtime-core:1.4.10-SNAPSHOT")
   29         -
                api("aws.smithy.kotlin:smithy-client:1.4.10-SNAPSHOT")
   30         -
                api("aws.smithy.kotlin:telemetry-api:1.4.10-SNAPSHOT")
          27  +
                api("aws.smithy.kotlin:http-client:1.4.4-SNAPSHOT")
          28  +
                api("aws.smithy.kotlin:runtime-core:1.4.4-SNAPSHOT")
          29  +
                api("aws.smithy.kotlin:smithy-client:1.4.4-SNAPSHOT")
          30  +
                api("aws.smithy.kotlin:telemetry-api:1.4.4-SNAPSHOT")
   31     31   
            }
   32     32   
        }
   33     33   
        commonTest {
   34     34   
            dependencies {
   35     35   
                implementation("org.jetbrains.kotlin:kotlin-test:2.1.0")
   36     36   
            }
   37     37   
        }
   38     38   
    }
   39     39   
   40     40   
    jvm {

tmp-codegen-diff/services/s3/build.gradle.kts

@@ -1,1 +41,41 @@
    1      1   
    2      2   
description = "The AWS SDK for Kotlin client for S3"
    3      3   
project.ext.set("aws.sdk.id", "S3")
    4      4   
    5      5   
kotlin {
    6      6   
    sourceSets {
    7      7   
        commonMain {
    8      8   
            dependencies {
    9         -
                implementation("aws.smithy.kotlin:aws-credentials:1.4.10-SNAPSHOT")
   10         -
                implementation("aws.smithy.kotlin:aws-event-stream:1.4.10-SNAPSHOT")
           9  +
                implementation("aws.smithy.kotlin:aws-credentials:1.4.4-SNAPSHOT")
          10  +
                implementation("aws.smithy.kotlin:aws-event-stream:1.4.4-SNAPSHOT")
   11     11   
                implementation(project(":aws-runtime:aws-http"))
   12         -
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.10-SNAPSHOT")
   13         -
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.10-SNAPSHOT")
   14         -
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.10-SNAPSHOT")
   15         -
                implementation("aws.smithy.kotlin:aws-xml-protocols:1.4.10-SNAPSHOT")
   16         -
                implementation("aws.smithy.kotlin:http:1.4.10-SNAPSHOT")
   17         -
                implementation("aws.smithy.kotlin:http-auth:1.4.10-SNAPSHOT")
   18         -
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.10-SNAPSHOT")
   19         -
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.10-SNAPSHOT")
   20         -
                implementation("aws.smithy.kotlin:identity-api:1.4.10-SNAPSHOT")
          12  +
                implementation("aws.smithy.kotlin:aws-protocol-core:1.4.4-SNAPSHOT")
          13  +
                implementation("aws.smithy.kotlin:aws-signing-common:1.4.4-SNAPSHOT")
          14  +
                implementation("aws.smithy.kotlin:aws-signing-default:1.4.4-SNAPSHOT")
          15  +
                implementation("aws.smithy.kotlin:aws-xml-protocols:1.4.4-SNAPSHOT")
          16  +
                implementation("aws.smithy.kotlin:http:1.4.4-SNAPSHOT")
          17  +
                implementation("aws.smithy.kotlin:http-auth:1.4.4-SNAPSHOT")
          18  +
                implementation("aws.smithy.kotlin:http-auth-aws:1.4.4-SNAPSHOT")
          19  +
                implementation("aws.smithy.kotlin:http-client-engine-default:1.4.4-SNAPSHOT")
          20  +
                implementation("aws.smithy.kotlin:identity-api:1.4.4-SNAPSHOT")
   21     21   
                implementation("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
   22         -
                implementation("aws.smithy.kotlin:serde:1.4.10-SNAPSHOT")
   23         -
                implementation("aws.smithy.kotlin:serde-xml:1.4.10-SNAPSHOT")
   24         -
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.10-SNAPSHOT")
          22  +
                implementation("aws.smithy.kotlin:serde:1.4.4-SNAPSHOT")
          23  +
                implementation("aws.smithy.kotlin:serde-xml:1.4.4-SNAPSHOT")
          24  +
                implementation("aws.smithy.kotlin:telemetry-defaults:1.4.4-SNAPSHOT")
   25     25   
                api(project(":aws-runtime:aws-config"))
   26     26   
                api(project(":aws-runtime:aws-core"))
   27     27   
                api(project(":aws-runtime:aws-endpoint"))
   28         -
                api("aws.smithy.kotlin:http-client:1.4.10-SNAPSHOT")
   29         -
                api("aws.smithy.kotlin:runtime-core:1.4.10-SNAPSHOT")
   30         -
                api("aws.smithy.kotlin:smithy-client:1.4.10-SNAPSHOT")
   31         -
                api("aws.smithy.kotlin:telemetry-api:1.4.10-SNAPSHOT")
          28  +
                api("aws.smithy.kotlin:http-client:1.4.4-SNAPSHOT")
          29  +
                api("aws.smithy.kotlin:runtime-core:1.4.4-SNAPSHOT")
          30  +
                api("aws.smithy.kotlin:smithy-client:1.4.4-SNAPSHOT")
          31  +
                api("aws.smithy.kotlin:telemetry-api:1.4.4-SNAPSHOT")
   32     32   
            }
   33     33   
        }
   34     34   
        commonTest {
   35     35   
            dependencies {
   36     36   
                implementation("org.jetbrains.kotlin:kotlin-test:2.1.0")
   37         -
                implementation("aws.smithy.kotlin:smithy-test:1.4.10-SNAPSHOT")
          37  +
                implementation("aws.smithy.kotlin:smithy-test:1.4.4-SNAPSHOT")
   38     38   
            }
   39     39   
        }
   40     40   
    }
   41     41   
}

tmp-codegen-diff/services/sqs/common/src/aws.sdk.kotlin.services.sqs/SqsMd5ChecksumValidationInterceptor.kt

@@ -0,1 +0,373 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
package aws.sdk.kotlin.services.sqs
           6  +
           7  +
import aws.sdk.kotlin.services.sqs.internal.ValidationEnabled
           8  +
import aws.sdk.kotlin.services.sqs.internal.ValidationScope
           9  +
import aws.sdk.kotlin.services.sqs.model.*
          10  +
import aws.smithy.kotlin.runtime.ClientException
          11  +
import aws.smithy.kotlin.runtime.InternalApi
          12  +
import aws.smithy.kotlin.runtime.client.ResponseInterceptorContext
          13  +
import aws.smithy.kotlin.runtime.hashing.Md5
          14  +
import aws.smithy.kotlin.runtime.hashing.md5
          15  +
import aws.smithy.kotlin.runtime.http.interceptors.ChecksumMismatchException
          16  +
import aws.smithy.kotlin.runtime.http.interceptors.HttpInterceptor
          17  +
import aws.smithy.kotlin.runtime.http.request.HttpRequest
          18  +
import aws.smithy.kotlin.runtime.http.response.HttpResponse
          19  +
import aws.smithy.kotlin.runtime.telemetry.logging.Logger
          20  +
import aws.smithy.kotlin.runtime.telemetry.logging.logger
          21  +
import kotlin.collections.Map
          22  +
import kotlin.collections.Set
          23  +
import kotlin.collections.hashMapOf
          24  +
import kotlin.collections.isNullOrEmpty
          25  +
import kotlin.collections.set
          26  +
import kotlin.collections.sorted
          27  +
import kotlin.collections.sortedBy
          28  +
          29  +
/**
          30  +
 * Interceptor that validates MD5 checksums for SQS message operations.
          31  +
 *
          32  +
 * This interceptor performs client-side validation of MD5 checksums returned by SQS to ensure
          33  +
 * message integrity during transmission. It validates the following components:
          34  +
 * - Message body
          35  +
 * - Message attributes
          36  +
 * - Message system attributes
          37  +
 *
          38  +
 * The validation behavior can be configured using:
          39  +
 * - [checksumValidationEnabled] - Controls when validation occurs (ALWAYS, WHEN_SENDING, WHEN_RECEIVING, NEVER)
          40  +
 * - [checksumValidationScopes] - Specifies which message components to validate
          41  +
 *
          42  +
 * Supported operations:
          43  +
 * - SendMessage
          44  +
 * - SendMessageBatch
          45  +
 * - ReceiveMessage
          46  +
 */
          47  +
@OptIn(InternalApi::class, ExperimentalStdlibApi::class)
          48  +
public class SqsMd5ChecksumValidationInterceptor(
          49  +
    private val validationEnabled: ValidationEnabled?,
          50  +
    private val validationScopes: Set<ValidationScope>,
          51  +
) : HttpInterceptor {
          52  +
    public companion object {
          53  +
        private const val STRING_TYPE_FIELD_INDEX: Byte = 1
          54  +
        private const val BINARY_TYPE_FIELD_INDEX: Byte = 2
          55  +
        private const val STRING_LIST_TYPE_FIELD_INDEX: Byte = 3
          56  +
        private const val BINARY_LIST_TYPE_FIELD_INDEX: Byte = 4
          57  +
          58  +
        private lateinit var logger: Logger
          59  +
          60  +
        private fun initLogger(logger: Logger) {
          61  +
            this.logger = logger
          62  +
        }
          63  +
    }
          64  +
          65  +
    override fun readAfterExecution(context: ResponseInterceptorContext<Any, Any, HttpRequest?, HttpResponse?>) {
          66  +
        val request = context.request
          67  +
        val response = context.response.getOrNull()
          68  +
          69  +
        if (validationEnabled == ValidationEnabled.NEVER) return
          70  +
          71  +
        val logger = context.executionContext.coroutineContext.logger<SqsMd5ChecksumValidationInterceptor>()
          72  +
        initLogger(logger)
          73  +
          74  +
        if (response != null) {
          75  +
            when (request) {
          76  +
                is SendMessageRequest -> {
          77  +
                    if (validationEnabled == ValidationEnabled.WHEN_RECEIVING) return
          78  +
          79  +
                    val sendMessageRequest = request as SendMessageRequest
          80  +
                    val sendMessageResponse = response as SendMessageResponse
          81  +
                    sendMessageOperationMd5Check(sendMessageRequest, sendMessageResponse)
          82  +
                }
          83  +
          84  +
                is ReceiveMessageRequest -> {
          85  +
                    if (validationEnabled == ValidationEnabled.WHEN_SENDING) return
          86  +
          87  +
                    val receiveMessageResponse = response as ReceiveMessageResponse
          88  +
                    receiveMessageResultMd5Check(receiveMessageResponse)
          89  +
                }
          90  +
          91  +
                is SendMessageBatchRequest -> {
          92  +
                    if (validationEnabled == ValidationEnabled.WHEN_RECEIVING) return
          93  +
          94  +
                    val sendMessageBatchRequest = request as SendMessageBatchRequest
          95  +
                    val sendMessageBatchResponse = response as SendMessageBatchResponse
          96  +
                    sendMessageBatchOperationMd5Check(sendMessageBatchRequest, sendMessageBatchResponse)
          97  +
                }
          98  +
            }
          99  +
        }
         100  +
    }
         101  +
         102  +
    private fun sendMessageOperationMd5Check(
         103  +
        sendMessageRequest: SendMessageRequest,
         104  +
        sendMessageResponse: SendMessageResponse,
         105  +
    ) {
         106  +
        if (validationScopes.contains(ValidationScope.MESSAGE_BODY)) {
         107  +
            val messageBodySent = sendMessageRequest.messageBody
         108  +
         109  +
            if (!messageBodySent.isNullOrEmpty()) {
         110  +
                logger.debug { "Validating message body MD5 checksum for SendMessage" }
         111  +
         112  +
                val bodyMD5Returned = sendMessageResponse.md5OfMessageBody
         113  +
                val clientSideBodyMd5 = calculateMessageBodyMd5(messageBodySent)
         114  +
                if (clientSideBodyMd5 != bodyMD5Returned) {
         115  +
                    throw ChecksumMismatchException("Checksum mismatch. Expected $clientSideBodyMd5 but was $bodyMD5Returned")
         116  +
                }
         117  +
            }
         118  +
        }
         119  +
         120  +
        if (validationScopes.contains(ValidationScope.MESSAGE_ATTRIBUTES)) {
         121  +
            val messageAttrSent = sendMessageRequest.messageAttributes
         122  +
            if (!messageAttrSent.isNullOrEmpty()) {
         123  +
                logger.debug { "Validating message attribute MD5 checksum for SendMessage" }
         124  +
         125  +
                val messageAttrMD5Returned = sendMessageResponse.md5OfMessageAttributes
         126  +
                val clientSideAttrMd5 = calculateMessageAttributesMd5(messageAttrSent)
         127  +
                if (clientSideAttrMd5 != messageAttrMD5Returned) {
         128  +
                    throw ChecksumMismatchException("Checksum mismatch. Expected $clientSideAttrMd5 but was $messageAttrMD5Returned")
         129  +
                }
         130  +
            }
         131  +
        }
         132  +
         133  +
        if (validationScopes.contains(ValidationScope.MESSAGE_SYSTEM_ATTRIBUTES)) {
         134  +
            val messageSysAttrSent = sendMessageRequest.messageSystemAttributes
         135  +
            if (!messageSysAttrSent.isNullOrEmpty()) {
         136  +
                logger.debug { "Validating message system attribute MD5 checksum for SendMessage" }
         137  +
         138  +
                val messageSysAttrMD5Returned = sendMessageResponse.md5OfMessageSystemAttributes
         139  +
                val clientSideSysAttrMd5 = calculateMessageSystemAttributesMd5(messageSysAttrSent)
         140  +
                if (clientSideSysAttrMd5 != messageSysAttrMD5Returned) {
         141  +
                    throw ChecksumMismatchException("Checksum mismatch. Expected $clientSideSysAttrMd5 but was $messageSysAttrMD5Returned")
         142  +
                }
         143  +
            }
         144  +
        }
         145  +
    }
         146  +
         147  +
    private fun receiveMessageResultMd5Check(receiveMessageResponse: ReceiveMessageResponse) {
         148  +
        val messages = receiveMessageResponse.messages
         149  +
        if (messages != null) {
         150  +
            for (messageReceived in messages) {
         151  +
                if (validationScopes.contains(ValidationScope.MESSAGE_BODY)) {
         152  +
                    val messageBody = messageReceived.body
         153  +
                    if (!messageBody.isNullOrEmpty()) {
         154  +
                        logger.debug { "Validating message body MD5 checksum for ReceiveMessage" }
         155  +
         156  +
                        val bodyMd5Returned = messageReceived.md5OfBody
         157  +
                        val clientSideBodyMd5 = calculateMessageBodyMd5(messageBody)
         158  +
                        if (clientSideBodyMd5 != bodyMd5Returned) {
         159  +
                            throw ChecksumMismatchException("Checksum mismatch. Expected $clientSideBodyMd5 but was $bodyMd5Returned")
         160  +
                        }
         161  +
                    }
         162  +
                }
         163  +
         164  +
                if (validationScopes.contains(ValidationScope.MESSAGE_ATTRIBUTES)) {
         165  +
                    val messageAttr = messageReceived.messageAttributes
         166  +
         167  +
                    if (!messageAttr.isNullOrEmpty()) {
         168  +
                        logger.debug { "Validating message attribute MD5 checksum for ReceiveMessage" }
         169  +
         170  +
                        val attrMd5Returned = messageReceived.md5OfMessageAttributes
         171  +
                        val clientSideAttrMd5 = calculateMessageAttributesMd5(messageAttr)
         172  +
                        if (clientSideAttrMd5 != attrMd5Returned) {
         173  +
                            throw ChecksumMismatchException("Checksum mismatch. Expected $clientSideAttrMd5 but was $attrMd5Returned")
         174  +
                        }
         175  +
                    }
         176  +
                }
         177  +
            }
         178  +
        }
         179  +
    }
         180  +
         181  +
    private fun sendMessageBatchOperationMd5Check(
         182  +
        sendMessageBatchRequest: SendMessageBatchRequest,
         183  +
        sendMessageBatchResponse: SendMessageBatchResponse,
         184  +
    ) {
         185  +
        val idToRequestEntryMap = hashMapOf<String, SendMessageBatchRequestEntry>()
         186  +
        val entries = sendMessageBatchRequest.entries
         187  +
        if (entries != null) {
         188  +
            for (entry in entries) {
         189  +
                idToRequestEntryMap[entry.id] = entry
         190  +
            }
         191  +
        }
         192  +
         193  +
        for (entry in sendMessageBatchResponse.successful) {
         194  +
            if (validationScopes.contains(ValidationScope.MESSAGE_BODY)) {
         195  +
                val messageBody = idToRequestEntryMap[entry.id]?.messageBody
         196  +
         197  +
                if (!messageBody.isNullOrEmpty()) {
         198  +
                    logger.debug { "Validating message body MD5 checksum for SendMessageBatch: ${entry.messageId}" }
         199  +
         200  +
                    val bodyMd5Returned = entry.md5OfMessageBody
         201  +
                    val clientSideBodyMd5 = calculateMessageBodyMd5(messageBody)
         202  +
                    if (clientSideBodyMd5 != bodyMd5Returned) {
         203  +
                        throw ChecksumMismatchException("Checksum mismatch. Expected $clientSideBodyMd5 but was $bodyMd5Returned")
         204  +
                    }
         205  +
                }
         206  +
            }
         207  +
         208  +
            if (validationScopes.contains(ValidationScope.MESSAGE_ATTRIBUTES)) {
         209  +
                val messageAttrSent = idToRequestEntryMap[entry.id]?.messageAttributes
         210  +
                if (!messageAttrSent.isNullOrEmpty()) {
         211  +
                    logger.debug { "Validating message attribute MD5 checksum for SendMessageBatch: ${entry.messageId}" }
         212  +
         213  +
                    val messageAttrMD5Returned = entry.md5OfMessageAttributes
         214  +
                    val clientSideAttrMd5 = calculateMessageAttributesMd5(messageAttrSent)
         215  +
                    if (clientSideAttrMd5 != messageAttrMD5Returned) {
         216  +
                        throw ChecksumMismatchException("Checksum mismatch. Expected $clientSideAttrMd5 but was $messageAttrMD5Returned")
         217  +
                    }
         218  +
                }
         219  +
            }
         220  +
         221  +
            if (validationScopes.contains(ValidationScope.MESSAGE_SYSTEM_ATTRIBUTES)) {
         222  +
                val messageSysAttrSent = idToRequestEntryMap[entry.id]?.messageSystemAttributes
         223  +
                if (!messageSysAttrSent.isNullOrEmpty()) {
         224  +
                    logger.debug { "Validating message system attribute MD5 checksum for SendMessageBatch: ${entry.messageId}" }
         225  +
         226  +
                    val messageSysAttrMD5Returned = entry.md5OfMessageSystemAttributes
         227  +
                    val clientSideSysAttrMd5 = calculateMessageSystemAttributesMd5(messageSysAttrSent)
         228  +
                    if (clientSideSysAttrMd5 != messageSysAttrMD5Returned) {
         229  +
                        throw ChecksumMismatchException("Checksum mismatch. Expected $clientSideSysAttrMd5 but was $messageSysAttrMD5Returned")
         230  +
                    }
         231  +
                }
         232  +
            }
         233  +
        }
         234  +
    }
         235  +
         236  +
    private fun calculateMessageBodyMd5(messageBody: String): String {
         237  +
        val expectedMD5 = try {
         238  +
            messageBody.encodeToByteArray().md5()
         239  +
        } catch (e: Exception) {
         240  +
            throw ClientException(
         241  +
                "Unable to calculate the MD5 hash of the message body." +
         242  +
                    "Potential reasons include JVM configuration or FIPS compliance issues." +
         243  +
                    "To disable message MD5 validation, you can set checksumValidationEnabled" +
         244  +
                    "to false when instantiating the client." + e.message,
         245  +
            )
         246  +
        }
         247  +
        val expectedMD5Hex = expectedMD5.toHexString()
         248  +
        return expectedMD5Hex
         249  +
    }
         250  +
         251  +
    /**
         252  +
     * Calculates the MD5 digest for message attributes according to SQS specifications.
         253  +
     * https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html#sqs-attributes-md5-message-digest-calculation
         254  +
     */
         255  +
    @OptIn(InternalApi::class, ExperimentalStdlibApi::class)
         256  +
    private fun calculateMessageAttributesMd5(messageAttributes: Map<String, MessageAttributeValue>): String {
         257  +
        val sortedAttributeNames = messageAttributes.keys.sorted()
         258  +
        val md5Digest = Md5()
         259  +
         260  +
        try {
         261  +
            for (attributeName in sortedAttributeNames) {
         262  +
                val attributeValue = messageAttributes[attributeName]
         263  +
                updateLengthAndBytes(md5Digest, attributeName.encodeToByteArray())
         264  +
         265  +
                attributeValue?.dataType?.let { dataType ->
         266  +
                    updateLengthAndBytes(md5Digest, dataType.encodeToByteArray())
         267  +
                }
         268  +
         269  +
                val stringValue = attributeValue?.stringValue
         270  +
                val binaryValue = attributeValue?.binaryValue
         271  +
                val stringListValues = attributeValue?.stringListValues
         272  +
                val binaryListValues = attributeValue?.binaryListValues
         273  +
         274  +
                when {
         275  +
                    stringValue != null -> updateForStringType(md5Digest, stringValue)
         276  +
                    binaryValue != null -> updateForBinaryType(md5Digest, binaryValue)
         277  +
                    !stringListValues.isNullOrEmpty() -> updateForStringListType(md5Digest, stringListValues)
         278  +
                    !binaryListValues.isNullOrEmpty() -> updateForBinaryListType(md5Digest, binaryListValues)
         279  +
                }
         280  +
            }
         281  +
        } catch (e: Exception) {
         282  +
            throw ClientException(
         283  +
                "Unable to calculate the MD5 hash of the message attributes." +
         284  +
                    "Potential reasons include JVM configuration or FIPS compliance issues." +
         285  +
                    "To disable message MD5 validation, you can set checksumValidationEnabled" +
         286  +
                    "to false when instantiating the client." + e.message,
         287  +
            )
         288  +
        }
         289  +
        val expectedMD5Hex = md5Digest.digest().toHexString()
         290  +
        return expectedMD5Hex
         291  +
    }
         292  +
         293  +
    private fun calculateMessageSystemAttributesMd5(
         294  +
        messageSysAttrs: Map<MessageSystemAttributeNameForSends, MessageSystemAttributeValue>,
         295  +
    ): String {
         296  +
        val sortedAttributeNames = messageSysAttrs.keys.sortedBy { it.value }
         297  +
        val md5Digest = Md5()
         298  +
         299  +
        try {
         300  +
            for (attributeName in sortedAttributeNames) {
         301  +
                val attributeValue = messageSysAttrs[attributeName]
         302  +
                updateLengthAndBytes(md5Digest, attributeName.value.encodeToByteArray())
         303  +
         304  +
                attributeValue?.dataType?.let { dataType ->
         305  +
                    updateLengthAndBytes(md5Digest, dataType.encodeToByteArray())
         306  +
                }
         307  +
         308  +
                val stringValue = attributeValue?.stringValue
         309  +
                val binaryValue = attributeValue?.binaryValue
         310  +
                val stringListValues = attributeValue?.stringListValues
         311  +
                val binaryListValues = attributeValue?.binaryListValues
         312  +
         313  +
                when {
         314  +
                    stringValue != null -> updateForStringType(md5Digest, stringValue)
         315  +
                    binaryValue != null -> updateForBinaryType(md5Digest, binaryValue)
         316  +
                    !stringListValues.isNullOrEmpty() -> updateForStringListType(md5Digest, stringListValues)
         317  +
                    !binaryListValues.isNullOrEmpty() -> updateForBinaryListType(md5Digest, binaryListValues)
         318  +
                }
         319  +
            }
         320  +
        } catch (e: Exception) {
         321  +
            throw ClientException(
         322  +
                "Unable to calculate the MD5 hash of the message system attributes." +
         323  +
                    "Potential reasons include JVM configuration or FIPS compliance issues." +
         324  +
                    "To disable message MD5 validation, you can set checksumValidationEnabled" +
         325  +
                    "to false when instantiating the client." + e.message,
         326  +
            )
         327  +
        }
         328  +
        val expectedMD5Hex = md5Digest.digest().toHexString()
         329  +
        return expectedMD5Hex
         330  +
    }
         331  +
         332  +
    private fun updateForStringType(md5Digest: Md5, value: String) {
         333  +
        md5Digest.update(STRING_TYPE_FIELD_INDEX)
         334  +
        updateLengthAndBytes(md5Digest, value.encodeToByteArray())
         335  +
    }
         336  +
         337  +
    private fun updateForBinaryType(md5Digest: Md5, value: ByteArray) {
         338  +
        md5Digest.update(BINARY_TYPE_FIELD_INDEX)
         339  +
        updateLengthAndBytes(md5Digest, value)
         340  +
    }
         341  +
         342  +
    private fun updateForStringListType(md5Digest: Md5, values: List<String>) {
         343  +
        md5Digest.update(STRING_LIST_TYPE_FIELD_INDEX)
         344  +
        values.forEach { value ->
         345  +
            updateLengthAndBytes(md5Digest, value.encodeToByteArray())
         346  +
        }
         347  +
    }
         348  +
         349  +
    private fun updateForBinaryListType(md5Digest: Md5, values: List<ByteArray>) {
         350  +
        md5Digest.update(BINARY_LIST_TYPE_FIELD_INDEX)
         351  +
        values.forEach { value ->
         352  +
            updateLengthAndBytes(md5Digest, value)
         353  +
        }
         354  +
    }
         355  +
         356  +
    /**
         357  +
     * Update the digest using a sequence of bytes that consists of the length (in 4 bytes) of the
         358  +
     * input binaryValue and all the bytes it contains.
         359  +
     */
         360  +
    private fun updateLengthAndBytes(messageDigest: Md5, binaryValue: ByteArray) {
         361  +
        println("updateLengthAndBytes")
         362  +
        val length = binaryValue.size
         363  +
        val lengthBytes = byteArrayOf(
         364  +
            (length shr 24).toByte(),
         365  +
            (length shr 16).toByte(),
         366  +
            (length shr 8).toByte(),
         367  +
            length.toByte(),
         368  +
        )
         369  +
         370  +
        messageDigest.update(lengthBytes)
         371  +
        messageDigest.update(binaryValue)
         372  +
    }
         373  +
}

tmp-codegen-diff/services/sqs/common/src/aws.sdk.kotlin.services.sqs/internal/FinalizeSqsConfig.kt

@@ -0,1 +0,35 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
package aws.sdk.kotlin.services.sqs.internal
           6  +
           7  +
import aws.sdk.kotlin.runtime.config.profile.*
           8  +
import aws.sdk.kotlin.services.sqs.SqsClient
           9  +
import aws.smithy.kotlin.runtime.config.resolve
          10  +
import aws.smithy.kotlin.runtime.util.LazyAsyncValue
          11  +
import aws.smithy.kotlin.runtime.util.PlatformProvider
          12  +
          13  +
internal suspend fun finalizeSqsConfig(
          14  +
    builder: SqsClient.Builder,
          15  +
    sharedConfig: LazyAsyncValue<AwsSharedConfig>,
          16  +
    provider: PlatformProvider = PlatformProvider.System,
          17  +
) {
          18  +
    val activeProfile = sharedConfig.get().activeProfile
          19  +
    builder.config.checksumValidationEnabled = builder.config.checksumValidationEnabled
          20  +
        ?: SQSSetting.checksumValidationEnabled.resolve(provider)
          21  +
        ?: activeProfile.checksumValidationEnabled
          22  +
        ?: ValidationEnabled.NEVER // TODO: MD5 checksum validation is temporarily disabled. Set default to ALWAYS in next minor version
          23  +
          24  +
    builder.config.checksumValidationScopes = builder.config.checksumValidationScopes.ifEmpty {
          25  +
        SQSSetting.checksumValidationScopes.resolve(provider)
          26  +
            ?: activeProfile.checksumValidationScopes
          27  +
            ?: ValidationScope.entries.toSet()
          28  +
    }
          29  +
}
          30  +
          31  +
private val AwsProfile.checksumValidationEnabled: ValidationEnabled?
          32  +
    get() = getEnumOrNull<ValidationEnabled>("sqs_checksum_validation_enabled")
          33  +
          34  +
private val AwsProfile.checksumValidationScopes: Set<ValidationScope>?
          35  +
    get() = getEnumSetOrNull<ValidationScope>("sqs_checksum_validation_scope")

tmp-codegen-diff/services/sqs/common/src/aws.sdk.kotlin.services.sqs/internal/SQSSetting.kt

@@ -0,1 +0,49 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
package aws.sdk.kotlin.services.sqs.internal
           6  +
           7  +
import aws.smithy.kotlin.runtime.config.*
           8  +
           9  +
/**
          10  +
 * SQS specific system settings
          11  +
 */
          12  +
internal object SQSSetting {
          13  +
    /**
          14  +
     * Configure when MD5 checksum validation is performed for SQS operations.
          15  +
     *
          16  +
     * Can be configured using:
          17  +
     * - System property: aws.SqsChecksumValidationEnabled
          18  +
     * - Environment variable: AWS_SQS_CHECKSUM_VALIDATION_ENABLED
          19  +
     *
          20  +
     * Valid values:
          21  +
     * - ALWAYS (default) - Validates checksums for both sending and receiving operations
          22  +
     * - WHEN_SENDING - Validates checksums only when sending messages
          23  +
     * - WHEN_RECEIVING - Validates checksums only when receiving messages
          24  +
     * - NEVER - Disables checksum validation
          25  +
     *
          26  +
     * Note: Value matching is case-insensitive when configured via environment variables.
          27  +
     */
          28  +
    public val checksumValidationEnabled: EnvironmentSetting<ValidationEnabled> =
          29  +
        enumEnvSetting("aws.SqsChecksumValidationEnabled", "AWS_SQS_CHECKSUM_VALIDATION_ENABLED")
          30  +
          31  +
    /**
          32  +
     * Configure the scope of checksum validation for SQS operations.
          33  +
     *
          34  +
     * Can be configured using:
          35  +
     * - System property: aws.SqsChecksumValidationScope
          36  +
     * - Environment variable: AWS_SQS_CHECKSUM_VALIDATION_SCOPE
          37  +
     *
          38  +
     * Valid values are comma-separated combinations of:
          39  +
     * - MESSAGE_BODY: Validate message body checksums
          40  +
     * - MESSAGE_ATTRIBUTES: Validate message attribute checksums
          41  +
     * - SYSTEM_ATTRIBUTES: Validate system attribute checksums
          42  +
     *
          43  +
     * Example: "MESSAGE_BODY,MESSAGE_ATTRIBUTES"
          44  +
     *
          45  +
     * If not specified, defaults to validating all scopes.
          46  +
     */
          47  +
    public val checksumValidationScopes: EnvironmentSetting<Set<ValidationScope>?> =
          48  +
        enumSetEnvSetting<ValidationScope>("aws.SqsChecksumValidationScope", "AWS_SQS_CHECKSUM_VALIDATION_SCOPE")
          49  +
}

tmp-codegen-diff/services/sqs/common/src/aws.sdk.kotlin.services.sqs/internal/ValidationConfig.kt

@@ -0,1 +0,46 @@
           1  +
package aws.sdk.kotlin.services.sqs.internal
           2  +
           3  +
/**
           4  +
 * Controls when MD5 checksum validation is performed for SQS operations.
           5  +
 *
           6  +
 * This configuration determines under which conditions checksums will be automatically
           7  +
 * calculated and validated for SQS message operations.
           8  +
 *
           9  +
 * Valid values:
          10  +
 * - ALWAYS - Validates checksums for both sending and receiving operations
          11  +
 *           (SendMessage, SendMessageBatch, and ReceiveMessage)
          12  +
 * - WHEN_SENDING - Validates checksums only when sending messages
          13  +
 *                 (SendMessage and SendMessageBatch)
          14  +
 * - WHEN_RECEIVING - Validates checksums only when receiving messages
          15  +
 *                   (ReceiveMessage)
          16  +
 * - NEVER - Disables checksum validation completely
          17  +
 *
          18  +
 * Default: ALWAYS
          19  +
 */
          20  +
public enum class ValidationEnabled {
          21  +
    ALWAYS,
          22  +
    WHEN_SENDING,
          23  +
    WHEN_RECEIVING,
          24  +
    NEVER,
          25  +
}
          26  +
          27  +
/**
          28  +
 * Specifies which parts of an SQS message should undergo MD5 checksum validation.
          29  +
 *
          30  +
 * This configuration determines which components of a message will be validated
          31  +
 * when checksum validation is enabled.
          32  +
 *
          33  +
 * Valid values:
          34  +
 * - MESSAGE_ATTRIBUTES - Validates checksums for message attributes
          35  +
 * - MESSAGE_SYSTEM_ATTRIBUTES - Validates checksums for message system attributes
          36  +
 *   (Note: Not available for ReceiveMessage operations as SQS does not calculate
          37  +
 *   checksums for system attributes during message receipt)
          38  +
 * - MESSAGE_BODY - Validates checksums for the message body
          39  +
 *
          40  +
 * Default: All scopes enabled
          41  +
 */
          42  +
public enum class ValidationScope {
          43  +
    MESSAGE_ATTRIBUTES,
          44  +
    MESSAGE_SYSTEM_ATTRIBUTES,
          45  +
    MESSAGE_BODY,
          46  +
}

tmp-codegen-diff/services/sqs/e2eTest/src/SqsMd5ChecksumValidationTest.kt

@@ -0,1 +0,241 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
package aws.sdk.kotlin.e2etest
           6  +
           7  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.DEFAULT_REGION
           8  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.TEST_MESSAGE_ATTRIBUTES_NAME
           9  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.TEST_MESSAGE_ATTRIBUTES_VALUE
          10  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.TEST_MESSAGE_BODY
          11  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.TEST_MESSAGE_SYSTEM_ATTRIBUTES_VALUE
          12  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.TEST_QUEUE_CORRECT_CHECKSUM_PREFIX
          13  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.TEST_QUEUE_WRONG_CHECKSUM_PREFIX
          14  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.buildSendMessageBatchRequestEntry
          15  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.deleteQueueAndAllMessages
          16  +
import aws.sdk.kotlin.e2etest.SqsTestUtils.getTestQueueUrl
          17  +
import aws.sdk.kotlin.services.sqs.SqsClient
          18  +
import aws.sdk.kotlin.services.sqs.internal.ValidationEnabled
          19  +
import aws.sdk.kotlin.services.sqs.internal.ValidationScope
          20  +
import aws.sdk.kotlin.services.sqs.model.*
          21  +
import aws.smithy.kotlin.runtime.client.ResponseInterceptorContext
          22  +
import aws.smithy.kotlin.runtime.hashing.md5
          23  +
import aws.smithy.kotlin.runtime.http.interceptors.ChecksumMismatchException
          24  +
import aws.smithy.kotlin.runtime.http.interceptors.HttpInterceptor
          25  +
import aws.smithy.kotlin.runtime.http.request.HttpRequest
          26  +
import aws.smithy.kotlin.runtime.http.response.HttpResponse
          27  +
import kotlinx.coroutines.runBlocking
          28  +
import org.junit.jupiter.api.*
          29  +
          30  +
/**
          31  +
 * Tests for Sqs MD5 checksum validation
          32  +
 */
          33  +
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
          34  +
class SqsMd5ChecksumValidationTest {
          35  +
    // An interceptor that set wrong md5 checksums in SQS response
          36  +
    private val wrongChecksumInterceptor = object : HttpInterceptor {
          37  +
        override suspend fun modifyBeforeCompletion(
          38  +
            context: ResponseInterceptorContext<Any, Any, HttpRequest?, HttpResponse?>,
          39  +
        ): Result<Any> {
          40  +
            val wrongMd5ofMessageBody = "wrong message md5".encodeToByteArray().md5().toString()
          41  +
            val wrongMd5ofMessageAttribute = "wrong attribute md5".encodeToByteArray().md5().toString()
          42  +
            val wrongMd5ofMessageSystemAttribute = "wrong system attribute md5".encodeToByteArray().md5().toString()
          43  +
          44  +
            when (val response = context.response.getOrNull()) {
          45  +
                is SendMessageResponse -> {
          46  +
                    val modifiedResponse = SendMessageResponse.invoke {
          47  +
                        messageId = response.messageId
          48  +
                        sequenceNumber = response.sequenceNumber
          49  +
                        md5OfMessageBody = wrongMd5ofMessageBody
          50  +
                        md5OfMessageAttributes = wrongMd5ofMessageAttribute
          51  +
                        md5OfMessageSystemAttributes = wrongMd5ofMessageSystemAttribute
          52  +
                    }
          53  +
                    println("modify SendMessage")
          54  +
                    return Result.success(modifiedResponse)
          55  +
                }
          56  +
                is ReceiveMessageResponse -> {
          57  +
                    val modifiedMessages = response.messages?.map { message ->
          58  +
                        Message {
          59  +
                            messageId = message.messageId
          60  +
                            receiptHandle = message.receiptHandle
          61  +
                            body = message.body
          62  +
                            attributes = message.attributes
          63  +
                            messageAttributes = message.messageAttributes
          64  +
                            md5OfBody = wrongMd5ofMessageBody
          65  +
                            md5OfMessageAttributes = wrongMd5ofMessageAttribute
          66  +
                        }
          67  +
                    }
          68  +
          69  +
                    val modifiedResponse = ReceiveMessageResponse {
          70  +
                        messages = modifiedMessages
          71  +
                    }
          72  +
                    return Result.success(modifiedResponse)
          73  +
                }
          74  +
                is SendMessageBatchResponse -> {
          75  +
                    val modifiedEntries = response.successful.map { entry ->
          76  +
                        SendMessageBatchResultEntry {
          77  +
                            id = entry.id
          78  +
                            messageId = entry.messageId
          79  +
                            md5OfMessageBody = wrongMd5ofMessageBody
          80  +
                            md5OfMessageAttributes = wrongMd5ofMessageAttribute
          81  +
                            md5OfMessageSystemAttributes = wrongMd5ofMessageSystemAttribute
          82  +
                            sequenceNumber = entry.sequenceNumber
          83  +
                        }
          84  +
                    }
          85  +
          86  +
                    val modifiedResponse = SendMessageBatchResponse {
          87  +
                        successful = modifiedEntries
          88  +
                        failed = response.failed
          89  +
                    }
          90  +
                    return Result.success(modifiedResponse)
          91  +
                }
          92  +
            }
          93  +
            return context.response
          94  +
        }
          95  +
    }
          96  +
          97  +
    private val correctChecksumClient = SqsClient {
          98  +
        region = DEFAULT_REGION
          99  +
        checksumValidationEnabled = ValidationEnabled.ALWAYS
         100  +
        checksumValidationScopes = ValidationScope.entries.toSet()
         101  +
    }
         102  +
         103  +
    // used for wrong checksum tests
         104  +
    private val wrongChecksumClient = SqsClient {
         105  +
        region = DEFAULT_REGION
         106  +
        checksumValidationEnabled = ValidationEnabled.ALWAYS
         107  +
        checksumValidationScopes = ValidationScope.entries.toSet()
         108  +
        interceptors += wrongChecksumInterceptor
         109  +
    }
         110  +
         111  +
    private lateinit var correctChecksumTestQueueUrl: String
         112  +
    private lateinit var wrongChecksumTestQueueUrl: String
         113  +
         114  +
    @BeforeAll
         115  +
    private fun setUp(): Unit = runBlocking {
         116  +
        correctChecksumTestQueueUrl = getTestQueueUrl(correctChecksumClient, TEST_QUEUE_CORRECT_CHECKSUM_PREFIX, DEFAULT_REGION)
         117  +
        wrongChecksumTestQueueUrl = getTestQueueUrl(wrongChecksumClient, TEST_QUEUE_WRONG_CHECKSUM_PREFIX, DEFAULT_REGION)
         118  +
    }
         119  +
         120  +
    @AfterAll
         121  +
    private fun cleanUp(): Unit = runBlocking {
         122  +
        deleteQueueAndAllMessages(correctChecksumClient, correctChecksumTestQueueUrl)
         123  +
        deleteQueueAndAllMessages(wrongChecksumClient, wrongChecksumTestQueueUrl)
         124  +
        correctChecksumClient.close()
         125  +
        wrongChecksumClient.close()
         126  +
    }
         127  +
         128  +
    @Test
         129  +
    fun testSendMessage(): Unit = runBlocking {
         130  +
        assertDoesNotThrow {
         131  +
            correctChecksumClient.sendMessage(
         132  +
                SendMessageRequest {
         133  +
                    queueUrl = correctChecksumTestQueueUrl
         134  +
                    messageBody = TEST_MESSAGE_BODY
         135  +
                    messageAttributes = hashMapOf(
         136  +
                        TEST_MESSAGE_ATTRIBUTES_NAME to MessageAttributeValue {
         137  +
                            dataType = "String"
         138  +
                            stringValue = TEST_MESSAGE_ATTRIBUTES_VALUE
         139  +
                        },
         140  +
                    )
         141  +
                    messageSystemAttributes = hashMapOf(
         142  +
                        MessageSystemAttributeNameForSends.AwsTraceHeader to MessageSystemAttributeValue {
         143  +
                            dataType = "String"
         144  +
                            stringValue = TEST_MESSAGE_SYSTEM_ATTRIBUTES_VALUE
         145  +
                        },
         146  +
                    )
         147  +
                },
         148  +
            )
         149  +
        }
         150  +
    }
         151  +
         152  +
    @Test
         153  +
    fun testReceiveMessage(): Unit = runBlocking {
         154  +
        assertDoesNotThrow {
         155  +
            correctChecksumClient.receiveMessage(
         156  +
                ReceiveMessageRequest {
         157  +
                    queueUrl = correctChecksumTestQueueUrl
         158  +
                    maxNumberOfMessages = 1
         159  +
                    messageAttributeNames = listOf(TEST_MESSAGE_ATTRIBUTES_NAME)
         160  +
                    messageSystemAttributeNames = listOf(MessageSystemAttributeName.AwsTraceHeader)
         161  +
                },
         162  +
            )
         163  +
        }
         164  +
    }
         165  +
         166  +
    @Test
         167  +
    fun testSendMessageBatch(): Unit = runBlocking {
         168  +
        val entries = (1..5).map { batchId ->
         169  +
            buildSendMessageBatchRequestEntry(batchId)
         170  +
        }
         171  +
         172  +
        assertDoesNotThrow {
         173  +
            correctChecksumClient.sendMessageBatch(
         174  +
                SendMessageBatchRequest {
         175  +
                    queueUrl = correctChecksumTestQueueUrl
         176  +
                    this.entries = entries
         177  +
                },
         178  +
            )
         179  +
        }
         180  +
    }
         181  +
         182  +
    @Test
         183  +
    fun testSendMessageWithWrongChecksum(): Unit = runBlocking {
         184  +
        val exception = assertThrows<ChecksumMismatchException> {
         185  +
            wrongChecksumClient.sendMessage(
         186  +
                SendMessageRequest {
         187  +
                    queueUrl = wrongChecksumTestQueueUrl
         188  +
                    messageBody = TEST_MESSAGE_BODY
         189  +
                    messageAttributes = hashMapOf(
         190  +
                        TEST_MESSAGE_ATTRIBUTES_NAME to MessageAttributeValue {
         191  +
                            dataType = "String"
         192  +
                            stringValue = TEST_MESSAGE_ATTRIBUTES_VALUE
         193  +
                        },
         194  +
                    )
         195  +
                    messageSystemAttributes = hashMapOf(
         196  +
                        MessageSystemAttributeNameForSends.AwsTraceHeader to MessageSystemAttributeValue {
         197  +
                            dataType = "String"
         198  +
                            stringValue = TEST_MESSAGE_SYSTEM_ATTRIBUTES_VALUE
         199  +
                        },
         200  +
                    )
         201  +
                },
         202  +
            )
         203  +
        }
         204  +
         205  +
        assert(exception.message!!.contains("Checksum mismatch"))
         206  +
    }
         207  +
         208  +
    @Test
         209  +
    fun testReceiveMessageWithWrongChecksum(): Unit = runBlocking {
         210  +
        val exception = assertThrows<ChecksumMismatchException> {
         211  +
            wrongChecksumClient.receiveMessage(
         212  +
                ReceiveMessageRequest {
         213  +
                    queueUrl = wrongChecksumTestQueueUrl
         214  +
                    maxNumberOfMessages = 1
         215  +
                    messageAttributeNames = listOf(TEST_MESSAGE_ATTRIBUTES_NAME)
         216  +
                    messageSystemAttributeNames = listOf(MessageSystemAttributeName.AwsTraceHeader)
         217  +
                },
         218  +
            )
         219  +
        }
         220  +
         221  +
        assert(exception.message!!.contains("Checksum mismatch"))
         222  +
    }
         223  +
         224  +
    @Test
         225  +
    fun testSendMessageBatchWithWrongChecksum(): Unit = runBlocking {
         226  +
        val entries = (1..5).map { batchId ->
         227  +
            buildSendMessageBatchRequestEntry(batchId)
         228  +
        }
         229  +
         230  +
        val exception = assertThrows<ChecksumMismatchException> {
         231  +
            wrongChecksumClient.sendMessageBatch(
         232  +
                SendMessageBatchRequest {
         233  +
                    queueUrl = wrongChecksumTestQueueUrl
         234  +
                    this.entries = entries
         235  +
                },
         236  +
            )
         237  +
        }
         238  +
         239  +
        assert(exception.message!!.contains("Checksum mismatch"))
         240  +
    }
         241  +
}

tmp-codegen-diff/services/sqs/e2eTest/src/SqsTestUtils.kt

@@ -0,1 +0,108 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
package aws.sdk.kotlin.e2etest
           6  +
           7  +
import aws.sdk.kotlin.services.sqs.SqsClient
           8  +
import aws.sdk.kotlin.services.sqs.createQueue
           9  +
import aws.sdk.kotlin.services.sqs.model.*
          10  +
import kotlinx.coroutines.coroutineScope
          11  +
import kotlinx.coroutines.withTimeout
          12  +
import java.net.URI
          13  +
import java.util.*
          14  +
import kotlin.time.Duration.Companion.seconds
          15  +
          16  +
object SqsTestUtils {
          17  +
    const val DEFAULT_REGION = "us-west-2"
          18  +
          19  +
    const val TEST_QUEUE_WRONG_CHECKSUM_PREFIX = "sqs-test-queue-"
          20  +
    const val TEST_QUEUE_CORRECT_CHECKSUM_PREFIX = "sqs-test-queue-"
          21  +
          22  +
    const val TEST_MESSAGE_BODY = "Hello World"
          23  +
    const val TEST_MESSAGE_ATTRIBUTES_NAME = "TestAttribute"
          24  +
    const val TEST_MESSAGE_ATTRIBUTES_VALUE = "TestAttributeValue"
          25  +
    const val TEST_MESSAGE_SYSTEM_ATTRIBUTES_VALUE = "TestSystemAttributeValue"
          26  +
          27  +
    suspend fun getTestQueueUrl(
          28  +
        client: SqsClient,
          29  +
        prefix: String,
          30  +
        region: String? = null,
          31  +
    ): String = getQueueUrlWithPrefix(client, prefix, region)
          32  +
          33  +
    suspend fun getQueueUrlWithPrefix(
          34  +
        client: SqsClient,
          35  +
        prefix: String,
          36  +
        region: String? = null,
          37  +
    ): String = withTimeout(60.seconds) {
          38  +
        val queueUrls = client.listQueues().queueUrls
          39  +
          40  +
        var matchingQueueUrl = queueUrls?.firstOrNull { url ->
          41  +
            val queueUrl = URI(url).toURL()
          42  +
            val hostParts = queueUrl.host.split(".")
          43  +
          44  +
            val regionMatches = if (region != null) {
          45  +
                hostParts.getOrNull(1)?.equals(region, ignoreCase = true) ?: false
          46  +
            } else {
          47  +
                true
          48  +
            }
          49  +
          50  +
            val queueName = queueUrl.path.split("/").last()
          51  +
            val prefixMatches = queueName.startsWith(prefix)
          52  +
          53  +
            regionMatches && prefixMatches
          54  +
        }
          55  +
          56  +
        if (matchingQueueUrl == null) {
          57  +
            matchingQueueUrl = prefix + UUID.randomUUID()
          58  +
            println("Creating Sqs queue: $matchingQueueUrl")
          59  +
          60  +
            client.createQueue {
          61  +
                queueName = matchingQueueUrl
          62  +
            }
          63  +
        } else {
          64  +
            println("Using existing Sqs queue: $matchingQueueUrl")
          65  +
        }
          66  +
          67  +
        matchingQueueUrl
          68  +
    }
          69  +
          70  +
    suspend fun deleteQueueAndAllMessages(client: SqsClient, queueUrl: String): Unit = coroutineScope {
          71  +
        try {
          72  +
            println("Purging Sqs queue: $queueUrl")
          73  +
            val purgeRequest = PurgeQueueRequest {
          74  +
                this.queueUrl = queueUrl
          75  +
            }
          76  +
          77  +
            client.purgeQueue(purgeRequest)
          78  +
            println("Queue purged successfully.")
          79  +
          80  +
            println("Deleting Sqs queue: $queueUrl")
          81  +
            val deleteRequest = DeleteQueueRequest {
          82  +
                this.queueUrl = queueUrl
          83  +
            }
          84  +
          85  +
            client.deleteQueue(deleteRequest)
          86  +
            println("Queue deleted successfully.")
          87  +
        } catch (e: SqsException) {
          88  +
            println("Error during delete SQS queue: ${e.message}")
          89  +
        }
          90  +
    }
          91  +
          92  +
    fun buildSendMessageBatchRequestEntry(batchId: Int): SendMessageBatchRequestEntry = SendMessageBatchRequestEntry {
          93  +
        id = batchId.toString()
          94  +
        messageBody = TEST_MESSAGE_BODY + batchId
          95  +
        messageAttributes = hashMapOf(
          96  +
            TEST_MESSAGE_ATTRIBUTES_NAME to MessageAttributeValue {
          97  +
                dataType = "String"
          98  +
                stringValue = TEST_MESSAGE_ATTRIBUTES_VALUE + batchId
          99  +
            },
         100  +
        )
         101  +
        messageSystemAttributes = hashMapOf(
         102  +
            MessageSystemAttributeNameForSends.AwsTraceHeader to MessageSystemAttributeValue {
         103  +
                dataType = "String"
         104  +
                stringValue = TEST_MESSAGE_SYSTEM_ATTRIBUTES_VALUE + batchId
         105  +
            },
         106  +
        )
         107  +
    }
         108  +
}