diff --git a/test/s3/iam/s3_sts_assume_role_test.go b/test/s3/iam/s3_sts_assume_role_test.go index 4f24197ad..f0a6846a4 100644 --- a/test/s3/iam/s3_sts_assume_role_test.go +++ b/test/s3/iam/s3_sts_assume_role_test.go @@ -1,19 +1,17 @@ package iam import ( - "crypto/hmac" - "crypto/sha256" - "encoding/hex" "encoding/xml" "fmt" "io" "net/http" "net/url" - "sort" "strings" "testing" "time" + "github.com/aws/aws-sdk-go/aws/credentials" + v4 "github.com/aws/aws-sdk-go/aws/signer/v4" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -334,88 +332,19 @@ func callSTSAPIWithSigV4(t *testing.T, params url.Values, accessKey, secretKey s req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Host", req.URL.Host) - // Sign request with AWS Signature V4 - signRequestV4(req, body, accessKey, secretKey, "us-east-1", "sts") + // Sign request with AWS Signature V4 using official SDK + creds := credentials.NewStaticCredentials(accessKey, secretKey, "") + signer := v4.NewSigner(creds) + + // Read body for signing + // Note: We need a ReadSeeker for the signer, or we can pass the body string/bytes to ComputeBodyHash if needed, + // but standard Sign method takes an io.ReadSeeker for the body. + bodyReader := strings.NewReader(body) + _, err = signer.Sign(req, bodyReader, "sts", "us-east-1", time.Now()) + if err != nil { + return nil, fmt.Errorf("failed to sign request: %w", err) + } client := &http.Client{Timeout: 30 * time.Second} return client.Do(req) } - -// signRequestV4 signs an HTTP request using AWS Signature Version 4 -func signRequestV4(req *http.Request, payload, accessKey, secretKey, region, service string) { - // AWS SigV4 signing implementation - now := time.Now().UTC() - amzDate := now.Format("20060102T150405Z") - dateStamp := now.Format("20060102") - - // Set required headers - req.Header.Set("X-Amz-Date", amzDate) - - // Create canonical request - canonicalURI := "/" - canonicalQueryString := "" - - // Sort and format headers - signedHeaders := []string{"content-type", "host", "x-amz-date"} - sort.Strings(signedHeaders) - - canonicalHeaders := fmt.Sprintf("content-type:%s\nhost:%s\nx-amz-date:%s\n", - req.Header.Get("Content-Type"), - req.Host, - amzDate) - - signedHeadersStr := strings.Join(signedHeaders, ";") - - // Hash payload - payloadHash := sha256Hex(payload) - - canonicalRequest := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s", - req.Method, - canonicalURI, - canonicalQueryString, - canonicalHeaders, - signedHeadersStr, - payloadHash) - - // Create string to sign - algorithm := "AWS4-HMAC-SHA256" - credentialScope := fmt.Sprintf("%s/%s/%s/aws4_request", dateStamp, region, service) - stringToSign := fmt.Sprintf("%s\n%s\n%s\n%s", - algorithm, - amzDate, - credentialScope, - sha256Hex(canonicalRequest)) - - // Calculate signature - signingKey := getSignatureKey(secretKey, dateStamp, region, service) - signature := hex.EncodeToString(hmacSHA256(signingKey, stringToSign)) - - // Create authorization header - authHeader := fmt.Sprintf("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s", - algorithm, - accessKey, - credentialScope, - signedHeadersStr, - signature) - - req.Header.Set("Authorization", authHeader) -} - -func sha256Hex(data string) string { - hash := sha256.Sum256([]byte(data)) - return hex.EncodeToString(hash[:]) -} - -func hmacSHA256(key []byte, data string) []byte { - h := hmac.New(sha256.New, key) - h.Write([]byte(data)) - return h.Sum(nil) -} - -func getSignatureKey(secretKey, dateStamp, region, service string) []byte { - kDate := hmacSHA256([]byte("AWS4"+secretKey), dateStamp) - kRegion := hmacSHA256(kDate, region) - kService := hmacSHA256(kRegion, service) - kSigning := hmacSHA256(kService, "aws4_request") - return kSigning -}