Skip to content

Commit fcdba1e

Browse files
committed
feat(object): bucket policy takes on bucket's region rather than default region if not explicit
1 parent 71db83b commit fcdba1e

32 files changed

+2710
-37548
lines changed

scaleway/data_source_object_bucket_policy_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func TestAccScalewayDataSourceObjectBucketPolicy_Basic(t *testing.T) {
5757
}
5858
`, bucketName),
5959
Check: resource.ComposeTestCheckFunc(
60+
testAccCheckScalewayObjectBucketExists(tt, "scaleway_object_bucket.main"),
6061
resource.TestCheckResourceAttr("data.scaleway_object_bucket_policy.selected", "bucket", bucketName),
6162
resource.TestCheckResourceAttrSet("data.scaleway_object_bucket_policy.selected", "policy"),
6263
resource.TestCheckResourceAttrPair("data.scaleway_object_bucket_policy.selected", "policy", "scaleway_object_bucket_policy.main", "policy"),

scaleway/data_source_object_bucket_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ func TestAccScalewayDataSourceObjectStorage_ProjectIDAllowed(t *testing.T) {
8181
project.ID,
8282
),
8383
Check: resource.ComposeTestCheckFunc(
84+
testAccCheckScalewayObjectBucketExists(tt, "scaleway_object_bucket.base"),
8485
resource.TestCheckResourceAttr("data.scaleway_object_bucket.selected", "name", bucketName),
8586
resource.TestCheckResourceAttr("data.scaleway_object_bucket.selected", "project_id", project.ID),
8687
),

scaleway/helpers_object.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ const (
3030
defaultObjectBucketTimeout = 10 * time.Minute
3131

3232
maxObjectVersionDeletionWorkers = 8
33+
34+
objectTestsMainRegion = "fr-par"
3335
)
3436

3537
func newS3Client(httpClient *http.Client, region, accessKey, secretKey string) (*s3.S3, error) {
@@ -66,6 +68,18 @@ func newS3ClientFromMeta(meta *Meta) (*s3.S3, error) {
6668
return newS3Client(meta.httpClient, region.String(), accessKey, secretKey)
6769
}
6870

71+
func newS3ClientFromMetaForceRegion(meta *Meta, region string) (*s3.S3, error) {
72+
accessKey, _ := meta.scwClient.GetAccessKey()
73+
secretKey, _ := meta.scwClient.GetSecretKey()
74+
75+
projectID, _ := meta.scwClient.GetDefaultProjectID()
76+
if projectID != "" {
77+
accessKey = accessKeyWithProjectID(accessKey, projectID)
78+
}
79+
80+
return newS3Client(meta.httpClient, region, accessKey, secretKey)
81+
}
82+
6983
func s3ClientWithRegion(d *schema.ResourceData, m interface{}) (*s3.S3, scw.Region, error) {
7084
meta := m.(*Meta)
7185
region, err := extractRegion(d, meta)
@@ -163,6 +177,23 @@ func s3ClientWithRegionWithNameACL(d *schema.ResourceData, m interface{}, name s
163177
return s3Client, scw.Region(region), name, outerID, err
164178
}
165179

180+
func s3ClientForceRegion(d *schema.ResourceData, m interface{}, region string) (*s3.S3, error) {
181+
meta := m.(*Meta)
182+
183+
accessKey, _ := meta.scwClient.GetAccessKey()
184+
if projectID, _, err := extractProjectID(d, meta); err == nil {
185+
accessKey = accessKeyWithProjectID(accessKey, projectID)
186+
}
187+
secretKey, _ := meta.scwClient.GetSecretKey()
188+
189+
s3Client, err := newS3Client(meta.httpClient, region, accessKey, secretKey)
190+
if err != nil {
191+
return nil, err
192+
}
193+
194+
return s3Client, err
195+
}
196+
166197
func accessKeyWithProjectID(accessKey string, projectID string) string {
167198
return accessKey + "@" + projectID
168199
}

scaleway/resource_object_bucket_policy.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ func resourceScalewayObjectBucketPolicyCreate(ctx context.Context, d *schema.Res
5555
bucket := expandID(d.Get("bucket"))
5656
tflog.Debug(ctx, fmt.Sprintf("bucket name: %s", bucket))
5757

58+
bucketRegion, err := s3Client.GetBucketLocation(&s3.GetBucketLocationInput{
59+
Bucket: &bucket,
60+
})
61+
if err != nil {
62+
return diag.FromErr(err)
63+
}
64+
if bucketRegion.LocationConstraint != nil && *bucketRegion.LocationConstraint != region.String() {
65+
s3Client, err = s3ClientForceRegion(d, meta, *bucketRegion.LocationConstraint)
66+
if err != nil {
67+
return diag.FromErr(err)
68+
}
69+
region = scw.Region(*bucketRegion.LocationConstraint)
70+
}
71+
5872
policy, err := structure.NormalizeJsonString(d.Get("policy").(string))
5973
if err != nil {
6074
return diag.FromErr(fmt.Errorf("policy (%s) is an invalid JSON: %w", policy, err))

scaleway/resource_object_bucket_policy_test.go

Lines changed: 130 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,42 @@ import (
1515
func TestAccScalewayBucketPolicy_Basic(t *testing.T) {
1616
bucketName := sdkacctest.RandomWithPrefix("tf-test-bucket")
1717

18+
tfConfig := fmt.Sprintf(`
19+
resource "scaleway_object_bucket" "bucket" {
20+
name = %[1]q
21+
region = %[2]q
22+
tags = {
23+
TestName = "TestAccSCWBucketPolicy_basic"
24+
}
25+
}
26+
27+
resource "scaleway_object_bucket_policy" "bucket" {
28+
bucket = scaleway_object_bucket.bucket.name
29+
policy = jsonencode(
30+
{
31+
Id = "MyPolicy"
32+
Statement = [
33+
{
34+
Action = [
35+
"s3:ListBucket",
36+
"s3:GetObject",
37+
]
38+
Effect = "Allow"
39+
Principal = {
40+
SCW = "*"
41+
}
42+
Resource = [
43+
"%[1]s",
44+
"%[1]s/*",
45+
]
46+
Sid = "GrantToEveryone"
47+
},
48+
]
49+
Version = "2012-10-17"
50+
}
51+
)
52+
}`, bucketName, objectTestsMainRegion)
53+
1854
expectedPolicyText := `{
1955
"Version":"2012-10-17",
2056
"Id":"MyPolicy",
@@ -43,52 +79,106 @@ func TestAccScalewayBucketPolicy_Basic(t *testing.T) {
4379
CheckDestroy: testAccCheckScalewayObjectBucketDestroy(tt),
4480
Steps: []resource.TestStep{
4581
{
46-
Config: fmt.Sprintf(`
47-
resource "scaleway_object_bucket" "bucket" {
48-
name = %[1]q
49-
50-
tags = {
51-
TestName = "TestAccSCWBucketPolicy_basic"
52-
}
53-
}
54-
55-
resource "scaleway_object_bucket_policy" "bucket" {
56-
bucket = scaleway_object_bucket.bucket.name
57-
policy = jsonencode(
58-
{
59-
Id = "MyPolicy"
60-
Statement = [
61-
{
62-
Action = [
63-
"s3:ListBucket",
64-
"s3:GetObject",
65-
]
66-
Effect = "Allow"
67-
Principal = {
68-
SCW = "*"
69-
}
70-
Resource = [
71-
"%[1]s",
72-
"%[1]s/*",
73-
]
74-
Sid = "GrantToEveryone"
75-
},
76-
]
77-
Version = "2012-10-17"
82+
Config: tfConfig,
83+
Check: resource.ComposeTestCheckFunc(
84+
testAccCheckScalewayObjectBucketExists(tt, "scaleway_object_bucket.bucket"),
85+
testAccCheckBucketHasPolicy(tt, "scaleway_object_bucket.bucket", expectedPolicyText),
86+
),
87+
ExpectNonEmptyPlan: !*UpdateCassettes,
88+
},
89+
{
90+
ResourceName: "scaleway_object_bucket_policy.bucket",
91+
ImportState: true,
92+
},
93+
{
94+
Config: tfConfig,
95+
PlanOnly: true,
96+
},
97+
},
98+
})
99+
}
100+
101+
func TestAccScalewayBucketPolicy_OtherRegion(t *testing.T) {
102+
bucketName := sdkacctest.RandomWithPrefix("tf-test-bucket")
103+
104+
tfConfig := fmt.Sprintf(`
105+
resource "scaleway_object_bucket" "bucket" {
106+
name = %[1]q
107+
region = "nl-ams"
108+
tags = {
109+
TestName = "TestAccSCWBucketPolicy_OtherZone"
110+
}
111+
}
112+
113+
resource "scaleway_object_bucket_policy" "bucket" {
114+
bucket = scaleway_object_bucket.bucket.name
115+
policy = jsonencode(
116+
{
117+
Id = "MyPolicy"
118+
Statement = [
119+
{
120+
Action = [
121+
"s3:*"
122+
]
123+
Effect = "Allow"
124+
Principal = {
125+
SCW = "*"
78126
}
79-
)
80-
}
81-
`, bucketName),
127+
Resource = [
128+
"%[1]s",
129+
"%[1]s/*",
130+
]
131+
Sid = "GrantToEveryone"
132+
},
133+
]
134+
Version = "2023-04-17"
135+
}
136+
)
137+
}`, bucketName)
138+
139+
expectedPolicyText := `{
140+
"Version":"2023-04-17",
141+
"Id":"MyPolicy",
142+
"Statement": [
143+
{
144+
"Sid":"GrantToEveryone",
145+
"Effect":"Allow",
146+
"Principal":{
147+
"SCW":"*"
148+
},
149+
"Action":[
150+
"s3:*"
151+
]
152+
}
153+
]
154+
}`
155+
156+
tt := NewTestTools(t)
157+
defer tt.Cleanup()
158+
159+
resource.ParallelTest(t, resource.TestCase{
160+
PreCheck: func() { testAccPreCheck(t) },
161+
ErrorCheck: ErrorCheck(t, EndpointsID),
162+
ProviderFactories: tt.ProviderFactories,
163+
CheckDestroy: testAccCheckScalewayObjectBucketDestroy(tt),
164+
Steps: []resource.TestStep{
165+
{
166+
Config: tfConfig,
82167
Check: resource.ComposeTestCheckFunc(
83168
testAccCheckScalewayObjectBucketExists(tt, "scaleway_object_bucket.bucket"),
84169
testAccCheckBucketHasPolicy(tt, "scaleway_object_bucket.bucket", expectedPolicyText),
170+
resource.TestCheckResourceAttr("scaleway_object_bucket.bucket", "region", "nl-ams"),
171+
resource.TestCheckResourceAttr("scaleway_object_bucket_policy.bucket", "region", "nl-ams"),
85172
),
86173
ExpectNonEmptyPlan: !*UpdateCassettes,
87174
},
88175
{
89-
ResourceName: "scaleway_object_bucket_policy.bucket",
90-
ImportState: true,
91-
ImportStateVerify: true,
176+
ResourceName: "scaleway_object_bucket_policy.bucket",
177+
ImportState: true,
178+
},
179+
{
180+
Config: tfConfig,
181+
PlanOnly: true,
92182
},
93183
},
94184
})
@@ -101,7 +191,8 @@ func testAccCheckBucketHasPolicy(tt *TestTools, n string, expectedPolicyText str
101191
return fmt.Errorf("not found: %s", n)
102192
}
103193

104-
s3Client, err := newS3ClientFromMeta(tt.Meta)
194+
bucketRegion := rs.Primary.Attributes["region"]
195+
s3Client, err := newS3ClientFromMetaForceRegion(tt.Meta, bucketRegion)
105196
if err != nil {
106197
return err
107198
}

scaleway/resource_object_bucket_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,8 +670,9 @@ func testAccCheckScalewayObjectBucketExists(tt *TestTools, n string) resource.Te
670670
return fmt.Errorf("resource not found")
671671
}
672672
bucketName := rs.Primary.Attributes["name"]
673+
bucketRegion := rs.Primary.Attributes["region"]
673674

674-
s3Client, err := newS3ClientFromMeta(tt.Meta)
675+
s3Client, err := newS3ClientFromMetaForceRegion(tt.Meta, bucketRegion)
675676
if err != nil {
676677
return err
677678
}

0 commit comments

Comments
 (0)