github.com/opentelekomcloud/gophertelekomcloud@v0.9.3/openstack/obs/authV4.go (about)

     1  package obs
     2  
     3  import (
     4  	"strings"
     5  	"time"
     6  )
     7  
     8  func getV4StringToSign(method, canonicalizedURL, queryURL, scope, longDate, payload string, signedHeaders []string, headers map[string][]string) string {
     9  	canonicalRequest := make([]string, 0, 10+len(signedHeaders)*4)
    10  	canonicalRequest = append(canonicalRequest, method)
    11  	canonicalRequest = append(canonicalRequest, "\n")
    12  	canonicalRequest = append(canonicalRequest, canonicalizedURL)
    13  	canonicalRequest = append(canonicalRequest, "\n")
    14  	canonicalRequest = append(canonicalRequest, queryURL)
    15  	canonicalRequest = append(canonicalRequest, "\n")
    16  
    17  	for _, signedHeader := range signedHeaders {
    18  		values := headers[signedHeader]
    19  		for _, value := range values {
    20  			canonicalRequest = append(canonicalRequest, signedHeader)
    21  			canonicalRequest = append(canonicalRequest, ":")
    22  			canonicalRequest = append(canonicalRequest, value)
    23  			canonicalRequest = append(canonicalRequest, "\n")
    24  		}
    25  	}
    26  	canonicalRequest = append(canonicalRequest, "\n")
    27  	canonicalRequest = append(canonicalRequest, strings.Join(signedHeaders, ";"))
    28  	canonicalRequest = append(canonicalRequest, "\n")
    29  	canonicalRequest = append(canonicalRequest, payload)
    30  
    31  	_canonicalRequest := strings.Join(canonicalRequest, "")
    32  
    33  	var isSecurityToken bool
    34  	var securityToken []string
    35  	if securityToken, isSecurityToken = headers[HEADER_STS_TOKEN_OBS]; !isSecurityToken {
    36  		securityToken, isSecurityToken = headers[HEADER_STS_TOKEN_AMZ]
    37  	}
    38  	var query []string
    39  	if !isSecurityToken {
    40  		query = strings.Split(queryURL, "&")
    41  		for _, value := range query {
    42  			if strings.HasPrefix(value, HEADER_STS_TOKEN_AMZ+"=") || strings.HasPrefix(value, HEADER_STS_TOKEN_OBS+"=") {
    43  				if value[len(HEADER_STS_TOKEN_AMZ)+1:] != "" {
    44  					securityToken = []string{value[len(HEADER_STS_TOKEN_AMZ)+1:]}
    45  					isSecurityToken = true
    46  				}
    47  			}
    48  		}
    49  	}
    50  	logCanonicalRequest := _canonicalRequest
    51  	if isSecurityToken && len(securityToken) > 0 {
    52  		logCanonicalRequest = strings.Replace(logCanonicalRequest, securityToken[0], "******", -1)
    53  	}
    54  	doLog(LEVEL_DEBUG, "The v4 auth canonicalRequest:\n%s", logCanonicalRequest)
    55  
    56  	stringToSign := make([]string, 0, 7)
    57  	stringToSign = append(stringToSign, V4_HASH_PREFIX)
    58  	stringToSign = append(stringToSign, "\n")
    59  	stringToSign = append(stringToSign, longDate)
    60  	stringToSign = append(stringToSign, "\n")
    61  	stringToSign = append(stringToSign, scope)
    62  	stringToSign = append(stringToSign, "\n")
    63  	stringToSign = append(stringToSign, HexSha256([]byte(_canonicalRequest)))
    64  
    65  	_stringToSign := strings.Join(stringToSign, "")
    66  
    67  	doLog(LEVEL_DEBUG, "The v4 auth stringToSign:\n%s", _stringToSign)
    68  	return _stringToSign
    69  }
    70  
    71  // V4Auth is a wrapper for v4Auth
    72  func V4Auth(ak, sk, region, method, canonicalizedURL, queryURL string, headers map[string][]string) map[string]string {
    73  	return v4Auth(ak, sk, region, method, canonicalizedURL, queryURL, headers)
    74  }
    75  
    76  func v4Auth(ak, sk, region, method, canonicalizedURL, queryURL string, headers map[string][]string) map[string]string {
    77  	var t time.Time
    78  	if val, ok := headers[HEADER_DATE_AMZ]; ok {
    79  		var err error
    80  		t, err = time.Parse(LONG_DATE_FORMAT, val[0])
    81  		if err != nil {
    82  			t = time.Now().UTC()
    83  		}
    84  	} else if val, ok := headers[PARAM_DATE_AMZ_CAMEL]; ok {
    85  		var err error
    86  		t, err = time.Parse(LONG_DATE_FORMAT, val[0])
    87  		if err != nil {
    88  			t = time.Now().UTC()
    89  		}
    90  	} else if val, ok := headers[HEADER_DATE_CAMEL]; ok {
    91  		var err error
    92  		t, err = time.Parse(RFC1123_FORMAT, val[0])
    93  		if err != nil {
    94  			t = time.Now().UTC()
    95  		}
    96  	} else if val, ok := headers[strings.ToLower(HEADER_DATE_CAMEL)]; ok {
    97  		var err error
    98  		t, err = time.Parse(RFC1123_FORMAT, val[0])
    99  		if err != nil {
   100  			t = time.Now().UTC()
   101  		}
   102  	} else {
   103  		t = time.Now().UTC()
   104  	}
   105  	shortDate := t.Format(SHORT_DATE_FORMAT)
   106  	longDate := t.Format(LONG_DATE_FORMAT)
   107  
   108  	signedHeaders, _headers := getSignedHeaders(headers)
   109  
   110  	credential, scope := getCredential(ak, region, shortDate)
   111  
   112  	payload := UNSIGNED_PAYLOAD
   113  	if val, ok := headers[HEADER_CONTENT_SHA256_AMZ]; ok {
   114  		payload = val[0]
   115  	}
   116  	stringToSign := getV4StringToSign(method, canonicalizedURL, queryURL, scope, longDate, payload, signedHeaders, _headers)
   117  
   118  	signature := getSignature(stringToSign, sk, region, shortDate)
   119  
   120  	ret := make(map[string]string, 3)
   121  	ret["Credential"] = credential
   122  	ret["SignedHeaders"] = strings.Join(signedHeaders, ";")
   123  	ret["Signature"] = signature
   124  	return ret
   125  }