in cluster-autoscaler/cloudprovider/tencentcloud/tencentcloud-sdk-go/common/client.go [280:443]
func (c *Client) sendWithSignatureV3(request tchttp.Request, response tchttp.Response) (err error) {
headers := map[string]string{
"Host": request.GetDomain(),
"X-TC-Action": request.GetAction(),
"X-TC-Version": request.GetVersion(),
"X-TC-Timestamp": request.GetParams()["Timestamp"],
"X-TC-RequestClient": request.GetParams()["RequestClient"],
"X-TC-Language": c.profile.Language,
}
if c.region != "" {
headers["X-TC-Region"] = c.region
}
if c.credential.GetToken() != "" {
headers["X-TC-Token"] = c.credential.GetToken()
}
if request.GetHttpMethod() == "GET" {
headers["Content-Type"] = "application/x-www-form-urlencoded"
} else {
headers["Content-Type"] = "application/json"
}
isOctetStream := false
cr := &tchttp.CommonRequest{}
ok := false
var octetStreamBody []byte
if cr, ok = request.(*tchttp.CommonRequest); ok {
if cr.IsOctetStream() {
isOctetStream = true
// custom headers must contain Content-Type : application/octet-stream
// todo:the custom header may overwrite headers
for k, v := range cr.GetHeader() {
headers[k] = v
}
octetStreamBody = cr.GetOctetStreamBody()
}
}
for k, v := range request.GetHeader() {
switch k {
case "X-TC-Action", "X-TC-Version", "X-TC-Timestamp", "X-TC-RequestClient",
"X-TC-Language", "X-TC-Region", "X-TC-Token":
c.logger.Printf("Skip header \"%s\": can not specify built-in header", k)
default:
headers[k] = v
}
}
if !isOctetStream && request.GetContentType() == octetStream {
isOctetStream = true
b, _ := json.Marshal(request)
var m map[string]string
_ = json.Unmarshal(b, &m)
for k, v := range m {
key := "X-" + strings.ToUpper(request.GetService()) + "-" + k
headers[key] = v
}
headers["Content-Type"] = octetStream
octetStreamBody = request.GetBody()
}
// start signature v3 process
// build canonical request string
httpRequestMethod := request.GetHttpMethod()
canonicalURI := "/"
canonicalQueryString := ""
if httpRequestMethod == "GET" {
err = tchttp.ConstructParams(request)
if err != nil {
return err
}
params := make(map[string]string)
for key, value := range request.GetParams() {
params[key] = value
}
delete(params, "Action")
delete(params, "Version")
delete(params, "Nonce")
delete(params, "Region")
delete(params, "RequestClient")
delete(params, "Timestamp")
canonicalQueryString = tchttp.GetUrlQueriesEncoded(params)
}
canonicalHeaders := fmt.Sprintf("content-type:%s\nhost:%s\n", headers["Content-Type"], headers["Host"])
signedHeaders := "content-type;host"
requestPayload := ""
if httpRequestMethod == "POST" {
if isOctetStream {
// todo Conversion comparison between string and []byte affects performance much
requestPayload = string(octetStreamBody)
} else {
b, err := json.Marshal(request)
if err != nil {
return err
}
requestPayload = string(b)
}
}
hashedRequestPayload := ""
if c.unsignedPayload {
hashedRequestPayload = sha256hex("UNSIGNED-PAYLOAD")
headers["X-TC-Content-SHA256"] = "UNSIGNED-PAYLOAD"
} else {
hashedRequestPayload = sha256hex(requestPayload)
}
canonicalRequest := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s",
httpRequestMethod,
canonicalURI,
canonicalQueryString,
canonicalHeaders,
signedHeaders,
hashedRequestPayload)
//log.Println("canonicalRequest:", canonicalRequest)
// build string to sign
algorithm := "TC3-HMAC-SHA256"
requestTimestamp := headers["X-TC-Timestamp"]
timestamp, _ := strconv.ParseInt(requestTimestamp, 10, 64)
t := time.Unix(timestamp, 0).UTC()
// must be the format 2006-01-02, ref to package time for more info
date := t.Format("2006-01-02")
credentialScope := fmt.Sprintf("%s/%s/tc3_request", date, request.GetService())
hashedCanonicalRequest := sha256hex(canonicalRequest)
string2sign := fmt.Sprintf("%s\n%s\n%s\n%s",
algorithm,
requestTimestamp,
credentialScope,
hashedCanonicalRequest)
//log.Println("string2sign", string2sign)
// sign string
secretDate := hmacsha256(date, "TC3"+c.credential.GetSecretKey())
secretService := hmacsha256(request.GetService(), secretDate)
secretKey := hmacsha256("tc3_request", secretService)
signature := hex.EncodeToString([]byte(hmacsha256(string2sign, secretKey)))
//log.Println("signature", signature)
// build authorization
authorization := fmt.Sprintf("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s",
algorithm,
c.credential.GetSecretId(),
credentialScope,
signedHeaders,
signature)
//log.Println("authorization", authorization)
headers["Authorization"] = authorization
url := request.GetScheme() + "://" + request.GetDomain() + request.GetPath()
if canonicalQueryString != "" {
url = url + "?" + canonicalQueryString
}
httpRequest, err := http.NewRequestWithContext(request.GetContext(), httpRequestMethod, url, strings.NewReader(requestPayload))
if err != nil {
return err
}
for k, v := range headers {
httpRequest.Header[k] = []string{v}
}
httpResponse, err := c.sendWithRateLimitRetry(httpRequest, isRetryable(request))
if err != nil {
return err
}
err = tchttp.ParseFromHttpResponse(httpResponse, response)
return err
}