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