Skip to content

Commit

Permalink
aws/signer/v4: Add helper for using unsigned payload instead of compu…
Browse files Browse the repository at this point in the history
…te hash

Updates the v4 package with a new helper to swap out the compute payload
hash middleware for the unsigned payload middleware. This allows API
operations to be updated to not compute the payload hash, and
use UNSIGNED-PAYLOAD instead.
  • Loading branch information
jasdel committed Mar 17, 2021
1 parent 93d967a commit e955ccf
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .changes/next-release/sdk-feature-1615946574682127000.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"ID": "sdk-feature-1615946574682127000",
"SchemaVersion": 1,
"Module": "/",
"Type": "feature",
"Description": "Add helper to V4 signer package to swap compute payload hash middleware with unsigned payload middleware",
"MinVersion": "",
"AffectedModules": null
}
10 changes: 10 additions & 0 deletions aws/signer/v4/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ func (m *computePayloadSHA256) HandleBuild(
return next.HandleBuild(ctx, in)
}

// SwapComputePayloadSHA256ForUnsignedPayloadMiddleware replaces the
// ComputePayloadSHA256 middleware with the UnsignedPayload middleware.
//
// Use this to disable computing the Payload SHA256 checksum and instead use
// UNSIGNED-PAYLOAD for the SHA256 value.
func SwapComputePayloadSHA256ForUnsignedPayloadMiddleware(stack *middleware.Stack) error {
_, err := stack.Build.Swap(computePayloadHashMiddlewareID, &unsignedPayload{})
return err
}

// contentSHA256Header sets the X-Amz-Content-Sha256 header value to
// the Payload hash stored in the context.
type contentSHA256Header struct{}
Expand Down
101 changes: 101 additions & 0 deletions aws/signer/v4/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/aws/smithy-go/logging"
"github.com/aws/smithy-go/middleware"
smithyhttp "github.com/aws/smithy-go/transport/http"
"github.com/google/go-cmp/cmp"
)

func TestComputePayloadHashMiddleware(t *testing.T) {
Expand Down Expand Up @@ -205,6 +206,106 @@ func TestSignHTTPRequestMiddleware(t *testing.T) {
}
}

func TestSwapComputePayloadSHA256ForUnsignedPayloadMiddleware(t *testing.T) {
cases := map[string]struct {
InitStep func(*middleware.Stack) error
Mutator func(*middleware.Stack) error
ExpectErr string
ExpectIDs []string
}{
"swap in place": {
InitStep: func(s *middleware.Stack) (err error) {
err = s.Build.Add(middleware.BuildMiddlewareFunc("before", nil), middleware.After)
if err != nil {
return err
}
err = AddComputePayloadSHA256Middleware(s)
if err != nil {
return err
}
err = s.Build.Add(middleware.BuildMiddlewareFunc("after", nil), middleware.After)
if err != nil {
return err
}
return nil
},
Mutator: SwapComputePayloadSHA256ForUnsignedPayloadMiddleware,
ExpectIDs: []string{
"before",
computePayloadHashMiddlewareID,
"after",
},
},

"already unsigned payload exists": {
InitStep: func(s *middleware.Stack) (err error) {
err = s.Build.Add(middleware.BuildMiddlewareFunc("before", nil), middleware.After)
if err != nil {
return err
}
err = AddUnsignedPayloadMiddleware(s)
if err != nil {
return err
}
err = s.Build.Add(middleware.BuildMiddlewareFunc("after", nil), middleware.After)
if err != nil {
return err
}
return nil
},
Mutator: SwapComputePayloadSHA256ForUnsignedPayloadMiddleware,
ExpectIDs: []string{
"before",
computePayloadHashMiddlewareID,
"after",
},
},

"no compute payload": {
InitStep: func(s *middleware.Stack) (err error) {
err = s.Build.Add(middleware.BuildMiddlewareFunc("before", nil), middleware.After)
if err != nil {
return err
}
err = s.Build.Add(middleware.BuildMiddlewareFunc("after", nil), middleware.After)
if err != nil {
return err
}
return nil
},
Mutator: SwapComputePayloadSHA256ForUnsignedPayloadMiddleware,
ExpectErr: "not found, " + computePayloadHashMiddlewareID,
},
}

for name, c := range cases {
t.Run(name, func(t *testing.T) {
stack := middleware.NewStack(t.Name(), smithyhttp.NewStackRequest)
if err := c.InitStep(stack); err != nil {
t.Fatalf("expect no error, got %v", err)
}

err := c.Mutator(stack)
if len(c.ExpectErr) != 0 {
if err == nil {
t.Fatalf("expect error, got none")
}
if e, a := c.ExpectErr, err.Error(); !strings.Contains(a, e) {
t.Fatalf("expect error to contain %v, got %v", e, a)
}
return
}
if err != nil {
t.Fatalf("expect no error, got %v", err)
}

if diff := cmp.Diff(c.ExpectIDs, stack.Build.List()); len(diff) != 0 {
t.Errorf("expect match\n%v", diff)
}
})
}
}

type nonSeeker struct{}

func (nonSeeker) Read(p []byte) (n int, err error) {
Expand Down

0 comments on commit e955ccf

Please sign in to comment.