provider/aws: IAM policy document: normalize wildcard principals
There are three equivalent forms for expressing "everyone" (including anonymous) in IAM policies: - "Principals": "*" - "Principals": {"AWS": "*"} - "Principals": {"*": "*"} The more-constrained syntax used by our aws_iam_policy_document data source means that the user can only express the latter two of these directly. However, when returning IAM policies from the API AWS likes to normalize to the first form, causing unresolvable diffs. This fixes #9335 by handling the "everyone" case as a special case, serializing it in JSON as the "*" shorthand form. This change does *not* address the normalization of hand-written policies containing such elements. A similar change would need to be made in the external package github.com/jen20/awspolicyequivalence in order to avoid the issue for hand-written policies.
This commit is contained in:
parent
f16309630e
commit
145bf42806
|
@ -106,6 +106,24 @@ data "aws_iam_policy_document" "test" {
|
|||
not_resources = ["arn:aws:s3:::*"]
|
||||
}
|
||||
|
||||
# Normalization of wildcard principals
|
||||
statement {
|
||||
effect = "Allow"
|
||||
actions = ["kinesis:*"]
|
||||
principals {
|
||||
type = "AWS"
|
||||
identifiers = ["*"]
|
||||
}
|
||||
}
|
||||
statement {
|
||||
effect = "Allow"
|
||||
actions = ["firehose:*"]
|
||||
principals {
|
||||
type = "*"
|
||||
identifiers = ["*"]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
`
|
||||
|
||||
|
@ -156,6 +174,18 @@ var testAccAWSIAMPolicyDocumentExpectedJSON = `{
|
|||
"Effect": "Deny",
|
||||
"NotAction": "s3:*",
|
||||
"NotResource": "arn:aws:s3:::*"
|
||||
},
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Action": "kinesis:*",
|
||||
"Principal": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Action": "firehose:*",
|
||||
"Principal": "*"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
|
|
@ -40,6 +40,23 @@ type IAMPolicyStatementConditionSet []IAMPolicyStatementCondition
|
|||
func (ps IAMPolicyStatementPrincipalSet) MarshalJSON() ([]byte, error) {
|
||||
raw := map[string]interface{}{}
|
||||
|
||||
// As a special case, IAM considers the string value "*" to be
|
||||
// equivalent to "AWS": "*", and normalizes policies as such.
|
||||
// We'll follow their lead and do the same normalization here.
|
||||
// IAM also considers {"*": "*"} to be equivalent to this.
|
||||
if len(ps) == 1 {
|
||||
p := ps[0]
|
||||
if p.Type == "AWS" || p.Type == "*" {
|
||||
if sv, ok := p.Identifiers.(string); ok && sv == "*" {
|
||||
return []byte(`"*"`), nil
|
||||
}
|
||||
|
||||
if av, ok := p.Identifiers.([]string); ok && len(av) == 1 && av[0] == "*" {
|
||||
return []byte(`"*"`), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range ps {
|
||||
switch i := p.Identifiers.(type) {
|
||||
case []string:
|
||||
|
|
Loading…
Reference in New Issue