From 91a37b23cc5970ef2d9d86e6de3c93d997bfc150 Mon Sep 17 00:00:00 2001 From: Gordon Shankman Date: Sat, 26 Jan 2019 16:48:08 -0500 Subject: [PATCH] Adding support for SSE in the S3 storage backend. (#5996) --- physical/s3/s3.go | 18 ++++++++-- physical/s3/s3_test.go | 13 ++++++-- .../docs/configuration/storage/s3.html.md | 33 +++++++++++++++++++ 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/physical/s3/s3.go b/physical/s3/s3.go index 5ccd0ad02a..8c1efdf19f 100644 --- a/physical/s3/s3.go +++ b/physical/s3/s3.go @@ -34,6 +34,7 @@ var _ physical.Backend = (*S3Backend)(nil) // within an S3 bucket. type S3Backend struct { bucket string + kmsKeyId string client *s3.S3 logger log.Logger permitPool *physical.PermitPool @@ -135,9 +136,15 @@ func NewS3Backend(conf map[string]string, logger log.Logger) (physical.Backend, } } + kmsKeyId, ok := conf["kms_key_id"] + if !ok { + kmsKeyId = "" + } + s := &S3Backend{ client: s3conn, bucket: bucket, + kmsKeyId: kmsKeyId, logger: logger, permitPool: physical.NewPermitPool(maxParInt), } @@ -151,12 +158,19 @@ func (s *S3Backend) Put(ctx context.Context, entry *physical.Entry) error { s.permitPool.Acquire() defer s.permitPool.Release() - _, err := s.client.PutObject(&s3.PutObjectInput{ + putObjectInput := &s3.PutObjectInput{ Bucket: aws.String(s.bucket), Key: aws.String(entry.Key), Body: bytes.NewReader(entry.Value), - }) + } + if s.kmsKeyId != "" { + putObjectInput.ServerSideEncryption = aws.String("aws:kms") + putObjectInput.SSEKMSKeyId = aws.String(s.kmsKeyId) + } + + _, err := s.client.PutObject(putObjectInput) + if err != nil { return err } diff --git a/physical/s3/s3_test.go b/physical/s3/s3_test.go index b1c195564f..2d0d004316 100644 --- a/physical/s3/s3_test.go +++ b/physical/s3/s3_test.go @@ -17,7 +17,15 @@ import ( "github.com/aws/aws-sdk-go/service/s3" ) -func TestS3Backend(t *testing.T) { +func TestDefaultS3Backend(t *testing.T) { + DoS3BackendTest(t, "") +} + +func TestS3BackendSseKms(t *testing.T) { + DoS3BackendTest(t, "alias/aws/s3") +} + +func DoS3BackendTest(t *testing.T, kmsKeyId string) { credsConfig := &awsutil.CredentialsConfig{} credsChain, err := credsConfig.GenerateCredentialChain() @@ -83,7 +91,8 @@ func TestS3Backend(t *testing.T) { // This uses the same logic to find the AWS credentials as we did at the beginning of the test b, err := NewS3Backend(map[string]string{ - "bucket": bucket, + "bucket": bucket, + "kmsKeyId": kmsKeyId, }, logger) if err != nil { t.Fatalf("err: %s", err) diff --git a/website/source/docs/configuration/storage/s3.html.md b/website/source/docs/configuration/storage/s3.html.md index c5ef6e163a..a4d56e9b74 100644 --- a/website/source/docs/configuration/storage/s3.html.md +++ b/website/source/docs/configuration/storage/s3.html.md @@ -68,6 +68,11 @@ cause Vault to attempt to retrieve credentials from the AWS metadata service. - `disable_ssl` `(string: "false")` - Specifies if SSL should be used for the endpoint connection (highly recommended not to disable for production). +- `kms_key_id` `(string: "")` - Specifies the ID or Alias of the KMS key used to + encrypt data in the S3 backend. Vault must have `kms:Encrypt` and `kms:Decrypt` + permissions for this key. You can use `alias/aws/s3` to specify the default + key for the account. + ## `s3` Examples ### Default Example @@ -82,4 +87,32 @@ storage "s3" { } ``` +### S3 KMS Encryption with Default Key + +This example shows using Amazon S3 as a storage backend using KMS +encryption with the default S3 KMS key for the account. + +```hcl +storage "s3" { + access_key = "abcd1234" + secret_key = "defg5678" + bucket = "my-bucket" + kms_key_id = "alias/aws/s3" +} +``` + +### S3 KMS Encryption with Custom Key + +This example shows using Amazon S3 as a storage backend using KMS +encryption with a customer managed KMS key. + +```hcl +storage "s3" { + access_key = "abcd1234" + secret_key = "defg5678" + bucket = "my-bucket" + kms_key_id = "001234ac-72d3-9902-a3fc-0123456789ab" +} +``` + [s3]: https://aws.amazon.com/s3/