From 79fa6331ed951a9b3231dfd22b52b60d9b3aefac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Tue, 27 Mar 2018 19:04:49 +0200 Subject: [PATCH 1/4] Fix stream SSE uploads with S3 encrypt type --- api-put-object-multipart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api-put-object-multipart.go b/api-put-object-multipart.go index 8805ecf96..1bd64de8c 100644 --- a/api-put-object-multipart.go +++ b/api-put-object-multipart.go @@ -259,7 +259,7 @@ func (c Client) uploadPart(ctx context.Context, bucketName, objectName, uploadID // Set encryption headers, if any. customHeader := make(http.Header) - if sse != nil { + if sse != nil && sse.Type() != encrypt.S3 { sse.Marshal(customHeader) } From 73c3fc18d0f2ad94d7a077a97989b32f67093741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Tue, 27 Mar 2018 19:32:13 +0200 Subject: [PATCH 2/4] Exclude KMS too from uploadPart SSE headers --- api-put-object-multipart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api-put-object-multipart.go b/api-put-object-multipart.go index 1bd64de8c..52dc069d0 100644 --- a/api-put-object-multipart.go +++ b/api-put-object-multipart.go @@ -259,7 +259,7 @@ func (c Client) uploadPart(ctx context.Context, bucketName, objectName, uploadID // Set encryption headers, if any. customHeader := make(http.Header) - if sse != nil && sse.Type() != encrypt.S3 { + if sse != nil && sse.Type() != encrypt.S3 && sse.Type() != encrypt.KMS { sse.Marshal(customHeader) } From ef97e0588af95733c8c687402b6a3cee2fe13ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Tue, 27 Mar 2018 19:56:43 +0200 Subject: [PATCH 3/4] Adding KMS SSE object creation --- pkg/encrypt/server-side.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pkg/encrypt/server-side.go b/pkg/encrypt/server-side.go index 92f5bf5ea..f2dbd6ffd 100644 --- a/pkg/encrypt/server-side.go +++ b/pkg/encrypt/server-side.go @@ -30,6 +30,11 @@ const ( // sseGenericHeader is the AWS SSE header used for SSE-S3 and SSE-KMS. sseGenericHeader = "X-Amz-Server-Side-Encryption" + // sseKmsKeyID is the AWS SSE-KMS key id. + sseKmsKeyID = sseGenericHeader + "-Aws-Kms-Key-Id" + // sseEncryptionContext is the AWS SSE-KMS Encryption Context data. + sseEncryptionContext = sseGenericHeader + "-Encryption-Context" + // sseCustomerAlgorithm is the AWS SSE-C algorithm HTTP header key. sseCustomerAlgorithm = sseGenericHeader + "-Customer-Algorithm" // sseCustomerKey is the AWS SSE-C encryption key HTTP header key. @@ -90,6 +95,14 @@ type ServerSide interface { // Using SSE-S3 the server will encrypt the object with server-managed keys. func NewSSE() ServerSide { return s3{} } +// NewSSEKMS returns a new server-side-encryption using SSE-KMS and the provided Key Id. +func NewSSEKMS(keyID string) ServerSide { return kms{key: keyID, context: nil} } + +// NewSSEKMSWithContext returns a new server-side-encryption using SSE-KMS and the provided Key Id and context. +func NewSSEKMSWithContext(keyID string, context *string) ServerSide { + return kms{key: keyID, context: context} +} + // NewSSEC returns a new server-side-encryption using SSE-C and the provided key. // The key must be 32 bytes long. func NewSSEC(key []byte) (ServerSide, error) { @@ -144,3 +157,18 @@ type s3 struct{} func (s s3) Type() Type { return S3 } func (s s3) Marshal(h http.Header) { h.Set(sseGenericHeader, "AES256") } + +type kms struct { + key string + context *string +} + +func (s kms) Type() Type { return KMS } + +func (s kms) Marshal(h http.Header) { + h.Set(sseGenericHeader, "aws:kms") + h.Set(sseKmsKeyID, s.key) + if s.context != nil { + h.Set(sseEncryptionContext, *s.context) + } +} From 63401ffd9f5adfc8734ffe9eabbb6419ced7b4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Tue, 27 Mar 2018 23:45:55 +0200 Subject: [PATCH 4/4] Changes proposed in the PR --- pkg/encrypt/server-side.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/pkg/encrypt/server-side.go b/pkg/encrypt/server-side.go index f2dbd6ffd..f3853e7b9 100644 --- a/pkg/encrypt/server-side.go +++ b/pkg/encrypt/server-side.go @@ -20,6 +20,7 @@ package encrypt import ( "crypto/md5" "encoding/base64" + "encoding/json" "errors" "net/http" @@ -95,12 +96,16 @@ type ServerSide interface { // Using SSE-S3 the server will encrypt the object with server-managed keys. func NewSSE() ServerSide { return s3{} } -// NewSSEKMS returns a new server-side-encryption using SSE-KMS and the provided Key Id. -func NewSSEKMS(keyID string) ServerSide { return kms{key: keyID, context: nil} } - -// NewSSEKMSWithContext returns a new server-side-encryption using SSE-KMS and the provided Key Id and context. -func NewSSEKMSWithContext(keyID string, context *string) ServerSide { - return kms{key: keyID, context: context} +// NewSSEKMS returns a new server-side-encryption using SSE-KMS and the provided Key Id and context. +func NewSSEKMS(keyID string, context interface{}) (ServerSide, error) { + if context == nil { + return kms{key: keyID, hasContext: false}, nil + } + serializedContext, err := json.Marshal(context) + if err != nil { + return nil, err + } + return kms{key: keyID, context: serializedContext, hasContext: true}, nil } // NewSSEC returns a new server-side-encryption using SSE-C and the provided key. @@ -159,8 +164,9 @@ func (s s3) Type() Type { return S3 } func (s s3) Marshal(h http.Header) { h.Set(sseGenericHeader, "AES256") } type kms struct { - key string - context *string + key string + context []byte + hasContext bool } func (s kms) Type() Type { return KMS } @@ -168,7 +174,7 @@ func (s kms) Type() Type { return KMS } func (s kms) Marshal(h http.Header) { h.Set(sseGenericHeader, "aws:kms") h.Set(sseKmsKeyID, s.key) - if s.context != nil { - h.Set(sseEncryptionContext, *s.context) + if s.hasContext { + h.Set(sseEncryptionContext, base64.StdEncoding.EncodeToString(s.context)) } }