aboutsummaryrefslogblamecommitdiffstats
path: root/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/client/ClientConfiguration.cpp
blob: 647c6e3f49ab4b7619cfaab5ea72f9d424706122 (plain) (tree)
1
2
3
4
5
6
7
8
9


                                                                     
                                                
                                                                 
                                                 
                                                 
                                                  
                                          
                                            
                                       

                                                      
                                                   

             


                                                        

                
                                                             


                                                                                                        
 
                                    
                       








                                                            

                  
                                                                              
 




















                                                                                                       
 



































































































































































                                                                                                                                                                                               


















                                                                                                           


                                                               


                                                                    
                                                 


                                
                                                                           





                                                                                                   
                                     
     
                            
         




                                                                                                   
         
        
     
                                                                                 
     
                         
 



                                                                                                          
 












                                                                                                                            
         




                                                                                                      
     
                  
 
                     
/**
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#include <aws/core/client/ClientConfiguration.h>
#include <aws/core/config/defaults/ClientConfigurationDefaults.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
#include <aws/core/client/DefaultRetryStrategy.h>
#include <aws/core/client/AdaptiveRetryStrategy.h>
#include <aws/core/platform/Environment.h>
#include <aws/core/platform/OSVersionInfo.h>
#include <aws/core/utils/memory/AWSMemory.h>
#include <aws/core/utils/StringUtils.h>
#include <aws/core/utils/threading/Executor.h>
#include <aws/core/utils/memory/stl/AWSStringStream.h>
#include <aws/core/Version.h>
#include <aws/core/config/AWSProfileConfigLoader.h>
#include <aws/core/utils/logging/LogMacros.h>

namespace Aws
{
namespace Auth
{
    AWS_CORE_API Aws::String GetConfigProfileFilename();
}
namespace Client
{

static const char* CLIENT_CONFIG_TAG = "ClientConfiguration";
static const char* USE_REQUEST_COMPRESSION_ENV_VAR = "USE_REQUEST_COMPRESSION";
static const char* USE_REQUEST_COMPRESSION_CONFIG_VAR = "use_request_compression";
static const char* REQUEST_MIN_COMPRESSION_SIZE_BYTES_ENV_VAR = "REQUEST_MIN_COMPRESSION_SIZE_BYTES";
static const char* REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_VAR = "request_min_compression_size_bytes";

Aws::String ComputeUserAgentString()
{
  Aws::StringStream ss;
  ss << "aws-sdk-cpp/" << Version::GetVersionString() << " "
#if defined(AWS_USER_AGENT_CUSTOMIZATION)
#define XSTR(V) STR(V)
#define STR(V) #V
     << XSTR(AWS_USER_AGENT_CUSTOMIZATION) << " "
#undef STR
#undef XSTR
#endif
     << Aws::OSVersionInfo::ComputeOSVersionString() << " "
     << Version::GetCompilerVersionString();
  return ss.str();
}

void setLegacyClientConfigurationParameters(ClientConfiguration& clientConfig)
{
    clientConfig.scheme = Aws::Http::Scheme::HTTPS;
    clientConfig.useDualStack = false;
    clientConfig.useFIPS = false;
    clientConfig.maxConnections = 25;
    clientConfig.httpRequestTimeoutMs = 0;
    clientConfig.requestTimeoutMs = 3000;
    clientConfig.connectTimeoutMs = 1000;
    clientConfig.enableTcpKeepAlive = true;
    clientConfig.tcpKeepAliveIntervalMs = 30000;
    clientConfig.lowSpeedLimit = 1;
    clientConfig.proxyScheme = Aws::Http::Scheme::HTTP;
    clientConfig.proxyPort = 0;
    clientConfig.executor = Aws::MakeShared<Aws::Utils::Threading::DefaultExecutor>(CLIENT_CONFIG_TAG);
    clientConfig.verifySSL = true;
    clientConfig.writeRateLimiter = nullptr;
    clientConfig.readRateLimiter = nullptr;
    clientConfig.httpLibOverride = Aws::Http::TransferLibType::DEFAULT_CLIENT;
    clientConfig.followRedirects = FollowRedirectsPolicy::DEFAULT;
    clientConfig.disableExpectHeader = false;
    clientConfig.enableClockSkewAdjustment = true;
    clientConfig.enableHostPrefixInjection = true;
    clientConfig.profileName = Aws::Auth::GetConfigProfileName();

    Aws::String useCompressionConfig = clientConfig.LoadConfigFromEnvOrProfile(
        USE_REQUEST_COMPRESSION_ENV_VAR,
        Aws::Auth::GetConfigProfileName(),
        USE_REQUEST_COMPRESSION_CONFIG_VAR,
        {"ENABLE", "DISABLE", "enable", "disable"},
        "ENABLE"
        );

    if (Aws::Utils::StringUtils::ToLower(useCompressionConfig.c_str())  == "disable") {
      clientConfig.requestCompressionConfig.useRequestCompression = Aws::Client::UseRequestCompression::DISABLE;
      AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "Request Compression disabled");
    } else {
      //Using default to true for forward compatibility in case new config is added but SDK is not updated.
      clientConfig.requestCompressionConfig.useRequestCompression = Aws::Client::UseRequestCompression::ENABLE;
      AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "Request Compression enabled");
    }

    // Getting min request compression length
    Aws::String minRequestCompressionString = Aws::Environment::GetEnv(REQUEST_MIN_COMPRESSION_SIZE_BYTES_ENV_VAR);
    if (minRequestCompressionString.empty())
    {
      minRequestCompressionString = Aws::Config::GetCachedConfigValue(REQUEST_MIN_COMPRESSION_SIZE_BYTES_CONFIG_VAR);
    }
    if (!minRequestCompressionString.empty()) {
      clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes = static_cast<int>(Aws::Utils::StringUtils::ConvertToInt32(minRequestCompressionString.c_str()));
      if (clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes > 10485760) {
        AWS_LOGSTREAM_ERROR(CLIENT_CONFIG_TAG, "ClientConfiguration for MinReqCompression is unsupported, received: " << clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes);
      }
    }
    AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use MinReqCompression: " << clientConfig.requestCompressionConfig.requestMinCompressionSizeBytes);

    AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG, "ClientConfiguration will use SDK Auto Resolved profile: [" << clientConfig.profileName << "] if not specified by users.");

    // Automatically determine the AWS region from environment variables, configuration file and EC2 metadata.
    clientConfig.region = Aws::Environment::GetEnv("AWS_DEFAULT_REGION");
    if (!clientConfig.region.empty())
    {
        return;
    }

    clientConfig.region = Aws::Environment::GetEnv("AWS_REGION");
    if (!clientConfig.region.empty())
    {
        return;
    }

    clientConfig.region = Aws::Config::GetCachedConfigValue("region");
    if (!clientConfig.region.empty())
    {
        return;
    }

    // Set the endpoint to interact with EC2 instance's metadata service
    Aws::String ec2MetadataServiceEndpoint = Aws::Environment::GetEnv("AWS_EC2_METADATA_SERVICE_ENDPOINT");
    if (! ec2MetadataServiceEndpoint.empty())
    {
        //By default we use the IPv4 default metadata service address
        auto client = Aws::Internal::GetEC2MetadataClient();
        if (client != nullptr)
        {
            client->SetEndpoint(ec2MetadataServiceEndpoint);
        }
    }
}

ClientConfiguration::ClientConfiguration()
{
    this->disableIMDS = false;
    setLegacyClientConfigurationParameters(*this);
    retryStrategy = InitRetryStrategy();

    if (!this->disableIMDS &&
        region.empty() &&
        Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true")
    {
        auto client = Aws::Internal::GetEC2MetadataClient();
        if (client)
        {
            region = client->GetCurrentRegion();
        }
    }
    if (!region.empty())
    {
        return;
    }
    region = Aws::String(Aws::Region::US_EAST_1);
}

ClientConfiguration::ClientConfiguration(const char* profile, bool shouldDisableIMDS)
{
    this->disableIMDS = shouldDisableIMDS;
    setLegacyClientConfigurationParameters(*this);
    // Call EC2 Instance Metadata service only once
    Aws::String ec2MetadataRegion;
    bool hasEc2MetadataRegion = false;
    if (!this->disableIMDS &&
        region.empty() &&
        Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true") {
        auto client = Aws::Internal::GetEC2MetadataClient();
        if (client)
        {
            ec2MetadataRegion = client->GetCurrentRegion();
            hasEc2MetadataRegion = true;
            region = ec2MetadataRegion;
        }
    }

    if(region.empty())
    {
        region = Aws::String(Aws::Region::US_EAST_1);
    }

    if (profile && Aws::Config::HasCachedConfigProfile(profile)) {
        this->profileName = Aws::String(profile);
        AWS_LOGSTREAM_DEBUG(CLIENT_CONFIG_TAG,
                            "Use user specified profile: [" << this->profileName << "] for ClientConfiguration.");
        auto tmpRegion = Aws::Config::GetCachedConfigProfile(this->profileName).GetRegion();
        if (!tmpRegion.empty()) {
            region = tmpRegion;
        }

        Aws::String profileDefaultsMode = Aws::Config::GetCachedConfigProfile(this->profileName).GetDefaultsMode();
        Aws::Config::Defaults::SetSmartDefaultsConfigurationParameters(*this, profileDefaultsMode,
                                                                       hasEc2MetadataRegion, ec2MetadataRegion);
        return;
    }
    if (!retryStrategy)
    {
        retryStrategy = InitRetryStrategy();
    }

    AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "User specified profile: [" << profile << "] is not found, will use the SDK resolved one.");
}

ClientConfiguration::ClientConfiguration(bool /*useSmartDefaults*/, const char* defaultMode, bool shouldDisableIMDS)
{
    this->disableIMDS = shouldDisableIMDS;
    setLegacyClientConfigurationParameters(*this);

    // Call EC2 Instance Metadata service only once
    Aws::String ec2MetadataRegion;
    bool hasEc2MetadataRegion = false;
    if (!this->disableIMDS &&
        region.empty() &&
        Aws::Utils::StringUtils::ToLower(Aws::Environment::GetEnv("AWS_EC2_METADATA_DISABLED").c_str()) != "true")
    {
        auto client = Aws::Internal::GetEC2MetadataClient();
        if (client)
        {
            ec2MetadataRegion = client->GetCurrentRegion();
            hasEc2MetadataRegion = true;
            region = ec2MetadataRegion;
        }
    }
    if (region.empty())
    {
        region = Aws::String(Aws::Region::US_EAST_1);
    }

    Aws::Config::Defaults::SetSmartDefaultsConfigurationParameters(*this, defaultMode, hasEc2MetadataRegion, ec2MetadataRegion);
}

std::shared_ptr<RetryStrategy> InitRetryStrategy(Aws::String retryMode)
{
    int maxAttempts = 0;
    Aws::String maxAttemptsString = Aws::Environment::GetEnv("AWS_MAX_ATTEMPTS");
    if (maxAttemptsString.empty())
    {
        maxAttemptsString = Aws::Config::GetCachedConfigValue("max_attempts");
    }
    // In case users specify 0 explicitly to disable retry.
    if (maxAttemptsString == "0")
    {
        maxAttempts = 0;
    }
    else
    {
        maxAttempts = static_cast<int>(Aws::Utils::StringUtils::ConvertToInt32(maxAttemptsString.c_str()));
        if (maxAttempts == 0)
        {
            AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "Retry Strategy will use the default max attempts.");
            maxAttempts = -1;
        }
    }

    if (retryMode.empty())
    {
        retryMode = Aws::Environment::GetEnv("AWS_RETRY_MODE");
    }
    if (retryMode.empty())
    {
        retryMode = Aws::Config::GetCachedConfigValue("retry_mode");
    }

    std::shared_ptr<RetryStrategy> retryStrategy;
    if (retryMode == "standard")
    {
        if (maxAttempts < 0)
        {
            // negative value set above force usage of default max attempts
            retryStrategy = Aws::MakeShared<StandardRetryStrategy>(CLIENT_CONFIG_TAG);
        }
        else
        {
            retryStrategy = Aws::MakeShared<StandardRetryStrategy>(CLIENT_CONFIG_TAG, maxAttempts);
        }
    }
    else if (retryMode == "adaptive")
    {
        if (maxAttempts < 0)
        {
            // negative value set above force usage of default max attempts
            retryStrategy = Aws::MakeShared<AdaptiveRetryStrategy>(CLIENT_CONFIG_TAG);
        }
        else
        {
            retryStrategy = Aws::MakeShared<AdaptiveRetryStrategy>(CLIENT_CONFIG_TAG, maxAttempts);
        }
    }
    else
    {
        retryStrategy = Aws::MakeShared<DefaultRetryStrategy>(CLIENT_CONFIG_TAG);
    }

    return retryStrategy;
}

Aws::String ClientConfiguration::LoadConfigFromEnvOrProfile(const Aws::String& envKey,
                                                            const Aws::String& profile,
                                                            const Aws::String& profileProperty,
                                                            const Aws::Vector<Aws::String>& allowedValues,
                                                            const Aws::String& defaultValue)
{
    Aws::String option = Aws::Environment::GetEnv(envKey.c_str());
    if (option.empty()) {
        option = Aws::Config::GetCachedConfigValue(profile, profileProperty);
    }
    option = Aws::Utils::StringUtils::ToLower(option.c_str());
    if (option.empty()) {
        return defaultValue;
    }

    if (!allowedValues.empty() && std::find(allowedValues.cbegin(), allowedValues.cend(), option) == allowedValues.cend()) {
        Aws::OStringStream expectedStr;
        expectedStr << "[";
        for(const auto& allowed : allowedValues) {
            expectedStr << allowed << ";";
        }
        expectedStr << "]";

        AWS_LOGSTREAM_WARN(CLIENT_CONFIG_TAG, "Unrecognised value for " << envKey << ": " << option <<
                                              ". Using default instead: " << defaultValue <<
                                              ". Expected empty or one of: " << expectedStr.str());
        option = defaultValue;
    }
    return option;
}

} // namespace Client
} // namespace Aws