diff --git a/aws/resource_aws_iam_role.go b/aws/resource_aws_iam_role.go index 7480ed3d027..693db8eb136 100644 --- a/aws/resource_aws_iam_role.go +++ b/aws/resource_aws_iam_role.go @@ -21,7 +21,7 @@ func resourceAwsIamRole() *schema.Resource { Update: resourceAwsIamRoleUpdate, Delete: resourceAwsIamRoleDelete, Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, + State: resourceAwsIamRoleImport, }, Schema: map[string]*schema.Schema{ @@ -95,6 +95,12 @@ func resourceAwsIamRole() *schema.Resource { ValidateFunc: validateJsonString, }, + "force_detach_policies": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "create_date": { Type: schema.TypeString, Computed: true, @@ -103,6 +109,12 @@ func resourceAwsIamRole() *schema.Resource { } } +func resourceAwsIamRoleImport( + d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + d.Set("force_detach_policies", false) + return []*schema.ResourceData{d}, nil +} + func resourceAwsIamRoleCreate(d *schema.ResourceData, meta interface{}) error { iamconn := meta.(*AWSClient).iamconn @@ -254,6 +266,27 @@ func resourceAwsIamRoleDelete(d *schema.ResourceData, meta interface{}) error { } } + if d.Get("force_detach_policies").(bool) { + policiesResp, err := iamconn.ListAttachedRolePolicies(&iam.ListAttachedRolePoliciesInput{ + RoleName: aws.String(d.Id()), + }) + if err != nil { + return fmt.Errorf("Error listing Policies for IAM Role (%s) when trying to delete: %s", d.Id(), err) + } + // Loop and remove this Role from any Profiles + if len(policiesResp.AttachedPolicies) > 0 { + for _, i := range policiesResp.AttachedPolicies { + _, err := iamconn.DetachRolePolicy(&iam.DetachRolePolicyInput{ + PolicyArn: i.PolicyArn, + RoleName: aws.String(d.Id()), + }) + if err != nil { + return fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err) + } + } + } + } + request := &iam.DeleteRoleInput{ RoleName: aws.String(d.Id()), } diff --git a/website/docs/r/iam_role.html.markdown b/website/docs/r/iam_role.html.markdown index ad8b983d33d..b7683c45ecf 100644 --- a/website/docs/r/iam_role.html.markdown +++ b/website/docs/r/iam_role.html.markdown @@ -41,6 +41,7 @@ The following arguments are supported: * `name` - (Optional, Forces new resource) The name of the role. If omitted, Terraform will assign a random, unique name. * `name_prefix` - (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with `name`. * `assume_role_policy` - (Required) The policy that grants an entity permission to assume the role. +* `force_detach_policies` - (Optional) Specifies to force detaching any policies the role has before destroying it. Defaults to `false`. ~> **NOTE:** This `assume_role_policy` is very similar but slightly different than just a standard IAM policy and cannot use an `aws_iam_policy` resource. It _can_ however, use an `aws_iam_policy_document` [data source](https://www.terraform.io/docs/providers/aws/d/iam_policy_document.html), see example below for how this could work.