github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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  }