diff --git a/generated/src/aws-cpp-sdk-s3-crt/include/aws/s3-crt/S3CrtClient.h b/generated/src/aws-cpp-sdk-s3-crt/include/aws/s3-crt/S3CrtClient.h index 817b000d1b0..a8efe7bcec8 100644 --- a/generated/src/aws-cpp-sdk-s3-crt/include/aws/s3-crt/S3CrtClient.h +++ b/generated/src/aws-cpp-sdk-s3-crt/include/aws/s3-crt/S3CrtClient.h @@ -5614,9 +5614,9 @@ namespace Aws const Aws::Http::URI &uri, Aws::Http::HttpMethod method) const; S3CrtClientConfiguration m_clientConfiguration; std::shared_ptr m_executor; - struct aws_s3_client* m_s3CrtClient; - struct aws_signing_config_aws m_s3CrtSigningConfig; - struct CrtClientShutdownCallbackDataWrapper m_wrappedData; + struct aws_s3_client* m_s3CrtClient = {}; + struct aws_signing_config_aws m_s3CrtSigningConfig = {}; + struct CrtClientShutdownCallbackDataWrapper m_wrappedData = {}; std::shared_ptr m_clientShutdownSem; Aws::String m_userAgent; std::shared_ptr m_credProvider; diff --git a/generated/src/aws-cpp-sdk-s3-crt/source/S3CrtClient.cpp b/generated/src/aws-cpp-sdk-s3-crt/source/S3CrtClient.cpp index c1915ea3625..315281714b2 100644 --- a/generated/src/aws-cpp-sdk-s3-crt/source/S3CrtClient.cpp +++ b/generated/src/aws-cpp-sdk-s3-crt/source/S3CrtClient.cpp @@ -180,7 +180,10 @@ S3CrtClient::S3CrtClient(const std::shared_ptr& credenti S3CrtClient::~S3CrtClient() { aws_s3_client_release(m_s3CrtClient); - m_clientShutdownSem->WaitOne(); // Wait aws_s3_client shutdown + if(m_clientShutdownSem) + { + m_clientShutdownSem->WaitOne(); // Wait aws_s3_client shutdown + } ShutdownSdkClient(this, -1); } @@ -261,20 +264,48 @@ void S3CrtClient::init(const S3Crt::ClientConfiguration& config, const std::shar static const size_t DEFAULT_PART_SIZE = 5 * 1024 * 1024; // 5MB s3CrtConfig.part_size = config.partSize < DEFAULT_PART_SIZE ? DEFAULT_PART_SIZE : config.partSize; - Aws::Crt::Io::TlsConnectionOptions* tlsConnectionOptions = config.tlsConnectionOptions ? config.tlsConnectionOptions.get() : Aws::GetDefaultTlsConnectionOptions(); - aws_tls_connection_options tlsOptions; - AWS_ZERO_STRUCT(tlsOptions); - if (tlsConnectionOptions) + Aws::UniquePtr pTlsConnectionOptions; + if (config.tlsConnectionOptions) + { + pTlsConnectionOptions = Aws::MakeUnique(ALLOCATION_TAG, *config.tlsConnectionOptions); + if (!config.caPath.empty() || !config.caFile.empty()) + { + AWS_LOGSTREAM_WARN(ALLOCATION_TAG, "caPath or caFile on client configuration are ignored in case of user-configured TlsConnectionOptions provided"); + } + } + + if (!pTlsConnectionOptions) + { + Aws::Crt::Io::TlsContextOptions crtTlsContextOptions = Aws::Crt::Io::TlsContextOptions::InitDefaultClient(); + if (!config.caPath.empty() || !config.caFile.empty()) + { + const char *caPath = config.caPath.empty() ? nullptr : config.caPath.c_str(); + const char *caFile = config.caFile.empty() ? nullptr : config.caFile.c_str(); + if(!crtTlsContextOptions.OverrideDefaultTrustStore(caPath, caFile)) { + AWS_LOGSTREAM_FATAL(ALLOCATION_TAG, "Failed to initialize S3 Crt client: failed to set caPath/caFile"); + m_isInitialized = false; + return; + } + } + Aws::Crt::Io::TlsContext crtTlsContext(crtTlsContextOptions, Aws::Crt::Io::TlsMode::CLIENT); + pTlsConnectionOptions = Aws::MakeUnique(ALLOCATION_TAG, crtTlsContext.NewConnectionOptions()); + } + + aws_tls_connection_options nonConstTlsOptions; + AWS_ZERO_STRUCT(nonConstTlsOptions); + if (pTlsConnectionOptions) { - aws_tls_connection_options_copy(&tlsOptions, tlsConnectionOptions->GetUnderlyingHandle()); ResolveEndpointOutcome endpointOutcome = m_endpointProvider->ResolveEndpoint({}); if (!endpointOutcome.IsSuccess()) { - AWS_LOGSTREAM_ERROR(ALLOCATION_TAG, "Failed to resolve base URI: " << endpointOutcome.GetError().GetMessage()); + AWS_LOGSTREAM_FATAL(ALLOCATION_TAG, "Failed to initialize S3 Crt client: failed to resolve base URI: " << endpointOutcome.GetError().GetMessage()); + m_isInitialized = false; return; } - tlsOptions.server_name = aws_string_new_from_c_str(Aws::get_aws_allocator(), endpointOutcome.GetResult().GetURL().c_str()); - s3CrtConfig.tls_connection_options = &tlsOptions; + Aws::Crt::ByteCursor serverName = Aws::Crt::ByteCursorFromCString(endpointOutcome.GetResult().GetURI().GetAuthority().c_str()); + pTlsConnectionOptions->SetServerName(serverName); + aws_tls_connection_options_copy(&nonConstTlsOptions, pTlsConnectionOptions->GetUnderlyingHandle()); + s3CrtConfig.tls_connection_options = &nonConstTlsOptions; } else { @@ -291,13 +322,14 @@ void S3CrtClient::init(const S3Crt::ClientConfiguration& config, const std::shar s3CrtConfig.shutdown_callback_user_data = static_cast(&m_wrappedData); m_s3CrtClient = aws_s3_client_new(Aws::get_aws_allocator(), &s3CrtConfig); - if (tlsConnectionOptions) + if (pTlsConnectionOptions) { - aws_tls_connection_options_clean_up(&tlsOptions); + aws_tls_connection_options_clean_up(&nonConstTlsOptions); } if (!m_s3CrtClient) { AWS_LOGSTREAM_FATAL(ALLOCATION_TAG, "Failed to allocate aws_s3_client instance, abort."); + m_isInitialized = false; } } diff --git a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp index d08b8217035..c827a7b5e5c 100644 --- a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp @@ -1355,4 +1355,23 @@ namespace ASSERT_FALSE(outcome.IsSuccess()); ASSERT_EQ(outcome.GetError().GetErrorType(), Aws::S3Crt::S3CrtErrors::NETWORK_CONNECTION); } + + TEST_F(BucketAndObjectOperationTest, MissingCertificate) { + Aws::S3Crt::ClientConfiguration s3ClientConfig; + s3ClientConfig.region = Aws::Region::US_EAST_1; + s3ClientConfig.caFile = "/some-non-existing-certificate/cert.crt"; + s3ClientConfig.verifySSL = true; + + S3CrtClient crtClient = S3CrtClient(Aws::Auth::AWSCredentials{"", ""}, + s3ClientConfig, + Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never); + + GetObjectRequest getObjectRequest; + getObjectRequest.SetBucket("aws-sdk-cpp-docs"); + getObjectRequest.SetKey("cpp/api/LATEST/index.html"); + + auto result = crtClient.GetObject(getObjectRequest); + ASSERT_FALSE(result.IsSuccess()); + ASSERT_EQ((Aws::Client::CoreErrors) result.GetError().GetErrorType(), Aws::Client::CoreErrors::NOT_INITIALIZED); + } } diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ClientHeader.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ClientHeader.vm index 26915e09ca1..bd385694449 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ClientHeader.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ClientHeader.vm @@ -250,9 +250,9 @@ namespace ${rootNamespace} #end std::shared_ptr m_executor; #if($serviceNamespace == "S3Crt") - struct aws_s3_client* m_s3CrtClient; - struct aws_signing_config_aws m_s3CrtSigningConfig; - struct CrtClientShutdownCallbackDataWrapper m_wrappedData; + struct aws_s3_client* m_s3CrtClient = {}; + struct aws_signing_config_aws m_s3CrtSigningConfig = {}; + struct CrtClientShutdownCallbackDataWrapper m_wrappedData = {}; std::shared_ptr m_clientShutdownSem; Aws::String m_userAgent; std::shared_ptr m_credProvider; diff --git a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/s3-crt/S3CrtServiceClientSourceInit.vm b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/s3-crt/S3CrtServiceClientSourceInit.vm index dd2c54c7adc..3c20f81e8e2 100644 --- a/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/s3-crt/S3CrtServiceClientSourceInit.vm +++ b/tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/s3-crt/S3CrtServiceClientSourceInit.vm @@ -170,7 +170,10 @@ ${className}::~${className}() { #if($serviceNamespace == "S3Crt") aws_s3_client_release(m_s3CrtClient); - m_clientShutdownSem->WaitOne(); // Wait aws_s3_client shutdown + if(m_clientShutdownSem) + { + m_clientShutdownSem->WaitOne(); // Wait aws_s3_client shutdown + } #end ShutdownSdkClient(this, -1); } @@ -304,20 +307,48 @@ void ${className}::init(const ${clientConfigurationNamespace}::ClientConfigurati static const size_t DEFAULT_PART_SIZE = 5 * 1024 * 1024; // 5MB s3CrtConfig.part_size = config.partSize < DEFAULT_PART_SIZE ? DEFAULT_PART_SIZE : config.partSize; - Aws::Crt::Io::TlsConnectionOptions* tlsConnectionOptions = config.tlsConnectionOptions ? config.tlsConnectionOptions.get() : Aws::GetDefaultTlsConnectionOptions(); - aws_tls_connection_options tlsOptions; - AWS_ZERO_STRUCT(tlsOptions); - if (tlsConnectionOptions) + Aws::UniquePtr pTlsConnectionOptions; + if (config.tlsConnectionOptions) + { + pTlsConnectionOptions = Aws::MakeUnique(ALLOCATION_TAG, *config.tlsConnectionOptions); + if (!config.caPath.empty() || !config.caFile.empty()) + { + AWS_LOGSTREAM_WARN(ALLOCATION_TAG, "caPath or caFile on client configuration are ignored in case of user-configured TlsConnectionOptions provided"); + } + } + + if (!pTlsConnectionOptions) + { + Aws::Crt::Io::TlsContextOptions crtTlsContextOptions = Aws::Crt::Io::TlsContextOptions::InitDefaultClient(); + if (!config.caPath.empty() || !config.caFile.empty()) + { + const char *caPath = config.caPath.empty() ? nullptr : config.caPath.c_str(); + const char *caFile = config.caFile.empty() ? nullptr : config.caFile.c_str(); + if(!crtTlsContextOptions.OverrideDefaultTrustStore(caPath, caFile)) { + AWS_LOGSTREAM_FATAL(ALLOCATION_TAG, "Failed to initialize S3 Crt client: failed to set caPath/caFile"); + m_isInitialized = false; + return; + } + } + Aws::Crt::Io::TlsContext crtTlsContext(crtTlsContextOptions, Aws::Crt::Io::TlsMode::CLIENT); + pTlsConnectionOptions = Aws::MakeUnique(ALLOCATION_TAG, crtTlsContext.NewConnectionOptions()); + } + + aws_tls_connection_options nonConstTlsOptions; + AWS_ZERO_STRUCT(nonConstTlsOptions); + if (pTlsConnectionOptions) { - aws_tls_connection_options_copy(&tlsOptions, tlsConnectionOptions->GetUnderlyingHandle()); ResolveEndpointOutcome endpointOutcome = m_endpointProvider->ResolveEndpoint({}); if (!endpointOutcome.IsSuccess()) { - AWS_LOGSTREAM_ERROR(ALLOCATION_TAG, "Failed to resolve base URI: " << endpointOutcome.GetError().GetMessage()); + AWS_LOGSTREAM_FATAL(ALLOCATION_TAG, "Failed to initialize S3 Crt client: failed to resolve base URI: " << endpointOutcome.GetError().GetMessage()); + m_isInitialized = false; return; } - tlsOptions.server_name = aws_string_new_from_c_str(Aws::get_aws_allocator(), endpointOutcome.GetResult().GetURL().c_str()); - s3CrtConfig.tls_connection_options = &tlsOptions; + Aws::Crt::ByteCursor serverName = Aws::Crt::ByteCursorFromCString(endpointOutcome.GetResult().GetURI().GetAuthority().c_str()); + pTlsConnectionOptions->SetServerName(serverName); + aws_tls_connection_options_copy(&nonConstTlsOptions, pTlsConnectionOptions->GetUnderlyingHandle()); + s3CrtConfig.tls_connection_options = &nonConstTlsOptions; } else { @@ -334,13 +365,14 @@ void ${className}::init(const ${clientConfigurationNamespace}::ClientConfigurati s3CrtConfig.shutdown_callback_user_data = static_cast(&m_wrappedData); m_s3CrtClient = aws_s3_client_new(Aws::get_aws_allocator(), &s3CrtConfig); - if (tlsConnectionOptions) + if (pTlsConnectionOptions) { - aws_tls_connection_options_clean_up(&tlsOptions); + aws_tls_connection_options_clean_up(&nonConstTlsOptions); } if (!m_s3CrtClient) { AWS_LOGSTREAM_FATAL(ALLOCATION_TAG, "Failed to allocate aws_s3_client instance, abort."); + m_isInitialized = false; } #end }