diff --git a/docs/configuration.md b/docs/configuration.md index 296c4b4f1..a3663e0f7 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -94,6 +94,7 @@ information about each option that appears later in this page. regionendpoint: http://myobjects.local bucket: bucketname encrypt: true + keyid: mykeyid secure: true v4auth: true chunksize: 5242880 @@ -359,6 +360,7 @@ Permitted values are `error`, `warn`, `info` and `debug`. The default is regionendpoint: http://myobjects.local bucket: bucketname encrypt: true + keyid: mykeyid secure: true v4auth: true chunksize: 5242880 diff --git a/docs/storage-drivers/s3.md b/docs/storage-drivers/s3.md index 7ee706575..86c3c8c18 100644 --- a/docs/storage-drivers/s3.md +++ b/docs/storage-drivers/s3.md @@ -87,6 +87,18 @@ An implementation of the `storagedriver.StorageDriver` interface which uses Amaz not. A boolean value. The default is false. + + + keyid + + + no + + + Optional KMS key ID to use for encryption (encrypt must be true, or this + parameter will be ignored). The default is none. + + secure @@ -163,6 +175,8 @@ An implementation of the `storagedriver.StorageDriver` interface which uses Amaz `encrypt`: (optional) Whether you would like your data encrypted on the server side (defaults to false if not specified). +`keyid`: (optional) Whether you would like your data encrypted with this KMS key ID (defaults to none if not specified, will be ignored if encrypt is not true). + `secure`: (optional) Whether you would like to transfer data to the bucket over ssl or not. Defaults to true (meaning transferring over ssl) if not specified. Note that while setting this to false will improve performance, it is not recommended due to security concerns. `v4auth`: (optional) Whether you would like to use aws signature version 4 with your requests. This defaults to false if not specified (note that the eu-central-1 region does not work with version 2 signatures, so the driver will error out if initialized with this region and v4auth set to false) diff --git a/registry/storage/driver/s3-aws/s3.go b/registry/storage/driver/s3-aws/s3.go index db61b4e7b..8683f80e1 100644 --- a/registry/storage/driver/s3-aws/s3.go +++ b/registry/storage/driver/s3-aws/s3.go @@ -60,6 +60,7 @@ type DriverParameters struct { Region string RegionEndpoint string Encrypt bool + KeyID string Secure bool ChunkSize int64 RootDirectory string @@ -100,6 +101,7 @@ type driver struct { Bucket string ChunkSize int64 Encrypt bool + KeyID string RootDirectory string StorageClass string } @@ -188,6 +190,11 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) { return nil, fmt.Errorf("The secure parameter should be a boolean") } + keyID := parameters["keyid"] + if keyID == nil { + keyID = "" + } + chunkSize := int64(defaultChunkSize) chunkSizeParam := parameters["chunksize"] switch v := chunkSizeParam.(type) { @@ -243,6 +250,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) { region, fmt.Sprint(regionEndpoint), encryptBool, + fmt.Sprint(keyID), secureBool, chunkSize, fmt.Sprint(rootDirectory), @@ -317,6 +325,7 @@ func New(params DriverParameters) (*Driver, error) { Bucket: params.Bucket, ChunkSize: params.ChunkSize, Encrypt: params.Encrypt, + KeyID: params.KeyID, RootDirectory: params.RootDirectory, StorageClass: params.StorageClass, } @@ -353,6 +362,7 @@ func (d *driver) PutContent(ctx context.Context, path string, contents []byte) e ContentType: d.getContentType(), ACL: d.getACL(), ServerSideEncryption: d.getEncryptionMode(), + SSEKMSKeyId: d.getSSEKMSKeyID(), StorageClass: d.getStorageClass(), Body: bytes.NewReader(contents), }) @@ -390,6 +400,7 @@ func (d *driver) Writer(ctx context.Context, path string, append bool) (storaged ContentType: d.getContentType(), ACL: d.getACL(), ServerSideEncryption: d.getEncryptionMode(), + SSEKMSKeyId: d.getSSEKMSKeyID(), StorageClass: d.getStorageClass(), }) if err != nil { @@ -534,6 +545,7 @@ func (d *driver) Move(ctx context.Context, sourcePath string, destPath string) e ContentType: d.getContentType(), ACL: d.getACL(), ServerSideEncryption: d.getEncryptionMode(), + SSEKMSKeyId: d.getSSEKMSKeyID(), StorageClass: d.getStorageClass(), CopySource: aws.String(d.Bucket + "/" + d.s3Path(sourcePath)), }) @@ -645,9 +657,19 @@ func parseError(path string, err error) error { } func (d *driver) getEncryptionMode() *string { - if d.Encrypt { + if !d.Encrypt { + return nil + } + if d.KeyID == "" { return aws.String("AES256") } + return aws.String("aws:kms") +} + +func (d *driver) getSSEKMSKeyID() *string { + if d.KeyID != "" { + return aws.String(d.KeyID) + } return nil } diff --git a/registry/storage/driver/s3-aws/s3_test.go b/registry/storage/driver/s3-aws/s3_test.go index f12297bff..bb64ccf44 100644 --- a/registry/storage/driver/s3-aws/s3_test.go +++ b/registry/storage/driver/s3-aws/s3_test.go @@ -27,6 +27,7 @@ func init() { secretKey := os.Getenv("AWS_SECRET_KEY") bucket := os.Getenv("S3_BUCKET") encrypt := os.Getenv("S3_ENCRYPT") + keyID := os.Getenv("S3_KEY_ID") secure := os.Getenv("S3_SECURE") region := os.Getenv("AWS_REGION") root, err := ioutil.TempDir("", "driver-") @@ -60,6 +61,7 @@ func init() { region, regionEndpoint, encryptBool, + keyID, secureBool, minChunkSize, rootDirectory,