github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/data_source_aws_iam_policy_document.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"encoding/json"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/terraform/helper/hashcode"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  	"strconv"
    12  )
    13  
    14  var dataSourceAwsIamPolicyDocumentVarReplacer = strings.NewReplacer("&{", "${")
    15  
    16  func dataSourceAwsIamPolicyDocument() *schema.Resource {
    17  	setOfString := &schema.Schema{
    18  		Type:     schema.TypeSet,
    19  		Optional: true,
    20  		Elem: &schema.Schema{
    21  			Type: schema.TypeString,
    22  		},
    23  	}
    24  
    25  	return &schema.Resource{
    26  		Read: dataSourceAwsIamPolicyDocumentRead,
    27  
    28  		Schema: map[string]*schema.Schema{
    29  			"policy_id": {
    30  				Type:     schema.TypeString,
    31  				Optional: true,
    32  			},
    33  			"statement": {
    34  				Type:     schema.TypeList,
    35  				Required: true,
    36  				Elem: &schema.Resource{
    37  					Schema: map[string]*schema.Schema{
    38  						"sid": {
    39  							Type:     schema.TypeString,
    40  							Optional: true,
    41  						},
    42  						"effect": {
    43  							Type:     schema.TypeString,
    44  							Optional: true,
    45  							Default:  "Allow",
    46  							ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
    47  								switch v.(string) {
    48  								case "Allow", "Deny":
    49  									return
    50  								default:
    51  									es = append(es, fmt.Errorf("%q must be either \"Allow\" or \"Deny\"", k))
    52  									return
    53  								}
    54  							},
    55  						},
    56  						"actions":        setOfString,
    57  						"not_actions":    setOfString,
    58  						"resources":      setOfString,
    59  						"not_resources":  setOfString,
    60  						"principals":     dataSourceAwsIamPolicyPrincipalSchema(),
    61  						"not_principals": dataSourceAwsIamPolicyPrincipalSchema(),
    62  						"condition": {
    63  							Type:     schema.TypeSet,
    64  							Optional: true,
    65  							Elem: &schema.Resource{
    66  								Schema: map[string]*schema.Schema{
    67  									"test": {
    68  										Type:     schema.TypeString,
    69  										Required: true,
    70  									},
    71  									"variable": {
    72  										Type:     schema.TypeString,
    73  										Required: true,
    74  									},
    75  									"values": {
    76  										Type:     schema.TypeSet,
    77  										Required: true,
    78  										Elem: &schema.Schema{
    79  											Type: schema.TypeString,
    80  										},
    81  									},
    82  								},
    83  							},
    84  						},
    85  					},
    86  				},
    87  			},
    88  			"json": {
    89  				Type:     schema.TypeString,
    90  				Computed: true,
    91  			},
    92  		},
    93  	}
    94  }
    95  
    96  func dataSourceAwsIamPolicyDocumentRead(d *schema.ResourceData, meta interface{}) error {
    97  	doc := &IAMPolicyDoc{
    98  		Version: "2012-10-17",
    99  	}
   100  
   101  	if policyId, hasPolicyId := d.GetOk("policy_id"); hasPolicyId {
   102  		doc.Id = policyId.(string)
   103  	}
   104  
   105  	var cfgStmts = d.Get("statement").([]interface{})
   106  	stmts := make([]*IAMPolicyStatement, len(cfgStmts))
   107  	doc.Statements = stmts
   108  	for i, stmtI := range cfgStmts {
   109  		cfgStmt := stmtI.(map[string]interface{})
   110  		stmt := &IAMPolicyStatement{
   111  			Effect: cfgStmt["effect"].(string),
   112  		}
   113  
   114  		if sid, ok := cfgStmt["sid"]; ok {
   115  			stmt.Sid = sid.(string)
   116  		}
   117  
   118  		if actions := cfgStmt["actions"].(*schema.Set).List(); len(actions) > 0 {
   119  			stmt.Actions = iamPolicyDecodeConfigStringList(actions)
   120  		}
   121  		if actions := cfgStmt["not_actions"].(*schema.Set).List(); len(actions) > 0 {
   122  			stmt.NotActions = iamPolicyDecodeConfigStringList(actions)
   123  		}
   124  
   125  		if resources := cfgStmt["resources"].(*schema.Set).List(); len(resources) > 0 {
   126  			stmt.Resources = dataSourceAwsIamPolicyDocumentReplaceVarsInList(
   127  				iamPolicyDecodeConfigStringList(resources),
   128  			)
   129  		}
   130  		if resources := cfgStmt["not_resources"].(*schema.Set).List(); len(resources) > 0 {
   131  			stmt.NotResources = dataSourceAwsIamPolicyDocumentReplaceVarsInList(
   132  				iamPolicyDecodeConfigStringList(resources),
   133  			)
   134  		}
   135  
   136  		if principals := cfgStmt["principals"].(*schema.Set).List(); len(principals) > 0 {
   137  			stmt.Principals = dataSourceAwsIamPolicyDocumentMakePrincipals(principals)
   138  		}
   139  
   140  		if principals := cfgStmt["not_principals"].(*schema.Set).List(); len(principals) > 0 {
   141  			stmt.NotPrincipals = dataSourceAwsIamPolicyDocumentMakePrincipals(principals)
   142  		}
   143  
   144  		if conditions := cfgStmt["condition"].(*schema.Set).List(); len(conditions) > 0 {
   145  			stmt.Conditions = dataSourceAwsIamPolicyDocumentMakeConditions(conditions)
   146  		}
   147  
   148  		stmts[i] = stmt
   149  	}
   150  
   151  	jsonDoc, err := json.MarshalIndent(doc, "", "  ")
   152  	if err != nil {
   153  		// should never happen if the above code is correct
   154  		return err
   155  	}
   156  	jsonString := string(jsonDoc)
   157  
   158  	d.Set("json", jsonString)
   159  	d.SetId(strconv.Itoa(hashcode.String(jsonString)))
   160  
   161  	return nil
   162  }
   163  
   164  func dataSourceAwsIamPolicyDocumentReplaceVarsInList(in interface{}) interface{} {
   165  	switch v := in.(type) {
   166  	case string:
   167  		return dataSourceAwsIamPolicyDocumentVarReplacer.Replace(v)
   168  	case []string:
   169  		out := make([]string, len(v))
   170  		for i, item := range v {
   171  			out[i] = dataSourceAwsIamPolicyDocumentVarReplacer.Replace(item)
   172  		}
   173  		return out
   174  	default:
   175  		panic("dataSourceAwsIamPolicyDocumentReplaceVarsInList: input not string nor []string")
   176  	}
   177  }
   178  
   179  func dataSourceAwsIamPolicyDocumentMakeConditions(in []interface{}) IAMPolicyStatementConditionSet {
   180  	out := make([]IAMPolicyStatementCondition, len(in))
   181  	for i, itemI := range in {
   182  		item := itemI.(map[string]interface{})
   183  		out[i] = IAMPolicyStatementCondition{
   184  			Test:     item["test"].(string),
   185  			Variable: item["variable"].(string),
   186  			Values: dataSourceAwsIamPolicyDocumentReplaceVarsInList(
   187  				iamPolicyDecodeConfigStringList(
   188  					item["values"].(*schema.Set).List(),
   189  				),
   190  			),
   191  		}
   192  	}
   193  	return IAMPolicyStatementConditionSet(out)
   194  }
   195  
   196  func dataSourceAwsIamPolicyDocumentMakePrincipals(in []interface{}) IAMPolicyStatementPrincipalSet {
   197  	out := make([]IAMPolicyStatementPrincipal, len(in))
   198  	for i, itemI := range in {
   199  		item := itemI.(map[string]interface{})
   200  		out[i] = IAMPolicyStatementPrincipal{
   201  			Type: item["type"].(string),
   202  			Identifiers: dataSourceAwsIamPolicyDocumentReplaceVarsInList(
   203  				iamPolicyDecodeConfigStringList(
   204  					item["identifiers"].(*schema.Set).List(),
   205  				),
   206  			),
   207  		}
   208  	}
   209  	return IAMPolicyStatementPrincipalSet(out)
   210  }
   211  
   212  func dataSourceAwsIamPolicyPrincipalSchema() *schema.Schema {
   213  	return &schema.Schema{
   214  		Type:     schema.TypeSet,
   215  		Optional: true,
   216  		Elem: &schema.Resource{
   217  			Schema: map[string]*schema.Schema{
   218  				"type": &schema.Schema{
   219  					Type:     schema.TypeString,
   220  					Required: true,
   221  				},
   222  				"identifiers": &schema.Schema{
   223  					Type:     schema.TypeSet,
   224  					Required: true,
   225  					Elem: &schema.Schema{
   226  						Type: schema.TypeString,
   227  					},
   228  				},
   229  			},
   230  		},
   231  	}
   232  }