From 9257de8439817883a5b70b3f056173edc3801569 Mon Sep 17 00:00:00 2001 From: Ray Miller Date: Sat, 10 Feb 2024 15:52:16 +0000 Subject: [PATCH] Add AWS housekeeping scripts, rename for consistency --- aws/delete_iam_policies.py | 61 +++++++++++++++++++ ...elete-iam-users.py => delete_iam_users.py} | 0 aws/delete_ssm_parameters.py | 46 ++++++++++++++ aws/delete_unused_security_groups.py | 48 +++++++++++++++ 4 files changed, 155 insertions(+) create mode 100755 aws/delete_iam_policies.py rename aws/{delete-iam-users.py => delete_iam_users.py} (100%) create mode 100755 aws/delete_ssm_parameters.py create mode 100755 aws/delete_unused_security_groups.py diff --git a/aws/delete_iam_policies.py b/aws/delete_iam_policies.py new file mode 100755 index 0000000..b669ef0 --- /dev/null +++ b/aws/delete_iam_policies.py @@ -0,0 +1,61 @@ +#!/usr/bin/python3 +# +# Delete IAM policies whose names match a pattern +# + +import argparse +import boto3 +import re +import click + +def list_policies(iam, pattern): + policies=[] + paginator = iam.get_paginator('list_policies') + for page in paginator.paginate(Scope='Local'): + for policy in page['Policies']: + if pattern.match(policy['PolicyName']): + policies.append(policy) + return policies + + +def delete_policy_versions(iam, policy): + paginator = iam.get_paginator('list_policy_versions') + for page in paginator.paginate(PolicyArn=policy['Arn']): + for version in page['Versions']: + if version['IsDefaultVersion']: + continue + print("Deleting version {v}".format(v=version['VersionId'])) + iam.delete_policy_version(PolicyArn=policy['Arn'], VersionId=version['VersionId']) + + +def delete_policy(iam, policy): + print("Deleting policy {name}".format(name=policy['PolicyName'])) + delete_policy_versions(iam, policy) + iam.delete_policy(PolicyArn=policy['Arn']) + + +def confirm_delete(policies): + print("Delete policies:") + for policy in policies: + print(policy['PolicyName']) + return click.confirm("Continue?") + + +def delete_matching_policies(pattern): + iam = boto3.client('iam') + policies = list_policies(iam, pattern) + if len(policies) == 0: + print("No matching policies") + return + if confirm_delete(policies): + for policy in policies: + delete_policy(iam, policy) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Delete IAM policies") + parser.add_argument("--pattern", help="Regex to match policy name", default=".*") + + args = parser.parse_args() + pattern = re.compile(args.pattern) + delete_matching_policies(pattern) diff --git a/aws/delete-iam-users.py b/aws/delete_iam_users.py similarity index 100% rename from aws/delete-iam-users.py rename to aws/delete_iam_users.py diff --git a/aws/delete_ssm_parameters.py b/aws/delete_ssm_parameters.py new file mode 100755 index 0000000..318e2b0 --- /dev/null +++ b/aws/delete_ssm_parameters.py @@ -0,0 +1,46 @@ +#!/usr/bin/python3 +# +# Delete all SSM parameters under the give prefix +# + +import argparse +import boto3 +import click +import sys + +def list_parameters(ssm, prefix): + parameters = [] + filter = {'Key': 'Name', 'Values': [prefix]} + paginator = ssm.get_paginator('describe_parameters') + for page in paginator.paginate(Filters=[filter]): + for param in page['Parameters']: + parameters.append(param['Name']) + return parameters + + +def delete_parameters(ssm, parameter_names): + n = len(parameter_names) + for i in range(0, n, 10): + batch = parameter_names[i:min(i+10, n)] + ssm.delete_parameters(Names=batch) + + +parser = argparse.ArgumentParser(description="Delete SSM Parameters") +parser.add_argument("--region", help="AWS Region name", default="eu-west-1") +parser.add_argument("--prefix", help="Delete parameters with this prefix", required=True) + +args = parser.parse_args() + +ssm = boto3.client('ssm', region_name=args.region) +params = list_parameters(ssm, args.prefix) + +if not params: + print("No parameters with prefix {prefix}".format(prefix=args.prefix)) + sys.exit(0) + +print("Delete parameters:") +for p in params: + print(" {name}".format(name=p)) + +if click.confirm("Continue?"): + delete_parameters(ssm, params) diff --git a/aws/delete_unused_security_groups.py b/aws/delete_unused_security_groups.py new file mode 100755 index 0000000..b55ed01 --- /dev/null +++ b/aws/delete_unused_security_groups.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +import boto3 +import botocore +import click + + +def get_interfaces(ec2, groupId): + ifs = ec2.describe_network_interfaces(Filters=[ + {"Name": "group-id", "Values": [groupId]} + ]) + return ifs['NetworkInterfaces'] + + +def list_unused_groups(ec2): + unused = [] + paginator = ec2.get_paginator('describe_security_groups') + for page in paginator.paginate(): + for sg in page['SecurityGroups']: + interfaces = get_interfaces(ec2, sg['GroupId']) + num_attachments = len(interfaces) + if num_attachments == 0: + unused.append(sg) + return unused + + +def delete_security_groups(ec2, security_groups): + for sg in security_groups: + try: + ec2.delete_security_group(GroupId=sg['GroupId']) + print("Deleted security group {id}".format(id=sg['GroupId'])) + except botocore.exceptions.ClientError as err: + print("Security group {id} could not be deleted".format(id=sg['GroupId'])) + print(err) + + +if __name__ == "__main__": + ec2 = boto3.client('ec2') + unused = list_unused_groups(ec2) + for sg in unused: + print(sg['GroupId'], sg['GroupName'], sg['Description']) + if click.confirm("Delete {n} groups?".format(n=len(unused))): + delete_security_groups(ec2, unused) + + + + +