github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/aws/resource_aws_iam_user.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/aws/awserr" 9 "github.com/aws/aws-sdk-go/service/iam" 10 11 "github.com/hashicorp/terraform/helper/schema" 12 ) 13 14 func resourceAwsIamUser() *schema.Resource { 15 return &schema.Resource{ 16 Create: resourceAwsIamUserCreate, 17 Read: resourceAwsIamUserRead, 18 Update: resourceAwsIamUserUpdate, 19 Delete: resourceAwsIamUserDelete, 20 Importer: &schema.ResourceImporter{ 21 State: schema.ImportStatePassthrough, 22 }, 23 24 Schema: map[string]*schema.Schema{ 25 "arn": &schema.Schema{ 26 Type: schema.TypeString, 27 Computed: true, 28 }, 29 /* 30 The UniqueID could be used as the Id(), but none of the API 31 calls allow specifying a user by the UniqueID: they require the 32 name. The only way to locate a user by UniqueID is to list them 33 all and that would make this provider unnecessarilly complex 34 and inefficient. Still, there are other reasons one might want 35 the UniqueID, so we can make it available. 36 */ 37 "unique_id": &schema.Schema{ 38 Type: schema.TypeString, 39 Computed: true, 40 }, 41 "name": &schema.Schema{ 42 Type: schema.TypeString, 43 Required: true, 44 }, 45 "path": &schema.Schema{ 46 Type: schema.TypeString, 47 Optional: true, 48 Default: "/", 49 ForceNew: true, 50 }, 51 "force_destroy": &schema.Schema{ 52 Type: schema.TypeBool, 53 Optional: true, 54 Default: false, 55 Description: "Delete user even if it has non-Terraform-managed IAM access keys", 56 }, 57 }, 58 } 59 } 60 61 func resourceAwsIamUserCreate(d *schema.ResourceData, meta interface{}) error { 62 iamconn := meta.(*AWSClient).iamconn 63 name := d.Get("name").(string) 64 path := d.Get("path").(string) 65 66 request := &iam.CreateUserInput{ 67 Path: aws.String(path), 68 UserName: aws.String(name), 69 } 70 71 log.Println("[DEBUG] Create IAM User request:", request) 72 createResp, err := iamconn.CreateUser(request) 73 if err != nil { 74 return fmt.Errorf("Error creating IAM User %s: %s", name, err) 75 } 76 d.SetId(*createResp.User.UserName) 77 return resourceAwsIamUserReadResult(d, createResp.User) 78 } 79 80 func resourceAwsIamUserRead(d *schema.ResourceData, meta interface{}) error { 81 iamconn := meta.(*AWSClient).iamconn 82 83 request := &iam.GetUserInput{ 84 UserName: aws.String(d.Id()), 85 } 86 87 getResp, err := iamconn.GetUser(request) 88 if err != nil { 89 if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { // XXX test me 90 log.Printf("[WARN] No IAM user by name (%s) found", d.Id()) 91 d.SetId("") 92 return nil 93 } 94 return fmt.Errorf("Error reading IAM User %s: %s", d.Id(), err) 95 } 96 return resourceAwsIamUserReadResult(d, getResp.User) 97 } 98 99 func resourceAwsIamUserReadResult(d *schema.ResourceData, user *iam.User) error { 100 if err := d.Set("name", user.UserName); err != nil { 101 return err 102 } 103 if err := d.Set("arn", user.Arn); err != nil { 104 return err 105 } 106 if err := d.Set("path", user.Path); err != nil { 107 return err 108 } 109 if err := d.Set("unique_id", user.UserId); err != nil { 110 return err 111 } 112 return nil 113 } 114 115 func resourceAwsIamUserUpdate(d *schema.ResourceData, meta interface{}) error { 116 if d.HasChange("name") || d.HasChange("path") { 117 iamconn := meta.(*AWSClient).iamconn 118 on, nn := d.GetChange("name") 119 _, np := d.GetChange("path") 120 121 request := &iam.UpdateUserInput{ 122 UserName: aws.String(on.(string)), 123 NewUserName: aws.String(nn.(string)), 124 NewPath: aws.String(np.(string)), 125 } 126 127 log.Println("[DEBUG] Update IAM User request:", request) 128 _, err := iamconn.UpdateUser(request) 129 if err != nil { 130 if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { 131 log.Printf("[WARN] No IAM user by name (%s) found", d.Id()) 132 d.SetId("") 133 return nil 134 } 135 return fmt.Errorf("Error updating IAM User %s: %s", d.Id(), err) 136 } 137 return resourceAwsIamUserRead(d, meta) 138 } 139 return nil 140 } 141 142 func resourceAwsIamUserDelete(d *schema.ResourceData, meta interface{}) error { 143 iamconn := meta.(*AWSClient).iamconn 144 145 // IAM Users must be removed from all groups before they can be deleted 146 var groups []string 147 listGroups := &iam.ListGroupsForUserInput{ 148 UserName: aws.String(d.Id()), 149 } 150 pageOfGroups := func(page *iam.ListGroupsForUserOutput, lastPage bool) (shouldContinue bool) { 151 for _, g := range page.Groups { 152 groups = append(groups, *g.GroupName) 153 } 154 return !lastPage 155 } 156 err := iamconn.ListGroupsForUserPages(listGroups, pageOfGroups) 157 if err != nil { 158 return fmt.Errorf("Error removing user %q from all groups: %s", d.Id(), err) 159 } 160 for _, g := range groups { 161 // use iam group membership func to remove user from all groups 162 log.Printf("[DEBUG] Removing IAM User %s from IAM Group %s", d.Id(), g) 163 if err := removeUsersFromGroup(iamconn, []*string{aws.String(d.Id())}, g); err != nil { 164 return err 165 } 166 } 167 168 // All access keys for the user must be removed 169 if d.Get("force_destroy").(bool) { 170 var accessKeys []string 171 listAccessKeys := &iam.ListAccessKeysInput{ 172 UserName: aws.String(d.Id()), 173 } 174 pageOfAccessKeys := func(page *iam.ListAccessKeysOutput, lastPage bool) (shouldContinue bool) { 175 for _, k := range page.AccessKeyMetadata { 176 accessKeys = append(accessKeys, *k.AccessKeyId) 177 } 178 return !lastPage 179 } 180 err = iamconn.ListAccessKeysPages(listAccessKeys, pageOfAccessKeys) 181 if err != nil { 182 return fmt.Errorf("Error removing access keys of user %s: %s", d.Id(), err) 183 } 184 for _, k := range accessKeys { 185 _, err := iamconn.DeleteAccessKey(&iam.DeleteAccessKeyInput{ 186 UserName: aws.String(d.Id()), 187 AccessKeyId: aws.String(k), 188 }) 189 if err != nil { 190 return fmt.Errorf("Error deleting access key %s: %s", k, err) 191 } 192 } 193 } 194 195 request := &iam.DeleteUserInput{ 196 UserName: aws.String(d.Id()), 197 } 198 199 log.Println("[DEBUG] Delete IAM User request:", request) 200 if _, err := iamconn.DeleteUser(request); err != nil { 201 return fmt.Errorf("Error deleting IAM User %s: %s", d.Id(), err) 202 } 203 return nil 204 }