provider/aws: Delete access keys before deleting IAM user (#7766)
* provider/aws: Delete access keys before deleting IAM user * provider/aws: Put IAM key removal behind force_destroy option * provider/aws: Move all access key deletion under force_destroy * Add iam_user force_destroy to website * provider/aws: Improve clarity of looping over pages in delete IAM user
This commit is contained in:
parent
9539b25966
commit
ad62f09061
|
@ -48,6 +48,12 @@ func resourceAwsIamUser() *schema.Resource {
|
|||
Default: "/",
|
||||
ForceNew: true,
|
||||
},
|
||||
"force_destroy": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: false,
|
||||
Description: "Delete user even if it has non-Terraform-managed IAM access keys",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -132,39 +138,25 @@ func resourceAwsIamUserUpdate(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceAwsIamUserDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
iamconn := meta.(*AWSClient).iamconn
|
||||
|
||||
// IAM Users must be removed from all groups before they can be deleted
|
||||
var groups []string
|
||||
var marker *string
|
||||
truncated := aws.Bool(true)
|
||||
|
||||
for *truncated == true {
|
||||
listOpts := iam.ListGroupsForUserInput{
|
||||
UserName: aws.String(d.Id()),
|
||||
}
|
||||
|
||||
if marker != nil {
|
||||
listOpts.Marker = marker
|
||||
}
|
||||
|
||||
r, err := iamconn.ListGroupsForUser(&listOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, g := range r.Groups {
|
||||
listGroups := &iam.ListGroupsForUserInput{
|
||||
UserName: aws.String(d.Id()),
|
||||
}
|
||||
pageOfGroups := func(page *iam.ListGroupsForUserOutput, lastPage bool) (shouldContinue bool) {
|
||||
for _, g := range page.Groups {
|
||||
groups = append(groups, *g.GroupName)
|
||||
}
|
||||
|
||||
// if there's a marker present, we need to save it for pagination
|
||||
if r.Marker != nil {
|
||||
*marker = *r.Marker
|
||||
}
|
||||
*truncated = *r.IsTruncated
|
||||
return !lastPage
|
||||
}
|
||||
err := iamconn.ListGroupsForUserPages(listGroups, pageOfGroups)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error removing user %q from all groups: %s", d.Id(), err)
|
||||
}
|
||||
|
||||
for _, g := range groups {
|
||||
// use iam group membership func to remove user from all groups
|
||||
log.Printf("[DEBUG] Removing IAM User %s from IAM Group %s", d.Id(), g)
|
||||
|
@ -173,6 +165,33 @@ func resourceAwsIamUserDelete(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
// All access keys for the user must be removed
|
||||
if d.Get("force_destroy").(bool) {
|
||||
var accessKeys []string
|
||||
listAccessKeys := &iam.ListAccessKeysInput{
|
||||
UserName: aws.String(d.Id()),
|
||||
}
|
||||
pageOfAccessKeys := func(page *iam.ListAccessKeysOutput, lastPage bool) (shouldContinue bool) {
|
||||
for _, k := range page.AccessKeyMetadata {
|
||||
accessKeys = append(accessKeys, *k.AccessKeyId)
|
||||
}
|
||||
return !lastPage
|
||||
}
|
||||
err = iamconn.ListAccessKeysPages(listAccessKeys, pageOfAccessKeys)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error removing access keys of user %s: %s", d.Id(), err)
|
||||
}
|
||||
for _, k := range accessKeys {
|
||||
_, err := iamconn.DeleteAccessKey(&iam.DeleteAccessKeyInput{
|
||||
UserName: aws.String(d.Id()),
|
||||
AccessKeyId: aws.String(k),
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting access key %s: %s", k, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
request := &iam.DeleteUserInput{
|
||||
UserName: aws.String(d.Id()),
|
||||
}
|
||||
|
|
|
@ -48,6 +48,9 @@ The following arguments are supported:
|
|||
|
||||
* `name` - (Required) The user's name.
|
||||
* `path` - (Optional, default "/") Path in which to create the user.
|
||||
* `force_destroy` - (Optional, default false) When destroying this user, destroy
|
||||
even if it has non-Terraform-managed IAM access keys. Without `force_destroy`
|
||||
a user with non-Terraform-managed access keys will fail to be destroyed.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
|
|
Loading…
Reference in New Issue