Skip to content

Commit

Permalink
aws/signer/v4: Fix Signer not trimming header value spaces (#4141)
Browse files Browse the repository at this point in the history
Fixes the AWS Sigv4 signer to trim header value's whitespace when
computing the canonical headers block of the string to sign.
  • Loading branch information
jasdel authored Nov 3, 2021
1 parent 55a78b3 commit a7b0293
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
### SDK Enhancements

### SDK Bugs
* `aws/signer/v4`: Fix Signer not trimming header value spaces
* Fixes the AWS Sigv4 signer to trim header value's whitespace when computing the canonical headers block of the string to sign.
18 changes: 11 additions & 7 deletions aws/signer/v4/v4.go
Original file line number Diff line number Diff line change
Expand Up @@ -634,21 +634,25 @@ func (ctx *signingCtx) buildCanonicalHeaders(r rule, header http.Header) {
ctx.Query.Set("X-Amz-SignedHeaders", ctx.signedHeaders)
}

headerValues := make([]string, len(headers))
headerItems := make([]string, len(headers))
for i, k := range headers {
if k == "host" {
if ctx.Request.Host != "" {
headerValues[i] = "host:" + ctx.Request.Host
headerItems[i] = "host:" + ctx.Request.Host
} else {
headerValues[i] = "host:" + ctx.Request.URL.Host
headerItems[i] = "host:" + ctx.Request.URL.Host
}
} else {
headerValues[i] = k + ":" +
strings.Join(ctx.SignedHeaderVals[k], ",")
headerValues := make([]string, len(ctx.SignedHeaderVals[k]))
for i, v := range ctx.SignedHeaderVals[k] {
headerValues[i] = strings.TrimSpace(v)
}
headerItems[i] = k + ":" +
strings.Join(headerValues, ",")
}
}
stripExcessSpaces(headerValues)
ctx.canonicalHeaders = strings.Join(headerValues, "\n")
stripExcessSpaces(headerItems)
ctx.canonicalHeaders = strings.Join(headerItems, "\n")
}

func (ctx *signingCtx) buildCanonicalString() {
Expand Down
47 changes: 47 additions & 0 deletions aws/signer/v4/v4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,53 @@ func TestRequestHost(t *testing.T) {
}
}

func TestSign_buildCanonicalHeaders(t *testing.T) {
serviceName := "mockAPI"
region := "mock-region"
endpoint := "https://" + serviceName + "." + region + ".amazonaws.com"

req, err := http.NewRequest("POST", endpoint, nil)
if err != nil {
t.Fatalf("failed to create request, %v", err)
}

req.Header.Set("FooInnerSpace", " inner space ")
req.Header.Set("FooLeadingSpace", " leading-space")
req.Header.Add("FooMultipleSpace", "no-space")
req.Header.Add("FooMultipleSpace", "\ttab-space")
req.Header.Add("FooMultipleSpace", "trailing-space ")
req.Header.Set("FooNoSpace", "no-space")
req.Header.Set("FooTabSpace", "\ttab-space\t")
req.Header.Set("FooTrailingSpace", "trailing-space ")
req.Header.Set("FooWrappedSpace", " wrapped-space ")

ctx := &signingCtx{
ServiceName: serviceName,
Region: region,
Request: req,
Body: nil,
Query: req.URL.Query(),
Time: time.Now(),
ExpireTime: 5 * time.Second,
}

ctx.buildCanonicalHeaders(ignoredHeaders, ctx.Request.Header)

expectCanonicalHeaders := strings.Join([]string{
`fooinnerspace:inner space`,
`fooleadingspace:leading-space`,
`foomultiplespace:no-space,tab-space,trailing-space`,
`foonospace:no-space`,
`footabspace:tab-space`,
`footrailingspace:trailing-space`,
`foowrappedspace:wrapped-space`,
`host:mockAPI.mock-region.amazonaws.com`,
}, "\n")
if e, a := expectCanonicalHeaders, ctx.canonicalHeaders; e != a {
t.Errorf("expect:\n%s\n\nactual:\n%s", e, a)
}
}

func BenchmarkPresignRequest(b *testing.B) {
signer := buildSigner()
req, body := buildRequestReaderSeeker("dynamodb", "us-east-1", "{}")
Expand Down

0 comments on commit a7b0293

Please sign in to comment.