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 }