Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package aws-c-s3 for openSUSE:Factory checked in at 2025-02-06 22:05:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/aws-c-s3 (Old) and /work/SRC/openSUSE:Factory/.aws-c-s3.new.2316 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "aws-c-s3" Thu Feb 6 22:05:05 2025 rev:16 rq:1243443 version:0.7.11 Changes: -------- --- /work/SRC/openSUSE:Factory/aws-c-s3/aws-c-s3.changes 2025-01-17 18:43:24.815973441 +0100 +++ /work/SRC/openSUSE:Factory/.aws-c-s3.new.2316/aws-c-s3.changes 2025-02-06 22:06:37.085065876 +0100 @@ -1,0 +2,10 @@ +Thu Jan 30 11:41:34 UTC 2025 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- Update to version 0.7.11 + * A bunch of CMake fixes by @graebm in (#480) +- from version 0.7.10 + * Auto - Update S3 Ruleset & Partition by @waahm7 in (#491) + * S3Express CreateSession Allowlist Headers by @waahm7 in (#492) +- Drop acs_fix-cmake-modules-path.patch, fixed upstream + +------------------------------------------------------------------- Old: ---- acs_fix-cmake-modules-path.patch v0.7.9.tar.gz New: ---- v0.7.11.tar.gz BETA DEBUG BEGIN: Old: * S3Express CreateSession Allowlist Headers by @waahm7 in (#492) - Drop acs_fix-cmake-modules-path.patch, fixed upstream BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ aws-c-s3.spec ++++++ --- /var/tmp/diff_new_pack.JeYpu6/_old 2025-02-06 22:06:38.937142195 +0100 +++ /var/tmp/diff_new_pack.JeYpu6/_new 2025-02-06 22:06:38.953142854 +0100 @@ -19,14 +19,13 @@ %define library_version 1.0.0 %define library_soversion 0unstable Name: aws-c-s3 -Version: 0.7.9 +Version: 0.7.11 Release: 0 Summary: AWS Cross-Platform, C99 wrapper for cryptography primitives License: Apache-2.0 Group: Development/Libraries/C and C++ URL: https://github.com/awslabs/aws-c-s3 Source0: https://github.com/awslabs/%{name}/archive/v%{version}.tar.gz -Patch0: acs_fix-cmake-modules-path.patch BuildRequires: cmake BuildRequires: fdupes BuildRequires: ninja ++++++ v0.7.9.tar.gz -> v0.7.11.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/.github/workflows/ci.yml new/aws-c-s3-0.7.11/.github/workflows/ci.yml --- old/aws-c-s3-0.7.9/.github/workflows/ci.yml 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/.github/workflows/ci.yml 2025-01-29 00:11:30.000000000 +0100 @@ -11,7 +11,7 @@ cancel-in-progress: true env: - BUILDER_VERSION: v0.9.72 + BUILDER_VERSION: v0.9.74 BUILDER_SOURCE: releases BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net PACKAGE_NAME: aws-c-s3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/.github/workflows/codecov.yml new/aws-c-s3-0.7.11/.github/workflows/codecov.yml --- old/aws-c-s3-0.7.9/.github/workflows/codecov.yml 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/.github/workflows/codecov.yml 2025-01-29 00:11:30.000000000 +0100 @@ -5,7 +5,7 @@ env: - BUILDER_VERSION: v0.9.72 + BUILDER_VERSION: v0.9.74 BUILDER_SOURCE: releases BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net PACKAGE_NAME: aws-c-s3 @@ -30,4 +30,4 @@ run: | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" chmod a+x builder - ./builder build -p ${{ env.PACKAGE_NAME }} --compiler=gcc-12 --cmake-extra=-DASSERT_LOCK_HELD=ON --coverage --coverage-exclude=source/s3_copy_object.c + ./builder build -p ${{ env.PACKAGE_NAME }} --compiler=gcc --cmake-extra=-DASSERT_LOCK_HELD=ON --coverage --coverage-exclude=source/s3_copy_object.c diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/CMakeLists.txt new/aws-c-s3-0.7.11/CMakeLists.txt --- old/aws-c-s3-0.7.9/CMakeLists.txt 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/CMakeLists.txt 2025-01-29 00:11:30.000000000 +0100 @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.9) +cmake_minimum_required(VERSION 3.9...3.31) project(aws-c-s3 C) option(ASSERT_LOCK_HELD "Enable ASSERT_SYNCED_DATA_LOCK_HELD for checking thread issue" OFF) @@ -11,32 +11,17 @@ add_definitions(-DASSERT_LOCK_HELD) endif() -if (DEFINED CMAKE_PREFIX_PATH) - file(TO_CMAKE_PATH "${CMAKE_PREFIX_PATH}" CMAKE_PREFIX_PATH) +if (NOT IN_SOURCE_BUILD) + # this is required so we can use aws-c-common's CMake modules + find_package(aws-c-common REQUIRED) endif() -if (DEFINED CMAKE_INSTALL_PREFIX) - file(TO_CMAKE_PATH "${CMAKE_INSTALL_PREFIX}" CMAKE_INSTALL_PREFIX) -endif() - - -if (UNIX AND NOT APPLE) - include(GNUInstallDirs) -elseif(NOT DEFINED CMAKE_INSTALL_LIBDIR) - set(CMAKE_INSTALL_LIBDIR "lib") -endif() - -# This is required in order to append /lib/cmake to each element in CMAKE_PREFIX_PATH -set(AWS_MODULE_DIR "/${CMAKE_INSTALL_LIBDIR}/cmake") -string(REPLACE ";" "${AWS_MODULE_DIR};" AWS_MODULE_PATH "${CMAKE_PREFIX_PATH}${AWS_MODULE_DIR}") -# Append that generated list to the module search path -list(APPEND CMAKE_MODULE_PATH ${AWS_MODULE_PATH}) - include(AwsCFlags) include(AwsCheckHeaders) include(AwsSharedLibSetup) include(AwsSanitizers) include(AwsFindPackage) +include(GNUInstallDirs) file(GLOB AWS_S3_ROOT_HEADERS "include/aws/s3/*.h" @@ -100,7 +85,7 @@ aws_prepare_shared_lib_exports(${PROJECT_NAME}) -install(FILES ${AWS_S3_ROOT_HEADERS} DESTINATION "include/aws/s3" COMPONENT Development) +install(FILES ${AWS_S3_ROOT_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/aws/s3" COMPONENT Development) if (BUILD_SHARED_LIBS) set (TARGET_DIR "shared") @@ -109,7 +94,7 @@ endif() install(EXPORT "${PROJECT_NAME}-targets" - DESTINATION "${LIBRARY_DIRECTORY}/${PROJECT_NAME}/cmake/${TARGET_DIR}/" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/${TARGET_DIR}/" NAMESPACE AWS:: COMPONENT Development) @@ -118,7 +103,7 @@ @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" - DESTINATION "${LIBRARY_DIRECTORY}/${PROJECT_NAME}/cmake/" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/" COMPONENT Development) include(CTest) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/include/aws/s3/private/s3_request_messages.h new/aws-c-s3-0.7.11/include/aws/s3/private/s3_request_messages.h --- old/aws-c-s3-0.7.9/include/aws/s3/private/s3_request_messages.h 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/include/aws/s3/private/s3_request_messages.h 2025-01-29 00:11:30.000000000 +0100 @@ -168,6 +168,12 @@ extern const struct aws_byte_cursor g_s3_abort_multipart_upload_excluded_headers[]; AWS_S3_API +extern const size_t g_s3_create_session_allowed_headers_count; + +AWS_S3_API +extern const struct aws_byte_cursor g_s3_create_session_allowed_headers[]; + +AWS_S3_API extern const size_t g_s3_abort_multipart_upload_excluded_headers_count; AWS_S3_API diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/include/aws/s3/private/s3express_credentials_provider_impl.h new/aws-c-s3-0.7.11/include/aws/s3/private/s3express_credentials_provider_impl.h --- old/aws-c-s3-0.7.9/include/aws/s3/private/s3express_credentials_provider_impl.h 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/include/aws/s3/private/s3express_credentials_provider_impl.h 2025-01-29 00:11:30.000000000 +0100 @@ -26,6 +26,8 @@ /* The region and host of the session */ struct aws_string *region; struct aws_string *host; + + struct aws_http_headers *headers; bool inactive; /* Only used for mock tests */ @@ -105,14 +107,19 @@ const struct aws_s3express_credentials_provider_default_options *options); /** - * Encode the hash key to be [host_value][hash_of_credentials] - * hash_of_credentials is the sha256 of [access_key][secret_access_key] + * Encodes the hash key in the format: [host_value][hash_of_credentials_and_headers] + * + * The hash_of_credentials_and_headers is calculated as follows: + * 1. Concatenate: [access_key][secret_access_key][headers] + * where headers = ",header_name1:header_value1,header_name2:header_value2..." + * 2. Generates SHA256 hash of the concatenated string */ AWS_S3_API struct aws_string *aws_encode_s3express_hash_key_new( struct aws_allocator *allocator, const struct aws_credentials *original_credentials, - struct aws_byte_cursor host_value); + struct aws_byte_cursor host_value, + struct aws_http_headers *headers); AWS_EXTERN_C_END #endif /* AWS_S3EXPRESS_CREDENTIALS_PROVIDER_IMPL_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/include/aws/s3/s3_client.h new/aws-c-s3-0.7.11/include/aws/s3/s3_client.h --- old/aws-c-s3-0.7.9/include/aws/s3/s3_client.h 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/include/aws/s3/s3_client.h 2025-01-29 00:11:30.000000000 +0100 @@ -552,6 +552,10 @@ * If set, client will invoke the factory to get the provider to use, when needed. * * If not set, client will create a default S3 Express provider under the hood. + * + * NOTE: THE FOLLOWING BEHAVIOR IS EXPERIMENTAL AND UNSTABLE + * Default S3 Express provider will pass the headers allowed in `g_s3_create_session_allowed_headers` to the + * CreateSession call. */ aws_s3express_provider_factory_fn *s3express_provider_override_factory; void *factory_user_data; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/include/aws/s3/s3express_credentials_provider.h new/aws-c-s3-0.7.11/include/aws/s3/s3express_credentials_provider.h --- old/aws-c-s3-0.7.9/include/aws/s3/s3express_credentials_provider.h 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/include/aws/s3/s3express_credentials_provider.h 2025-01-29 00:11:30.000000000 +0100 @@ -27,6 +27,8 @@ * If empty, the region of the S3 client will be used. */ struct aws_byte_cursor region; + + struct aws_http_headers *headers; }; struct aws_s3express_credentials_provider_vtable { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/samples/s3/CMakeLists.txt new/aws-c-s3-0.7.11/samples/s3/CMakeLists.txt --- old/aws-c-s3-0.7.9/samples/s3/CMakeLists.txt 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/samples/s3/CMakeLists.txt 2025-01-29 00:11:30.000000000 +0100 @@ -1,7 +1,5 @@ project(s3 C) -list(APPEND CMAKE_MODULE_PATH "${CMAKE_INSTALL_PREFIX}/lib/cmake") - file(GLOB S3_SRC "*.c" ) @@ -25,5 +23,5 @@ EXPORT ${S3_PROJECT_NAME}-targets COMPONENT Runtime RUNTIME - DESTINATION bin + DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/source/s3_client.c new/aws-c-s3-0.7.11/source/s3_client.c --- old/aws-c-s3-0.7.9/source/s3_client.c 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/source/s3_client.c 2025-01-29 00:11:30.000000000 +0100 @@ -1030,6 +1030,7 @@ } endpoint_host_name = aws_string_new_from_cursor(client->allocator, aws_uri_host_name(&host_uri)); + port = aws_uri_port(&host_uri); aws_uri_clean_up(&host_uri); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/source/s3_endpoint_resolver/aws_s3_endpoint_resolver_partition.c new/aws-c-s3-0.7.11/source/s3_endpoint_resolver/aws_s3_endpoint_resolver_partition.c --- old/aws-c-s3-0.7.9/source/s3_endpoint_resolver/aws_s3_endpoint_resolver_partition.c 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/source/s3_endpoint_resolver/aws_s3_endpoint_resolver_partition.c 2025-01-29 00:11:30.000000000 +0100 @@ -95,132 +95,134 @@ '"', 'M', 'i', 'd', 'd', 'l', 'e', ' ', 'E', 'a', 's', 't', ' ', '(', 'U', 'A', 'E', ')', '"', '}', ',', '"', 'm', 'e', '-', 's', 'o', 'u', 't', 'h', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'M', 'i', 'd', 'd', 'l', 'e', ' ', 'E', 'a', 's', - 't', ' ', '(', 'B', 'a', 'h', 'r', 'a', 'i', 'n', ')', '"', '}', ',', '"', 's', 'a', '-', 'e', 'a', + 't', ' ', '(', 'B', 'a', 'h', 'r', 'a', 'i', 'n', ')', '"', '}', ',', '"', 'm', 'x', '-', 'c', 'e', + 'n', 't', 'r', 'a', 'l', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', + 'o', 'n', '"', ':', '"', 'M', 'e', 'x', 'i', 'c', 'o', ' ', '(', 'C', 'e', 'n', 't', 'r', 'a', 'l', + ')', '"', '}', ',', '"', 's', 'a', '-', 'e', 'a', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', + 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'S', 'o', 'u', 't', 'h', ' ', 'A', 'm', + 'e', 'r', 'i', 'c', 'a', ' ', '(', 'S', 'a', 'o', ' ', 'P', 'a', 'u', 'l', 'o', ')', '"', '}', ',', + '"', 'u', 's', '-', 'e', 'a', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', + 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'E', 'a', 's', 't', ' ', '(', 'N', '.', ' ', + 'V', 'i', 'r', 'g', 'i', 'n', 'i', 'a', ')', '"', '}', ',', '"', 'u', 's', '-', 'e', 'a', 's', 't', + '-', '2', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', + 'U', 'S', ' ', 'E', 'a', 's', 't', ' ', '(', 'O', 'h', 'i', 'o', ')', '"', '}', ',', '"', 'u', 's', + '-', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', + 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'W', 'e', 's', 't', ' ', '(', 'N', '.', ' ', 'C', 'a', 'l', + 'i', 'f', 'o', 'r', 'n', 'i', 'a', ')', '"', '}', ',', '"', 'u', 's', '-', 'w', 'e', 's', 't', '-', + '2', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', + 'S', ' ', 'W', 'e', 's', 't', ' ', '(', 'O', 'r', 'e', 'g', 'o', 'n', ')', '"', '}', '}', '}', ',', + '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', 'c', 'n', '"', ',', '"', 'o', 'u', 't', 'p', + 'u', 't', 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', + 'm', 'a', 'z', 'o', 'n', 'a', 'w', 's', '.', 'c', 'o', 'm', '.', 'c', 'n', '"', ',', '"', 'd', 'u', + 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', + 'p', 'i', '.', 'a', 'm', 'a', 'z', 'o', 'n', 'w', 'e', 'b', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', + '.', 'c', 'o', 'm', '.', 'c', 'n', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', + 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'c', 'n', '-', 'n', 'o', 'r', 't', + 'h', 'w', 'e', 's', 't', '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', + '-', 'c', 'n', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', + 'a', 'c', 'k', '"', ':', 't', 'r', 'u', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', + 'I', 'P', 'S', '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', + 'g', 'e', 'x', '"', ':', '"', '^', 'c', 'n', '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', + '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', '{', '"', 'a', 'w', + 's', '-', 'c', 'n', '-', 'g', 'l', 'o', 'b', 'a', 'l', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', + 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'A', 'W', 'S', ' ', 'C', 'h', 'i', 'n', 'a', ' ', 'g', + 'l', 'o', 'b', 'a', 'l', ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', '}', ',', '"', 'c', 'n', '-', 'n', + 'o', 'r', 't', 'h', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', + 'n', '"', ':', '"', 'C', 'h', 'i', 'n', 'a', ' ', '(', 'B', 'e', 'i', 'j', 'i', 'n', 'g', ')', '"', + '}', ',', '"', 'c', 'n', '-', 'n', 'o', 'r', 't', 'h', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', + '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'C', 'h', 'i', 'n', 'a', + ' ', '(', 'N', 'i', 'n', 'g', 'x', 'i', 'a', ')', '"', '}', '}', '}', ',', '{', '"', 'i', 'd', '"', + ':', '"', 'a', 'w', 's', '-', 'u', 's', '-', 'g', 'o', 'v', '"', ',', '"', 'o', 'u', 't', 'p', 'u', + 't', 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', 'm', + 'a', 'z', 'o', 'n', 'a', 'w', 's', '.', 'c', 'o', 'm', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', + 'a', 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', 'p', 'i', '.', 'a', + 'w', 's', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', + 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'u', 's', '-', 'g', 'o', 'v', '-', 'w', 'e', 's', 't', '-', + '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', 'u', 's', '-', 'g', 'o', + 'v', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', + 'k', '"', ':', 't', 'r', 'u', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', + 'S', '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', + 'x', '"', ':', '"', '^', 'u', 's', '\\', '\\', '-', 'g', 'o', 'v', '\\', '\\', '-', '\\', '\\', 'w', '+', + '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', + '{', '"', 'a', 'w', 's', '-', 'u', 's', '-', 'g', 'o', 'v', '-', 'g', 'l', 'o', 'b', 'a', 'l', '"', + ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'A', 'W', 'S', + ' ', 'G', 'o', 'v', 'C', 'l', 'o', 'u', 'd', ' ', '(', 'U', 'S', ')', ' ', 'g', 'l', 'o', 'b', 'a', + 'l', ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', '}', ',', '"', 'u', 's', '-', 'g', 'o', 'v', '-', 'e', + 'a', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', + '"', ':', '"', 'A', 'W', 'S', ' ', 'G', 'o', 'v', 'C', 'l', 'o', 'u', 'd', ' ', '(', 'U', 'S', '-', + 'E', 'a', 's', 't', ')', '"', '}', ',', '"', 'u', 's', '-', 'g', 'o', 'v', '-', 'w', 'e', 's', 't', + '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', + 'A', 'W', 'S', ' ', 'G', 'o', 'v', 'C', 'l', 'o', 'u', 'd', ' ', '(', 'U', 'S', '-', 'W', 'e', 's', + 't', ')', '"', '}', '}', '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', + 'o', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', + 'f', 'f', 'i', 'x', '"', ':', '"', 'c', '2', 's', '.', 'i', 'c', '.', 'g', 'o', 'v', '"', ',', '"', + 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', + '"', 'c', '2', 's', '.', 'i', 'c', '.', 'g', 'o', 'v', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', + 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'u', 's', '-', + 'i', 's', 'o', '-', 'e', 'a', 's', 't', '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', + 'a', 'w', 's', '-', 'i', 's', 'o', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', + 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', 'f', 'a', 'l', 's', 'e', ',', '"', 's', 'u', 'p', 'p', + 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', + 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', '"', '^', 'u', 's', '\\', '\\', '-', 'i', 's', 'o', + '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', + 'g', 'i', 'o', 'n', 's', '"', ':', '{', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'g', 'l', 'o', + 'b', 'a', 'l', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', + '"', 'A', 'W', 'S', ' ', 'I', 'S', 'O', ' ', '(', 'U', 'S', ')', ' ', 'g', 'l', 'o', 'b', 'a', 'l', + ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', '}', ',', '"', 'u', 's', '-', 'i', 's', 'o', '-', 'e', 'a', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', - ':', '"', 'S', 'o', 'u', 't', 'h', ' ', 'A', 'm', 'e', 'r', 'i', 'c', 'a', ' ', '(', 'S', 'a', 'o', - ' ', 'P', 'a', 'u', 'l', 'o', ')', '"', '}', ',', '"', 'u', 's', '-', 'e', 'a', 's', 't', '-', '1', - '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', - ' ', 'E', 'a', 's', 't', ' ', '(', 'N', '.', ' ', 'V', 'i', 'r', 'g', 'i', 'n', 'i', 'a', ')', '"', - '}', ',', '"', 'u', 's', '-', 'e', 'a', 's', 't', '-', '2', '"', ':', '{', '"', 'd', 'e', 's', 'c', - 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'E', 'a', 's', 't', ' ', '(', 'O', - 'h', 'i', 'o', ')', '"', '}', ',', '"', 'u', 's', '-', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', - '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'W', 'e', - 's', 't', ' ', '(', 'N', '.', ' ', 'C', 'a', 'l', 'i', 'f', 'o', 'r', 'n', 'i', 'a', ')', '"', '}', - ',', '"', 'u', 's', '-', 'w', 'e', 's', 't', '-', '2', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', - 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'W', 'e', 's', 't', ' ', '(', 'O', 'r', - 'e', 'g', 'o', 'n', ')', '"', '}', '}', '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', - '-', 'c', 'n', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', 'n', 's', - 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', 'm', 'a', 'z', 'o', 'n', 'a', 'w', 's', '.', 'c', - 'o', 'm', '.', 'c', 'n', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', - 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', 'p', 'i', '.', 'a', 'm', 'a', 'z', 'o', 'n', 'w', - 'e', 'b', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', '.', 'c', 'o', 'm', '.', 'c', 'n', '"', ',', '"', - 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', - '"', ':', '"', 'c', 'n', '-', 'n', 'o', 'r', 't', 'h', 'w', 'e', 's', 't', '-', '1', '"', ',', '"', - 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', 'c', 'n', '"', ',', '"', 's', 'u', 'p', 'p', - 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', 't', 'r', 'u', 'e', ',', + ':', '"', 'U', 'S', ' ', 'I', 'S', 'O', ' ', 'E', 'a', 's', 't', '"', '}', ',', '"', 'u', 's', '-', + 'i', 's', 'o', '-', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', + 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'I', 'S', 'O', ' ', 'W', 'E', 'S', 'T', '"', + '}', '}', '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'b', + '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', + 'f', 'i', 'x', '"', ':', '"', 's', 'c', '2', 's', '.', 's', 'g', 'o', 'v', '.', 'g', 'o', 'v', '"', + ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', + '"', ':', '"', 's', 'c', '2', 's', '.', 's', 'g', 'o', 'v', '.', 'g', 'o', 'v', '"', ',', '"', 'i', + 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', '"', + ':', '"', 'u', 's', '-', 'i', 's', 'o', 'b', '-', 'e', 'a', 's', 't', '-', '1', '"', ',', '"', 'n', + 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'b', '"', ',', '"', 's', 'u', + 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', 'f', 'a', 'l', + 's', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', ':', 't', 'r', + 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', '"', '^', + 'u', 's', '\\', '\\', '-', 'i', 's', 'o', 'b', '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', + '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', '{', '"', 'a', 'w', + 's', '-', 'i', 's', 'o', '-', 'b', '-', 'g', 'l', 'o', 'b', 'a', 'l', '"', ':', '{', '"', 'd', 'e', + 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'A', 'W', 'S', ' ', 'I', 'S', 'O', 'B', + ' ', '(', 'U', 'S', ')', ' ', 'g', 'l', 'o', 'b', 'a', 'l', ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', + '}', ',', '"', 'u', 's', '-', 'i', 's', 'o', 'b', '-', 'e', 'a', 's', 't', '-', '1', '"', ':', '{', + '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'I', 'S', + 'O', 'B', ' ', 'E', 'a', 's', 't', ' ', '(', 'O', 'h', 'i', 'o', ')', '"', '}', '}', '}', ',', '{', + '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'e', '"', ',', '"', 'o', 'u', + 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', + '"', 'c', 'l', 'o', 'u', 'd', '.', 'a', 'd', 'c', '-', 'e', '.', 'u', 'k', '"', ',', '"', 'd', 'u', + 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'c', + 'l', 'o', 'u', 'd', '.', 'a', 'd', 'c', '-', 'e', '.', 'u', 'k', '"', ',', '"', 'i', 'm', 'p', 'l', + 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'e', + 'u', '-', 'i', 's', 'o', 'e', '-', 'w', 'e', 's', 't', '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', + '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'e', '"', ',', '"', 's', 'u', 'p', 'p', 'o', + 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', 'f', 'a', 'l', 's', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', ':', 't', 'r', 'u', 'e', '}', - ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', '"', '^', 'c', 'n', '\\', - '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', - 'i', 'o', 'n', 's', '"', ':', '{', '"', 'a', 'w', 's', '-', 'c', 'n', '-', 'g', 'l', 'o', 'b', 'a', - 'l', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'A', - 'W', 'S', ' ', 'C', 'h', 'i', 'n', 'a', ' ', 'g', 'l', 'o', 'b', 'a', 'l', ' ', 'r', 'e', 'g', 'i', - 'o', 'n', '"', '}', ',', '"', 'c', 'n', '-', 'n', 'o', 'r', 't', 'h', '-', '1', '"', ':', '{', '"', - 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'C', 'h', 'i', 'n', 'a', ' ', - '(', 'B', 'e', 'i', 'j', 'i', 'n', 'g', ')', '"', '}', ',', '"', 'c', 'n', '-', 'n', 'o', 'r', 't', - 'h', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', - 'o', 'n', '"', ':', '"', 'C', 'h', 'i', 'n', 'a', ' ', '(', 'N', 'i', 'n', 'g', 'x', 'i', 'a', ')', - '"', '}', '}', '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', 'u', 's', '-', 'g', - 'o', 'v', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', - 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'a', 'm', 'a', 'z', 'o', 'n', 'a', 'w', 's', '.', 'c', 'o', - 'm', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', - 'i', 'x', '"', ':', '"', 'a', 'p', 'i', '.', 'a', 'w', 's', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', - 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'u', 's', - '-', 'g', 'o', 'v', '-', 'w', 'e', 's', 't', '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', - '"', 'a', 'w', 's', '-', 'u', 's', '-', 'g', 'o', 'v', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', - 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', 't', 'r', 'u', 'e', ',', '"', 's', - 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', - 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', '"', '^', 'u', 's', '\\', '\\', '-', - 'g', 'o', 'v', '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', - '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', '{', '"', 'a', 'w', 's', '-', 'u', 's', '-', 'g', - 'o', 'v', '-', 'g', 'l', 'o', 'b', 'a', 'l', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', - 't', 'i', 'o', 'n', '"', ':', '"', 'A', 'W', 'S', ' ', 'G', 'o', 'v', 'C', 'l', 'o', 'u', 'd', ' ', - '(', 'U', 'S', ')', ' ', 'g', 'l', 'o', 'b', 'a', 'l', ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', '}', - ',', '"', 'u', 's', '-', 'g', 'o', 'v', '-', 'e', 'a', 's', 't', '-', '1', '"', ':', '{', '"', 'd', - 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'A', 'W', 'S', ' ', 'G', 'o', 'v', - 'C', 'l', 'o', 'u', 'd', ' ', '(', 'U', 'S', '-', 'E', 'a', 's', 't', ')', '"', '}', ',', '"', 'u', - 's', '-', 'g', 'o', 'v', '-', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', - 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'A', 'W', 'S', ' ', 'G', 'o', 'v', 'C', 'l', 'o', - 'u', 'd', ' ', '(', 'U', 'S', '-', 'W', 'e', 's', 't', ')', '"', '}', '}', '}', ',', '{', '"', 'i', - 'd', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', - 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'c', '2', 's', - '.', 'i', 'c', '.', 'g', 'o', 'v', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', - 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'c', '2', 's', '.', 'i', 'c', '.', 'g', 'o', - 'v', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', - 'g', 'i', 'o', 'n', '"', ':', '"', 'u', 's', '-', 'i', 's', 'o', '-', 'e', 'a', 's', 't', '-', '1', - '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '"', ',', '"', - 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', 'f', - 'a', 'l', 's', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', ':', - 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', - '"', '^', 'u', 's', '\\', '\\', '-', 'i', 's', 'o', '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', - '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', '{', '"', 'a', - 'w', 's', '-', 'i', 's', 'o', '-', 'g', 'l', 'o', 'b', 'a', 'l', '"', ':', '{', '"', 'd', 'e', 's', - 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'A', 'W', 'S', ' ', 'I', 'S', 'O', ' ', '(', - 'U', 'S', ')', ' ', 'g', 'l', 'o', 'b', 'a', 'l', ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', '}', ',', - '"', 'u', 's', '-', 'i', 's', 'o', '-', 'e', 'a', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', - 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'I', 'S', 'O', ' ', 'E', - 'a', 's', 't', '"', '}', ',', '"', 'u', 's', '-', 'i', 's', 'o', '-', 'w', 'e', 's', 't', '-', '1', - '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'U', 'S', - ' ', 'I', 'S', 'O', ' ', 'W', 'E', 'S', 'T', '"', '}', '}', '}', ',', '{', '"', 'i', 'd', '"', ':', - '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'b', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', - '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 's', 'c', '2', 's', - '.', 's', 'g', 'o', 'v', '.', 'g', 'o', 'v', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', - 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 's', 'c', '2', 's', '.', 's', 'g', - 'o', 'v', '.', 'g', 'o', 'v', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', - 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'u', 's', '-', 'i', 's', 'o', 'b', '-', - 'e', 'a', 's', 't', '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', - 'i', 's', 'o', '-', 'b', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', - 'S', 't', 'a', 'c', 'k', '"', ':', 'f', 'a', 'l', 's', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', - 't', 's', 'F', 'I', 'P', 'S', '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', - 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', '"', '^', 'u', 's', '\\', '\\', '-', 'i', 's', 'o', 'b', '\\', - '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', - 'i', 'o', 'n', 's', '"', ':', '{', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'b', '-', 'g', 'l', - 'o', 'b', 'a', 'l', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', - ':', '"', 'A', 'W', 'S', ' ', 'I', 'S', 'O', 'B', ' ', '(', 'U', 'S', ')', ' ', 'g', 'l', 'o', 'b', - 'a', 'l', ' ', 'r', 'e', 'g', 'i', 'o', 'n', '"', '}', ',', '"', 'u', 's', '-', 'i', 's', 'o', 'b', - '-', 'e', 'a', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', - 'o', 'n', '"', ':', '"', 'U', 'S', ' ', 'I', 'S', 'O', 'B', ' ', 'E', 'a', 's', 't', ' ', '(', 'O', - 'h', 'i', 'o', ')', '"', '}', '}', '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', - 'i', 's', 'o', '-', 'e', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', - 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'c', 'l', 'o', 'u', 'd', '.', 'a', 'd', 'c', - '-', 'e', '.', 'u', 'k', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', - 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'c', 'l', 'o', 'u', 'd', '.', 'a', 'd', 'c', '-', 'e', - '.', 'u', 'k', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', - 'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'e', 'u', '-', 'i', 's', 'o', 'e', '-', 'w', 'e', 's', - 't', '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', - '-', 'e', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', - 'c', 'k', '"', ':', 'f', 'a', 'l', 's', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', - 'I', 'P', 'S', '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', - 'g', 'e', 'x', '"', ':', '"', '^', 'e', 'u', '\\', '\\', '-', 'i', 's', 'o', 'e', '\\', '\\', '-', '\\', - '\\', 'w', '+', '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', - 's', '"', ':', '{', '"', 'e', 'u', '-', 'i', 's', 'o', 'e', '-', 'w', 'e', 's', 't', '-', '1', '"', - ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', '"', ':', '"', 'E', 'U', ' ', - 'I', 'S', 'O', 'E', ' ', 'W', 'e', 's', 't', '"', '}', '}', '}', ',', '{', '"', 'i', 'd', '"', ':', - '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'f', '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', - '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'c', 's', 'p', '.', - 'h', 'c', 'i', '.', 'i', 'c', '.', 'g', 'o', 'v', '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', - 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', 'x', '"', ':', '"', 'c', 's', 'p', '.', 'h', 'c', - 'i', '.', 'i', 'c', '.', 'g', 'o', 'v', '"', ',', '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', - 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', 'n', '"', ':', '"', 'u', 's', '-', 'i', 's', 'o', - 'f', '-', 's', 'o', 'u', 't', 'h', '-', '1', '"', ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', - 'w', 's', '-', 'i', 's', 'o', '-', 'f', '"', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', - 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', 'f', 'a', 'l', 's', 'e', ',', '"', 's', 'u', 'p', - 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', - 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', '"', '^', 'u', 's', '\\', '\\', '-', 'i', 's', - 'o', 'f', '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', - 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', '{', '}', '}', ']', ',', '"', 'v', 'e', 'r', 's', 'i', - 'o', 'n', '"', ':', '"', '1', '.', '1', '"', '}'}; + ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', ':', '"', '^', 'e', 'u', '\\', + '\\', '-', 'i', 's', 'o', 'e', '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', '\\', '-', '\\', '\\', 'd', '+', + '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', '{', '"', 'e', 'u', '-', 'i', 's', + 'o', 'e', '-', 'w', 'e', 's', 't', '-', '1', '"', ':', '{', '"', 'd', 'e', 's', 'c', 'r', 'i', 'p', + 't', 'i', 'o', 'n', '"', ':', '"', 'E', 'U', ' ', 'I', 'S', 'O', 'E', ' ', 'W', 'e', 's', 't', '"', + '}', '}', '}', ',', '{', '"', 'i', 'd', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'f', + '"', ',', '"', 'o', 'u', 't', 'p', 'u', 't', 's', '"', ':', '{', '"', 'd', 'n', 's', 'S', 'u', 'f', + 'f', 'i', 'x', '"', ':', '"', 'c', 's', 'p', '.', 'h', 'c', 'i', '.', 'i', 'c', '.', 'g', 'o', 'v', + '"', ',', '"', 'd', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', 'D', 'n', 's', 'S', 'u', 'f', 'f', 'i', + 'x', '"', ':', '"', 'c', 's', 'p', '.', 'h', 'c', 'i', '.', 'i', 'c', '.', 'g', 'o', 'v', '"', ',', + '"', 'i', 'm', 'p', 'l', 'i', 'c', 'i', 't', 'G', 'l', 'o', 'b', 'a', 'l', 'R', 'e', 'g', 'i', 'o', + 'n', '"', ':', '"', 'u', 's', '-', 'i', 's', 'o', 'f', '-', 's', 'o', 'u', 't', 'h', '-', '1', '"', + ',', '"', 'n', 'a', 'm', 'e', '"', ':', '"', 'a', 'w', 's', '-', 'i', 's', 'o', '-', 'f', '"', ',', + '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'D', 'u', 'a', 'l', 'S', 't', 'a', 'c', 'k', '"', ':', + 'f', 'a', 'l', 's', 'e', ',', '"', 's', 'u', 'p', 'p', 'o', 'r', 't', 's', 'F', 'I', 'P', 'S', '"', + ':', 't', 'r', 'u', 'e', '}', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 'R', 'e', 'g', 'e', 'x', '"', + ':', '"', '^', 'u', 's', '\\', '\\', '-', 'i', 's', 'o', 'f', '\\', '\\', '-', '\\', '\\', 'w', '+', '\\', + '\\', '-', '\\', '\\', 'd', '+', '$', '"', ',', '"', 'r', 'e', 'g', 'i', 'o', 'n', 's', '"', ':', '{', + '}', '}', ']', ',', '"', 'v', 'e', 'r', 's', 'i', 'o', 'n', '"', ':', '"', '1', '.', '1', '"', '}'}; const struct aws_byte_cursor aws_s3_endpoint_resolver_partitions = { - .len = 4150, + .len = 4200, .ptr = (uint8_t *) s_generated_array }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/source/s3_meta_request.c new/aws-c-s3-0.7.11/source/s3_meta_request.c --- old/aws-c-s3-0.7.9/source/s3_meta_request.c 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/source/s3_meta_request.c 2025-01-29 00:11:30.000000000 +0100 @@ -968,6 +968,7 @@ context->user_data = user_data; context->properties.host = aws_byte_cursor_from_string(meta_request->s3express_session_host); context->properties.region = signing_config.region; + context->properties.headers = aws_http_message_get_headers(meta_request->initial_request_message); if (signing_config.credentials) { context->original_credentials = signing_config.credentials; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/source/s3_request_messages.c new/aws-c-s3-0.7.11/source/s3_request_messages.c --- old/aws-c-s3-0.7.9/source/s3_request_messages.c 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/source/s3_request_messages.c 2025-01-29 00:11:30.000000000 +0100 @@ -27,6 +27,7 @@ AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-sha1"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-sha256"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("if-none-match"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-create-session-mode"), }; const size_t g_s3_create_multipart_upload_excluded_headers_count = @@ -62,6 +63,7 @@ AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-sha1"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-sha256"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("if-none-match"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-create-session-mode"), }; const size_t g_s3_upload_part_excluded_headers_count = AWS_ARRAY_SIZE(g_s3_upload_part_excluded_headers); @@ -96,6 +98,7 @@ AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-copy-source"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-copy-source-range"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-mp-object-size"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-create-session-mode"), }; const size_t g_s3_complete_multipart_upload_excluded_headers_count = @@ -131,6 +134,7 @@ AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-copy-source-range"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-sdk-checksum-algorithm"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-mp-object-size"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-create-session-mode"), }; const struct aws_byte_cursor g_s3_list_parts_excluded_headers[] = { @@ -162,6 +166,7 @@ AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-object-lock-legal-hold"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-copy-source"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-copy-source-range"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-create-session-mode"), }; const size_t g_s3_list_parts_excluded_headers_count = AWS_ARRAY_SIZE(g_s3_list_parts_excluded_headers); @@ -192,6 +197,7 @@ AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-object-lock-legal-hold"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-copy-source"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-copy-source-range"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-create-session-mode"), }; const size_t g_s3_list_parts_with_checksum_excluded_headers_count = @@ -227,8 +233,19 @@ AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-copy-source"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-copy-source-range"), AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("if-none-match"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-create-session-mode"), }; +const struct aws_byte_cursor g_s3_create_session_allowed_headers[] = { + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-create-session-mode"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-aws-kms-key-id"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-context"), + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-server-side-encryption-bucket-key-enabled"), +}; + +const size_t g_s3_create_session_allowed_headers_count = AWS_ARRAY_SIZE(g_s3_create_session_allowed_headers); + static const struct aws_byte_cursor s_x_amz_meta_prefix = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-meta-"); static const struct aws_byte_cursor s_checksum_type_header = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/source/s3express_credentials_provider.c new/aws-c-s3-0.7.11/source/s3express_credentials_provider.c --- old/aws-c-s3-0.7.9/source/s3express_credentials_provider.c 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/source/s3express_credentials_provider.c 2025-01-29 00:11:30.000000000 +0100 @@ -6,9 +6,11 @@ #include "aws/s3/private/s3_client_impl.h" #include "aws/s3/private/s3express_credentials_provider_impl.h" #include <aws/auth/credentials.h> +#include <aws/s3/private/s3_request_messages.h> #include <aws/s3/private/s3_util.h> #include <aws/s3/s3_client.h> +#include <aws/cal/hash.h> #include <aws/common/clock.h> #include <aws/common/lru_cache.h> #include <aws/common/uri.h> @@ -18,8 +20,6 @@ #include <aws/io/channel_bootstrap.h> #include <aws/io/event_loop.h> -#include <aws/cal/hash.h> - #include <inttypes.h> static struct aws_byte_cursor s_create_session_path_query = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("/?session="); @@ -48,6 +48,7 @@ /* The region and host of the session we are creating */ struct aws_string *region; struct aws_string *host; + struct aws_http_headers *headers; struct { /* Protected by the impl lock */ @@ -66,6 +67,7 @@ const struct aws_string *hash_key, const struct aws_string *region, const struct aws_string *host, + struct aws_http_headers *headers, struct aws_credentials *credentials) { struct aws_s3express_session *session = @@ -74,6 +76,10 @@ session->impl = provider->impl; session->hash_key = aws_string_new_from_string(provider->allocator, hash_key); session->host = aws_string_new_from_string(provider->allocator, host); + if (headers != NULL) { + aws_http_headers_acquire(headers); + session->headers = headers; + } if (region) { session->region = aws_string_new_from_string(provider->allocator, region); } @@ -94,6 +100,7 @@ aws_string_destroy(session->hash_key); aws_string_destroy(session->region); aws_string_destroy(session->host); + aws_http_headers_release(session->headers); aws_credentials_release(session->s3express_credentials); aws_mem_release(session->allocator, session); } @@ -368,6 +375,7 @@ session_creator->hash_key, session_creator->region, session_creator->host, + session_creator->headers, credentials); aws_cache_put(impl->synced_data.cache, session->hash_key, session); } @@ -388,14 +396,20 @@ static struct aws_http_message *s_create_session_request_new( struct aws_allocator *allocator, - struct aws_byte_cursor host_value) { + struct aws_byte_cursor host_value, + struct aws_http_headers *headers, + const struct aws_uri *endpoint_override) { struct aws_http_message *request = aws_http_message_new_request(allocator); + struct aws_byte_cursor host = host_value; + /* NOTE: Only for Tests. */ + if (endpoint_override != NULL) { + host = *aws_uri_authority(endpoint_override); + } struct aws_http_header host_header = { .name = g_host_header_name, - .value = host_value, + .value = host, }; - if (aws_http_message_add_header(request, host_header)) { goto error; } @@ -407,12 +421,37 @@ if (aws_http_message_add_header(request, user_agent_header)) { goto error; } + if (headers != NULL) { + for (size_t header_index = 0; header_index < g_s3_create_session_allowed_headers_count; ++header_index) { + struct aws_byte_cursor header_name = g_s3_create_session_allowed_headers[header_index]; + struct aws_byte_cursor header_value; + if (aws_http_headers_get(headers, header_name, &header_value) == AWS_OP_SUCCESS && header_value.len > 0) { + struct aws_http_header header = { + .name = header_name, + .value = header_value, + }; + if (aws_http_message_add_header(request, header)) { + goto error; + } + } + } + } if (aws_http_message_set_request_method(request, aws_http_method_get)) { goto error; } - if (aws_http_message_set_request_path(request, s_create_session_path_query)) { + struct aws_byte_cursor path_and_query = s_create_session_path_query; + if (endpoint_override != NULL) { + const struct aws_byte_cursor *override_path_query = aws_uri_path_and_query(endpoint_override); + /* NOTE: Only for Tests. + * path_and_query is at least 1 due to /. Only override if its length is more than 1 + */ + if (override_path_query->len > 1) { + path_and_query = *override_path_query; + } + } + if (aws_http_message_set_request_path(request, path_and_query)) { goto error; } return request; @@ -434,35 +473,49 @@ aws_string_destroy(session_creator->hash_key); aws_string_destroy(session_creator->region); aws_string_destroy(session_creator->host); + aws_http_headers_release(session_creator->headers); aws_byte_buf_clean_up(&session_creator->response_buf); aws_mem_release(session_creator->allocator, session_creator); return NULL; } -/** - * Encode the hash key to be [host_value][hash_of_credentials] - * hash_of_credentials is the sha256 of [access_key][secret_access_key] - **/ struct aws_string *aws_encode_s3express_hash_key_new( struct aws_allocator *allocator, const struct aws_credentials *original_credentials, - struct aws_byte_cursor host_value) { + struct aws_byte_cursor host_value, + struct aws_http_headers *headers) { - struct aws_byte_buf combine_key_buf; + struct aws_byte_buf combined_buf; /* 1. Combine access_key and secret_access_key into one buffer */ struct aws_byte_cursor access_key = aws_credentials_get_access_key_id(original_credentials); struct aws_byte_cursor secret_access_key = aws_credentials_get_secret_access_key(original_credentials); - aws_byte_buf_init(&combine_key_buf, allocator, access_key.len + secret_access_key.len); - aws_byte_buf_write_from_whole_cursor(&combine_key_buf, access_key); - aws_byte_buf_write_from_whole_cursor(&combine_key_buf, secret_access_key); + aws_byte_buf_init(&combined_buf, allocator, access_key.len + secret_access_key.len); + aws_byte_buf_write_from_whole_cursor(&combined_buf, access_key); + aws_byte_buf_write_from_whole_cursor(&combined_buf, secret_access_key); + + /* Write the allowed headers into hash */ + if (headers != NULL) { + struct aws_byte_cursor collon = aws_byte_cursor_from_c_str(":"); + struct aws_byte_cursor comma = aws_byte_cursor_from_c_str(","); + for (size_t header_index = 0; header_index < g_s3_create_session_allowed_headers_count; ++header_index) { + struct aws_byte_cursor header_name = g_s3_create_session_allowed_headers[header_index]; + struct aws_byte_cursor header_value; + if (aws_http_headers_get(headers, header_name, &header_value) == AWS_OP_SUCCESS && header_value.len > 0) { + aws_byte_buf_append_dynamic(&combined_buf, &comma); + aws_byte_buf_append_dynamic(&combined_buf, &header_name); + aws_byte_buf_append_dynamic(&combined_buf, &collon); + aws_byte_buf_append_dynamic(&combined_buf, &header_value); + } + } + } /* 2. Get sha256 digest from the combined key */ - struct aws_byte_cursor combine_key = aws_byte_cursor_from_buf(&combine_key_buf); + struct aws_byte_cursor combined_cursor = aws_byte_cursor_from_buf(&combined_buf); struct aws_byte_buf digest_buf; aws_byte_buf_init(&digest_buf, allocator, AWS_SHA256_LEN); - aws_sha256_compute(allocator, &combine_key, &digest_buf, 0); + aws_sha256_compute(allocator, &combined_cursor, &digest_buf, 0); /* 3. Encode the result to be [host_value][hash_of_credentials] */ struct aws_byte_buf result_buffer; @@ -473,7 +526,7 @@ /* Clean up */ aws_byte_buf_clean_up(&result_buffer); - aws_byte_buf_clean_up(&combine_key_buf); + aws_byte_buf_clean_up(&combined_buf); aws_byte_buf_clean_up(&digest_buf); return result; @@ -485,14 +538,14 @@ const struct aws_credentials_properties_s3express *s3express_properties) { struct aws_s3express_credentials_provider_impl *impl = provider->impl; - struct aws_http_message *request = s_create_session_request_new(provider->allocator, s3express_properties->host); + struct aws_http_message *request = s_create_session_request_new( + provider->allocator, + s3express_properties->host, + s3express_properties->headers, + impl->mock_test.endpoint_override); if (!request) { return NULL; } - if (impl->mock_test.endpoint_override) { - /* NOTE: ONLY FOR TESTS. Erase the host header for endpoint override. */ - aws_http_headers_erase(aws_http_message_get_headers(request), g_host_header_name); - } struct aws_s3express_session_creator *session_creator = aws_mem_calloc(provider->allocator, 1, sizeof(struct aws_s3express_session_creator)); @@ -500,6 +553,10 @@ session_creator->provider = provider; session_creator->host = aws_string_new_from_cursor(session_creator->allocator, &s3express_properties->host); session_creator->region = aws_string_new_from_cursor(session_creator->allocator, &s3express_properties->region); + if (s3express_properties->headers != NULL) { + aws_http_headers_acquire(s3express_properties->headers); + session_creator->headers = s3express_properties->headers; + } struct aws_signing_config_aws s3express_signing_config = { .credentials = original_credentials, @@ -514,8 +571,6 @@ .body_callback = s_on_incoming_body_fn, .finish_callback = s_on_request_finished, .signing_config = &s3express_signing_config, - /* Override endpoint only for tests. */ - .endpoint = impl->mock_test.endpoint_override ? impl->mock_test.endpoint_override : NULL, .user_data = session_creator, .operation_name = aws_byte_cursor_from_c_str("CreateSession"), }; @@ -556,8 +611,8 @@ uint64_t current_stamp = UINT64_MAX; aws_sys_clock_get_ticks(¤t_stamp); - struct aws_string *hash_key = - aws_encode_s3express_hash_key_new(provider->allocator, original_credentials, s3express_properties->host); + struct aws_string *hash_key = aws_encode_s3express_hash_key_new( + provider->allocator, original_credentials, s3express_properties->host, s3express_properties->headers); uint64_t now_seconds = aws_timestamp_convert(current_stamp, AWS_TIMESTAMP_NANOS, AWS_TIMESTAMP_SECS, NULL); s_credentials_provider_s3express_impl_lock_synced_data(impl); @@ -764,7 +819,8 @@ struct aws_string *current_creds_hash = aws_encode_s3express_hash_key_new( provider->allocator, current_original_credentials, - aws_byte_cursor_from_string(session->host)); + aws_byte_cursor_from_string(session->host), + session->headers); bool creds_match = aws_string_eq(current_creds_hash, hash_key); aws_string_destroy(current_creds_hash); if (!creds_match) { @@ -784,6 +840,7 @@ struct aws_credentials_properties_s3express s3express_properties = { .host = aws_byte_cursor_from_string(session->host), + .headers = session->headers, }; if (session->region) { s3express_properties.region = aws_byte_cursor_from_string(session->region); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/tests/CMakeLists.txt new/aws-c-s3-0.7.11/tests/CMakeLists.txt --- old/aws-c-s3-0.7.9/tests/CMakeLists.txt 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/tests/CMakeLists.txt 2025-01-29 00:11:30.000000000 +0100 @@ -351,6 +351,7 @@ add_net_test_case(s3express_provider_background_refresh_mock_server) add_net_test_case(s3express_provider_background_refresh_remove_inactive_creds_mock_server) add_net_test_case(s3express_provider_stress_mock_server) + add_net_test_case(s3express_provider_get_credentials_sse_headers_mock_server) add_net_test_case(s3express_client_sanity_test_mock_server) add_net_test_case(s3express_client_sanity_override_test_mock_server) @@ -369,6 +370,7 @@ add_net_test_case(s3express_client_get_object_create_session_error) add_net_test_case(s3express_client_copy_object) add_net_test_case(s3express_client_copy_object_multipart) +add_net_test_case(s3express_hash_key_test) add_net_test_case(meta_request_auto_ranged_get_new_error_handling) add_net_test_case(meta_request_auto_ranged_put_new_error_handling) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/tests/mock_s3_server/CompleteMultipartUpload/sse_kms.json new/aws-c-s3-0.7.11/tests/mock_s3_server/CompleteMultipartUpload/sse_kms.json --- old/aws-c-s3-0.7.9/tests/mock_s3_server/CompleteMultipartUpload/sse_kms.json 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-c-s3-0.7.11/tests/mock_s3_server/CompleteMultipartUpload/sse_kms.json 2025-01-29 00:11:30.000000000 +0100 @@ -0,0 +1,14 @@ +{ + "status": 200, + "headers": {"Connection": "close", + "x-amz-server-side-encryption": "aws:kms"}, + "body": [ + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", + "<CompleteMultipartUploadResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">", + "<Location>http://default.s3.us-west-2.amazonaws.com/default</Location>", + "<Bucket>default</Bucket>", + "<Key>default</Key>", + "<ETag>\"3858f62230ac3c915f300c664312c11f-9\"</ETag>", + "</CompleteMultipartUploadResult>" + ] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/tests/mock_s3_server/CreateSession/sse_kms.json new/aws-c-s3-0.7.11/tests/mock_s3_server/CreateSession/sse_kms.json --- old/aws-c-s3-0.7.9/tests/mock_s3_server/CreateSession/sse_kms.json 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-c-s3-0.7.11/tests/mock_s3_server/CreateSession/sse_kms.json 2025-01-29 00:11:30.000000000 +0100 @@ -0,0 +1,21 @@ +{ + "status": 200, + "headers": { + "x-amz-request-id": "12345", + "x-amz-server-side-encryption": "aws:kms" + }, + "request_headers": { + "x-amz-server-side-encryption": "aws:kms" + }, + "body": [ + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", + "<CreateSessionResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">", + "<Credentials>", + "<SessionToken>sessionToken</SessionToken>", + "<SecretAccessKey>secretKey</SecretAccessKey>", + "<AccessKeyId>accessKeyId</AccessKeyId>", + "<Expiration>2023-06-26T17:33:30Z</Expiration>", + "</Credentials>", + "</CreateSessionResult>" + ] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/tests/mock_s3_server/README.md new/aws-c-s3-0.7.11/tests/mock_s3_server/README.md --- old/aws-c-s3-0.7.9/tests/mock_s3_server/README.md 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/tests/mock_s3_server/README.md 2025-01-29 00:11:30.000000000 +0100 @@ -25,6 +25,7 @@ { "status": 200, "headers": {"Connection": "close"}, + "request_headers:" {"HeaderA": "ValueA"} "body": [ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "", @@ -40,6 +41,7 @@ Where you can define the expected response status, header and response body. If the {Key}.json is not found from file system, it will load the `default.json`. +The server validates that all specified headers in the "request_headers" field are present in the incoming request. If any required header is missing, the request will fail. These headers will not be part of the Response headers. If the "delay" field is present, the response will be delayed by X seconds. ### GetObject Response diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/tests/mock_s3_server/mock_s3_server.py new/aws-c-s3-0.7.11/tests/mock_s3_server/mock_s3_server.py --- old/aws-c-s3-0.7.9/tests/mock_s3_server/mock_s3_server.py 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/tests/mock_s3_server/mock_s3_server.py 2025-01-29 00:11:30.000000000 +0100 @@ -8,7 +8,7 @@ from itertools import count from urllib.parse import parse_qs, urlparse import os -from typing import Optional +from typing import Optional, List, Tuple from enum import Enum import trio @@ -56,6 +56,7 @@ json_path: str = None throttle: bool = False force_retry: bool = False + request_headers: Optional[List[Tuple[bytes, bytes]]] = None def _resolve_file_path(self, wrapper, request_type): global SHOULD_THROTTLE @@ -85,6 +86,16 @@ ".\n generate_body_size: ", self.generate_body_size) with open(self.json_path, 'r') as f: data = json.load(f) + headers = wrapper.basic_headers() + + # If request_headers is present, validate that the request contains all required headers + if 'request_headers' in data: + for header in data['request_headers']: + header_bytes = header.encode('utf-8') + if not any(header_bytes == h[0] for h in self.request_headers): + response = Response(status_code=500, delay=0, headers=headers, + data=json.dumps({'error': f"Missing required header: {header}"}), chunked=chunked, head_request=head_request) + return response # if response has delay, then sleep before sending it delay = data.get('delay', 0) @@ -95,7 +106,6 @@ else: body = "\n".join(data['body']) - headers = wrapper.basic_headers() content_length_set = False for header in data['headers'].items(): headers.append((header[0], str(header[1]))) @@ -424,8 +434,8 @@ else: RETRY_REQUEST_COUNT = 0 - if (parsed_path.path == "/get_object_invalid_response_missing_content_range" or - parsed_path.path == "/get_object_invalid_response_missing_etags" or + if (parsed_path.path == "/get_object_invalid_response_missing_content_range" or + parsed_path.path == "/get_object_invalid_response_missing_etags" or parsed_path.path == "/get_object_long_error"): # Don't generate the body for those requests return response_config @@ -499,6 +509,7 @@ if response_config is None: response_config = ResponseConfig(parsed_path.path) + response_config.request_headers = request.headers response = response_config.resolve_response( wrapper, request_type, head_request=method == "HEAD") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/tests/s3_mock_server_s3express_provider_test.c new/aws-c-s3-0.7.11/tests/s3_mock_server_s3express_provider_test.c --- old/aws-c-s3-0.7.9/tests/s3_mock_server_s3express_provider_test.c 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/tests/s3_mock_server_s3express_provider_test.c 2025-01-29 00:11:30.000000000 +0100 @@ -45,6 +45,8 @@ struct aws_uri mock_server; struct aws_s3_client *client; + aws_simple_completion_callback *on_provider_shutdown_callback; + void *shutdown_user_data; int error_code; }; @@ -252,6 +254,83 @@ return AWS_OP_SUCCESS; } +struct aws_s3express_credentials_provider *s_s3express_credentials_provider_factory( + struct aws_allocator *allocator, + struct aws_s3_client *client, + aws_simple_completion_callback on_provider_shutdown_callback, + void *shutdown_user_data, + void *factory_user_data) { + + (void)shutdown_user_data; + (void)factory_user_data; + s_s3express_tester.on_provider_shutdown_callback = on_provider_shutdown_callback; + s_s3express_tester.shutdown_user_data = shutdown_user_data; + struct aws_s3express_credentials_provider_default_options options = { + .client = client, + .mock_test.bg_refresh_secs_override = s_bg_refresh_secs_override, + }; + struct aws_s3express_credentials_provider *provider = + aws_s3express_credentials_provider_new_default(allocator, &options); + struct aws_s3express_credentials_provider_impl *impl = provider->impl; + impl->mock_test.endpoint_override = &s_s3express_tester.mock_server; + impl->mock_test.s3express_session_is_valid_override = s_s3express_session_always_true; + + return provider; +} + +TEST_CASE(s3express_provider_get_credentials_sse_headers_mock_server) { + (void)ctx; + + struct aws_s3_tester tester; + ASSERT_SUCCESS(aws_s3_tester_init(allocator, &tester)); + ASSERT_SUCCESS(s_s3express_tester_init(allocator)); + + struct aws_s3_tester_client_options client_options = { + .part_size = MB_TO_BYTES(5), + .tls_usage = AWS_S3_TLS_DISABLED, + .s3express_provider_override_factory = s_s3express_credentials_provider_factory, + .factory_user_data = NULL, + }; + + struct aws_s3_client *client = NULL; + ASSERT_SUCCESS(aws_s3_tester_client_new(&tester, &client_options, &client)); + + struct aws_byte_cursor object_path = aws_byte_cursor_from_c_str("/sse_kms"); + char uri[1024] = {'\0'}; + snprintf(uri, sizeof(uri), "" PRInSTR "sse_kms?session=", AWS_BYTE_CURSOR_PRI(g_mock_server_uri)); + struct aws_byte_cursor uri_cursor = aws_byte_cursor_from_c_str(uri); + aws_uri_clean_up(&s_s3express_tester.mock_server); + ASSERT_SUCCESS(aws_uri_init_parse(&s_s3express_tester.mock_server, allocator, &uri_cursor)); + + struct aws_s3_tester_meta_request_options put_options = { + .allocator = allocator, + .meta_request_type = AWS_S3_META_REQUEST_TYPE_PUT_OBJECT, + .client = client, + .checksum_algorithm = AWS_SCA_CRC32, + .validate_get_response_checksum = false, + .put_options = + { + .object_size_mb = 10, + .object_path_override = object_path, + }, + .mock_server = true, + .use_s3express_signing = true, + .sse_type = AWS_S3_TESTER_SSE_KMS, + }; + struct aws_s3_meta_request_test_results out_results; + aws_s3_meta_request_test_results_init(&out_results, allocator); + ASSERT_SUCCESS(aws_s3_tester_send_meta_request_with_options(&tester, &put_options, &out_results)); + aws_s3_meta_request_test_results_clean_up(&out_results); + aws_s3_client_release(client); + + /* Call the provider shutdown callback to finish cleanup */ + s_s3express_tester.on_provider_shutdown_callback(s_s3express_tester.shutdown_user_data); + ASSERT_SUCCESS(s_s3express_tester_cleanup()); + aws_s3_tester_clean_up(&tester); + + return AWS_OP_SUCCESS; +} + TEST_CASE(s3express_provider_get_credentials_multiple_mock_server) { (void)ctx; @@ -445,8 +524,8 @@ AWS_CONTAINER_OF(node, struct aws_linked_hash_table_node, node); node = aws_linked_list_next(node); struct aws_s3express_session *session = table_node->value; - struct aws_string *hash_key = - aws_encode_s3express_hash_key_new(s_s3express_tester.allocator, original_credentials, host_value); + struct aws_string *hash_key = aws_encode_s3express_hash_key_new( + s_s3express_tester.allocator, original_credentials, host_value, session->headers); if (aws_string_eq(session->hash_key, hash_key)) { aws_string_destroy(hash_key); aws_mutex_unlock(&impl->synced_data.lock); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/tests/s3_s3express_client_test.c new/aws-c-s3-0.7.11/tests/s3_s3express_client_test.c --- old/aws-c-s3-0.7.9/tests/s3_s3express_client_test.c 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/tests/s3_s3express_client_test.c 2025-01-29 00:11:30.000000000 +0100 @@ -10,6 +10,7 @@ #include "s3_tester.h" #include <aws/common/atomics.h> #include <aws/common/clock.h> +#include <aws/common/encoding.h> #include <aws/common/lru_cache.h> #include <aws/io/stream.h> #include <aws/io/uri.h> @@ -714,3 +715,60 @@ aws_s3_tester_clean_up(&tester); return AWS_OP_SUCCESS; } + +/** + * Test hash of the express cache key + */ +TEST_CASE(s3express_hash_key_test) { + (void)ctx; + aws_s3_library_init(allocator); + + struct aws_string *access_key = aws_string_new_from_c_str(allocator, "AccessKey"); + struct aws_string *secret_access_key = aws_string_new_from_c_str(allocator, "SecretAccessKey"); + struct aws_http_headers *headers = aws_http_headers_new(allocator); + aws_http_headers_add( + headers, aws_byte_cursor_from_c_str("x-amz-create-session-mode"), aws_byte_cursor_from_c_str("ReadOnly")); + aws_http_headers_add( + headers, aws_byte_cursor_from_c_str("x-amz-server-side-encryption"), aws_byte_cursor_from_c_str("aws:kms")); + aws_http_headers_add( + headers, + aws_byte_cursor_from_c_str("x-amz-server-side-encryption-aws-kms-key-id"), + aws_byte_cursor_from_c_str("kms-key-id")); + aws_http_headers_add( + headers, + aws_byte_cursor_from_c_str("x-amz-server-side-encryption-context"), + aws_byte_cursor_from_c_str("context")); + aws_http_headers_add( + headers, + aws_byte_cursor_from_c_str("x-amz-server-side-encryption-bucket-key-enabled"), + aws_byte_cursor_from_c_str("true")); + aws_http_headers_add( + headers, + aws_byte_cursor_from_c_str("header-not-in-allow-list"), + aws_byte_cursor_from_c_str("should-be-ignored")); + + struct aws_credentials *creds = + aws_credentials_new_from_string(allocator, access_key, secret_access_key, NULL, UINT64_MAX); + + struct aws_string *hash_key = + aws_encode_s3express_hash_key_new(allocator, creds, aws_byte_cursor_from_c_str(""), headers); + struct aws_byte_cursor hash_cursor = aws_byte_cursor_from_string(hash_key); + + struct aws_byte_buf encoded_buf; + aws_byte_buf_init(&encoded_buf, allocator, 200); + aws_hex_encode_append_dynamic(&hash_cursor, &encoded_buf); + + char *expected_encoded_key = "cabfefee4365e075646ba8928ed9f757481d1062ffcb0a3afe5b9c428dd45800"; + ASSERT_BIN_ARRAYS_EQUALS(expected_encoded_key, strlen(expected_encoded_key), encoded_buf.buffer, encoded_buf.len); + + aws_byte_buf_clean_up(&encoded_buf); + aws_string_destroy(access_key); + aws_string_destroy(secret_access_key); + aws_credentials_release(creds); + aws_string_destroy(hash_key); + aws_http_headers_release(headers); + + aws_s3_library_clean_up(); + + return AWS_OP_SUCCESS; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/tests/s3_tester.c new/aws-c-s3-0.7.11/tests/s3_tester.c --- old/aws-c-s3-0.7.9/tests/s3_tester.c 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/tests/s3_tester.c 2025-01-29 00:11:30.000000000 +0100 @@ -1387,6 +1387,9 @@ struct aws_s3_client_config client_config = { .part_size = options->part_size, .max_part_size = options->max_part_size, + .s3express_provider_override_factory = options->s3express_provider_override_factory, + .factory_user_data = options->factory_user_data, + .enable_s3express = options->s3express_provider_override_factory != NULL, }; struct aws_http_proxy_options proxy_options = { .connection_type = AWS_HPCT_HTTP_FORWARD, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-c-s3-0.7.9/tests/s3_tester.h new/aws-c-s3-0.7.11/tests/s3_tester.h --- old/aws-c-s3-0.7.9/tests/s3_tester.h 2025-01-14 19:51:03.000000000 +0100 +++ new/aws-c-s3-0.7.11/tests/s3_tester.h 2025-01-29 00:11:30.000000000 +0100 @@ -140,6 +140,8 @@ size_t num_network_interface_names; uint32_t setup_region : 1; uint32_t use_proxy : 1; + aws_s3express_provider_factory_fn *s3express_provider_override_factory; + void *factory_user_data; }; /* should really break this up to a client setup, and a meta_request sending */