rebuy-de / aws-nuke

Nuke a whole AWS account and delete all its resources.
MIT License
5.74k stars 718 forks source link

EKS related IAM Roles are not deleted #1136

Open rcanavan opened 10 months ago

rcanavan commented 10 months ago

Some IAM Roles that are created (possibly by terraform) while spinning up an EKS cluster aren't deleted by aws-nuke.

I've not seen any logs indicating that aws-nuke has attempted to delete those roles, however, a related one was deleted, despite the log indicating that it failed:

[eu-central-1 - EC2SecurityGroup - sg-0debb513f8620b980 - [Name: "default-eks-node-group-2023102713260613530000000d", OwnerID: "989443001648", tag:Name: "default-eks-node-group", tag:environment: "XXXX", tag:managed_by: "Terraform"] - failed

Are those remaining roles left behind intentionally, or do I have to adjust my configuration or parameters? I only have an IAMUser, its policies and access keys, as well as the dynamo db tables and S3 buckets used for terraform in my filter section of my config.

ryanpeach commented 6 months ago

Same

ryanpeach commented 6 months ago

Here's a hack if anyone wants it:

"""
Used to fix this issue https://github.com/rebuy-de/aws-nuke/issues/1136
REF: https://chat.openai.com/share/6ac94163-61c5-41e7-a7d1-4a90e247a949
"""

import boto3
from fnmatch import fnmatch

# Create an IAM service client
iam = boto3.client("iam")

# Constant for the pattern to match
PATTERN = "" # TODO: Use a glob pattern and replace this with your role/policy names

# Detach policy from all entities
def detach_policy_from_all_entities(policy_arn):
    # Detach from users
    for user in iam.list_entities_for_policy(PolicyArn=policy_arn, EntityFilter="User")[
        "PolicyUsers"
    ]:
        print(f"Detaching policy {policy_arn} from user {user['UserName']}")
        iam.detach_user_policy(UserName=user["UserName"], PolicyArn=policy_arn)
    # Detach from roles
    for role in iam.list_entities_for_policy(PolicyArn=policy_arn, EntityFilter="Role")[
        "PolicyRoles"
    ]:
        print(f"Detaching policy {policy_arn} from role {role['RoleName']}")
        iam.detach_role_policy(RoleName=role["RoleName"], PolicyArn=policy_arn)
    # Detach from groups
    for group in iam.list_entities_for_policy(
        PolicyArn=policy_arn, EntityFilter="Group"
    )["PolicyGroups"]:
        print(f"Detaching policy {policy_arn} from group {group['GroupName']}")
        iam.detach_group_policy(GroupName=group["GroupName"], PolicyArn=policy_arn)

# Function to remove all inline policies from a role
def remove_inline_policies_from_role(role_name):
    inline_policies = iam.list_role_policies(RoleName=role_name)["PolicyNames"]
    for policy_name in inline_policies:
        print(f"Deleting inline policy {policy_name} from role {role_name}")
        iam.delete_role_policy(RoleName=role_name, PolicyName=policy_name)

# Function to detach all managed policies from a role
def detach_policies_from_role(role_name):
    attached_policies = iam.list_attached_role_policies(RoleName=role_name)
    for policy in attached_policies["AttachedPolicies"]:
        print(f"Detaching managed policy {policy['PolicyName']} from role {role_name}")
        iam.detach_role_policy(RoleName=role_name, PolicyArn=policy["PolicyArn"])

# Delete policies matching the pattern
def delete_policies():
    paginator = iam.get_paginator("list_policies")
    for page in paginator.paginate(Scope="Local"):
        for policy in page["Policies"]:
            if fnmatch(policy["PolicyName"], PATTERN):
                print(f"Detaching and deleting policy {policy['PolicyName']}")
                detach_policy_from_all_entities(policy["Arn"])
                iam.delete_policy(PolicyArn=policy["Arn"])

# Delete roles matching the pattern
def delete_roles():
    paginator = iam.get_paginator("list_roles")
    for page in paginator.paginate():
        for role in page["Roles"]:
            if fnmatch(role["RoleName"], PATTERN):
                # Detach all attached managed policies and delete inline policies before deleting a role
                detach_policies_from_role(role["RoleName"])
                remove_inline_policies_from_role(role["RoleName"])

                print(f"Deleting role {role['RoleName']}")
                iam.delete_role(RoleName=role["RoleName"])

# Execute the deletion functions
delete_policies()
delete_roles()