mirror of https://github.com/milvus-io/milvus.git
				
				
				
			
		
			
				
	
	
		
			220 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
 | 
						|
// with the License. You may obtain a copy of the License at
 | 
						|
//
 | 
						|
// http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software distributed under the License
 | 
						|
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 | 
						|
// or implied. See the License for the specific language governing permissions and limitations under the License
 | 
						|
 | 
						|
/**
 | 
						|
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 | 
						|
 * SPDX-License-Identifier: Apache-2.0.
 | 
						|
 */
 | 
						|
 | 
						|
#include <aws/core/internal/AWSHttpResourceClient.h>
 | 
						|
#include <aws/core/client/DefaultRetryStrategy.h>
 | 
						|
#include <aws/core/http/HttpClient.h>
 | 
						|
#include <aws/core/http/HttpClientFactory.h>
 | 
						|
#include <aws/core/http/HttpResponse.h>
 | 
						|
#include <aws/core/utils/logging/LogMacros.h>
 | 
						|
#include <aws/core/utils/StringUtils.h>
 | 
						|
#include <aws/core/utils/HashingUtils.h>
 | 
						|
#include <aws/core/platform/Environment.h>
 | 
						|
#include <aws/core/client/AWSError.h>
 | 
						|
#include <aws/core/client/CoreErrors.h>
 | 
						|
#include <aws/core/utils/xml/XmlSerializer.h>
 | 
						|
#include <limits.h>
 | 
						|
#include <mutex>
 | 
						|
#include <sstream>
 | 
						|
#include <random>
 | 
						|
#include "AliyunSTSClient.h"
 | 
						|
 | 
						|
namespace Aws {
 | 
						|
namespace Http {
 | 
						|
class HttpClient;
 | 
						|
class HttpRequest;
 | 
						|
enum class HttpResponseCode;
 | 
						|
}  // namespace Http
 | 
						|
 | 
						|
namespace Client {
 | 
						|
Aws::String
 | 
						|
ComputeUserAgentString();
 | 
						|
}
 | 
						|
 | 
						|
namespace Internal {
 | 
						|
 | 
						|
static const char STS_RESOURCE_CLIENT_LOG_TAG[] =
 | 
						|
    "AliyunSTSResourceClient";  // [aliyun]
 | 
						|
 | 
						|
int
 | 
						|
IntRand(const int& min, const int& max) {
 | 
						|
    static thread_local std::mt19937 generator;
 | 
						|
    std::uniform_int_distribution<int> distribution(min, max);
 | 
						|
    return distribution(generator);
 | 
						|
}
 | 
						|
 | 
						|
AliyunSTSCredentialsClient::AliyunSTSCredentialsClient(
 | 
						|
    const Aws::Client::ClientConfiguration& clientConfiguration)
 | 
						|
    : AWSHttpResourceClient(clientConfiguration, STS_RESOURCE_CLIENT_LOG_TAG) {
 | 
						|
    m_aliyunOidcProviderArn =
 | 
						|
        Aws::Environment::GetEnv("ALIBABA_CLOUD_OIDC_PROVIDER_ARN");
 | 
						|
    if (m_aliyunOidcProviderArn.empty()) {
 | 
						|
        AWS_LOGSTREAM_WARN(STS_RESOURCE_CLIENT_LOG_TAG,
 | 
						|
                           "oidc role arn must be specified to use STS "
 | 
						|
                           "AssumeRole web identity creds provider.");
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    SetErrorMarshaller(Aws::MakeUnique<Aws::Client::XmlErrorMarshaller>(
 | 
						|
        STS_RESOURCE_CLIENT_LOG_TAG));
 | 
						|
 | 
						|
    // [aliyun]
 | 
						|
    m_endpoint = "https://sts.aliyuncs.com";
 | 
						|
 | 
						|
    AWS_LOGSTREAM_INFO(
 | 
						|
        STS_RESOURCE_CLIENT_LOG_TAG,
 | 
						|
        "Creating STS ResourceClient with endpoint: " << m_endpoint);
 | 
						|
}
 | 
						|
 | 
						|
AliyunSTSCredentialsClient::STSAssumeRoleWithWebIdentityResult
 | 
						|
AliyunSTSCredentialsClient::GetAssumeRoleWithWebIdentityCredentials(
 | 
						|
    const STSAssumeRoleWithWebIdentityRequest& request) {
 | 
						|
    // Calculate query string
 | 
						|
    Aws::StringStream ss;
 | 
						|
    // [aliyun]
 | 
						|
    // linux curl example:
 | 
						|
    // Action=AssumeRoleWithOIDC
 | 
						|
    // Timestamp=`date -Iseconds`
 | 
						|
    // Version="2015-04-01"
 | 
						|
    // SignatureNonce=`$RANDOM`
 | 
						|
    // RoleSessionName="default_session"
 | 
						|
    // RoleArn=$ALIBABA_CLOUD_ROLE_ARN
 | 
						|
    // OIDCProviderArn=$ALIBABA_CLOUD_OIDC_PROVIDER_ARN
 | 
						|
    // OIDCToken=`cat $ALIBABA_CLOUD_OIDC_TOKEN_FILE`
 | 
						|
    // curl "https://sts.aliyuncs.com?Action=$Action&Timestamp=$time" \
 | 
						|
            //     -H "Host: sts.aliyuncs.com" \
 | 
						|
            //     -H "Accept-Encoding: identity" \
 | 
						|
            //     -H "SignatureNonce: $SignatureNonce" \
 | 
						|
            //     -d
 | 
						|
    //     "RoleArn=$RoleArn&OIDCProviderArn=$OIDCProviderArn&OIDCToken=$OIDCToken&RoleSessionName=$RoleSessionName&Version=$Version"
 | 
						|
    ss << "Action=AssumeRoleWithOIDC"
 | 
						|
       << "&Timestamp=" /*iso8601*/
 | 
						|
       << Aws::Utils::StringUtils::URLEncode(
 | 
						|
              Aws::Utils::DateTime::Now()
 | 
						|
                  .ToGmtString(Aws::Utils::DateFormat::ISO_8601)
 | 
						|
                  .c_str())
 | 
						|
       << "&Version=2015-04-01"
 | 
						|
       << "&SignatureNonce="
 | 
						|
       << Aws::Utils::HashingUtils::HashString(
 | 
						|
              Aws::Utils::StringUtils::to_string(IntRand(0, INT_MAX)).c_str())
 | 
						|
       << "&RoleSessionName="
 | 
						|
       << Aws::Utils::StringUtils::URLEncode(request.roleSessionName.c_str())
 | 
						|
       << "&RoleArn="
 | 
						|
       << Aws::Utils::StringUtils::URLEncode(request.roleArn.c_str())
 | 
						|
       << "&OIDCProviderArn="
 | 
						|
       << Aws::Utils::StringUtils::URLEncode(m_aliyunOidcProviderArn.c_str())
 | 
						|
       << "&OIDCToken="
 | 
						|
       << Aws::Utils::StringUtils::URLEncode(request.webIdentityToken.c_str());
 | 
						|
 | 
						|
    std::shared_ptr<Aws::Http::HttpRequest> httpRequest(
 | 
						|
        Aws::Http::CreateHttpRequest(
 | 
						|
            m_endpoint,
 | 
						|
            Aws::Http::HttpMethod::HTTP_POST,
 | 
						|
            Aws::Utils::Stream::DefaultResponseStreamFactoryMethod));
 | 
						|
 | 
						|
    httpRequest->SetUserAgent(Aws::Client::ComputeUserAgentString());
 | 
						|
 | 
						|
    std::shared_ptr<Aws::IOStream> body =
 | 
						|
        Aws::MakeShared<Aws::StringStream>("STS_RESOURCE_CLIENT_LOG_TAG");
 | 
						|
    *body << ss.str();
 | 
						|
 | 
						|
    httpRequest->AddContentBody(body);
 | 
						|
    body->seekg(0, body->end);
 | 
						|
    auto streamSize = body->tellg();
 | 
						|
    body->seekg(0, body->beg);
 | 
						|
    Aws::StringStream contentLength;
 | 
						|
    contentLength << streamSize;
 | 
						|
    httpRequest->SetContentLength(contentLength.str());
 | 
						|
    httpRequest->SetContentType("application/x-www-form-urlencoded");
 | 
						|
 | 
						|
    Aws::String credentialsStr =
 | 
						|
        GetResourceWithAWSWebServiceResult(httpRequest).GetPayload();
 | 
						|
 | 
						|
    // Parse credentials
 | 
						|
    STSAssumeRoleWithWebIdentityResult result;
 | 
						|
    if (credentialsStr.empty()) {
 | 
						|
        AWS_LOGSTREAM_WARN(STS_RESOURCE_CLIENT_LOG_TAG,
 | 
						|
                           "Get an empty credential from sts");
 | 
						|
        return result;
 | 
						|
    }
 | 
						|
 | 
						|
    // [aliyun] output example
 | 
						|
    // <?xml version='1.0' encoding='UTF-8'?>
 | 
						|
    // <AssumeRoleWithOIDCResponse>
 | 
						|
    //     <RequestId>D94AFCC3-54CA-508C-B6AF-21481E761BDB</RequestId>
 | 
						|
    //     <OIDCTokenInfo>
 | 
						|
    //         <Issuer>https://oidc-ack-cn-shanghai.oss-cn-shanghai.aliyuncs.com/c532c4ce5e84048a1972535df283f737d</Issuer>
 | 
						|
    //         <Subject>system:serviceaccount:default:my-release</Subject>
 | 
						|
    //         <ClientIds>sts.aliyuncs.com</ClientIds>
 | 
						|
    //     </OIDCTokenInfo>
 | 
						|
    //     <AssumedRoleUser>
 | 
						|
    //         <Arn>acs:ram::1413891078881348:role/vdc-poc-milvus/default</Arn>
 | 
						|
    //         <AssumedRoleId>383373758575348335:default</AssumedRoleId>
 | 
						|
    //     </AssumedRoleUser>
 | 
						|
    //     <Credentials>
 | 
						|
    //         <SecurityToken>xxx</SecurityToken>
 | 
						|
    //         <AccessKeyId>xxx</AccessKeyId>
 | 
						|
    //         <AccessKeySecret>xxx</AccessKeySecret>
 | 
						|
    //         <Expiration>2023-03-02T07:39:09Z</Expiration>
 | 
						|
    //     </Credentials>
 | 
						|
    // </AssumeRoleWithOIDCResponse>
 | 
						|
    const Utils::Xml::XmlDocument xmlDocument =
 | 
						|
        Utils::Xml::XmlDocument::CreateFromXmlString(credentialsStr);
 | 
						|
    Utils::Xml::XmlNode rootNode = xmlDocument.GetRootElement();
 | 
						|
    Utils::Xml::XmlNode resultNode = rootNode;
 | 
						|
    if (!rootNode.IsNull() &&
 | 
						|
        (rootNode.GetName() != "AssumeRoleWithOIDCResponse")) {
 | 
						|
        resultNode =
 | 
						|
            rootNode.FirstChild("AssumeRoleWithOIDCResponse");  // [aliyun]
 | 
						|
    }
 | 
						|
 | 
						|
    if (!resultNode.IsNull()) {
 | 
						|
        Utils::Xml::XmlNode credentialsNode =
 | 
						|
            resultNode.FirstChild("Credentials");
 | 
						|
        if (!credentialsNode.IsNull()) {
 | 
						|
            Utils::Xml::XmlNode accessKeyIdNode =
 | 
						|
                credentialsNode.FirstChild("AccessKeyId");
 | 
						|
            if (!accessKeyIdNode.IsNull()) {
 | 
						|
                result.creds.SetAWSAccessKeyId(accessKeyIdNode.GetText());
 | 
						|
            }
 | 
						|
 | 
						|
            Utils::Xml::XmlNode secretAccessKeyNode =
 | 
						|
                credentialsNode.FirstChild("AccessKeySecret");  // [aliyun]
 | 
						|
            if (!secretAccessKeyNode.IsNull()) {
 | 
						|
                result.creds.SetAWSSecretKey(secretAccessKeyNode.GetText());
 | 
						|
            }
 | 
						|
 | 
						|
            Utils::Xml::XmlNode sessionTokenNode =
 | 
						|
                credentialsNode.FirstChild("SecurityToken");  // [aliyun]
 | 
						|
            if (!sessionTokenNode.IsNull()) {
 | 
						|
                result.creds.SetSessionToken(sessionTokenNode.GetText());
 | 
						|
            }
 | 
						|
 | 
						|
            Utils::Xml::XmlNode expirationNode =
 | 
						|
                credentialsNode.FirstChild("Expiration");
 | 
						|
            if (!expirationNode.IsNull()) {
 | 
						|
                result.creds.SetExpiration(
 | 
						|
                    Aws::Utils::DateTime(Aws::Utils::StringUtils::Trim(
 | 
						|
                                             expirationNode.GetText().c_str())
 | 
						|
                                             .c_str(),
 | 
						|
                                         Aws::Utils::DateFormat::ISO_8601));
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return result;
 | 
						|
}
 | 
						|
}  // namespace Internal
 | 
						|
}  // namespace Aws
 |