|
1 | 1 | package object_test
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "errors" |
4 | 5 | "fmt"
|
5 | 6 | "regexp"
|
| 7 | + "strings" |
6 | 8 | "testing"
|
7 | 9 |
|
| 10 | + "github.com/aws/aws-sdk-go/service/s3" |
8 | 11 | sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
|
9 | 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
| 13 | + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" |
10 | 14 | "github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest"
|
| 15 | + "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/object" |
11 | 16 | objectchecks "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/object/testfuncs"
|
| 17 | + "github.com/scaleway/terraform-provider-scaleway/v2/internal/types" |
| 18 | +) |
| 19 | + |
| 20 | +const ( |
| 21 | + s3ACLGranteeAllUsers = "AllUsers" |
| 22 | + s3ACLGranteeAuthenticatedUsers = "AuthenticatedUsers" |
12 | 23 | )
|
13 | 24 |
|
14 | 25 | func TestAccObjectBucketACL_Basic(t *testing.T) {
|
@@ -263,3 +274,178 @@ func TestAccObjectBucketACL_WithBucketName(t *testing.T) {
|
263 | 274 | },
|
264 | 275 | })
|
265 | 276 | }
|
| 277 | + |
| 278 | +func TestAccObjectBucketACL_Remove(t *testing.T) { |
| 279 | + tt := acctest.NewTestTools(t) |
| 280 | + defer tt.Cleanup() |
| 281 | + testBucketName := sdkacctest.RandomWithPrefix("test-acc-scw-object-acl-remove") |
| 282 | + |
| 283 | + resource.Test(t, resource.TestCase{ |
| 284 | + PreCheck: func() { acctest.PreCheck(t) }, |
| 285 | + ProviderFactories: tt.ProviderFactories, |
| 286 | + CheckDestroy: objectchecks.IsBucketDestroyed(tt), |
| 287 | + Steps: []resource.TestStep{ |
| 288 | + { |
| 289 | + Config: fmt.Sprintf(` |
| 290 | + resource "scaleway_object_bucket" "main" { |
| 291 | + name = "%s" |
| 292 | + region = "%s" |
| 293 | + acl = "authenticated-read" |
| 294 | + } |
| 295 | + `, testBucketName, objectTestsMainRegion), |
| 296 | + Check: resource.ComposeTestCheckFunc( |
| 297 | + objectchecks.CheckBucketExists(tt, "scaleway_object_bucket.main", true), |
| 298 | + resource.TestCheckResourceAttr("scaleway_object_bucket.main", "acl", "authenticated-read"), |
| 299 | + testAccObjectBucketACLCheck(tt, "scaleway_object_bucket.main", "authenticated-read"), |
| 300 | + ), |
| 301 | + }, |
| 302 | + { |
| 303 | + Config: fmt.Sprintf(` |
| 304 | + resource "scaleway_object_bucket" "main" { |
| 305 | + name = "%s" |
| 306 | + region = "%s" |
| 307 | + acl = "authenticated-read" |
| 308 | + } |
| 309 | + |
| 310 | + resource "scaleway_object_bucket_acl" "main" { |
| 311 | + bucket = scaleway_object_bucket.main.id |
| 312 | + acl = "public-read" |
| 313 | + } |
| 314 | + `, testBucketName, objectTestsMainRegion), |
| 315 | + Check: resource.ComposeTestCheckFunc( |
| 316 | + objectchecks.CheckBucketExists(tt, "scaleway_object_bucket.main", true), |
| 317 | + resource.TestCheckResourceAttr("scaleway_object_bucket_acl.main", "bucket", testBucketName), |
| 318 | + resource.TestCheckResourceAttr("scaleway_object_bucket.main", "acl", "authenticated-read"), |
| 319 | + resource.TestCheckResourceAttr("scaleway_object_bucket_acl.main", "acl", "public-read"), |
| 320 | + testAccObjectBucketACLCheck(tt, "scaleway_object_bucket.main", "public-read"), |
| 321 | + ), |
| 322 | + }, |
| 323 | + { |
| 324 | + Config: fmt.Sprintf(` |
| 325 | + resource "scaleway_object_bucket" "main" { |
| 326 | + name = "%s" |
| 327 | + region = "%s" |
| 328 | + acl = "authenticated-read" |
| 329 | + } |
| 330 | + `, testBucketName, objectTestsMainRegion), |
| 331 | + Check: resource.ComposeTestCheckFunc( |
| 332 | + objectchecks.CheckBucketExists(tt, "scaleway_object_bucket.main", true), |
| 333 | + resource.TestCheckResourceAttr("scaleway_object_bucket.main", "acl", "authenticated-read"), |
| 334 | + testAccObjectBucketACLCheck(tt, "scaleway_object_bucket.main", "private"), |
| 335 | + ), |
| 336 | + }, |
| 337 | + { |
| 338 | + Config: fmt.Sprintf(` |
| 339 | + resource "scaleway_object_bucket" "main" { |
| 340 | + name = "%s" |
| 341 | + region = "%s" |
| 342 | + } |
| 343 | + `, testBucketName, objectTestsMainRegion), |
| 344 | + Check: resource.ComposeTestCheckFunc( |
| 345 | + objectchecks.CheckBucketExists(tt, "scaleway_object_bucket.main", true), |
| 346 | + resource.TestCheckResourceAttr("scaleway_object_bucket.main", "acl", "private"), |
| 347 | + testAccObjectBucketACLCheck(tt, "scaleway_object_bucket.main", "private"), |
| 348 | + ), |
| 349 | + }, |
| 350 | + }, |
| 351 | + }) |
| 352 | +} |
| 353 | + |
| 354 | +func testAccObjectBucketACLCheck(tt *acctest.TestTools, name string, expectedACL string) resource.TestCheckFunc { |
| 355 | + return func(s *terraform.State) error { |
| 356 | + rs, ok := s.RootModule().Resources[name] |
| 357 | + if !ok { |
| 358 | + return fmt.Errorf("resource not found: %s", name) |
| 359 | + } |
| 360 | + |
| 361 | + bucketRegion := rs.Primary.Attributes["region"] |
| 362 | + s3Client, err := object.NewS3ClientFromMeta(tt.Meta, bucketRegion) |
| 363 | + if err != nil { |
| 364 | + return err |
| 365 | + } |
| 366 | + if rs.Primary.ID == "" { |
| 367 | + return errors.New("no ID is set") |
| 368 | + } |
| 369 | + |
| 370 | + bucketName := rs.Primary.Attributes["name"] |
| 371 | + actualACL, err := s3Client.GetBucketAcl(&s3.GetBucketAclInput{ |
| 372 | + Bucket: types.ExpandStringPtr(bucketName), |
| 373 | + }) |
| 374 | + if err != nil { |
| 375 | + return fmt.Errorf("could not get ACL for bucket %s: %v", bucketName, err) |
| 376 | + } |
| 377 | + |
| 378 | + errs := s3ACLAreEqual(expectedACL, actualACL) |
| 379 | + if len(errs) > 0 { |
| 380 | + return fmt.Errorf("unexpected result: %w", errors.Join(errs...)) |
| 381 | + } |
| 382 | + return nil |
| 383 | + } |
| 384 | +} |
| 385 | + |
| 386 | +func s3ACLAreEqual(expected string, actual *s3.GetBucketAclOutput) (errs []error) { |
| 387 | + ownerID := *object.NormalizeOwnerID(actual.Owner.ID) |
| 388 | + grantsMap := make(map[string]string) |
| 389 | + for _, actualACL := range actual.Grants { |
| 390 | + if actualACL.Permission == nil { |
| 391 | + return append(errs, errors.New("grant has no permission")) |
| 392 | + } |
| 393 | + if actualACL.Grantee.ID != nil { |
| 394 | + grantsMap[*actualACL.Permission] = *object.NormalizeOwnerID(actualACL.Grantee.ID) |
| 395 | + } else { |
| 396 | + groupURI := strings.Split(*actualACL.Grantee.URI, "/") |
| 397 | + grantsMap[*actualACL.Permission] = groupURI[len(groupURI)-1] |
| 398 | + } |
| 399 | + } |
| 400 | + |
| 401 | + switch expected { |
| 402 | + case "private": |
| 403 | + if len(grantsMap) != 1 { |
| 404 | + errs = append(errs, fmt.Errorf("expected 1 grant, but got %d", len(grantsMap))) |
| 405 | + return errs |
| 406 | + } |
| 407 | + if grantsMap["FULL_CONTROL"] != ownerID { |
| 408 | + errs = append(errs, fmt.Errorf("expected FULL_CONTROL to be granted to owner (%s), instead got %q", ownerID, grantsMap["FULL_CONTROL"])) |
| 409 | + } |
| 410 | + |
| 411 | + case "public-read": |
| 412 | + if len(grantsMap) != 2 { |
| 413 | + errs = append(errs, fmt.Errorf("expected 2 grants, but got %d", len(grantsMap))) |
| 414 | + return errs |
| 415 | + } |
| 416 | + if grantsMap["FULL_CONTROL"] != ownerID { |
| 417 | + errs = append(errs, fmt.Errorf("expected FULL_CONTROL to be granted to owner (%s), instead got %q", ownerID, grantsMap["FULL_CONTROL"])) |
| 418 | + } |
| 419 | + if grantsMap["READ"] != s3ACLGranteeAllUsers { |
| 420 | + errs = append(errs, fmt.Errorf("expected READ to be granted to %q, instead got %q", s3ACLGranteeAllUsers, grantsMap["READ"])) |
| 421 | + } |
| 422 | + |
| 423 | + case "public-read-write": |
| 424 | + if len(grantsMap) != 3 { |
| 425 | + errs = append(errs, fmt.Errorf("expected 3 grants, but got %d", len(grantsMap))) |
| 426 | + return errs |
| 427 | + } |
| 428 | + if grantsMap["FULL_CONTROL"] != ownerID { |
| 429 | + errs = append(errs, fmt.Errorf("expected FULL_CONTROL to be granted to owner (%s), instead got %q", ownerID, grantsMap["FULL_CONTROL"])) |
| 430 | + } |
| 431 | + if grantsMap["READ"] != s3ACLGranteeAllUsers { |
| 432 | + errs = append(errs, fmt.Errorf("expected READ to be granted to %q, instead got %q", s3ACLGranteeAllUsers, grantsMap["READ"])) |
| 433 | + } |
| 434 | + if grantsMap["WRITE"] != s3ACLGranteeAllUsers { |
| 435 | + errs = append(errs, fmt.Errorf("expected WRITE to be granted to %q, instead got %q", s3ACLGranteeAllUsers, grantsMap["WRITE"])) |
| 436 | + } |
| 437 | + |
| 438 | + case "authenticated-read": |
| 439 | + if len(grantsMap) != 2 { |
| 440 | + errs = append(errs, fmt.Errorf("expected 2 grants, but got %d", len(grantsMap))) |
| 441 | + return errs |
| 442 | + } |
| 443 | + if grantsMap["FULL_CONTROL"] != ownerID { |
| 444 | + errs = append(errs, fmt.Errorf("expected FULL_CONTROL to be granted to owner (%s), instead got %q", ownerID, grantsMap["FULL_CONTROL"])) |
| 445 | + } |
| 446 | + if grantsMap["READ"] != s3ACLGranteeAuthenticatedUsers { |
| 447 | + errs = append(errs, fmt.Errorf("expected READ to be granted to %q, instead got %q", s3ACLGranteeAuthenticatedUsers, grantsMap["READ"])) |
| 448 | + } |
| 449 | + } |
| 450 | + return errs |
| 451 | +} |
0 commit comments