cubefs/objectnode/auth_signature_v2.go
yhjiango 135da4ec9f refactor(object): add CubeFS's statement comment
Signed-off-by: yhjiango <jiangyunhua@oppo.com>
2024-01-10 14:58:30 +08:00

131 lines
3.5 KiB
Go

// Copyright 2019 The CubeFS Authors.
//
// 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.
package objectnode
import (
"encoding/base64"
"net/http"
"net/url"
"sort"
"strings"
)
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/RESTAuthentication.html
var signV2SubresourceQueries = map[string]bool{
"acl": true,
"cors": true,
"delete": true,
"encryption": true,
"lifecycle": true,
"location": true,
"logging": true,
"notification": true,
"partNumber": true,
"policy": true,
"requestPayment": true,
"restore": true,
"retention": true,
"tagging": true,
"torrent": true,
"uploadId": true,
"uploads": true,
"versionId": true,
"versioning": true,
"versions": true,
"website": true,
}
var signV2ResponseHeaderQueries = map[string]bool{
"response-cache-control": true,
"response-content-disposition": true,
"response-content-encoding": true,
"response-content-language": true,
"response-content-type": true,
"response-expires": true,
}
func buildStringToSignV2(method, date, canonicalizedResource string, header http.Header) string {
canonicalAmzHeaders := buildCanonicalizedAmzHeadersV2(header)
if len(canonicalAmzHeaders) > 0 {
canonicalAmzHeaders += "\n"
}
return strings.Join([]string{
method,
header.Get(ContentMD5),
header.Get(ContentType),
date,
canonicalAmzHeaders,
}, "\n") + canonicalizedResource
}
func buildCanonicalizedAmzHeadersV2(headers http.Header) string {
xAmzKeys := make([]string, 0)
xAmzHeaders := make(map[string]string)
for key := range headers {
lowKey := strings.ToLower(key)
if !strings.HasPrefix(lowKey, "x-amz-") {
continue
}
xAmzKeys = append(xAmzKeys, lowKey)
xAmzHeaders[lowKey] = strings.Join(headers[key], ",")
}
sort.Strings(xAmzKeys)
canonicalizedHeaders := make([]string, 0, len(xAmzKeys))
for _, key := range xAmzKeys {
canonicalizedHeaders = append(canonicalizedHeaders, key+":"+xAmzHeaders[key])
}
return strings.Join(canonicalizedHeaders, "\n")
}
func buildCanonicalizedResourceQueryV2(resource string, query url.Values) string {
var queries []string
for name := range query {
if signV2SubresourceQueries[name] || signV2ResponseHeaderQueries[name] {
var q string
value := query.Get(name)
if value == "" && signV2SubresourceQueries[name] {
q = name
} else {
q = name + "=" + value
}
queries = append(queries, q)
}
}
sort.Strings(queries)
if q := strings.Join(queries, "&"); q != "" {
return resource + "?" + q
}
return resource
}
func buildCanonicalizedResourceV2(r *http.Request, ws Wildcards) (resource string) {
path := r.URL.EscapedPath()
if bucket, wildcard := ws.Parse(r.Host); wildcard {
resource = "/" + bucket + path
} else {
resource = path
}
return
}
func calculateSignatureV2(secretKey, stringToSign string) string {
return base64.StdEncoding.EncodeToString(MakeHmacSha1([]byte(secretKey), []byte(stringToSign)))
}