From 87917f30529e6a7fca8eaff2932424915fb11225 Mon Sep 17 00:00:00 2001 From: Frank Chen Date: Wed, 27 Jul 2016 12:26:57 -0700 Subject: [PATCH] Add 'objectAcl' Option to the S3 Storage Backend (#1867) * Add Object ACL Support to the S3 Storage Backend Signed-off-by: Frank Chen * Made changes per @RichardScothern's comments Signed-off-by: Frank Chen * Fix Typos Signed-off-by: Frank Chen --- docs/storage-drivers/s3.md | 13 +++++++++ registry/storage/driver/s3-aws/s3.go | 35 ++++++++++++++++++++++- registry/storage/driver/s3-aws/s3_test.go | 2 ++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/docs/storage-drivers/s3.md b/docs/storage-drivers/s3.md index 97cfbfc18..32f199fc0 100644 --- a/docs/storage-drivers/s3.md +++ b/docs/storage-drivers/s3.md @@ -160,6 +160,17 @@ An implementation of the `storagedriver.StorageDriver` interface which uses Amaz The S3 storage class applied to each registry file. The default value is STANDARD. + + + objectacl + + + no + + + The S3 Canned ACL for objects. The default value is "private". + + @@ -189,6 +200,8 @@ An implementation of the `storagedriver.StorageDriver` interface which uses Amaz `storageclass`: (optional) The storage class applied to each registry file. Defaults to STANDARD. Valid options are STANDARD and REDUCED_REDUNDANCY. +`objectacl`: (optional) The canned object ACL to be applied to each registry object. Defaults to `private`. If you are using a bucket owned by another AWS account, it is recommended that you set this to `bucket-owner-full-control` so that the bucket owner can access your objects. Other valid options are available in the [AWS S3 documentation](http://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl). + ## S3 permission scopes The following IAM permissions are required by the registry for push and pull. See [the S3 policy documentation](http://docs.aws.amazon.com/AmazonS3/latest/dev/mpuAndPermissions.html) for more details. diff --git a/registry/storage/driver/s3-aws/s3.go b/registry/storage/driver/s3-aws/s3.go index 6fa28d4de..6c1c3370a 100644 --- a/registry/storage/driver/s3-aws/s3.go +++ b/registry/storage/driver/s3-aws/s3.go @@ -53,6 +53,9 @@ const listMax = 1000 // validRegions maps known s3 region identifiers to region descriptors var validRegions = map[string]struct{}{} +// validObjectAcls contains known s3 object Acls +var validObjectAcls = map[string]struct{}{} + //DriverParameters A struct that encapsulates all of the driver parameters after all values have been set type DriverParameters struct { AccessKey string @@ -67,6 +70,7 @@ type DriverParameters struct { RootDirectory string StorageClass string UserAgent string + ObjectAcl string } func init() { @@ -87,6 +91,18 @@ func init() { validRegions[region] = struct{}{} } + for _, objectAcl := range []string{ + s3.ObjectCannedACLPrivate, + s3.ObjectCannedACLPublicRead, + s3.ObjectCannedACLPublicReadWrite, + s3.ObjectCannedACLAuthenticatedRead, + s3.ObjectCannedACLAwsExecRead, + s3.ObjectCannedACLBucketOwnerRead, + s3.ObjectCannedACLBucketOwnerFullControl, + } { + validObjectAcls[objectAcl] = struct{}{} + } + // Register this as the default s3 driver in addition to s3aws factory.Register("s3", &s3DriverFactory{}) factory.Register(driverName, &s3DriverFactory{}) @@ -107,6 +123,7 @@ type driver struct { KeyID string RootDirectory string StorageClass string + ObjectAcl string } type baseEmbed struct { @@ -248,6 +265,20 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) { userAgent = "" } + objectAcl := s3.ObjectCannedACLPrivate + objectAclParam := parameters["objectacl"] + if objectAclParam != nil { + objectAclString, ok := objectAclParam.(string) + if !ok { + return nil, fmt.Errorf("Invalid value for objectacl parameter: %v", objectAclParam) + } + + if _, ok = validObjectAcls[objectAclString]; !ok { + return nil, fmt.Errorf("Invalid value for objectacl parameter: %v", objectAclParam) + } + objectAcl = objectAclString + } + params := DriverParameters{ fmt.Sprint(accessKey), fmt.Sprint(secretKey), @@ -261,6 +292,7 @@ func FromParameters(parameters map[string]interface{}) (*Driver, error) { fmt.Sprint(rootDirectory), storageClass, fmt.Sprint(userAgent), + objectAcl, } return New(params) @@ -321,6 +353,7 @@ func New(params DriverParameters) (*Driver, error) { KeyID: params.KeyID, RootDirectory: params.RootDirectory, StorageClass: params.StorageClass, + ObjectAcl: params.ObjectAcl, } return &Driver{ @@ -688,7 +721,7 @@ func (d *driver) getContentType() *string { } func (d *driver) getACL() *string { - return aws.String("private") + return aws.String(d.ObjectAcl) } func (d *driver) getStorageClass() *string { diff --git a/registry/storage/driver/s3-aws/s3_test.go b/registry/storage/driver/s3-aws/s3_test.go index 703587633..e1df500fa 100644 --- a/registry/storage/driver/s3-aws/s3_test.go +++ b/registry/storage/driver/s3-aws/s3_test.go @@ -30,6 +30,7 @@ func init() { keyID := os.Getenv("S3_KEY_ID") secure := os.Getenv("S3_SECURE") region := os.Getenv("AWS_REGION") + objectAcl := os.Getenv("S3_OBJECT_ACL") root, err := ioutil.TempDir("", "driver-") regionEndpoint := os.Getenv("REGION_ENDPOINT") if err != nil { @@ -67,6 +68,7 @@ func init() { rootDirectory, storageClass, driverName + "-test", + objectAcl, } return New(parameters)