diff --git a/backend/azure/azure.go b/backend/azure/azure.go index 17f29ccf..021ce4c3 100644 --- a/backend/azure/azure.go +++ b/backend/azure/azure.go @@ -19,6 +19,7 @@ import ( "context" "encoding/base64" "encoding/binary" + "encoding/json" "errors" "fmt" "io" @@ -34,11 +35,14 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3/types" + "github.com/versity/versitygw/auth" "github.com/versity/versitygw/backend" "github.com/versity/versitygw/s3err" "github.com/versity/versitygw/s3response" ) +const aclKey string = "Acl" + type Azure struct { backend.BackendUnsupported @@ -70,8 +74,16 @@ func (az *Azure) String() string { } func (az *Azure) CreateBucket(ctx context.Context, input *s3.CreateBucketInput) error { - // TODO: handle ownership/ACLs - _, err := az.client.CreateContainer(ctx, *input.Bucket, nil) + owner := string(input.ObjectOwnership) + acl := auth.ACL{ACL: "private", Owner: owner, Grantees: []auth.Grantee{}} + jsonACL, err := json.Marshal(acl) + if err != nil { + return fmt.Errorf("marshal acl: %w", err) + } + meta := map[string]*string{ + aclKey: getStringPtr(string(jsonACL)), + } + _, err = az.client.CreateContainer(ctx, *input.Bucket, &container.CreateOptions{Metadata: meta}) return azureErrToS3Err(err) } @@ -579,6 +591,41 @@ func (az *Azure) CompleteMultipartUpload(ctx context.Context, input *s3.Complete }, nil } +func (az *Azure) PutBucketAcl(ctx context.Context, bucket string, data []byte) error { + client, err := az.getContainerClient(bucket) + if err != nil { + return err + } + meta := map[string]*string{ + aclKey: getStringPtr(string(data)), + } + _, err = client.SetMetadata(ctx, &container.SetMetadataOptions{ + Metadata: meta, + }) + if err != nil { + return azureErrToS3Err(err) + } + return nil +} + +func (az *Azure) GetBucketAcl(ctx context.Context, input *s3.GetBucketAclInput) ([]byte, error) { + client, err := az.getContainerClient(*input.Bucket) + if err != nil { + return nil, err + } + props, err := client.GetProperties(ctx, nil) + if err != nil { + return nil, azureErrToS3Err(err) + } + + aclPtr, ok := props.Metadata[aclKey] + if !ok { + return nil, s3err.GetAPIError(s3err.ErrInternalError) + } + + return []byte(*aclPtr), nil +} + func (az *Azure) getBlobClient(container, blb string) (*blob.Client, error) { return blob.NewClientWithSharedKeyCredential(fmt.Sprintf("%v/%v/%v", az.serviceURL, container, blb), az.creds, nil) }