bool AWSAuthV4Signer::SignRequestWithSigV4a()

in src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp [80:182]


bool AWSAuthV4Signer::SignRequestWithSigV4a(Aws::Http::HttpRequest& request, const char* region, const char* serviceName,
    bool signBody, long long expirationTimeInSeconds, Aws::Crt::Auth::SignatureType signatureType) const
{
    AWSCredentials credentials = GetCredentials(request.GetServiceSpecificParameters());
    auto crtCredentials = Aws::MakeShared<Aws::Crt::Auth::Credentials>(v4AsymmetricLogTag,
        Aws::Crt::ByteCursorFromCString(credentials.GetAWSAccessKeyId().c_str()),
        Aws::Crt::ByteCursorFromCString(credentials.GetAWSSecretKey().c_str()),
        Aws::Crt::ByteCursorFromCString(credentials.GetSessionToken().c_str()),
        credentials.GetExpiration().Seconds());

    Aws::Crt::Auth::AwsSigningConfig awsSigningConfig;
    awsSigningConfig.SetSigningAlgorithm(static_cast<Aws::Crt::Auth::SigningAlgorithm>(AWSSigningAlgorithm::ASYMMETRIC_SIGV4));
    awsSigningConfig.SetSignatureType(signatureType);
    awsSigningConfig.SetRegion(region);
    awsSigningConfig.SetService(serviceName);
    awsSigningConfig.SetSigningTimepoint(GetSigningTimestamp().UnderlyingTimestamp());
    awsSigningConfig.SetUseDoubleUriEncode(m_urlEscapePath);
    awsSigningConfig.SetShouldNormalizeUriPath(true);
    awsSigningConfig.SetOmitSessionToken(false);
    awsSigningConfig.SetShouldSignHeaderUserData(reinterpret_cast<void*>(const_cast<Aws::Set<Aws::String>*>(&m_unsignedHeaders)));
    awsSigningConfig.SetShouldSignHeaderCallback([](const Aws::Crt::ByteCursor *name, void *user_data) {
        Aws::Set<Aws::String>* unsignedHeaders = static_cast<Aws::Set<Aws::String>*>(user_data);
        Aws::String headerKey(reinterpret_cast<const char*>(name->ptr), name->len);
        return unsignedHeaders->find(Aws::Utils::StringUtils::ToLower(headerKey.c_str())) == unsignedHeaders->cend();
    });
    if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaHeaders)
    {
        Aws::String payloadHash(UNSIGNED_PAYLOAD);
        if(signBody || request.GetUri().GetScheme() != Http::Scheme::HTTPS)
        {
            if (!request.GetContentBody())
            {
                AWS_LOGSTREAM_DEBUG(v4AsymmetricLogTag, "Using cached empty string sha256 " << EMPTY_STRING_SHA256 << " because payload is empty.");
                payloadHash = EMPTY_STRING_SHA256;
            }
            else
            {
                // The hash will be calculated from the payload during signing.
                payloadHash = {};
            }
        }
        else
        {
            AWS_LOGSTREAM_DEBUG(v4AsymmetricLogTag, "Note: Http payloads are not being signed. signPayloads=" << signBody
                    << " http scheme=" << Http::SchemeMapper::ToString(request.GetUri().GetScheme()));
        }
        awsSigningConfig.SetSignedBodyValue(payloadHash.c_str());
        awsSigningConfig.SetSignedBodyHeader(m_includeSha256HashHeader ? Aws::Crt::Auth::SignedBodyHeaderType::XAmzContentSha256 : Aws::Crt::Auth::SignedBodyHeaderType::None);
    }
    else if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaQueryParams)
    {
        if (ServiceRequireUnsignedPayload(serviceName))
        {
            awsSigningConfig.SetSignedBodyValue(UNSIGNED_PAYLOAD);
        }
        else
        {
            awsSigningConfig.SetSignedBodyValue(EMPTY_STRING_SHA256);
        }
    }
    else
    {
        AWS_LOGSTREAM_ERROR(v4AsymmetricLogTag, "The signature type should be either \"HttpRequestViaHeaders\" or \"HttpRequestViaQueryParams\"");
        return false;
    }
    awsSigningConfig.SetExpirationInSeconds(static_cast<uint64_t>(expirationTimeInSeconds));
    awsSigningConfig.SetCredentials(crtCredentials);

    std::shared_ptr<Aws::Crt::Http::HttpRequest> crtHttpRequest = request.ToCrtHttpRequest();
    bool success = true;
    m_crtSigner.SignRequest(crtHttpRequest, awsSigningConfig,
        [&request, &success, signatureType](const std::shared_ptr<Aws::Crt::Http::HttpRequest>& signedCrtHttpRequest, int errorCode) {
            success = (errorCode == AWS_ERROR_SUCCESS);
            if (success)
            {
                if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaHeaders)
                {
                    for (size_t i = 0; i < signedCrtHttpRequest->GetHeaderCount(); i++)
                    {
                        Aws::Crt::Optional<Aws::Crt::Http::HttpHeader> httpHeader = signedCrtHttpRequest->GetHeader(i);
                        request.SetHeaderValue(Aws::String(reinterpret_cast<const char*>(httpHeader->name.ptr), httpHeader->name.len),
                            Aws::String(reinterpret_cast<const char*>(httpHeader->value.ptr), httpHeader->value.len));
                    }
                }
                else if (signatureType == Aws::Crt::Auth::SignatureType::HttpRequestViaQueryParams)
                {
                    Aws::Http::URI newPath(reinterpret_cast<const char*>(signedCrtHttpRequest->GetPath()->ptr));
                    request.GetUri().SetQueryString(newPath.GetQueryString());
                }
                else
                {
                    AWS_LOGSTREAM_ERROR(v4AsymmetricLogTag, "No action to take when signature type is neither \"HttpRequestViaHeaders\" nor \"HttpRequestViaQueryParams\"");
                    success = false;
                }
            }
            else
            {
                AWS_LOGSTREAM_ERROR(v4AsymmetricLogTag, "Encountered internal error during signing process with AWS signature version 4 (Asymmetric):" << aws_error_str(errorCode));
            }
        }
    );
    return success;
}