Skip to content

Commit 12e343c

Browse files
authored
fix: normalize bucket policy Principal values (#38)
1 parent 2456a3e commit 12e343c

File tree

5 files changed

+43
-35
lines changed

5 files changed

+43
-35
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ See updating [Changelog example here](https://keepachangelog.com/en/1.0.0/)
55

66
## [Unreleased]
77

8+
### Fixed
9+
10+
- objsto_bucket_policy: when comparing policy documents, treat wildcard `Principal` value (`"*"`) as equal to `{"AWS": ["*"]}`.
11+
- objsto_bucket_policy: when comparing policy documents, treat string value in `Principal` field as equal to list containing that string as its only item, e.g. `{"AWS": "*"}` vs. `{"AWS": ["*"]}`.
12+
813
## [0.2.1]
914

1015
### Fixed

internal/provider/bucket_policy_resource.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ func normalizePolicyDocument(document string) (string, diag.Diagnostics) {
191191
return "", errToDiags(err)
192192
}
193193

194-
// Change ID key into Id (Minio)
194+
// Change ID key into Id
195195
if id, ok := unmarshaled["ID"]; ok {
196196
unmarshaled["Id"] = id
197197
delete(unmarshaled, "ID")
@@ -200,12 +200,12 @@ func normalizePolicyDocument(document string) (string, diag.Diagnostics) {
200200
if statements, ok := unmarshaled["Statement"].([]interface{}); ok {
201201
for _, statement := range statements {
202202
if statement, ok := statement.(map[string]interface{}); ok {
203-
// Always use array type for Action (Minio)
203+
// Always use array type for Action
204204
if action, ok := statement["Action"].(string); ok {
205205
statement["Action"] = []string{action}
206206
}
207207

208-
// Sort statement actions (Minio)
208+
// Sort statement actions
209209
if actions, ok := statement["Action"].([]interface{}); ok {
210210
sort.Slice(actions, func(i, j int) bool {
211211
a, aOk := actions[i].(string)
@@ -216,11 +216,27 @@ func normalizePolicyDocument(document string) (string, diag.Diagnostics) {
216216
return a < b
217217
})
218218
}
219+
220+
// Use {"AWS": ["*"]} instead of "*" for Principal
221+
if _, ok := statement["Principal"].(string); ok {
222+
statement["Principal"] = map[string]interface{}{
223+
"AWS": []string{"*"},
224+
}
225+
}
226+
227+
// Always use array type for Principal values
228+
if principal, ok := statement["Principal"].(map[string]interface{}); ok {
229+
for key, value := range principal {
230+
if s, ok := value.(string); ok {
231+
principal[key] = []string{s}
232+
}
233+
}
234+
}
219235
}
220236
}
221237
}
222238

223-
// Remove "null" Id (UpCloud Managed Object Storage)
239+
// Remove "null" Id
224240
if id := unmarshaled["Id"]; id == "null" {
225241
delete(unmarshaled, "Id")
226242
}

internal/provider/bucket_policy_resource_test.go

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ func TestNormalizePolicyDocument(t *testing.T) {
5353
input: `{"Statement":[{"Action":["s3:ListBucket","s3:GetBucketLocation"]}]}`,
5454
expected: `{"Statement":[{"Action":["s3:GetBucketLocation","s3:ListBucket"]}]}`,
5555
},
56+
{
57+
name: "Normalizes wildcard Principal",
58+
input: `{"Statement":[{"Principal":"*"}]}`,
59+
expected: `{"Statement":[{"Principal":{"AWS":["*"]}}]}`,
60+
},
61+
{
62+
name: "Normalizes Principal values to arrays",
63+
input: `{"Statement":[{"Principal":{"AWS":"*"}}]}`,
64+
expected: `{"Statement":[{"Principal":{"AWS":["*"]}}]}`,
65+
},
5666
}
5767
for _, test := range tests {
5868
t.Run(test.name, func(t *testing.T) {
@@ -104,23 +114,14 @@ func TestAccBucketPolicyResource(t *testing.T) {
104114
}
105115

106116
func TestAccBucketPolicyResource_Normalization(t *testing.T) {
107-
tests := []struct {
108-
configName string
109-
testImport bool
110-
}{
111-
{
112-
configName: "bucket_policy_str_action",
113-
testImport: false,
114-
},
115-
{
116-
configName: "bucket_policy_no_id",
117-
testImport: true,
118-
},
117+
configFiles := []string{
118+
"bucket_policy_str_action",
119+
"bucket_policy_no_id",
119120
}
120121

121-
for _, test := range tests {
122-
t.Run(test.configName, func(t *testing.T) {
123-
configPath := fmt.Sprintf("testdata/%s.tf", test.configName)
122+
for _, configFile := range configFiles {
123+
t.Run(configFile, func(t *testing.T) {
124+
configPath := fmt.Sprintf("testdata/%s.tf", configFile)
124125

125126
bucket_name := withSuffix("bucket-policy-no-id")
126127
variables := func(allow_get_object bool) map[string]config.Variable {
@@ -143,18 +144,6 @@ func TestAccBucketPolicyResource_Normalization(t *testing.T) {
143144
},
144145
}
145146

146-
if test.testImport {
147-
steps = append(steps, resource.TestStep{
148-
ConfigFile: config.StaticFile(configPath),
149-
ConfigVariables: variables(true),
150-
ResourceName: "objsto_bucket_policy.this",
151-
ImportState: true,
152-
ImportStateId: bucket_name,
153-
ImportStateVerifyIdentifierAttribute: "bucket",
154-
ImportStateVerify: true,
155-
})
156-
}
157-
158147
resource.Test(t, resource.TestCase{
159148
PreCheck: func() { testAccPreCheck(t) },
160149
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,

internal/provider/testdata/bucket_policy_no_id.tf

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ resource "objsto_bucket_policy" "this" {
1818
Version = "2012-10-17",
1919
Statement = [
2020
{
21-
Principal = {
22-
"AWS" = ["*"]
23-
}
21+
Principal = "*"
2422
Effect = var.allow_get_object ? "Allow" : "Deny"
2523
Action = [
2624
"s3:GetObject",

internal/provider/testdata/bucket_policy_str_action.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ resource "objsto_bucket_policy" "this" {
1919
Statement = [
2020
{
2121
Principal = {
22-
"AWS" = ["*"]
22+
"AWS" = "*"
2323
}
2424
Effect = var.allow_get_object ? "Allow" : "Deny"
2525
Action = "s3:GetObject"

0 commit comments

Comments
 (0)