github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/aws/resource_aws_iam_policy.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 6 "github.com/aws/aws-sdk-go/aws" 7 "github.com/aws/aws-sdk-go/aws/awserr" 8 "github.com/aws/aws-sdk-go/service/iam" 9 10 "github.com/hashicorp/terraform/helper/schema" 11 ) 12 13 func resourceAwsIamPolicy() *schema.Resource { 14 return &schema.Resource{ 15 Create: resourceAwsIamPolicyCreate, 16 Read: resourceAwsIamPolicyRead, 17 Update: resourceAwsIamPolicyUpdate, 18 Delete: resourceAwsIamPolicyDelete, 19 20 Schema: map[string]*schema.Schema{ 21 "description": &schema.Schema{ 22 Type: schema.TypeString, 23 ForceNew: true, 24 Optional: true, 25 }, 26 "path": &schema.Schema{ 27 Type: schema.TypeString, 28 Optional: true, 29 Default: "/", 30 ForceNew: true, 31 }, 32 "policy": &schema.Schema{ 33 Type: schema.TypeString, 34 Required: true, 35 }, 36 "name": &schema.Schema{ 37 Type: schema.TypeString, 38 Required: true, 39 ForceNew: true, 40 }, 41 "arn": &schema.Schema{ 42 Type: schema.TypeString, 43 Computed: true, 44 }, 45 }, 46 } 47 } 48 49 func resourceAwsIamPolicyCreate(d *schema.ResourceData, meta interface{}) error { 50 iamconn := meta.(*AWSClient).iamconn 51 name := d.Get("name").(string) 52 53 request := &iam.CreatePolicyInput{ 54 Description: aws.String(d.Get("description").(string)), 55 Path: aws.String(d.Get("path").(string)), 56 PolicyDocument: aws.String(d.Get("policy").(string)), 57 PolicyName: aws.String(name), 58 } 59 60 response, err := iamconn.CreatePolicy(request) 61 if err != nil { 62 return fmt.Errorf("Error creating IAM policy %s: %s", name, err) 63 } 64 65 return readIamPolicy(d, response.Policy) 66 } 67 68 func resourceAwsIamPolicyRead(d *schema.ResourceData, meta interface{}) error { 69 iamconn := meta.(*AWSClient).iamconn 70 71 request := &iam.GetPolicyInput{ 72 PolicyArn: aws.String(d.Id()), 73 } 74 75 response, err := iamconn.GetPolicy(request) 76 if err != nil { 77 if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { 78 d.SetId("") 79 return nil 80 } 81 return fmt.Errorf("Error reading IAM policy %s: %s", d.Id(), err) 82 } 83 84 return readIamPolicy(d, response.Policy) 85 } 86 87 func resourceAwsIamPolicyUpdate(d *schema.ResourceData, meta interface{}) error { 88 iamconn := meta.(*AWSClient).iamconn 89 90 if err := iamPolicyPruneVersions(d.Id(), iamconn); err != nil { 91 return err 92 } 93 94 if !d.HasChange("policy") { 95 return nil 96 } 97 request := &iam.CreatePolicyVersionInput{ 98 PolicyArn: aws.String(d.Id()), 99 PolicyDocument: aws.String(d.Get("policy").(string)), 100 SetAsDefault: aws.Bool(true), 101 } 102 103 if _, err := iamconn.CreatePolicyVersion(request); err != nil { 104 return fmt.Errorf("Error updating IAM policy %s: %s", d.Id(), err) 105 } 106 return nil 107 } 108 109 func resourceAwsIamPolicyDelete(d *schema.ResourceData, meta interface{}) error { 110 iamconn := meta.(*AWSClient).iamconn 111 112 if err := iamPolicyDeleteNondefaultVersions(d.Id(), iamconn); err != nil { 113 return err 114 } 115 116 request := &iam.DeletePolicyInput{ 117 PolicyArn: aws.String(d.Id()), 118 } 119 120 _, err := iamconn.DeletePolicy(request) 121 if err != nil { 122 if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { 123 return nil 124 } 125 return fmt.Errorf("Error reading IAM policy %s: %#v", d.Id(), err) 126 } 127 return nil 128 } 129 130 // iamPolicyPruneVersions deletes the oldest versions. 131 // 132 // Old versions are deleted until there are 4 or less remaining, which means at 133 // least one more can be created before hitting the maximum of 5. 134 // 135 // The default version is never deleted. 136 137 func iamPolicyPruneVersions(arn string, iamconn *iam.IAM) error { 138 versions, err := iamPolicyListVersions(arn, iamconn) 139 if err != nil { 140 return err 141 } 142 if len(versions) < 5 { 143 return nil 144 } 145 146 var oldestVersion *iam.PolicyVersion 147 148 for _, version := range versions { 149 if *version.IsDefaultVersion { 150 continue 151 } 152 if oldestVersion == nil || 153 version.CreateDate.Before(*oldestVersion.CreateDate) { 154 oldestVersion = version 155 } 156 } 157 158 if err := iamPolicyDeleteVersion(arn, *oldestVersion.VersionId, iamconn); err != nil { 159 return err 160 } 161 return nil 162 } 163 164 func iamPolicyDeleteNondefaultVersions(arn string, iamconn *iam.IAM) error { 165 versions, err := iamPolicyListVersions(arn, iamconn) 166 if err != nil { 167 return err 168 } 169 170 for _, version := range versions { 171 if *version.IsDefaultVersion { 172 continue 173 } 174 if err := iamPolicyDeleteVersion(arn, *version.VersionId, iamconn); err != nil { 175 return err 176 } 177 } 178 179 return nil 180 } 181 182 func iamPolicyDeleteVersion(arn, versionID string, iamconn *iam.IAM) error { 183 request := &iam.DeletePolicyVersionInput{ 184 PolicyArn: aws.String(arn), 185 VersionId: aws.String(versionID), 186 } 187 188 _, err := iamconn.DeletePolicyVersion(request) 189 if err != nil { 190 return fmt.Errorf("Error deleting version %s from IAM policy %s: %s", versionID, arn, err) 191 } 192 return nil 193 } 194 195 func iamPolicyListVersions(arn string, iamconn *iam.IAM) ([]*iam.PolicyVersion, error) { 196 request := &iam.ListPolicyVersionsInput{ 197 PolicyArn: aws.String(arn), 198 } 199 200 response, err := iamconn.ListPolicyVersions(request) 201 if err != nil { 202 return nil, fmt.Errorf("Error listing versions for IAM policy %s: %s", arn, err) 203 } 204 return response.Versions, nil 205 } 206 207 func readIamPolicy(d *schema.ResourceData, policy *iam.Policy) error { 208 d.SetId(*policy.Arn) 209 if policy.Description != nil { 210 // the description isn't present in the response to CreatePolicy. 211 if err := d.Set("description", *policy.Description); err != nil { 212 return err 213 } 214 } 215 if err := d.Set("path", *policy.Path); err != nil { 216 return err 217 } 218 if err := d.Set("name", *policy.PolicyName); err != nil { 219 return err 220 } 221 if err := d.Set("arn", *policy.Arn); err != nil { 222 return err 223 } 224 // TODO: set policy 225 226 return nil 227 }