diff --git a/builtin/providers/aws/data_source_aws_iam_policy_document.go b/builtin/providers/aws/data_source_aws_iam_policy_document.go index 8d5051f771..5bea111eec 100644 --- a/builtin/providers/aws/data_source_aws_iam_policy_document.go +++ b/builtin/providers/aws/data_source_aws_iam_policy_document.go @@ -150,12 +150,19 @@ func dataSourceAwsIamPolicyDocumentRead(d *schema.ResourceData, meta interface{} return nil } -func dataSourceAwsIamPolicyDocumentReplaceVarsInList(in []string) []string { - out := make([]string, len(in)) - for i, item := range in { - out[i] = dataSourceAwsIamPolicyDocumentVarReplacer.Replace(item) +func dataSourceAwsIamPolicyDocumentReplaceVarsInList(in interface{}) interface{} { + switch v := in.(type) { + case string: + return dataSourceAwsIamPolicyDocumentVarReplacer.Replace(v) + case []string: + out := make([]string, len(v)) + for i, item := range v { + out[i] = dataSourceAwsIamPolicyDocumentVarReplacer.Replace(item) + } + return out + default: + panic("dataSourceAwsIamPolicyDocumentReplaceVarsInList: input not string nor []string") } - return out } func dataSourceAwsIamPolicyDocumentMakeConditions(in []interface{}) IAMPolicyStatementConditionSet { diff --git a/builtin/providers/aws/data_source_aws_iam_policy_document_test.go b/builtin/providers/aws/data_source_aws_iam_policy_document_test.go index 8a2210265f..a50a8ae29e 100644 --- a/builtin/providers/aws/data_source_aws_iam_policy_document_test.go +++ b/builtin/providers/aws/data_source_aws_iam_policy_document_test.go @@ -75,7 +75,6 @@ data "aws_iam_policy_document" "test" { test = "StringLike" variable = "s3:prefix" values = [ - "", "home/", "home/&{aws:username}/", ] @@ -118,59 +117,45 @@ var testAccAWSIAMPolicyDocumentExpectedJSON = `{ "Sid": "1", "Effect": "Allow", "Action": [ - "s3:GetBucketLocation", - "s3:ListAllMyBuckets" + "s3:ListAllMyBuckets", + "s3:GetBucketLocation" ], - "Resource": [ - "arn:aws:s3:::*" - ] + "Resource": "arn:aws:s3:::*" }, { + "Sid": "", "Effect": "Allow", - "Action": [ - "s3:ListBucket" - ], - "Resource": [ - "arn:aws:s3:::foo" - ], + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::foo", "NotPrincipal": { - "AWS": [ - "arn:blahblah:example" - ] + "AWS": "arn:blahblah:example" }, "Condition": { "StringLike": { "s3:prefix": [ - "", - "home/", - "home/${aws:username}/" + "home/${aws:username}/", + "home/" ] } } }, { + "Sid": "", "Effect": "Allow", - "Action": [ - "s3:*" - ], + "Action": "s3:*", "Resource": [ "arn:aws:s3:::foo/home/${aws:username}/*", "arn:aws:s3:::foo/home/${aws:username}" ], "Principal": { - "AWS": [ - "arn:blahblah:example" - ] + "AWS": "arn:blahblah:example" } }, { + "Sid": "", "Effect": "Deny", - "NotAction": [ - "s3:*" - ], - "NotResource": [ - "arn:aws:s3:::*" - ] + "NotAction": "s3:*", + "NotResource": "arn:aws:s3:::*" } ] }` diff --git a/builtin/providers/aws/iam_policy_model.go b/builtin/providers/aws/iam_policy_model.go index 56ffc9d5cf..59192fbf11 100644 --- a/builtin/providers/aws/iam_policy_model.go +++ b/builtin/providers/aws/iam_policy_model.go @@ -2,6 +2,7 @@ package aws import ( "encoding/json" + "sort" ) type IAMPolicyDoc struct { @@ -11,12 +12,12 @@ type IAMPolicyDoc struct { } type IAMPolicyStatement struct { - Sid string `json:",omitempty"` + Sid string Effect string `json:",omitempty"` - Actions []string `json:"Action,omitempty"` - NotActions []string `json:"NotAction,omitempty"` - Resources []string `json:"Resource,omitempty"` - NotResources []string `json:"NotResource,omitempty"` + Actions interface{} `json:"Action,omitempty"` + NotActions interface{} `json:"NotAction,omitempty"` + Resources interface{} `json:"Resource,omitempty"` + NotResources interface{} `json:"NotResource,omitempty"` Principals IAMPolicyStatementPrincipalSet `json:"Principal,omitempty"` NotPrincipals IAMPolicyStatementPrincipalSet `json:"NotPrincipal,omitempty"` Conditions IAMPolicyStatementConditionSet `json:"Condition,omitempty"` @@ -24,51 +25,71 @@ type IAMPolicyStatement struct { type IAMPolicyStatementPrincipal struct { Type string - Identifiers []string + Identifiers interface{} } type IAMPolicyStatementCondition struct { Test string Variable string - Values []string + Values interface{} } type IAMPolicyStatementPrincipalSet []IAMPolicyStatementPrincipal type IAMPolicyStatementConditionSet []IAMPolicyStatementCondition func (ps IAMPolicyStatementPrincipalSet) MarshalJSON() ([]byte, error) { - raw := map[string][]string{} + raw := map[string]interface{}{} for _, p := range ps { - if _, ok := raw[p.Type]; !ok { - raw[p.Type] = make([]string, 0, len(p.Identifiers)) + switch i := p.Identifiers.(type) { + case []string: + if _, ok := raw[p.Type]; !ok { + raw[p.Type] = make([]string, 0, len(i)) + } + sort.Sort(sort.Reverse(sort.StringSlice(i))) + raw[p.Type] = append(raw[p.Type].([]string), i...) + case string: + raw[p.Type] = i + default: + panic("Unsupported data type for IAMPolicyStatementPrincipalSet") } - raw[p.Type] = append(raw[p.Type], p.Identifiers...) } return json.Marshal(&raw) } func (cs IAMPolicyStatementConditionSet) MarshalJSON() ([]byte, error) { - raw := map[string]map[string][]string{} + raw := map[string]map[string]interface{}{} for _, c := range cs { if _, ok := raw[c.Test]; !ok { - raw[c.Test] = map[string][]string{} + raw[c.Test] = map[string]interface{}{} } - if _, ok := raw[c.Test][c.Variable]; !ok { - raw[c.Test][c.Variable] = make([]string, 0, len(c.Values)) + switch i := c.Values.(type) { + case []string: + if _, ok := raw[c.Test][c.Variable]; !ok { + raw[c.Test][c.Variable] = make([]string, 0, len(i)) + } + sort.Sort(sort.Reverse(sort.StringSlice(i))) + raw[c.Test][c.Variable] = append(raw[c.Test][c.Variable].([]string), i...) + case string: + raw[c.Test][c.Variable] = i + default: + panic("Unsupported data type for IAMPolicyStatementConditionSet") } - raw[c.Test][c.Variable] = append(raw[c.Test][c.Variable], c.Values...) } return json.Marshal(&raw) } -func iamPolicyDecodeConfigStringList(lI []interface{}) []string { +func iamPolicyDecodeConfigStringList(lI []interface{}) interface{} { + if len(lI) == 1 { + return lI[0].(string) + } ret := make([]string, len(lI)) for i, vI := range lI { ret[i] = vI.(string) } + sort.Sort(sort.Reverse(sort.StringSlice(ret))) return ret }