github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/iam_policy_model.go (about) 1 package aws 2 3 import ( 4 "encoding/json" 5 "sort" 6 ) 7 8 type IAMPolicyDoc struct { 9 Version string `json:",omitempty"` 10 Id string `json:",omitempty"` 11 Statements []*IAMPolicyStatement `json:"Statement"` 12 } 13 14 type IAMPolicyStatement struct { 15 Sid string 16 Effect string `json:",omitempty"` 17 Actions interface{} `json:"Action,omitempty"` 18 NotActions interface{} `json:"NotAction,omitempty"` 19 Resources interface{} `json:"Resource,omitempty"` 20 NotResources interface{} `json:"NotResource,omitempty"` 21 Principals IAMPolicyStatementPrincipalSet `json:"Principal,omitempty"` 22 NotPrincipals IAMPolicyStatementPrincipalSet `json:"NotPrincipal,omitempty"` 23 Conditions IAMPolicyStatementConditionSet `json:"Condition,omitempty"` 24 } 25 26 type IAMPolicyStatementPrincipal struct { 27 Type string 28 Identifiers interface{} 29 } 30 31 type IAMPolicyStatementCondition struct { 32 Test string 33 Variable string 34 Values interface{} 35 } 36 37 type IAMPolicyStatementPrincipalSet []IAMPolicyStatementPrincipal 38 type IAMPolicyStatementConditionSet []IAMPolicyStatementCondition 39 40 func (ps IAMPolicyStatementPrincipalSet) MarshalJSON() ([]byte, error) { 41 raw := map[string]interface{}{} 42 43 // As a special case, IAM considers the string value "*" to be 44 // equivalent to "AWS": "*", and normalizes policies as such. 45 // We'll follow their lead and do the same normalization here. 46 // IAM also considers {"*": "*"} to be equivalent to this. 47 if len(ps) == 1 { 48 p := ps[0] 49 if p.Type == "AWS" || p.Type == "*" { 50 if sv, ok := p.Identifiers.(string); ok && sv == "*" { 51 return []byte(`"*"`), nil 52 } 53 54 if av, ok := p.Identifiers.([]string); ok && len(av) == 1 && av[0] == "*" { 55 return []byte(`"*"`), nil 56 } 57 } 58 } 59 60 for _, p := range ps { 61 switch i := p.Identifiers.(type) { 62 case []string: 63 if _, ok := raw[p.Type]; !ok { 64 raw[p.Type] = make([]string, 0, len(i)) 65 } 66 sort.Sort(sort.Reverse(sort.StringSlice(i))) 67 raw[p.Type] = append(raw[p.Type].([]string), i...) 68 case string: 69 raw[p.Type] = i 70 default: 71 panic("Unsupported data type for IAMPolicyStatementPrincipalSet") 72 } 73 } 74 75 return json.Marshal(&raw) 76 } 77 78 func (cs IAMPolicyStatementConditionSet) MarshalJSON() ([]byte, error) { 79 raw := map[string]map[string]interface{}{} 80 81 for _, c := range cs { 82 if _, ok := raw[c.Test]; !ok { 83 raw[c.Test] = map[string]interface{}{} 84 } 85 switch i := c.Values.(type) { 86 case []string: 87 if _, ok := raw[c.Test][c.Variable]; !ok { 88 raw[c.Test][c.Variable] = make([]string, 0, len(i)) 89 } 90 sort.Sort(sort.Reverse(sort.StringSlice(i))) 91 raw[c.Test][c.Variable] = append(raw[c.Test][c.Variable].([]string), i...) 92 case string: 93 raw[c.Test][c.Variable] = i 94 default: 95 panic("Unsupported data type for IAMPolicyStatementConditionSet") 96 } 97 } 98 99 return json.Marshal(&raw) 100 } 101 102 func iamPolicyDecodeConfigStringList(lI []interface{}) interface{} { 103 if len(lI) == 1 { 104 return lI[0].(string) 105 } 106 ret := make([]string, len(lI)) 107 for i, vI := range lI { 108 ret[i] = vI.(string) 109 } 110 sort.Sort(sort.Reverse(sort.StringSlice(ret))) 111 return ret 112 }