From f37e17a2add81101704177e540eb34b2cbcdb71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Lang?= Date: Tue, 14 Jun 2022 19:27:03 +0300 Subject: [PATCH] fix: aws signer v4 behavior broken with pre-existing Content-Length header Fixes https://github.com/aws/aws-sdk-go-v2/issues/1728 --- aws/signer/v4/v4.go | 1 + aws/signer/v4/v4_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/aws/signer/v4/v4.go b/aws/signer/v4/v4.go index 06ba7773ab5..54add923ba5 100644 --- a/aws/signer/v4/v4.go +++ b/aws/signer/v4/v4.go @@ -409,6 +409,7 @@ func (s *httpSigner) buildCanonicalHeaders(host string, rule v4Internal.Rule, he if length > 0 { const contentLengthHeader = "content-length" + header.Del(contentLengthHeader) headers = append(headers, contentLengthHeader) signed[contentLengthHeader] = append(signed[contentLengthHeader], strconv.FormatInt(length, 10)) } diff --git a/aws/signer/v4/v4_test.go b/aws/signer/v4/v4_test.go index 6cd881394e9..bd69644bb5c 100644 --- a/aws/signer/v4/v4_test.go +++ b/aws/signer/v4/v4_test.go @@ -5,6 +5,7 @@ import ( "context" "crypto/sha256" "encoding/hex" + "fmt" "io" "io/ioutil" "net/http" @@ -246,6 +247,38 @@ func TestRequestHost(t *testing.T) { t.Errorf("canonical host header invalid") } } + +func TestSign_buildCanonicalHeadersContentLengthPresent(t *testing.T) { + body := `{"description": "this is a test"}` + req, _ := buildRequest("dynamodb", "us-east-1", body) + req.URL.RawQuery = "Foo=z&Foo=o&Foo=m&Foo=a" + req.Host = "myhost" + + contentLength := fmt.Sprintf("%d", len([]byte(body))) + req.Header.Add("Content-Length", contentLength) + + query := req.URL.Query() + query.Set("X-Amz-Expires", "5") + req.URL.RawQuery = query.Encode() + + ctx := &httpSigner{ + ServiceName: "dynamodb", + Region: "us-east-1", + Request: req, + Time: v4Internal.NewSigningTime(time.Now()), + KeyDerivator: v4Internal.NewSigningKeyDeriver(), + } + + build, err := ctx.Build() + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + + if !strings.Contains(build.CanonicalString, "content-length:"+contentLength+"\n") { + t.Errorf("canonical header content-length invalid") + } +} + func TestSign_buildCanonicalHeaders(t *testing.T) { serviceName := "mockAPI" region := "mock-region"