Skip to content

Commit 1caf287

Browse files
authored
feat(obj): resource object bucket acl (#1465)
1 parent dfe2bae commit 1caf287

11 files changed

+4427
-1836
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
---
2+
page_title: "Scaleway: scaleway_object_bucket_acl"
3+
description: |-
4+
Manages Scaleway object storage bucket ACL resource.
5+
---
6+
7+
# scaleway_object_bucket
8+
9+
Creates and manages Scaleway object storage bucket ACL.
10+
For more information, see [the documentation](https://www.scaleway.com/en/docs/storage/object/concepts/#access-control-list-(acl)).
11+
12+
-> **Note:** `terraform destroy` does not delete the Object Bucket ACL but does remove the resource from Terraform state.
13+
14+
-> **Note:** [Account identifiers](https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html) is not supported by scaleway.
15+
16+
## Example Usage
17+
18+
```hcl
19+
resource "scaleway_object_bucket" "some_bucket" {
20+
name = "some-unique-name"
21+
}
22+
23+
resource "scaleway_object_bucket_acl" "main" {
24+
bucket = scaleway_object_bucket.main.name
25+
acl = "private"
26+
}
27+
```
28+
29+
## Example with Grants
30+
31+
```hcl
32+
resource "scaleway_object_bucket" "main" {
33+
name = "your-bucket"
34+
}
35+
36+
resource "scaleway_object_bucket_acl" "main" {
37+
bucket = scaleway_object_bucket.main.name
38+
access_control_policy {
39+
grant {
40+
grantee {
41+
id = "<project-id>:<project-id>"
42+
type = "CanonicalUser"
43+
}
44+
permission = "FULL_CONTROL"
45+
}
46+
47+
grant {
48+
grantee {
49+
id = "<project-id>"
50+
type = "CanonicalUser"
51+
}
52+
permission = "WRITE"
53+
}
54+
55+
owner {
56+
id = "<project-id>"
57+
}
58+
}
59+
}
60+
```
61+
62+
## Arguments Reference
63+
64+
The following arguments are supported:
65+
66+
* `bucket` - (Required) The name of the bucket.
67+
* `acl` - (Optional) The canned ACL you want to apply to the bucket.
68+
* `access_control_policy` - (Optional, Conflicts with acl) A configuration block that sets the ACL permissions for an object per grantee documented below.
69+
* `expected_bucket_owner` - (Optional, Forces new resource) The project ID of the expected bucket owner.
70+
* `region` - (Optional) The [region](https://developers.scaleway.com/en/quickstart/#region-definition) in which the bucket should be created.
71+
72+
73+
## The ACL
74+
75+
Please check the [canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl_overview.html#canned-acl)
76+
77+
## The Access Control policy
78+
79+
The `access_control_policy` configuration block supports the following arguments:
80+
81+
* `grant` - (Required) Set of grant configuration blocks documented below.
82+
* `owner` - (Required) Configuration block of the bucket owner's display name and ID documented below.
83+
84+
## The Grant
85+
86+
The `grant` configuration block supports the following arguments:
87+
88+
* `grantee` - (Required) Configuration block for the project being granted permissions documented below.
89+
* `permission` - (Required) Logging permissions assigned to the grantee for the bucket.
90+
91+
## The permission
92+
93+
The following list shows each access policy permissions supported.
94+
95+
`READ`, `WRITE`, `READ_ACP`, `WRITE_ACP`, `FULL_CONTROL`
96+
97+
For more information about ACL permissions in the S3 bucket, see [ACL permissions](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html).
98+
99+
## The owner
100+
101+
The `owner` configuration block supports the following arguments:
102+
103+
* `id` - (Required) The ID of the project owner.
104+
* `display_name` - (Optional) The display name of the owner.
105+
106+
## the grantee
107+
108+
The `grantee` configuration block supports the following arguments:
109+
110+
* `id` - (Required) The canonical user ID of the grantee.
111+
* `type` - (Required) Type of grantee. Valid values: CanonicalUser.
112+
113+
## Attributes Reference
114+
115+
In addition to all above arguments, the following attribute is exported:
116+
117+
* `id` - The `region`,`bucket` and `acl` separated by (`/`).
118+
119+
## Import
120+
121+
Buckets can be imported using the `{region}/{bucketName}/{acl}` identifier, e.g.
122+
123+
```bash
124+
$ terraform import scaleway_object_bucket_acl.some_bucket fr-par/some-bucket
125+
/private```

scaleway/helpers.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func expandZonedID(id interface{}) ZonedID {
9292
}
9393

9494
// parseLocalizedID parses a localizedID and extracts the resource locality and id.
95-
func parseLocalizedID(localizedID string) (locality string, id string, err error) {
95+
func parseLocalizedID(localizedID string) (locality, id string, err error) {
9696
tab := strings.Split(localizedID, "/")
9797
if len(tab) != 2 {
9898
return "", localizedID, fmt.Errorf("cant parse localized id: %s", localizedID)
@@ -109,6 +109,27 @@ func parseLocalizedNestedID(localizedID string) (locality string, innerID, outer
109109
return tab[0], tab[1], tab[2], nil
110110
}
111111

112+
// parseLocalizedNestedID parses a localizedNestedOwnerID and extracts the resource locality, the inner and outer id and owner.
113+
func parseLocalizedNestedOwnerID(localizedID string) (locality string, innerID, outerID string, err error) {
114+
tab := strings.Split(localizedID, "/")
115+
n := len(tab)
116+
switch n {
117+
case 2:
118+
locality = tab[0]
119+
innerID = tab[1]
120+
case 3:
121+
locality, innerID, outerID, err = parseLocalizedNestedID(localizedID)
122+
default:
123+
err = fmt.Errorf("cant parse localized id: %s", localizedID)
124+
}
125+
126+
if err != nil {
127+
return "", "", localizedID, err
128+
}
129+
130+
return locality, innerID, outerID, nil
131+
}
132+
112133
// parseZonedID parses a zonedID and extracts the resource zone and id.
113134
func parseZonedID(zonedID string) (zone scw.Zone, id string, err error) {
114135
locality, id, err := parseLocalizedID(zonedID)

scaleway/helpers_object.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,22 @@ func s3ClientWithRegionAndNestedName(m interface{}, name string) (*s3.S3, scw.Re
101101
return s3Client, region, outerID, innerID, err
102102
}
103103

104+
func s3ClientWithRegionWithNameACL(m interface{}, name string) (*s3.S3, scw.Region, string, string, error) {
105+
meta := m.(*Meta)
106+
region, name, outerID, err := parseLocalizedNestedOwnerID(name)
107+
if err != nil {
108+
return nil, "", name, "", err
109+
}
110+
111+
accessKey, _ := meta.scwClient.GetAccessKey()
112+
secretKey, _ := meta.scwClient.GetSecretKey()
113+
s3Client, err := newS3Client(meta.httpClient, region, accessKey, secretKey)
114+
if err != nil {
115+
return nil, "", "", "", err
116+
}
117+
return s3Client, scw.Region(region), name, outerID, err
118+
}
119+
104120
func flattenObjectBucketTags(tagsSet []*s3.Tag) map[string]interface{} {
105121
tags := map[string]interface{}{}
106122

@@ -482,3 +498,17 @@ func WebsiteDomainURL(region string) string {
482498
// https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_website_region_endpoints
483499
return fmt.Sprintf("s3-website.%s.scw.cloud", region)
484500
}
501+
502+
func buildBucketOwnerID(id *string) *string {
503+
s := fmt.Sprintf("%[1]s:%[1]s", *id)
504+
return &s
505+
}
506+
507+
func normalizeOwnerID(id *string) *string {
508+
tab := strings.Split(*id, ":")
509+
if len(tab) != 2 {
510+
return id
511+
}
512+
513+
return &tab[0]
514+
}

scaleway/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ func Provider(config *ProviderConfig) plugin.ProviderFunc {
141141
"scaleway_redis_cluster": resourceScalewayRedisCluster(),
142142
"scaleway_object": resourceScalewayObject(),
143143
"scaleway_object_bucket": resourceScalewayObjectBucket(),
144+
"scaleway_object_bucket_acl": resourceScalewayObjectBucketACL(),
144145
"scaleway_object_bucket_policy": resourceScalewayObjectBucketPolicy(),
145146
"scaleway_object_bucket_website_configuration": ResourceBucketWebsiteConfiguration(),
146147
"scaleway_vpc_public_gateway": resourceScalewayVPCPublicGateway(),

scaleway/resource_object_bucket.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func resourceScalewayObjectBucket() *schema.Resource {
4747
s3.ObjectCannedACLPublicReadWrite,
4848
s3.ObjectCannedACLAuthenticatedRead,
4949
}, false),
50+
Deprecated: "ACL is deprecated. Please use resource_bucket_acl instead.",
5051
},
5152
"tags": {
5253
Type: schema.TypeMap,
@@ -433,7 +434,7 @@ func resourceScalewayObjectBucketRead(ctx context.Context, d *schema.ResourceDat
433434
// Known issue:
434435
// Import a bucket (eg. terraform import scaleway_object_bucket.x fr-par/x)
435436
// will always trigger a diff (eg. terraform plan) on acl attribute because
436-
// we do not read it and it has a "private" default value.
437+
// we do not read it, and it has a "private" default value.
437438
// AWS has the same issue: https://github.com/terraform-providers/terraform-provider-aws/issues/6193
438439

439440
_, err = s3Client.ListObjectsWithContext(ctx, &s3.ListObjectsInput{

0 commit comments

Comments
 (0)