diff --git a/.github/docker-images/base-images/device-client/amazonlinux/Dockerfile b/.github/docker-images/base-images/device-client/amazonlinux/Dockerfile index c991087ef..24a0a9b52 100644 --- a/.github/docker-images/base-images/device-client/amazonlinux/Dockerfile +++ b/.github/docker-images/base-images/device-client/amazonlinux/Dockerfile @@ -89,7 +89,7 @@ RUN mkdir sdk-cpp-workspace \ && cd sdk-cpp-workspace \ && git clone https://github.com/aws/aws-iot-device-sdk-cpp-v2.git \ && cd aws-iot-device-sdk-cpp-v2 \ - && git checkout ac3ba3774b031dde1b988e698880d6064d53b9d9 \ + && git checkout 74c8b683ebe5b1cbf484f6acaa281f56aaa63948 \ && git submodule update --init --recursive \ && cd .. \ && mkdir aws-iot-device-sdk-cpp-v2-build \ diff --git a/.github/docker-images/base-images/device-client/ubi8/Dockerfile b/.github/docker-images/base-images/device-client/ubi8/Dockerfile index a91e940b9..3cbb3746c 100644 --- a/.github/docker-images/base-images/device-client/ubi8/Dockerfile +++ b/.github/docker-images/base-images/device-client/ubi8/Dockerfile @@ -102,7 +102,7 @@ RUN mkdir sdk-cpp-workspace \ && cd sdk-cpp-workspace \ && git clone https://github.com/aws/aws-iot-device-sdk-cpp-v2.git \ && cd aws-iot-device-sdk-cpp-v2 \ - && git checkout ac3ba3774b031dde1b988e698880d6064d53b9d9 \ + && git checkout 74c8b683ebe5b1cbf484f6acaa281f56aaa63948 \ && git submodule update --init --recursive \ && cd .. \ && mkdir aws-iot-device-sdk-cpp-v2-build \ diff --git a/.github/docker-images/base-images/device-client/ubuntu/Dockerfile b/.github/docker-images/base-images/device-client/ubuntu/Dockerfile index a0e371f59..b01eb9ca2 100644 --- a/.github/docker-images/base-images/device-client/ubuntu/Dockerfile +++ b/.github/docker-images/base-images/device-client/ubuntu/Dockerfile @@ -86,7 +86,7 @@ RUN mkdir sdk-cpp-workspace \ && cd sdk-cpp-workspace \ && git clone https://github.com/aws/aws-iot-device-sdk-cpp-v2.git \ && cd aws-iot-device-sdk-cpp-v2 \ - && git checkout ac3ba3774b031dde1b988e698880d6064d53b9d9 \ + && git checkout 74c8b683ebe5b1cbf484f6acaa281f56aaa63948 \ && git submodule update --init --recursive \ && cd .. \ && mkdir aws-iot-device-sdk-cpp-v2-build \ diff --git a/.github/workflows/e2e-ci.yml b/.github/workflows/e2e-ci.yml index ad9376558..d7467e9c8 100644 --- a/.github/workflows/e2e-ci.yml +++ b/.github/workflows/e2e-ci.yml @@ -370,7 +370,7 @@ jobs: DEVICE_KEY_SECRET: ${{ secrets.FP_DEVICE_KEY_SECRET }} AMAZON_ROOT_CA: ${{ secrets.AMAZON_ROOT_CA }} run: | - docker run -e AWS_ACCESS_KEY_ID="$(echo ${{ secrets.INTEG_USER_KEY_ID }})" -e AWS_SECRET_ACCESS_KEY="$(echo ${{ secrets.INTEG_USER_KEY_SECRET }})" -e IOT_ENDPOINT="$(echo $IOT_ENDPOINT)" -e CERTIFICATE="$(echo $CERTIFICATE)" -e DEVICE_KEY_SECRET="$(echo $DEVICE_KEY_SECRET)" -e AMAZON_ROOT_CA="$(echo $AMAZON_ROOT_CA)" -e THING_NAME=fleetprovisioning ${{ steps.build-test-runner.outputs.imageid }} --clean-up + docker run -e AWS_ACCESS_KEY_ID="$(echo ${{ secrets.INTEG_USER_KEY_ID }})" -e AWS_SECRET_ACCESS_KEY="$(echo ${{ secrets.INTEG_USER_KEY_SECRET }})" -e IOT_ENDPOINT="$(echo $IOT_ENDPOINT)" -e CERTIFICATE="$(echo $CERTIFICATE)" -e DEVICE_KEY_SECRET="$(echo $DEVICE_KEY_SECRET)" -e AMAZON_ROOT_CA="$(echo $AMAZON_ROOT_CA)" -e THING_NAME=fleetprovisioning ${{ steps.build-test-runner.outputs.imageid }} --skip-st --clean-up e2e-tests-ubuntu-aarch64: runs-on: ubuntu-latest if: ${{ false }} # Disabled for now. aarch64 local proxy build takes too long diff --git a/CMakeLists.txt.awssdk b/CMakeLists.txt.awssdk index c1dbc21be..f5d161d0f 100644 --- a/CMakeLists.txt.awssdk +++ b/CMakeLists.txt.awssdk @@ -5,7 +5,7 @@ project(aws-iot-device-sdk-cpp-v2-download NONE) include(ExternalProject) ExternalProject_Add(aws-iot-device-sdk-cpp-v2 GIT_REPOSITORY https://github.com/aws/aws-iot-device-sdk-cpp-v2.git - GIT_TAG ac3ba3774b031dde1b988e698880d6064d53b9d9 + GIT_TAG 74c8b683ebe5b1cbf484f6acaa281f56aaa63948 SOURCE_DIR "${CMAKE_BINARY_DIR}/aws-iot-device-sdk-cpp-v2-src" BINARY_DIR "${CMAKE_BINARY_DIR}/aws-iot-device-sdk-cpp-v2-build" CONFIGURE_COMMAND "" diff --git a/integration-tests/source/GTestMain.cpp b/integration-tests/source/GTestMain.cpp index ac4709ab1..a67f6f51f 100644 --- a/integration-tests/source/GTestMain.cpp +++ b/integration-tests/source/GTestMain.cpp @@ -104,7 +104,7 @@ bool parseCliArgs(int argc, char **argv) } else if (currentArg == CLI_CLEAN_UP) { - CLEAN_UP = true; + CLEAN_UP = false; } else { @@ -185,4 +185,4 @@ int main(int argc, char **argv) printf("Tests Complete!\n"); Aws::ShutdownAPI(options); return rc; -} \ No newline at end of file +} diff --git a/source/SharedCrtResourceManager.cpp b/source/SharedCrtResourceManager.cpp index e0f232a7c..115a18630 100644 --- a/source/SharedCrtResourceManager.cpp +++ b/source/SharedCrtResourceManager.cpp @@ -39,11 +39,31 @@ bool SharedCrtResourceManager::initialize( std::shared_ptr featureRegistry) { features = featureRegistry; - initializeAllocator(config); initialized = buildClient(config) == SharedCrtResourceManager::SUCCESS; return initialized; } +void SharedCrtResourceManager::loadMemTraceLevelFromEnvironment() +{ + const char *memTraceLevelStr = std::getenv("AWS_CRT_MEMORY_TRACING"); + if (memTraceLevelStr) + { + switch (atoi(memTraceLevelStr)) + { + case AWS_MEMTRACE_BYTES: + LOG_DEBUG(Config::TAG, "Set AWS_CRT_MEMORY_TRACING=AWS_MEMTRACE_BYTES"); + memTraceLevel = AWS_MEMTRACE_BYTES; + break; + case AWS_MEMTRACE_STACKS: + LOG_DEBUG(Config::TAG, "Set AWS_CRT_MEMORY_TRACING=AWS_MEMTRACE_STACKS"); + memTraceLevel = AWS_MEMTRACE_STACKS; + break; + default: + break; + } + } +} + bool SharedCrtResourceManager::locateCredentials(const PlainConfig &config) const { struct stat fileInfo; @@ -174,22 +194,24 @@ bool SharedCrtResourceManager::setupLogging(const PlainConfig &config) const return true; } -void SharedCrtResourceManager::initializeAllocator(const PlainConfig &config) +void SharedCrtResourceManager::initializeAllocator() { + loadMemTraceLevelFromEnvironment(); allocator = aws_default_allocator(); - memTraceLevel = config.memTraceLevel; + if (memTraceLevel != AWS_MEMTRACE_NONE) { // If memTraceLevel == AWS_MEMTRACE_STACKS(2), then by default 8 frames per stack are used. allocator = aws_mem_tracer_new(allocator, nullptr, memTraceLevel, 0); } -} -int SharedCrtResourceManager::buildClient(const PlainConfig &config) -{ // We MUST declare an instance of the ApiHandle to perform global initialization // of the SDK libraries apiHandle = unique_ptr(new ApiHandle()); +} + +int SharedCrtResourceManager::buildClient(const PlainConfig &config) +{ if (config.logConfig.sdkLoggingEnabled) { if (!setupLogging(config)) @@ -318,12 +340,13 @@ int SharedCrtResourceManager::establishConnection(const PlainConfig &config) { proxyOptions.HostName = proxyConfig.proxyHost->c_str(); proxyOptions.Port = proxyConfig.proxyPort.value(); + proxyOptions.ProxyConnectionType = Aws::Crt::Http::AwsHttpProxyConnectionType::Tunneling; LOGM_INFO( TAG, "Attempting to establish MQTT connection with proxy: %s:%u", - proxyConfig.proxyHost->c_str(), - proxyConfig.proxyPort.value()); + proxyOptions.HostName.c_str(), + proxyOptions.Port); if (proxyConfig.httpProxyAuthEnabled) { @@ -520,6 +543,7 @@ void SharedCrtResourceManager::disconnect() { return; } + if (connection->Disconnect()) { if (connectionClosedPromise.get_future().wait_for(std::chrono::seconds(DEFAULT_WAIT_TIME_SECONDS)) == diff --git a/source/SharedCrtResourceManager.h b/source/SharedCrtResourceManager.h index a2ada4025..4b1f1df0b 100644 --- a/source/SharedCrtResourceManager.h +++ b/source/SharedCrtResourceManager.h @@ -49,7 +49,7 @@ namespace Aws int buildClient(const PlainConfig &config); - void initializeAllocator(const PlainConfig &config); + void loadMemTraceLevelFromEnvironment(); protected: /** @@ -58,7 +58,7 @@ namespace Aws bool locateCredentials(const PlainConfig &config) const; public: - SharedCrtResourceManager() = default; + SharedCrtResourceManager() {} virtual ~SharedCrtResourceManager(); @@ -80,6 +80,8 @@ namespace Aws bool initialize(const PlainConfig &config, std::shared_ptr featureRegistry); + void initializeAllocator(); + void initializeAWSHttpLib(); int establishConnection(const PlainConfig &config); diff --git a/source/config/Config.cpp b/source/config/Config.cpp index c010e4161..279c7b834 100644 --- a/source/config/Config.cpp +++ b/source/config/Config.cpp @@ -290,24 +290,6 @@ bool PlainConfig::LoadFromCliArgs(const CliArgs &cliArgs) bool PlainConfig::LoadFromEnvironment() { - const char *memTraceLevelStr = std::getenv("AWS_CRT_MEMORY_TRACING"); - if (memTraceLevelStr) - { - switch (atoi(memTraceLevelStr)) - { - case AWS_MEMTRACE_BYTES: - LOG_DEBUG(Config::TAG, "Set AWS_CRT_MEMORY_TRACING=AWS_MEMTRACE_BYTES"); - memTraceLevel = AWS_MEMTRACE_BYTES; - break; - case AWS_MEMTRACE_STACKS: - LOG_DEBUG(Config::TAG, "Set AWS_CRT_MEMORY_TRACING=AWS_MEMTRACE_STACKS"); - memTraceLevel = AWS_MEMTRACE_STACKS; - break; - default: - break; - } - } - const char *lockFilePathIn = std::getenv("LOCK_FILE_PATH"); if (lockFilePathIn) { diff --git a/source/config/Config.h b/source/config/Config.h index 56dc9beb7..5d13b468e 100644 --- a/source/config/Config.h +++ b/source/config/Config.h @@ -108,7 +108,6 @@ namespace Aws Aws::Crt::Optional rootCa; Aws::Crt::Optional thingName; - aws_mem_trace_level memTraceLevel{AWS_MEMTRACE_NONE}; std::string lockFilePath{DEFAULT_LOCK_FILE_PATH}; struct LogConfig : public LoadableFromJsonAndCliAndEnvironment diff --git a/source/main.cpp b/source/main.cpp index 9080d9c7f..eeecf125d 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -293,12 +293,17 @@ namespace Aws int main(int argc, char *argv[]) { - CliArgs cliArgs; + if (Config::CheckTerminalArgs(argc, argv)) { LoggerFactory::getLoggerInstance()->shutdown(); return 0; } + + resourceManager = std::make_shared(); + resourceManager->initializeAllocator(); + + CliArgs cliArgs; if (!Config::ParseCliArgs(argc, argv, cliArgs) || !config.init(cliArgs)) { LOGM_ERROR( @@ -352,8 +357,6 @@ int main(int argc, char *argv[]) sigprocmask(SIG_BLOCK, &sigset, nullptr); auto listener = std::make_shared(); - resourceManager = std::make_shared(); - if (!resourceManager.get()->initialize(config.config, features)) { LOGM_ERROR(TAG, "*** %s: Failed to initialize AWS CRT SDK.", DC_FATAL_ERROR); diff --git a/source/tunneling/SecureTunnelWrapper.cpp b/source/tunneling/SecureTunnelWrapper.cpp index a7c8b3bc1..25ec1af23 100644 --- a/source/tunneling/SecureTunnelWrapper.cpp +++ b/source/tunneling/SecureTunnelWrapper.cpp @@ -40,6 +40,43 @@ SecureTunnelWrapper::SecureTunnelWrapper( onSessionReset)) { } + +SecureTunnelWrapper::SecureTunnelWrapper( + Aws::Crt::Allocator *allocator, + Aws::Crt::Io::ClientBootstrap *bootstrap, + const Aws::Crt::Io::SocketOptions &socketOptions, + const Aws::Crt::Http::HttpClientConnectionProxyOptions &proxyOptions, + const std::string &accessToken, + aws_secure_tunneling_local_proxy_mode localProxyMode, + const std::string &endpoint, + const std::string &rootCa, + const Aws::Iotsecuretunneling::OnConnectionComplete &onConnectionComplete, + const Aws::Iotsecuretunneling::OnConnectionShutdown &onConnectionShutdown, + const Aws::Iotsecuretunneling::OnSendDataComplete &onSendDataComplete, + const Aws::Iotsecuretunneling::OnDataReceive &onDataReceive, + const Aws::Iotsecuretunneling::OnStreamStart &onStreamStart, + const Aws::Iotsecuretunneling::OnStreamReset &onStreamReset, + const Aws::Iotsecuretunneling::OnSessionReset &onSessionReset) + : secureTunnel((Aws::Iotsecuretunneling::SecureTunnelBuilder( + allocator, + *bootstrap, + socketOptions, + accessToken, + localProxyMode, + endpoint)) + .WithHttpClientConnectionProxyOptions(proxyOptions) + .WithRootCa(rootCa) + .WithOnConnectionComplete(onConnectionComplete) + .WithOnConnectionShutdown(onConnectionShutdown) + .WithOnSendDataComplete(onSendDataComplete) + .WithOnDataReceive(onDataReceive) + .WithOnStreamStart(onStreamStart) + .WithOnStreamReset(onSessionReset) + .WithOnSessionReset(onSessionReset) + .Build()) +{ +} + int SecureTunnelWrapper::Connect() { return secureTunnel->Connect(); diff --git a/source/tunneling/SecureTunnelWrapper.h b/source/tunneling/SecureTunnelWrapper.h index af07c0714..babf0124b 100644 --- a/source/tunneling/SecureTunnelWrapper.h +++ b/source/tunneling/SecureTunnelWrapper.h @@ -19,10 +19,32 @@ namespace Aws public: SecureTunnelWrapper() = default; virtual ~SecureTunnelWrapper() = default; + + // Without HTTP Proxy + SecureTunnelWrapper( + Aws::Crt::Allocator *allocator, + Aws::Crt::Io::ClientBootstrap *clientBootstrap, + const Aws::Crt::Io::SocketOptions &socketOptions, + + const std::string &accessToken, + aws_secure_tunneling_local_proxy_mode localProxyMode, + const std::string &endpointHost, + const std::string &rootCa, + + const Aws::Iotsecuretunneling::OnConnectionComplete &onConnectionComplete, + const Aws::Iotsecuretunneling::OnConnectionShutdown &onConnectionShutdown, + const Aws::Iotsecuretunneling::OnSendDataComplete &onSendDataComplete, + const Aws::Iotsecuretunneling::OnDataReceive &onDataReceive, + const Aws::Iotsecuretunneling::OnStreamStart &onStreamStart, + const Aws::Iotsecuretunneling::OnStreamReset &onStreamReset, + const Aws::Iotsecuretunneling::OnSessionReset &onSessionReset); + + // With HTTP Proxy SecureTunnelWrapper( Aws::Crt::Allocator *allocator, Aws::Crt::Io::ClientBootstrap *clientBootstrap, const Aws::Crt::Io::SocketOptions &socketOptions, + const Aws::Crt::Http::HttpClientConnectionProxyOptions &proxyOptions, const std::string &accessToken, aws_secure_tunneling_local_proxy_mode localProxyMode, @@ -47,7 +69,7 @@ namespace Aws virtual bool IsValid(); - std::unique_ptr secureTunnel; + std::shared_ptr secureTunnel; private: /** diff --git a/source/tunneling/SecureTunnelingContext.cpp b/source/tunneling/SecureTunnelingContext.cpp index 15f91a83b..234e0f2e1 100644 --- a/source/tunneling/SecureTunnelingContext.cpp +++ b/source/tunneling/SecureTunnelingContext.cpp @@ -33,6 +33,20 @@ namespace Aws { } + SecureTunnelingContext::SecureTunnelingContext( + shared_ptr manager, + const Aws::Crt::Http::HttpClientConnectionProxyOptions &proxyOptions, + const Aws::Crt::Optional &rootCa, + const string &accessToken, + const string &endpoint, + const int port, + const OnConnectionShutdownFn &onConnectionShutdown) + : mSharedCrtResourceManager(manager), mProxyOptions(proxyOptions), + mRootCa(rootCa.has_value() ? rootCa.value() : ""), mAccessToken(accessToken), mEndpoint(endpoint), + mPort(port), mOnConnectionShutdown(onConnectionShutdown) + { + } + SecureTunnelingContext::~SecureTunnelingContext() { if (mSecureTunnel && mSecureTunnel->IsValid()) @@ -191,21 +205,44 @@ namespace Aws const Aws::Iotsecuretunneling::OnStreamReset &onStreamReset, const Aws::Iotsecuretunneling::OnSessionReset &onSessionReset) { - return std::make_shared( - mSharedCrtResourceManager->getAllocator(), - mSharedCrtResourceManager->getClientBootstrap(), - Crt::Io::SocketOptions(), - mAccessToken, - AWS_SECURE_TUNNELING_DESTINATION_MODE, - mEndpoint, - mRootCa, - onConnectionComplete, - onConnectionShutdown, - onSendDataComplete, - onDataReceive, - onStreamStart, - onStreamReset, - onSessionReset); + if (mProxyOptions.HostName.length() > 0) + { + LOGM_INFO(TAG, "Creating Secure Tunneling with proxy to: %s", mProxyOptions.HostName.c_str()); + return std::make_shared( + mSharedCrtResourceManager->getAllocator(), + mSharedCrtResourceManager->getClientBootstrap(), + Crt::Io::SocketOptions(), + mProxyOptions, + mAccessToken, + AWS_SECURE_TUNNELING_DESTINATION_MODE, + mEndpoint, + mRootCa, + onConnectionComplete, + nullptr, // TODO: long term fix needed for onConnectionShutdown callback + onSendDataComplete, + onDataReceive, + onStreamStart, + onStreamReset, + onSessionReset); + } + else + { + return std::make_shared( + mSharedCrtResourceManager->getAllocator(), + mSharedCrtResourceManager->getClientBootstrap(), + Crt::Io::SocketOptions(), + mAccessToken, + AWS_SECURE_TUNNELING_DESTINATION_MODE, + mEndpoint, + mRootCa, + onConnectionComplete, + nullptr, // TODO: long term fix needed for onConnectionShutdown callback + onSendDataComplete, + onDataReceive, + onStreamStart, + onStreamReset, + onSessionReset); + } } std::shared_ptr SecureTunnelingContext::CreateTcpForward() diff --git a/source/tunneling/SecureTunnelingContext.h b/source/tunneling/SecureTunnelingContext.h index d0aed1efa..dab946c01 100644 --- a/source/tunneling/SecureTunnelingContext.h +++ b/source/tunneling/SecureTunnelingContext.h @@ -47,6 +47,15 @@ namespace Aws const int port, const OnConnectionShutdownFn &onConnectionShutdown); + SecureTunnelingContext( + std::shared_ptr manager, + const Aws::Crt::Http::HttpClientConnectionProxyOptions &proxyOptions, + const Aws::Crt::Optional &rootCa, + const std::string &accessToken, + const std::string &endpoint, + const int port, + const OnConnectionShutdownFn &onConnectionShutdown); + /** * \brief Constructor */ @@ -178,6 +187,11 @@ namespace Aws */ std::shared_ptr mSharedCrtResourceManager; + /** + * \brief HTTP proxy strategy and auth config + */ + Aws::Crt::Http::HttpClientConnectionProxyOptions mProxyOptions; + /** * \brief Path to the Amazon root CA */ diff --git a/source/tunneling/SecureTunnelingFeature.cpp b/source/tunneling/SecureTunnelingFeature.cpp index a77ab6972..6aaf57928 100644 --- a/source/tunneling/SecureTunnelingFeature.cpp +++ b/source/tunneling/SecureTunnelingFeature.cpp @@ -94,6 +94,38 @@ namespace Aws void SecureTunnelingFeature::LoadFromConfig(const PlainConfig &config) { + PlainConfig::HttpProxyConfig proxyConfig = config.httpProxyConfig; + + if (proxyConfig.httpProxyEnabled) + { + proxyOptions.HostName = proxyConfig.proxyHost->c_str(); + proxyOptions.Port = proxyConfig.proxyPort.value(); + proxyOptions.ProxyConnectionType = Aws::Crt::Http::AwsHttpProxyConnectionType::Tunneling; + + LOGM_INFO( + TAG, + "Attempting to establish tunneling connection with proxy: %s:%u", + proxyOptions.HostName.c_str(), + proxyOptions.Port); + + if (proxyConfig.httpProxyAuthEnabled) + { + LOG_INFO(TAG, "Proxy Authentication is enabled"); + Aws::Crt::Http::HttpProxyStrategyBasicAuthConfig basicAuthConfig; + basicAuthConfig.ConnectionType = Aws::Crt::Http::AwsHttpProxyConnectionType::Tunneling; + proxyOptions.AuthType = Aws::Crt::Http::AwsHttpProxyAuthenticationType::Basic; + basicAuthConfig.Username = proxyConfig.proxyUsername->c_str(); + basicAuthConfig.Password = proxyConfig.proxyPassword->c_str(); + proxyOptions.ProxyStrategy = + Aws::Crt::Http::HttpProxyStrategy::CreateBasicHttpProxyStrategy( + basicAuthConfig, Aws::Crt::g_allocator); + } + else + { + LOG_INFO(TAG, "Proxy Authentication is disabled"); + proxyOptions.AuthType = Aws::Crt::Http::AwsHttpProxyAuthenticationType::None; + } + } mThingName = *config.thingName; mRootCa = config.rootCa; mSubscribeNotification = config.tunneling.subscribeNotification; @@ -101,13 +133,10 @@ namespace Aws if (!config.tunneling.subscribeNotification) { - auto context = unique_ptr(new SecureTunnelingContext( - mSharedCrtResourceManager, - mRootCa, + auto context = createContext( *config.tunneling.destinationAccessToken, - GetEndpoint(*config.tunneling.region), - static_cast(config.tunneling.port.value()), - bind(&SecureTunnelingFeature::OnConnectionShutdown, this, placeholders::_1))); + *config.tunneling.region, + static_cast(config.tunneling.port.value())); mContexts.push_back(std::move(context)); } } @@ -257,6 +286,7 @@ namespace Aws { return std::unique_ptr(new SecureTunnelingContext( mSharedCrtResourceManager, + proxyOptions, mRootCa, accessToken, GetEndpoint(region), diff --git a/source/tunneling/SecureTunnelingFeature.h b/source/tunneling/SecureTunnelingFeature.h index e7b855547..f07642c72 100644 --- a/source/tunneling/SecureTunnelingFeature.h +++ b/source/tunneling/SecureTunnelingFeature.h @@ -9,6 +9,7 @@ #include "../SharedCrtResourceManager.h" #include "IotSecureTunnelingClientWrapper.h" #include "SecureTunnelingContext.h" +#include "aws/crt/http/HttpProxyStrategy.h" #include #include @@ -177,6 +178,11 @@ namespace Aws */ std::shared_ptr mClientBaseNotifier; + /** + * \brief HTTP proxy strategy and auth config + */ + Aws::Crt::Http::HttpClientConnectionProxyOptions proxyOptions; + /** * \brief The ThingName to use */ diff --git a/test/config/TestConfig.cpp b/test/config/TestConfig.cpp index d17b70750..fee6b665f 100644 --- a/test/config/TestConfig.cpp +++ b/test/config/TestConfig.cpp @@ -1,6 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "../../source/SharedCrtResourceManager.h" #include "../../source/config/Config.h" #include "../../source/util/FileUtils.h" #include "../../source/util/UniqueString.h" @@ -33,9 +34,13 @@ class ConfigTestFixture : public ::testing::Test public: ConfigTestFixture() = default; string outputPath; + SharedCrtResourceManager resourceManager; void SetUp() override { + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + // Config::Validate will check that cert, key, and root-ca files exist. // Create a temporary file to use as a placeholder for this purpose. ofstream file(filePath, std::fstream::app); @@ -154,6 +159,7 @@ TEST_F(ConfigTestFixture, AllFeaturesEnabled) "secure-element-token-label": "token-label" } })"; + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -1678,23 +1684,3 @@ TEST_F(ConfigTestFixture, HTTPProxyConfigNoAuth) ASSERT_FALSE(httpProxyConfig.httpProxyAuthEnabled); ASSERT_STREQ("None", httpProxyConfig.proxyAuthMethod->c_str()); } - -TEST(Config, MemoryTrace) -{ - PlainConfig config; - - // Test all permutations of memory trace set through the environment. - vector levels{ - AWS_MEMTRACE_NONE, - AWS_MEMTRACE_BYTES, - AWS_MEMTRACE_STACKS, - }; - - for (const auto &level : levels) - { - auto levelstr = std::to_string(level); - ::setenv("AWS_CRT_MEMORY_TRACING", levelstr.c_str(), 1); - ASSERT_TRUE(config.LoadFromEnvironment()) << "read AWS_CRT_MEMORY_TRACING=" << level; - ASSERT_EQ(config.memTraceLevel, level); - } -} diff --git a/test/config/TestConfigSerialization.cpp b/test/config/TestConfigSerialization.cpp index 9968d6259..c8e6b4fda 100644 --- a/test/config/TestConfigSerialization.cpp +++ b/test/config/TestConfigSerialization.cpp @@ -1,6 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "../../source/SharedCrtResourceManager.h" #include "../../source/config/Config.h" #include "../../source/util/FileUtils.h" #include "../../source/util/UniqueString.h" @@ -20,32 +21,9 @@ using namespace Aws::Crt; using namespace Aws::Iot::DeviceClient; using namespace Aws::Iot::DeviceClient::Util; -class SerializeConfigTestFixture : public ::testing::TestWithParam +TEST(SerializeConfigTestFixture, SerializeCompleteConfigTest) { - protected: - const char *jsonString; -}; - -TEST_P(SerializeConfigTestFixture, SerializeConfigTest) -{ - const char *jsonString = GetParam(); - PlainConfig config; - JsonObject jsonObject(jsonString); - config.LoadFromJson(jsonObject.View()); - auto inputJsonString = jsonObject.View().WriteCompact(); - - JsonObject serializedConfig; - config.SerializeToObject(serializedConfig); - auto serializedJsonString = serializedConfig.View().WriteCompact(); - - ASSERT_STREQ(inputJsonString.c_str(), serializedJsonString.c_str()); -} - -INSTANTIATE_TEST_CASE_P( - SerializationTests, - SerializeConfigTestFixture, - ::testing::Values( - R"( + constexpr char jsonString[] = R"( { "endpoint": "endpoint value", "cert": "/tmp/aws-iot-device-client-test-file", @@ -61,7 +39,7 @@ INSTANTIATE_TEST_CASE_P( }, "jobs": { "enabled": true, - "handler-directory": "directory" + "handler-directory": "directory" }, "tunneling": { "enabled": true @@ -138,8 +116,27 @@ INSTANTIATE_TEST_CASE_P( } ] } -})", - R"({ +})"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + PlainConfig config; + + JsonObject jsonObject(jsonString); + config.LoadFromJson(jsonObject.View()); + auto inputJsonString = jsonObject.View().WriteCompact(); + + JsonObject serializedConfig; + config.SerializeToObject(serializedConfig); + auto serializedJsonString = serializedConfig.View().WriteCompact(); + + ASSERT_STREQ(inputJsonString.c_str(), serializedJsonString.c_str()); +} + +TEST(SerializeConfigTestFixture, SerializeBasicConfigTest) +{ + constexpr char jsonString[] = R"( +{ "logging": { "level": "DEBUG", "type": "file", @@ -150,7 +147,7 @@ INSTANTIATE_TEST_CASE_P( }, "jobs": { "enabled": true, - "handler-directory": "" + "handler-directory": "" }, "tunneling": { "enabled": true @@ -166,17 +163,32 @@ INSTANTIATE_TEST_CASE_P( "completed-fp": false }, "samples": { - "pub-sub": { - "enabled": true - } - }, + "pub-sub": { + "enabled": true + } + }, "config-shadow": { "enabled": true - }, + }, "sample-shadow": { "enabled": true - }, + }, "secure-element": { "enabled": true - } -})")); + } +})"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + PlainConfig config; + + JsonObject jsonObject(jsonString); + config.LoadFromJson(jsonObject.View()); + auto inputJsonString = jsonObject.View().WriteCompact(); + + JsonObject serializedConfig; + config.SerializeToObject(serializedConfig); + auto serializedJsonString = serializedConfig.View().WriteCompact(); + + ASSERT_STREQ(inputJsonString.c_str(), serializedJsonString.c_str()); +} \ No newline at end of file diff --git a/test/devicedefender/TestDeviceDefender.cpp b/test/devicedefender/TestDeviceDefender.cpp index ab30c3c1d..e81d10867 100644 --- a/test/devicedefender/TestDeviceDefender.cpp +++ b/test/devicedefender/TestDeviceDefender.cpp @@ -85,6 +85,9 @@ class TestDeviceDefender : public testing::Test { deviceDefender = unique_ptr(new MockDDFeature()); manager = shared_ptr(new SharedCrtResourceManager()); + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + manager->initializeAllocator(); + notifier = shared_ptr(new MockNotifier()); task = shared_ptr(new MockReportTask()); config = getSimpleDDConfig(); diff --git a/test/fleetprovisioning/TestFleetProvisioning.cpp b/test/fleetprovisioning/TestFleetProvisioning.cpp index c013dcc20..74f7033cf 100644 --- a/test/fleetprovisioning/TestFleetProvisioning.cpp +++ b/test/fleetprovisioning/TestFleetProvisioning.cpp @@ -11,6 +11,7 @@ using namespace Aws::Iot::DeviceClient::FleetProvisioningNS; TEST(FleetProvisioning, EmptyTemplateParameters) { + Aws::Iot::DeviceClient::SharedCrtResourceManager resourceManager; Aws::Crt::Optional params; // start with empty value FleetProvisioning fp; ASSERT_TRUE(fp.MapParameters(params)); @@ -19,6 +20,10 @@ TEST(FleetProvisioning, EmptyTemplateParameters) TEST(FleetProvisioning, MalformedTemplateParameters) { + Aws::Iot::DeviceClient::SharedCrtResourceManager resourceManager; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + Aws::Crt::Optional params("{\"SerialNumber\" \"Device-SN\"}"); // test missing colon FleetProvisioning fp; ASSERT_FALSE(fp.MapParameters(params)); @@ -30,6 +35,10 @@ TEST(FleetProvisioning, MalformedTemplateParameters) TEST(FleetProvisioning, ValidTemplateParameters) { + Aws::Iot::DeviceClient::SharedCrtResourceManager resourceManager; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + Aws::Crt::Optional params("{\"SerialNumber\": \"Device-SN\"}"); // test single JSON property FleetProvisioning fp; ASSERT_TRUE(fp.MapParameters(params)); diff --git a/test/jobs/TestJobDocument.cpp b/test/jobs/TestJobDocument.cpp index 674fbc203..4f12353d2 100644 --- a/test/jobs/TestJobDocument.cpp +++ b/test/jobs/TestJobDocument.cpp @@ -1,8 +1,10 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "../../source/SharedCrtResourceManager.h" #include "../../source/jobs/JobDocument.h" #include "../../source/util/UniqueString.h" + #include "gtest/gtest.h" #include #include @@ -171,6 +173,10 @@ TEST(JobDocument, SampleJobDocument) } })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -376,6 +382,10 @@ TEST(JobDocument, MissingRequiredFields) } })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -429,6 +439,10 @@ TEST(JobDocument, MinimumJobDocument) ] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -522,6 +536,10 @@ TEST(JobDocument, MissingRequiredFieldsValue) } })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -549,6 +567,10 @@ TEST(JobDocument, CommandFieldsIsEmpty) ] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -576,6 +598,10 @@ TEST(JobDocument, CommandContainsSpaceCharacters) ] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -603,6 +629,10 @@ TEST(JobDocument, SpaceCharactersContainedWithinFirstWordOfCommand) ] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); @@ -621,6 +651,10 @@ TEST(JobDocument, oldJobDocumentCompatibility) "path": "default" })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View(); diff --git a/test/jobs/TestJobsFeature.cpp b/test/jobs/TestJobsFeature.cpp index 1f04cc53f..38bdc95e1 100644 --- a/test/jobs/TestJobsFeature.cpp +++ b/test/jobs/TestJobsFeature.cpp @@ -258,6 +258,9 @@ class TestJobsFeature : public ::testing::Test public: void SetUp() { + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + ThingName = Aws::Crt::String("thing-name value"); notifier = shared_ptr(new MockNotifier()); config = getSimpleConfig(); @@ -269,6 +272,7 @@ class TestJobsFeature : public ::testing::Test } Aws::Crt::String ThingName; shared_ptr notifier; + SharedCrtResourceManager resourceManager; PlainConfig config; unique_ptr startNextJobExecutionResponse; unique_ptr jobsMock; diff --git a/test/shadow/TestConfigShadowFeature.cpp b/test/shadow/TestConfigShadowFeature.cpp index a465ec996..740f05d55 100644 --- a/test/shadow/TestConfigShadowFeature.cpp +++ b/test/shadow/TestConfigShadowFeature.cpp @@ -59,6 +59,10 @@ TEST(ConfigShadowFeature, resetClientConfigWithValidJSON) } })"; + SharedCrtResourceManager resourceManager; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); + JsonObject oldJsonObject(oldJsonString); JsonView jsonView = oldJsonObject.View(); PlainConfig config; @@ -149,6 +153,9 @@ TEST(ConfigShadowFeature, resetClientConfigWithInvalidJSON) "shadow-output-file": "" } })"; + SharedCrtResourceManager resourceManager; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + resourceManager.initializeAllocator(); JsonObject oldJsonObject(oldJsonString); JsonView jsonView = oldJsonObject.View(); diff --git a/test/tunneling/TestSecureTunnelingFeature.cpp b/test/tunneling/TestSecureTunnelingFeature.cpp index 6bae9f810..6aeaf880e 100644 --- a/test/tunneling/TestSecureTunnelingFeature.cpp +++ b/test/tunneling/TestSecureTunnelingFeature.cpp @@ -103,9 +103,12 @@ class TestSecureTunnelingFeature : public testing::Test public: void SetUp() override { + manager = shared_ptr(new SharedCrtResourceManager()); + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + manager->initializeAllocator(); + thingName = Aws::Crt::String("thing-name value"); secureTunnelingFeature = shared_ptr(new MockSecureTunnelingFeature()); - manager = shared_ptr(new SharedCrtResourceManager()); mockClient = shared_ptr(new MockIotSecureTunnelingClient()); notifier = shared_ptr(new MockNotifier()); fakeContext = unique_ptr(new FakeSecureTunnelContext()); diff --git a/test/util/TestSharedResourceManager.cpp b/test/util/TestSharedResourceManager.cpp index 25d1229c7..a5d3215b0 100644 --- a/test/util/TestSharedResourceManager.cpp +++ b/test/util/TestSharedResourceManager.cpp @@ -57,6 +57,9 @@ class SharedResourceManagerTest : public ::testing::Test void SetUp() override { + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + manager.initializeAllocator(); + // SharedCrtResourceManager::locateCredentials will check that cert, key files // have valid permissions. Create a temporary file to use as a placeholder for this purpose. FileUtils::CreateDirectoryWithPermissions(certDir.c_str(), 0700); @@ -150,4 +153,4 @@ TEST_F(SharedResourceManagerTest, badPermissionsDirectory) chmod(certDir.c_str(), 0777); ASSERT_FALSE(manager.locateCredentialsWrapper(config)); -} +} \ No newline at end of file diff --git a/test/util/TestStringUtils.cpp b/test/util/TestStringUtils.cpp index cc82c3991..ca6a70a87 100644 --- a/test/util/TestStringUtils.cpp +++ b/test/util/TestStringUtils.cpp @@ -1,8 +1,10 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "../../source/SharedCrtResourceManager.h" #include "../../source/config/Config.h" #include "../../source/util/StringUtils.h" + #include "gtest/gtest.h" #include @@ -65,6 +67,10 @@ TEST(StringUtils, leavesNewLineAndTabAlone) TEST(StringUtils, maptoString) { + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + Aws::Crt::Map map; map.insert(std::pair("a", "b")); map.insert(std::pair("c", "d")); @@ -130,6 +136,10 @@ TEST(StringUtils, ParseToStringVector) { "args": ["hello", "world"] })"; + // Initializing allocator, so we can use CJSON lib from SDK in our unit tests. + SharedCrtResourceManager resourceManager; + resourceManager.initializeAllocator(); + JsonObject jsonObject(jsonString); JsonView jsonView = jsonObject.View();