Skip to content

Commit 6cdbb4a

Browse files
authored
fix: PutObject with empty body (#64)
1 parent e68ea95 commit 6cdbb4a

File tree

2 files changed

+69
-3
lines changed

2 files changed

+69
-3
lines changed

v3/client/encryption_client_v3_test.go

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ import (
88
"context"
99
"encoding/hex"
1010
"fmt"
11-
"github.com/aws/amazon-s3-encryption-client-go/v3/internal/awstesting"
12-
"github.com/aws/amazon-s3-encryption-client-go/v3/materials"
13-
"github.com/aws/aws-sdk-go-v2/service/s3"
1411
"io"
1512
"net/http"
1613
"net/http/httptest"
1714
"reflect"
1815
"testing"
1916

17+
"github.com/aws/amazon-s3-encryption-client-go/v3/internal/awstesting"
18+
"github.com/aws/amazon-s3-encryption-client-go/v3/materials"
19+
"github.com/aws/aws-sdk-go-v2/service/s3"
20+
2021
"github.com/aws/aws-sdk-go-v2/aws"
2122
"github.com/aws/aws-sdk-go-v2/service/kms"
2223
)
@@ -137,3 +138,65 @@ func TestEncryptionClientV3_PutObject_KMSCONTEXT_AESGCM(t *testing.T) {
137138
t.Errorf("expected no error, got %v", err)
138139
}
139140
}
141+
142+
func TestEncryptionClientV3_PutObject_KMSCONTEXT_AESGCM_EmptyBody(t *testing.T) {
143+
ts := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
144+
fmt.Fprintln(writer, `{"CiphertextBlob":"8gSzlk7giyfFbLPUVgoVjvQebI1827jp8lDkO+n2chsiSoegx1sjm8NdPk0Bl70I","KeyId":"test-key-id","Plaintext":"lP6AbIQTmptyb/+WQq+ubDw+w7na0T1LGSByZGuaono="}`)
145+
}))
146+
147+
tKmsConfig := awstesting.Config()
148+
tKmsConfig.Region = "us-west-2"
149+
tKmsConfig.RetryMaxAttempts = 0
150+
tKmsConfig.EndpointResolverWithOptions = awstesting.TestEndpointResolver(ts.URL)
151+
kmsClient := kms.NewFromConfig(tKmsConfig)
152+
153+
var md materials.MaterialDescription
154+
iv, _ := hex.DecodeString("ae325acae2bfd5b9c3d0b813")
155+
kmsWithStaticIV := keyringWithStaticTestIV{
156+
IV: iv,
157+
Keyring: materials.NewKmsKeyring(kmsClient, "test-key-id", func(options *materials.KeyringOptions) {
158+
options.EnableLegacyWrappingAlgorithms = false
159+
}),
160+
}
161+
162+
tConfig := awstesting.Config()
163+
tHttpClient := &awstesting.MockHttpClient{
164+
Response: &http.Response{
165+
Status: http.StatusText(200),
166+
StatusCode: http.StatusOK,
167+
Body: io.NopCloser(bytes.NewReader([]byte{})),
168+
},
169+
}
170+
tConfig.HTTPClient = tHttpClient
171+
s3Client := s3.NewFromConfig(tConfig)
172+
173+
cmm, err := materials.NewCryptographicMaterialsManager(kmsWithStaticIV)
174+
if err != nil {
175+
t.Fatalf("error while trying to create new CMM: %v", err)
176+
}
177+
client, _ := New(s3Client, cmm)
178+
179+
_, err = client.PutObject(context.Background(), &s3.PutObjectInput{
180+
Bucket: aws.String("test-bucket"),
181+
Key: aws.String("test-key"),
182+
Body: new(bytes.Buffer),
183+
Metadata: md,
184+
})
185+
if err != nil {
186+
t.Fatalf("PutObject failed with %v", err)
187+
}
188+
189+
if tHttpClient.CapturedReq == nil || tHttpClient.CapturedBody == nil {
190+
t.Errorf("captured HTTP request/body was nil")
191+
}
192+
193+
expected, _ := hex.DecodeString("38a7dff91ec56105eedb716fe171675f")
194+
195+
if !bytes.Equal(tHttpClient.CapturedBody, expected) {
196+
t.Errorf("encrypted bytes did not match expected")
197+
}
198+
199+
if err != nil {
200+
t.Errorf("expected no error, got %v", err)
201+
}
202+
}

v3/internal/hash_io.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ func NewContentLengthReader(f io.Reader) *contentLengthReader {
2424
}
2525

2626
func (r *contentLengthReader) Read(b []byte) (int, error) {
27+
if r.body == nil {
28+
return 0, io.EOF
29+
}
2730
n, err := r.body.Read(b)
2831
if err != nil && err != io.EOF {
2932
return n, err

0 commit comments

Comments
 (0)