Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

service/internal/checksum: Fix opt-in to checksum output validation #1607

Merged
merged 2 commits into from Mar 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changelog/239ee1b10e4041c484cf14e5e4c25337.json
@@ -0,0 +1,8 @@
{
"id": "239ee1b1-0e40-41c4-84cf-14e5e4c25337",
"type": "feature",
"description": " Updates the SDK's checksum validation logic to require opt-in to output response payload validation. The SDK was always preforming output response payload checksum validation, not respecting the output validation model option. Fixes [#1606](https://github.com/aws/aws-sdk-go-v2/issues/1606)",
"modules": [
"service/internal/checksum"
]
}
5 changes: 5 additions & 0 deletions service/internal/checksum/middleware_validate_output.go
Expand Up @@ -66,6 +66,11 @@ func (m *validateOutputPayloadChecksum) HandleDeserialize(
return out, metadata, err
}

// If there is no validation mode specified nothing is supported.
if mode := getContextOutputValidationMode(ctx); mode != "ENABLED" {
return out, metadata, err
}

response, ok := out.RawResponse.(*smithyhttp.Response)
if !ok {
return out, metadata, &smithy.DeserializationError{
Expand Down
58 changes: 54 additions & 4 deletions service/internal/checksum/middleware_validate_output_test.go
Expand Up @@ -23,6 +23,7 @@ func TestValidateOutputPayloadChecksum(t *testing.T) {
cases := map[string]struct {
response *smithyhttp.Response
validateOptions func(*validateOutputPayloadChecksum)
modifyContext func(context.Context) context.Context
expectHaveAlgorithmsUsed bool
expectAlgorithmsUsed []string
expectErr string
Expand All @@ -31,6 +32,9 @@ func TestValidateOutputPayloadChecksum(t *testing.T) {
expectPayload []byte
}{
"success": {
modifyContext: func(ctx context.Context) context.Context {
return setContextOutputValidationMode(ctx, "ENABLED")
},
response: &smithyhttp.Response{
Response: &http.Response{
StatusCode: 200,
Expand All @@ -47,6 +51,9 @@ func TestValidateOutputPayloadChecksum(t *testing.T) {
expectPayload: []byte("hello world"),
},
"failure": {
modifyContext: func(ctx context.Context) context.Context {
return setContextOutputValidationMode(ctx, "ENABLED")
},
response: &smithyhttp.Response{
Response: &http.Response{
StatusCode: 200,
Expand All @@ -61,6 +68,9 @@ func TestValidateOutputPayloadChecksum(t *testing.T) {
expectReadErr: "checksum did not match",
},
"read error": {
modifyContext: func(ctx context.Context) context.Context {
return setContextOutputValidationMode(ctx, "ENABLED")
},
response: &smithyhttp.Response{
Response: &http.Response{
StatusCode: 200,
Expand All @@ -75,6 +85,9 @@ func TestValidateOutputPayloadChecksum(t *testing.T) {
expectReadErr: "some read error",
},
"unsupported algorithm": {
modifyContext: func(ctx context.Context) context.Context {
return setContextOutputValidationMode(ctx, "ENABLED")
},
response: &smithyhttp.Response{
Response: &http.Response{
StatusCode: 200,
Expand All @@ -89,7 +102,39 @@ func TestValidateOutputPayloadChecksum(t *testing.T) {
expectLogged: "no supported checksum",
expectPayload: []byte("hello world"),
},
"no output validation model": {
response: &smithyhttp.Response{
Response: &http.Response{
StatusCode: 200,
Header: func() http.Header {
h := http.Header{}
return h
}(),
Body: ioutil.NopCloser(strings.NewReader("hello world")),
},
},
expectPayload: []byte("hello world"),
},
"unknown output validation model": {
modifyContext: func(ctx context.Context) context.Context {
return setContextOutputValidationMode(ctx, "something else")
},
response: &smithyhttp.Response{
Response: &http.Response{
StatusCode: 200,
Header: func() http.Header {
h := http.Header{}
return h
}(),
Body: ioutil.NopCloser(strings.NewReader("hello world")),
},
},
expectPayload: []byte("hello world"),
},
"success ignore multipart checksum": {
modifyContext: func(ctx context.Context) context.Context {
return setContextOutputValidationMode(ctx, "ENABLED")
},
response: &smithyhttp.Response{
Response: &http.Response{
StatusCode: 200,
Expand All @@ -109,6 +154,9 @@ func TestValidateOutputPayloadChecksum(t *testing.T) {
expectPayload: []byte("hello world"),
},
"success skip ignore multipart checksum": {
modifyContext: func(ctx context.Context) context.Context {
return setContextOutputValidationMode(ctx, "ENABLED")
},
response: &smithyhttp.Response{
Response: &http.Response{
StatusCode: 200,
Expand Down Expand Up @@ -136,6 +184,10 @@ func TestValidateOutputPayloadChecksum(t *testing.T) {
fmt.Fprintf(&logged, format, v...)
}))

if c.modifyContext != nil {
ctx = c.modifyContext(ctx)
}

validateOutput := validateOutputPayloadChecksum{
Algorithms: []Algorithm{
AlgorithmSHA1, AlgorithmCRC32, AlgorithmCRC32C,
Expand Down Expand Up @@ -187,10 +239,8 @@ func TestValidateOutputPayloadChecksum(t *testing.T) {
return
}

if c.expectLogged != "" {
if e, a := c.expectLogged, logged.String(); !strings.Contains(a, e) {
t.Errorf("expected %q logged in:\n%s", e, a)
}
if e, a := c.expectLogged, logged.String(); !strings.Contains(a, e) || !((e == "") == (a == "")) {
t.Errorf("expected %q logged in:\n%s", e, a)
}

if diff := cmp.Diff(string(c.expectPayload), string(actualPayload)); diff != "" {
Expand Down