rewrite, simplify, avoid unused functions (#6989)

* adding cors support

* address some comments

* optimize matchesWildcard

* address comments

* fix for tests

* address comments

* address comments

* address comments

* path building

* refactor

* Update weed/s3api/s3api_bucket_config.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* address comment

Service-level responses need both Access-Control-Allow-Methods and Access-Control-Allow-Headers. After setting Access-Control-Allow-Origin and Access-Control-Expose-Headers, also set Access-Control-Allow-Methods: * and Access-Control-Allow-Headers: * so service endpoints satisfy CORS preflight requirements.

* Update weed/s3api/s3api_bucket_config.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update weed/s3api/s3api_object_handlers.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update weed/s3api/s3api_object_handlers.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix

* refactor

* Update weed/s3api/s3api_bucket_config.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update weed/s3api/s3api_object_handlers.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update weed/s3api/s3api_server.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* simplify

* add cors tests

* fix tests

* fix tests

* remove unused functions

* fix tests

* simplify

* address comments

* fix

* Update weed/s3api/auth_signature_v4.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* rename variable

* Revert "Apply suggestion from @Copilot"

This reverts commit fce2d4e57e6f712672e62e8c63468c6b89878c6c.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Chris Lu
2025-07-15 10:11:49 -07:00
committed by GitHub
parent 4b040e8a87
commit 74f4e9ba5a
4 changed files with 529 additions and 951 deletions

View File

@@ -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})