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

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"regexp"
     7  	"strings"
     8  
     9  	"github.com/aws/aws-sdk-go/aws"
    10  	"github.com/aws/aws-sdk-go/aws/awserr"
    11  	"github.com/aws/aws-sdk-go/service/iam"
    12  
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  )
    15  
    16  func resourceAwsIamRolePolicy() *schema.Resource {
    17  	return &schema.Resource{
    18  		// PutRolePolicy API is idempotent, so these can be the same.
    19  		Create: resourceAwsIamRolePolicyPut,
    20  		Update: resourceAwsIamRolePolicyPut,
    21  
    22  		Read:   resourceAwsIamRolePolicyRead,
    23  		Delete: resourceAwsIamRolePolicyDelete,
    24  		Importer: &schema.ResourceImporter{
    25  			State: schema.ImportStatePassthrough,
    26  		},
    27  
    28  		Schema: map[string]*schema.Schema{
    29  			"policy": &schema.Schema{
    30  				Type:     schema.TypeString,
    31  				Required: true,
    32  			},
    33  			"name": &schema.Schema{
    34  				Type:     schema.TypeString,
    35  				Required: true,
    36  				ForceNew: true,
    37  				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
    38  					// https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8291-L8296
    39  					value := v.(string)
    40  					if len(value) > 128 {
    41  						errors = append(errors, fmt.Errorf(
    42  							"%q cannot be longer than 128 characters", k))
    43  					}
    44  					if !regexp.MustCompile("^[\\w+=,.@-]+$").MatchString(value) {
    45  						errors = append(errors, fmt.Errorf(
    46  							"%q must match [\\w+=,.@-]", k))
    47  					}
    48  					return
    49  				},
    50  			},
    51  			"role": &schema.Schema{
    52  				Type:     schema.TypeString,
    53  				Required: true,
    54  				ForceNew: true,
    55  			},
    56  		},
    57  	}
    58  }
    59  
    60  func resourceAwsIamRolePolicyPut(d *schema.ResourceData, meta interface{}) error {
    61  	iamconn := meta.(*AWSClient).iamconn
    62  
    63  	request := &iam.PutRolePolicyInput{
    64  		RoleName:       aws.String(d.Get("role").(string)),
    65  		PolicyName:     aws.String(d.Get("name").(string)),
    66  		PolicyDocument: aws.String(d.Get("policy").(string)),
    67  	}
    68  
    69  	if _, err := iamconn.PutRolePolicy(request); err != nil {
    70  		return fmt.Errorf("Error putting IAM role policy %s: %s", *request.PolicyName, err)
    71  	}
    72  
    73  	d.SetId(fmt.Sprintf("%s:%s", *request.RoleName, *request.PolicyName))
    74  	return nil
    75  }
    76  
    77  func resourceAwsIamRolePolicyRead(d *schema.ResourceData, meta interface{}) error {
    78  	iamconn := meta.(*AWSClient).iamconn
    79  
    80  	role, name, err := resourceAwsIamRolePolicyParseId(d.Id())
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	request := &iam.GetRolePolicyInput{
    86  		PolicyName: aws.String(name),
    87  		RoleName:   aws.String(role),
    88  	}
    89  
    90  	getResp, err := iamconn.GetRolePolicy(request)
    91  	if err != nil {
    92  		if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { // XXX test me
    93  			d.SetId("")
    94  			return nil
    95  		}
    96  		return fmt.Errorf("Error reading IAM policy %s from role %s: %s", name, role, err)
    97  	}
    98  
    99  	if getResp.PolicyDocument == nil {
   100  		return fmt.Errorf("GetRolePolicy returned a nil policy document")
   101  	}
   102  
   103  	policy, err := url.QueryUnescape(*getResp.PolicyDocument)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	if err := d.Set("policy", policy); err != nil {
   108  		return err
   109  	}
   110  	if err := d.Set("name", name); err != nil {
   111  		return err
   112  	}
   113  	return d.Set("role", role)
   114  }
   115  
   116  func resourceAwsIamRolePolicyDelete(d *schema.ResourceData, meta interface{}) error {
   117  	iamconn := meta.(*AWSClient).iamconn
   118  
   119  	role, name, err := resourceAwsIamRolePolicyParseId(d.Id())
   120  	if err != nil {
   121  		return err
   122  	}
   123  
   124  	request := &iam.DeleteRolePolicyInput{
   125  		PolicyName: aws.String(name),
   126  		RoleName:   aws.String(role),
   127  	}
   128  
   129  	if _, err := iamconn.DeleteRolePolicy(request); err != nil {
   130  		return fmt.Errorf("Error deleting IAM role policy %s: %s", d.Id(), err)
   131  	}
   132  	return nil
   133  }
   134  
   135  func resourceAwsIamRolePolicyParseId(id string) (roleName, policyName string, err error) {
   136  	parts := strings.SplitN(id, ":", 2)
   137  	if len(parts) != 2 {
   138  		err = fmt.Errorf("role_policy id must be of the for <role name>:<policy name>")
   139  		return
   140  	}
   141  
   142  	roleName = parts[0]
   143  	policyName = parts[1]
   144  	return
   145  }