Skip to content

Commit f7d5314

Browse files
committed
fix(object): copyObject with encryption
1 parent faa7035 commit f7d5314

File tree

3 files changed

+3017
-13
lines changed

3 files changed

+3017
-13
lines changed

internal/services/object/object.go

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"context"
66
"crypto/md5"
77
"encoding/base64"
8+
"errors"
89
"fmt"
910
"github.com/aws/aws-sdk-go-v2/aws"
1011
"os"
@@ -113,6 +114,13 @@ func ResourceObject() *schema.Resource {
113114
Sensitive: true,
114115
Description: "Customer's encryption keys to encrypt data (SSE-C)",
115116
},
117+
"sse_cutomer_key_md5": {
118+
Type: schema.TypeString,
119+
Optional: true,
120+
Sensitive: true,
121+
Description: "Cutomer's encryption key MD5 to encrypt data (SSE-C)",
122+
Computed: true,
123+
},
116124
"region": regional.Schema(),
117125
"project_id": account.ProjectIDSchema(),
118126
},
@@ -157,17 +165,13 @@ func resourceObjectCreate(ctx context.Context, d *schema.ResourceData, m interfa
157165
}
158166

159167
if encryptionKeyStr, ok := d.Get("sse_customer_key").(string); ok {
160-
encryptionKey := []byte(encryptionKeyStr)
161-
h := md5.New()
162-
_, err := h.Write(encryptionKey)
168+
digestMD5, encryption, err := EncryptCustomerKey(encryptionKeyStr)
163169
if err != nil {
164170
return diag.FromErr(err)
165171
}
166-
digest := h.Sum(nil)
167-
digestMD5 := base64.StdEncoding.EncodeToString(digest)
168172
req.SSECustomerAlgorithm = scw.StringPtr("AES256")
169173
req.SSECustomerKeyMD5 = &digestMD5
170-
req.SSECustomerKey = aws.String(base64.StdEncoding.EncodeToString(encryptionKey))
174+
req.SSECustomerKey = encryption
171175
}
172176

173177
if filePath, hasFile := d.GetOk("file"); hasFile {
@@ -214,6 +218,23 @@ func resourceObjectCreate(ctx context.Context, d *schema.ResourceData, m interfa
214218
return resourceObjectRead(ctx, d, m)
215219
}
216220

221+
func EncryptCustomerKey(encryptionKeyStr string) (string, *string, error) {
222+
encryptionKey := []byte(encryptionKeyStr)
223+
// TODO remove when error message fix
224+
if len(encryptionKey) != 32 {
225+
return "", nil, errors.New("encryption key must be 32 bytes long")
226+
}
227+
h := md5.New()
228+
_, err := h.Write(encryptionKey)
229+
if err != nil {
230+
return "", nil, err
231+
}
232+
digest := h.Sum(nil)
233+
digestMD5 := base64.StdEncoding.EncodeToString(digest)
234+
encryption := aws.String(base64.StdEncoding.EncodeToString(encryptionKey))
235+
return digestMD5, encryption, nil
236+
}
237+
217238
func resourceObjectUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
218239
s3Client, region, key, bucket, err := s3ClientWithRegionAndNestedName(ctx, d, m, d.Id())
219240
if err != nil {
@@ -234,7 +255,15 @@ func resourceObjectUpdate(ctx context.Context, d *schema.ResourceData, m interfa
234255
Metadata: types.ExpandMapStringString(d.Get("metadata")),
235256
ACL: s3Types.ObjectCannedACL(d.Get("visibility").(string)),
236257
}
237-
258+
if encryptionKey, ok := d.GetOk("sse_customer_key"); ok {
259+
digestMD5, encryption, err := EncryptCustomerKey(encryptionKey.(string))
260+
if err != nil {
261+
return diag.FromErr(err)
262+
}
263+
req.SSECustomerAlgorithm = scw.StringPtr("AES256")
264+
req.SSECustomerKeyMD5 = &digestMD5
265+
req.SSECustomerKey = encryption
266+
}
238267
if filePath, hasFile := d.GetOk("file"); hasFile {
239268
file, err := os.Open(filePath.(string))
240269
if err != nil {
@@ -246,14 +275,24 @@ func resourceObjectUpdate(ctx context.Context, d *schema.ResourceData, m interfa
246275
}
247276
_, err = s3Client.PutObject(ctx, req)
248277
} else {
249-
_, err = s3Client.CopyObject(ctx, &s3.CopyObjectInput{
278+
req := &s3.CopyObjectInput{
250279
Bucket: types.ExpandStringPtr(bucketUpdated),
251280
Key: types.ExpandStringPtr(keyUpdated),
252281
StorageClass: s3Types.StorageClass(d.Get("storage_class").(string)),
253282
CopySource: scw.StringPtr(fmt.Sprintf("%s/%s", bucket, key)),
254283
Metadata: types.ExpandMapStringString(d.Get("metadata")),
255284
ACL: s3Types.ObjectCannedACL(d.Get("visibility").(string)),
256-
})
285+
}
286+
if encryptionKey, ok := d.GetOk("sse_customer_key"); ok {
287+
digestMD5, encryption, err := EncryptCustomerKey(encryptionKey.(string))
288+
if err != nil {
289+
return diag.FromErr(err)
290+
}
291+
req.CopySourceSSECustomerAlgorithm = scw.StringPtr("AES256")
292+
req.CopySourceSSECustomerKeyMD5 = &digestMD5
293+
req.CopySourceSSECustomerKey = encryption
294+
}
295+
_, err = s3Client.CopyObject(ctx, req)
257296
}
258297
if err != nil {
259298
return diag.FromErr(err)
@@ -301,6 +340,11 @@ func resourceObjectRead(ctx context.Context, d *schema.ResourceData, m interface
301340
Key: types.ExpandStringPtr(key),
302341
}
303342

343+
if encryption, ok := d.GetOk("sse_customer_key"); ok {
344+
req.SSECustomerKey = aws.String(base64.StdEncoding.EncodeToString([]byte(encryption.(string))))
345+
req.SSECustomerAlgorithm = scw.StringPtr("AES256")
346+
}
347+
304348
obj, err := s3Client.HeadObject(ctx, req)
305349
if err != nil {
306350
return diag.FromErr(err)

internal/services/object/object_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ func TestAccObject_Encryption(t *testing.T) {
758758
}
759759
}
760760
761-
resource scaleway_object "file" {
761+
resource scaleway_object "by-content" {
762762
bucket = scaleway_object_bucket.base-01.id
763763
key = "myfile/foo"
764764
content = "Hello World"
@@ -767,7 +767,7 @@ func TestAccObject_Encryption(t *testing.T) {
767767
`, bucketName, objectTestsMainRegion, encryptionStr),
768768
Check: resource.ComposeTestCheckFunc(
769769
objectchecks.CheckBucketExists(tt, "scaleway_object_bucket.base-01", true),
770-
testAccCheckObjectExists(tt, "scaleway_object.content"),
770+
resource.TestCheckResourceAttr("scaleway_object.by-content", "content", "Hello World"),
771771
),
772772
},
773773
{
@@ -780,7 +780,7 @@ func TestAccObject_Encryption(t *testing.T) {
780780
}
781781
}
782782
783-
resource scaleway_object "file" {
783+
resource scaleway_object "by-content" {
784784
bucket = scaleway_object_bucket.base-01.id
785785
key = "myfile/foo/bar"
786786
content = "Hello World"
@@ -789,7 +789,7 @@ func TestAccObject_Encryption(t *testing.T) {
789789
`, bucketName, objectTestsMainRegion, encryptionStr),
790790
Check: resource.ComposeTestCheckFunc(
791791
objectchecks.CheckBucketExists(tt, "scaleway_object_bucket.base-01", true),
792-
testAccCheckObjectExists(tt, "scaleway_object.content"),
792+
resource.TestCheckResourceAttr("scaleway_object.by-content", "content", "Hello World"),
793793
),
794794
},
795795
},

0 commit comments

Comments
 (0)