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: "/",
|
Default: "/",
|
||||||
ForceNew: true,
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceAwsIamUserDelete(d *schema.ResourceData, meta interface{}) error {
|
func resourceAwsIamUserDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
iamconn := meta.(*AWSClient).iamconn
|
iamconn := meta.(*AWSClient).iamconn
|
||||||
|
|
||||||
// IAM Users must be removed from all groups before they can be deleted
|
// IAM Users must be removed from all groups before they can be deleted
|
||||||
var groups []string
|
var groups []string
|
||||||
var marker *string
|
listGroups := &iam.ListGroupsForUserInput{
|
||||||
truncated := aws.Bool(true)
|
UserName: aws.String(d.Id()),
|
||||||
|
}
|
||||||
for *truncated == true {
|
pageOfGroups := func(page *iam.ListGroupsForUserOutput, lastPage bool) (shouldContinue bool) {
|
||||||
listOpts := iam.ListGroupsForUserInput{
|
for _, g := range page.Groups {
|
||||||
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 {
|
|
||||||
groups = append(groups, *g.GroupName)
|
groups = append(groups, *g.GroupName)
|
||||||
}
|
}
|
||||||
|
return !lastPage
|
||||||
// if there's a marker present, we need to save it for pagination
|
}
|
||||||
if r.Marker != nil {
|
err := iamconn.ListGroupsForUserPages(listGroups, pageOfGroups)
|
||||||
*marker = *r.Marker
|
if err != nil {
|
||||||
}
|
return fmt.Errorf("Error removing user %q from all groups: %s", d.Id(), err)
|
||||||
*truncated = *r.IsTruncated
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, g := range groups {
|
for _, g := range groups {
|
||||||
// use iam group membership func to remove user from all 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)
|
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{
|
request := &iam.DeleteUserInput{
|
||||||
UserName: aws.String(d.Id()),
|
UserName: aws.String(d.Id()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,9 @@ The following arguments are supported:
|
||||||
|
|
||||||
* `name` - (Required) The user's name.
|
* `name` - (Required) The user's name.
|
||||||
* `path` - (Optional, default "/") Path in which to create the user.
|
* `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
|
## Attributes Reference
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue