diff options
Diffstat (limited to 'weed/s3api/auto_signature_v4_test.go')
| -rw-r--r-- | weed/s3api/auto_signature_v4_test.go | 112 |
1 files changed, 54 insertions, 58 deletions
diff --git a/weed/s3api/auto_signature_v4_test.go b/weed/s3api/auto_signature_v4_test.go index 86fbbd19e..b8b817ab8 100644 --- a/weed/s3api/auto_signature_v4_test.go +++ b/weed/s3api/auto_signature_v4_test.go @@ -6,13 +6,10 @@ import ( "crypto/sha256" "encoding/base64" "encoding/hex" - "errors" "fmt" "io" "net/http" - "net/url" "sort" - "strconv" "strings" "sync" "testing" @@ -76,7 +73,7 @@ func TestIsReqAuthenticated(t *testing.T) { SecretKey: "secret_key_1", }, }, - Actions: []string{}, + Actions: []string{"Read", "Write"}, }, }, }) @@ -149,7 +146,7 @@ func TestCheckAdminRequestAuthType(t *testing.T) { SecretKey: "secret_key_1", }, }, - Actions: []string{}, + Actions: []string{"Admin", "Read", "Write"}, }, }, }) @@ -170,15 +167,12 @@ func TestCheckAdminRequestAuthType(t *testing.T) { func BenchmarkGetSignature(b *testing.B) { t := time.Now() - iam := IdentityAccessManagement{ - hashes: make(map[string]*sync.Pool), - hashCounters: make(map[string]*int32), - } b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - iam.getSignature("secret-key", t, "us-east-1", "s3", "random data") + signingKey := getSigningKey("secret-key", t.Format(yyyymmdd), "us-east-1", "s3") + getSignature(signingKey, "random data") } } @@ -213,6 +207,53 @@ func mustNewPresignedRequest(iam *IdentityAccessManagement, method string, urlSt return req } +// preSignV4 adds presigned URL parameters to the request +func preSignV4(iam *IdentityAccessManagement, req *http.Request, accessKey, secretKey string, expires int64) error { + // Create credential scope + now := time.Now().UTC() + dateStr := now.Format(iso8601Format) + + // Create credential header + scope := fmt.Sprintf("%s/%s/%s/%s", now.Format(yyyymmdd), "us-east-1", "s3", "aws4_request") + credential := fmt.Sprintf("%s/%s", accessKey, scope) + + // Get the query parameters + query := req.URL.Query() + query.Set("X-Amz-Algorithm", signV4Algorithm) + query.Set("X-Amz-Credential", credential) + query.Set("X-Amz-Date", dateStr) + query.Set("X-Amz-Expires", fmt.Sprintf("%d", expires)) + query.Set("X-Amz-SignedHeaders", "host") + + // Set the query on the URL (without signature yet) + req.URL.RawQuery = query.Encode() + + // Get the payload hash + hashedPayload := getContentSha256Cksum(req) + + // Extract signed headers + extractedSignedHeaders := make(http.Header) + extractedSignedHeaders["host"] = []string{req.Host} + + // Get canonical request + canonicalRequest := getCanonicalRequest(extractedSignedHeaders, hashedPayload, req.URL.RawQuery, req.URL.Path, req.Method) + + // Get string to sign + stringToSign := getStringToSign(canonicalRequest, now, scope) + + // Get signing key + signingKey := getSigningKey(secretKey, now.Format(yyyymmdd), "us-east-1", "s3") + + // Calculate signature + signature := getSignature(signingKey, stringToSign) + + // Add signature to query + query.Set("X-Amz-Signature", signature) + req.URL.RawQuery = query.Encode() + + return nil +} + // Returns new HTTP request object. func newTestRequest(method, urlStr string, contentLength int64, body io.ReadSeeker) (*http.Request, error) { if method == "" { @@ -254,11 +295,6 @@ func newTestRequest(method, urlStr string, contentLength int64, body io.ReadSeek return req, nil } -// getSHA256Hash returns SHA-256 hash in hex encoding of given data. -func getSHA256Hash(data []byte) string { - return hex.EncodeToString(getSHA256Sum(data)) -} - // getMD5HashBase64 returns MD5 hash in base64 encoding of given data. func getMD5HashBase64(data []byte) string { return base64.StdEncoding.EncodeToString(getMD5Sum(data)) @@ -467,46 +503,6 @@ func signRequestV4(req *http.Request, accessKey, secretKey string) error { return nil } -// preSignV4 presign the request, in accordance with -// http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html. -func preSignV4(iam *IdentityAccessManagement, req *http.Request, accessKeyID, secretAccessKey string, expires int64) error { - // Presign is not needed for anonymous credentials. - if accessKeyID == "" || secretAccessKey == "" { - return errors.New("Presign cannot be generated without access and secret keys") - } - - region := "us-east-1" - date := time.Now().UTC() - scope := getScope(date, region) - credential := fmt.Sprintf("%s/%s", accessKeyID, scope) - - // Set URL query. - query := req.URL.Query() - query.Set("X-Amz-Algorithm", signV4Algorithm) - query.Set("X-Amz-Date", date.Format(iso8601Format)) - query.Set("X-Amz-Expires", strconv.FormatInt(expires, 10)) - query.Set("X-Amz-SignedHeaders", "host") - query.Set("X-Amz-Credential", credential) - query.Set("X-Amz-Content-Sha256", unsignedPayload) - - // "host" is the only header required to be signed for Presigned URLs. - extractedSignedHeaders := make(http.Header) - extractedSignedHeaders.Set("host", req.Host) - - queryStr := strings.Replace(query.Encode(), "+", "%20", -1) - canonicalRequest := getCanonicalRequest(extractedSignedHeaders, unsignedPayload, queryStr, req.URL.Path, req.Method) - stringToSign := getStringToSign(canonicalRequest, date, scope) - signature := iam.getSignature(secretAccessKey, date, region, "s3", stringToSign) - - req.URL.RawQuery = query.Encode() - - // Add signature header to RawQuery. - req.URL.RawQuery += "&X-Amz-Signature=" + url.QueryEscape(signature) - - // Construct the final presigned URL. - return nil -} - // EncodePath encode the strings from UTF-8 byte representations to HTML hex escape sequences // // This is necessary since regular url.Parse() and url.Encode() functions do not support UTF-8 @@ -529,12 +525,12 @@ func EncodePath(pathName string) string { encodedPathname = encodedPathname + string(s) continue default: - len := utf8.RuneLen(s) - if len < 0 { + runeLen := utf8.RuneLen(s) + if runeLen < 0 { // if utf8 cannot convert return the same string as is return pathName } - u := make([]byte, len) + u := make([]byte, runeLen) utf8.EncodeRune(u, s) for _, r := range u { hex := hex.EncodeToString([]byte{r}) |
