Skip to content

Commit 7dde1ac

Browse files
committed
feat(object): support the group bucket ACL
1 parent 22616d2 commit 7dde1ac

File tree

4 files changed

+1111
-746
lines changed

4 files changed

+1111
-746
lines changed

internal/services/object/bucket_acl.go

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,26 @@ func ResourceBucketACL() *schema.Resource {
6060
Type: schema.TypeString,
6161
Computed: true,
6262
},
63+
"uri": {
64+
Type: schema.TypeString,
65+
Optional: true,
66+
Description: "The uri of the grantee if you are granting permissions to a predefined group.",
67+
ValidateFunc: validation.StringInSlice([]string{
68+
"http://acs.amazonaws.com/groups/global/AuthenticatedUsers",
69+
"http://acs.amazonaws.com/groups/global/AllUsers",
70+
}, false),
71+
},
6372
"id": {
6473
Type: schema.TypeString,
65-
Required: true,
74+
Optional: true,
6675
Description: "The project ID owner of the grantee.",
6776
ValidateDiagFunc: verify.IsUUID(),
6877
},
6978
"type": {
7079
Type: schema.TypeString,
71-
Required: true,
72-
Description: "Type of grantee. Valid values: `CanonicalUser`",
73-
ValidateFunc: validation.StringInSlice([]string{string(s3Types.TypeCanonicalUser)}, false),
80+
Optional: true,
81+
Description: "Type of grantee. Valid values: `CanonicalUser`, `Group`",
82+
ValidateFunc: validation.StringInSlice([]string{string(s3Types.TypeCanonicalUser), string(s3Types.TypeGroup)}, false),
7483
},
7584
},
7685
},
@@ -183,7 +192,12 @@ func resourceBucketACLCreate(ctx context.Context, d *schema.ResourceData, m any)
183192
}
184193

185194
if v, ok := d.GetOk("access_control_policy"); ok && len(v.([]any)) > 0 && v.([]any)[0] != nil {
186-
input.AccessControlPolicy = expandBucketACLAccessControlPolicy(v.([]any))
195+
accessControlPolicy, err := expandAndValidateBucketACLAccessControlPolicy(v.([]any))
196+
if err != nil {
197+
return diag.FromErr(err)
198+
}
199+
200+
input.AccessControlPolicy = accessControlPolicy
187201
}
188202

189203
out, err := conn.PutBucketAcl(ctx, input)
@@ -198,30 +212,35 @@ func resourceBucketACLCreate(ctx context.Context, d *schema.ResourceData, m any)
198212
return resourceBucketACLRead(ctx, d, m)
199213
}
200214

201-
func expandBucketACLAccessControlPolicy(l []any) *s3Types.AccessControlPolicy {
215+
func expandAndValidateBucketACLAccessControlPolicy(l []any) (*s3Types.AccessControlPolicy, error) {
202216
if len(l) == 0 || l[0] == nil {
203-
return nil
217+
return nil, nil
204218
}
205219

206220
tfMap, ok := l[0].(map[string]any)
207221
if !ok {
208-
return nil
222+
return nil, nil
209223
}
210224

211225
result := &s3Types.AccessControlPolicy{}
212226

213227
if v, ok := tfMap["grant"].(*schema.Set); ok && v.Len() > 0 {
214-
result.Grants = expandBucketACLAccessControlPolicyGrants(v.List())
228+
grants, err := expandAndValidateBucketACLAccessControlPolicyGrants(v.List())
229+
if err != nil {
230+
return nil, err
231+
}
232+
233+
result.Grants = grants
215234
}
216235

217236
if v, ok := tfMap["owner"].([]any); ok && len(v) > 0 && v[0] != nil {
218237
result.Owner = expandBucketACLAccessControlPolicyOwner(v)
219238
}
220239

221-
return result
240+
return result, nil
222241
}
223242

224-
func expandBucketACLAccessControlPolicyGrants(l []any) []s3Types.Grant {
243+
func expandAndValidateBucketACLAccessControlPolicyGrants(l []any) ([]s3Types.Grant, error) {
225244
grants := make([]s3Types.Grant, 0, len(l))
226245

227246
for _, tfMapRaw := range l {
@@ -233,7 +252,12 @@ func expandBucketACLAccessControlPolicyGrants(l []any) []s3Types.Grant {
233252
grant := s3Types.Grant{}
234253

235254
if v, ok := tfMap["grantee"].([]any); ok && len(v) > 0 && v[0] != nil {
236-
grant.Grantee = expandBucketACLAccessControlPolicyGrantsGrantee(v)
255+
grantee, err := expandAndValidateBucketACLAccessControlPolicyGrantsGrantee(v)
256+
if err != nil {
257+
return nil, err
258+
}
259+
260+
grant.Grantee = grantee
237261
}
238262

239263
if v, ok := tfMap["permission"].(string); ok && v != "" {
@@ -243,17 +267,17 @@ func expandBucketACLAccessControlPolicyGrants(l []any) []s3Types.Grant {
243267
grants = append(grants, grant)
244268
}
245269

246-
return grants
270+
return grants, nil
247271
}
248272

249-
func expandBucketACLAccessControlPolicyGrantsGrantee(l []any) *s3Types.Grantee {
273+
func expandAndValidateBucketACLAccessControlPolicyGrantsGrantee(l []any) (*s3Types.Grantee, error) {
250274
if len(l) == 0 || l[0] == nil {
251-
return nil
275+
return nil, nil
252276
}
253277

254278
tfMap, ok := l[0].(map[string]any)
255279
if !ok {
256-
return nil
280+
return nil, nil
257281
}
258282

259283
result := &s3Types.Grantee{}
@@ -262,11 +286,23 @@ func expandBucketACLAccessControlPolicyGrantsGrantee(l []any) *s3Types.Grantee {
262286
result.ID = buildBucketOwnerID(aws.String(v))
263287
}
264288

289+
if v, ok := tfMap["uri"].(string); ok && v != "" {
290+
result.URI = aws.String(v)
291+
}
292+
265293
if v, ok := tfMap["type"].(string); ok && v != "" {
266294
result.Type = s3Types.Type(v)
267295
}
268296

269-
return result
297+
if result.Type == s3Types.TypeCanonicalUser && result.ID == nil {
298+
return nil, errors.New("id is required when grantee type is CanonicalUser")
299+
}
300+
301+
if result.Type == s3Types.TypeGroup && result.URI == nil {
302+
return nil, errors.New("uri is required when grantee type is Group")
303+
}
304+
305+
return result, nil
270306
}
271307

272308
func expandBucketACLAccessControlPolicyOwner(l []any) *s3Types.Owner {
@@ -345,6 +381,10 @@ func flattenBucketACLAccessControlPolicyGrantsGrantee(grantee *s3Types.Grantee)
345381
m["display_name"] = NormalizeOwnerID(grantee.DisplayName)
346382
}
347383

384+
if grantee.URI != nil {
385+
m["uri"] = *grantee.URI
386+
}
387+
348388
if grantee.ID != nil {
349389
m["id"] = NormalizeOwnerID(grantee.ID)
350390
}
@@ -451,7 +491,12 @@ func resourceBucketACLUpdate(ctx context.Context, d *schema.ResourceData, m any)
451491
}
452492

453493
if d.HasChange("access_control_policy") {
454-
input.AccessControlPolicy = expandBucketACLAccessControlPolicy(d.Get("access_control_policy").([]any))
494+
accessControlPolicy, err := expandAndValidateBucketACLAccessControlPolicy(d.Get("access_control_policy").([]any))
495+
if err != nil {
496+
return diag.FromErr(err)
497+
}
498+
499+
input.AccessControlPolicy = accessControlPolicy
455500
}
456501

457502
_, err = conn.PutBucketAcl(ctx, input)

internal/services/object/bucket_acl_test.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ func TestAccObjectBucketACL_Grantee(t *testing.T) {
8080

8181
testBucketName := sdkacctest.RandomWithPrefix("tf-tests-scw-object-acl-grantee")
8282

83-
ownerID := "105bdce1-64c0-48ab-899d-868455867ecf"
84-
ownerIDChild := "50ab77d5-56bd-4981-a118-4e0fa5309b59"
83+
ownerID := "105bdce1-64c0-48ab-899d-868455867ecf" // scaleway-dev-tools-org
8584
resource.Test(t, resource.TestCase{
8685
PreCheck: func() { acctest.PreCheck(t) },
8786
ProviderFactories: tt.ProviderFactories,
@@ -128,9 +127,13 @@ func TestAccObjectBucketACL_Grantee(t *testing.T) {
128127
Config: fmt.Sprintf(`
129128
resource "scaleway_object_bucket" "main" {
130129
name = "%[1]s"
131-
region = "%[4]s"
130+
region = "%[3]s"
132131
}
133-
132+
133+
data "scaleway_iam_user" "devtool" {
134+
135+
}
136+
134137
resource "scaleway_object_bucket_acl" "main" {
135138
bucket = scaleway_object_bucket.main.id
136139
access_control_policy {
@@ -141,29 +144,44 @@ func TestAccObjectBucketACL_Grantee(t *testing.T) {
141144
}
142145
permission = "FULL_CONTROL"
143146
}
144-
147+
145148
grant {
146149
grantee {
147150
id = "%[2]s"
148151
type = "CanonicalUser"
149152
}
150153
permission = "WRITE"
151154
}
152-
155+
153156
grant {
154157
grantee {
155-
id = "%[3]s"
158+
id = data.scaleway_iam_user.devtool.id
156159
type = "CanonicalUser"
157160
}
158161
permission = "FULL_CONTROL"
159162
}
160-
163+
164+
grant {
165+
grantee {
166+
uri = "http://acs.amazonaws.com/groups/global/AuthenticatedUsers"
167+
type = "Group"
168+
}
169+
permission = "READ_ACP"
170+
}
171+
172+
grant {
173+
grantee {
174+
uri = "http://acs.amazonaws.com/groups/global/AllUsers"
175+
type = "Group"
176+
}
177+
permission = "READ"
178+
}
161179
owner {
162180
id = "%[2]s"
163181
}
164182
}
165183
}
166-
`, testBucketName, ownerID, ownerIDChild, objectTestsMainRegion),
184+
`, testBucketName, ownerID, objectTestsMainRegion),
167185
Check: resource.ComposeTestCheckFunc(
168186
objectchecks.CheckBucketExists(tt, "scaleway_object_bucket.main", true),
169187
resource.TestCheckResourceAttr("scaleway_object_bucket_acl.main", "bucket", testBucketName),
@@ -263,7 +281,7 @@ func TestAccObjectBucketACL_WithBucketName(t *testing.T) {
263281
name = "%s"
264282
region = "%s"
265283
}
266-
284+
267285
resource "scaleway_object_bucket_acl" "main" {
268286
bucket = scaleway_object_bucket.main.name
269287
acl = "public-read"

0 commit comments

Comments
 (0)