Forked from TomRyan-321/security-group-cleanup.py
          
        
    
          Last active
          August 25, 2022 18:08 
        
      - 
      
 - 
        
Save snixon/059b0a0edf87e9a34d020bb2c9546874 to your computer and use it in GitHub Desktop.  
Revisions
- 
        
snixon revised this gist
Jul 13, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -241,7 +241,7 @@ def lookup_by_id(sgid): for group in sorted(delete_candidates): security_group = ec2.SecurityGroup(group) table.add_row([region, security_group.vpc_id or "None", group, security_group.group_name]) print( table.get_string( title="Account: {} ({}) - {}".format(acct_name, acct_id, region)  - 
        
snixon revised this gist
Dec 5, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -115,7 +115,7 @@ def lookup_by_id(sgid): for tag_group in exclusion_tags: for tags in groupobj["Tags"]: if str(tag_group).casefold() == str(tags).casefold(): tag_excluded_sgs.append(groupobj["GroupId"]) all_groups.append(groupobj["GroupId"]) total_groups = len(all_groups)  - 
        
snixon revised this gist
Jul 3, 2019 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,6 +4,7 @@ import boto3 import argparse import json # `pip install -U PTable` will get you the right fork of PrettyTable from prettytable import PrettyTable from botocore.exceptions import ClientError  - 
        
snixon revised this gist
Jul 3, 2019 . No changes.There are no files selected for viewing
 - 
        
snixon revised this gist
Jul 3, 2019 . 1 changed file with 271 additions and 110 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,116 +1,277 @@ #!/usr/bin/env python import os import boto3 import argparse import json from prettytable import PrettyTable from botocore.exceptions import ClientError # Tags in this list will be checked against any tags Security Groups may have on them # If a match is found, the SG will be excluded. Matches are case insensitive for both key and value exclusion_tags = [{"Key": "ephemeral", "Value": "true"}] try: parser = argparse.ArgumentParser(description="Find and delete unused Security Groups") parser.add_argument( "-r", "--region", type=str, default="us-east-1", help="The default region is us-east-1" ) parser.add_argument( "-p", "--profile", type=str, default="default", help="The AWS profile to use for the connection", ) parser.add_argument( "-d", "--delete", action="store_true", help="Try to delete the security groups we find" ) parser.add_argument("--dry-run", dest="dry_run", action="store_true", help="Simulate deletes") parser.add_argument( "--todos", dest="all_regions", action="store_true", help="Run on each region in turn" ) parser.add_argument( "--json", dest="json_output", action="store_true", help="Output JSON Doc of rules for each SG to be deleted", ) parser.add_argument( "-q", "--quiet", action="store_true", help="Don't show summaries for non-deletable resources", ) parser.add_argument( "-o", "--output", action="store", default="output", help="Optional directory prefix for the output json files if json_output is specified.", ) args = parser.parse_args() session = boto3.session.Session(profile_name=args.profile) regions = [] if args.all_regions: for region in session.get_available_regions("ec2"): regions.append(region) else: regions.append(args.region) for region in regions: ec2 = session.resource("ec2", region_name=region) client = session.client("ec2", region_name=region) acct_name = session.client("iam").list_account_aliases()["AccountAliases"][0] acct_id = session.client("sts").get_caller_identity().get("Account") all_groups = [] security_groups_in_use = [] rule_referenced_sgs = [] tag_excluded_sgs = [] def lookup_by_id(sgid): sg = ec2.get_all_security_groups(group_ids=sgid) return sg[0].name # Get ALL security groups names try: security_groups_dict = client.describe_security_groups() except ClientError as e: if e.response["Error"]["Code"] == "AuthFailure": if args.quiet: continue else: error_table = PrettyTable(["Error Message"]) error_table.add_row( ["Authentication Failure: You may not have access to this Region"] ) print( error_table.get_string( title="Account: {} ({}) - {}".format(acct_name, acct_id, region) ) ) continue security_groups = security_groups_dict["SecurityGroups"] for groupobj in security_groups: if ( groupobj["GroupName"] == "default" or groupobj["GroupName"].startswith("d-") or groupobj["GroupName"].startswith("AWS-OpsWorks-") ): security_groups_in_use.append(groupobj["GroupId"]) for ruleset in groupobj["IpPermissions"]: if len(ruleset["UserIdGroupPairs"]) > 0: for group in ruleset["UserIdGroupPairs"]: rule_referenced_sgs.append(group["GroupId"]) if len(exclusion_tags) > 0: if "Tags" in groupobj: for tag_group in exclusion_tags: for tags in groupobj["Tags"]: if str(tag_group).casefold() == str(tags).casefold(): tag_excluded_sgs.append(group["GroupId"]) all_groups.append(groupobj["GroupId"]) total_groups = len(all_groups) # Prune the groups that are referenced by other groups for group in rule_referenced_sgs: if group in all_groups: all_groups.remove(group) security_groups_in_use.append(group) for group in tag_excluded_sgs: if group in all_groups: all_groups.remove(group) security_groups_in_use.append(group) # Get all security groups used by instances instances_dict = client.describe_instances() reservations = instances_dict["Reservations"] network_interface_count = 0 for i in reservations: for j in i["Instances"]: for k in j["SecurityGroups"]: if k["GroupId"] not in security_groups_in_use: security_groups_in_use.append(k["GroupId"]) # Security Groups in use by Network Interfaces eni_dict = client.describe_network_interfaces() for i in eni_dict["NetworkInterfaces"]: for j in i["Groups"]: if j["GroupId"] not in security_groups_in_use: security_groups_in_use.append(j["GroupId"]) # Security groups used by classic ELBs elb_client = session.client("elb", region_name=region) elb_dict = elb_client.describe_load_balancers() for i in elb_dict["LoadBalancerDescriptions"]: for j in i["SecurityGroups"]: if j not in security_groups_in_use: security_groups_in_use.append(j) # Security groups used by ALBs elb2_client = session.client("elbv2", region_name=region) elb2_dict = elb2_client.describe_load_balancers() for i in elb2_dict["LoadBalancers"]: if "SecurityGroups" in i.keys(): for j in i["SecurityGroups"]: if j not in security_groups_in_use: security_groups_in_use.append(j) # Security groups used by RDS rds_client = session.client("rds", region_name=region) rds_dict = rds_client.describe_db_instances() for i in rds_dict["DBInstances"]: for j in i["VpcSecurityGroups"]: if j["VpcSecurityGroupId"] not in security_groups_in_use: security_groups_in_use.append(j["VpcSecurityGroupId"]) delete_candidates = [] for group in all_groups: if group not in security_groups_in_use: delete_candidates.append(group) if args.json_output: region_dict = {} # Create json docs in directory structure account_id/vpc_id/sg_id.json path = "./{}/{}".format(args.output, acct_id) os.makedirs(path, exist_ok=True) for group in sorted(delete_candidates): security_group = ec2.SecurityGroup(group) sg_doc = { "id": security_group.id, "region": region, "name": security_group.group_name, "description": security_group.description, "owner_id": security_group.owner_id, "vpc_id": security_group.vpc_id, "tags": security_group.tags, "ingress_rules": security_group.ip_permissions, "egress_rules": security_group.ip_permissions_egress, } if region not in region_dict: region_dict[region] = [] region_dict[region].append({security_group.id: sg_doc}) for region_name in region_dict: filename = path + "/" + region_name + "_unused_sg.json" with open(filename, "w") as outfile: outfile.write(json.dumps(region_dict, indent=2)) if args.delete: print("We will now delete security groups identified to not be in use.") dry_run_deletes = 0 for group in delete_candidates: security_group = ec2.SecurityGroup(group) try: if args.dry_run: security_group.delete(DryRun=True) else: security_group.delete() except ClientError as e: if e.response["Error"]["Code"] == "DependencyViolation": print( "{0} requires manual remediation. DependencyViolation".format( security_group.group_name ) ) elif e.response["Error"]["Code"] == "DryRunOperation": dry_run_deletes += 1 else: print("{0} requires manual remediation.".format(security_group.group_name)) else: if args.quiet and len(delete_candidates) == 0: continue else: table = PrettyTable(["Region", "VPC ID", "SecurityGroup ID", "SecurityGroup Name"]) table.align["SecurityGroup ID"] = "l" table.align["VPC ID"] = "c" table.align["SecurityGroup Name"] = "l" table.sortby = "VPC ID" for group in sorted(delete_candidates): security_group = ec2.SecurityGroup(group) table.add_row([region, security_group.vpc_id, group, security_group.group_name]) print( table.get_string( title="Account: {} ({}) - {}".format(acct_name, acct_id, region) ) ) if args.quiet: continue else: summary_table = PrettyTable(["Category Evaluated", "Count"]) summary_table.align["Category Evaluated"] = "l" summary_table.align["Count"] = "r" summary_table.add_row(["Total Security Groups", total_groups]) summary_table.add_row(["Total EC2 Instances", len(reservations)]) summary_table.add_row( [ "Total Load Balancers", len(elb_dict["LoadBalancerDescriptions"]) + len(elb2_dict["LoadBalancers"]), ] ) summary_table.add_row(["Total RDS Instances", len(rds_dict["DBInstances"])]) summary_table.add_row(["Total Network Interfaces", len(eni_dict["NetworkInterfaces"])]) summary_table.add_row(["In-Use Security Groups", len(set(security_groups_in_use))]) summary_table.add_row(["Security Groups Excluded by Tag", len(tag_excluded_sgs)]) summary_table.add_row(["---", "---"]) if args.dry_run: summary_table.add_row(["Unused SG to Delete (DRY-RUN)", dry_run_deletes]) elif args.delete: summary_table.add_row(["Unused SG Deleted", len(delete_candidates)]) else: summary_table.add_row(["Unused SG to Delete", len(delete_candidates)]) print(summary_table.get_string(title="Summary")) except KeyboardInterrupt: print("\nCtrl+C Caught, Terminating")  - 
        
Tom Ryan revised this gist
Jun 30, 2017 . 1 changed file with 0 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,9 +0,0 @@  - 
        
Tom Ryan revised this gist
Jun 19, 2017 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,8 +2,8 @@ Usage: Evaluate all sec groups in a region: security-group-cleanup.py -r region Evaluate and delete all unused sec groups in a region: security-group-cleanup.py -r region -d  - 
        
Tom Ryan revised this gist
Jun 19, 2017 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,9 @@ Usage: Evaluate all sec groups in a region: security-group-cleanup.py -r <region> Evaluate and delete all unused sec groups in a region: security-group-cleanup.py -r <region> -d  - 
        
Tom Ryan revised this gist
Jun 19, 2017 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,7 @@ Usage: Evaluate all sec groups in a region: security-group-cleanup.py -r <region> Evaluate and delete all unused sec groups in a region: security-group-cleanup.py -r <region> -d  - 
        
Tom Ryan revised this gist
Jun 19, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,4 +2,4 @@ Usage: Evaluate all sec groups in a region: security-group-cleanup.py -r <region> Evaluate and delete all unused sec groups in a region: security-group-cleanup.py -r <region> -d  - 
        
Tom Ryan revised this gist
Jun 19, 2017 . No changes.There are no files selected for viewing
 - 
        
Tom Ryan revised this gist
Jun 19, 2017 . No changes.There are no files selected for viewing
 - 
        
Tom Ryan renamed this gist
Jun 19, 2017 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. - 
        
Tom Ryan revised this gist
Jun 19, 2017 . 1 changed file with 5 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,5 @@ Usage: Evaluate all sec groups in a region: security-group-cleanup.py -r <region> Evaluate and delete all unused sec groups in a region: security-group-cleanup.py -r <region> -d  - 
        
Tom Ryan revised this gist
Jun 19, 2017 . 1 changed file with 10 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -42,13 +42,15 @@ def lookup_by_id(sgid): for j in i['Instances']: for k in j['SecurityGroups']: if k['GroupId'] not in security_groups_in_use: security_groups_in_use.append(k['GroupId']) # Security Groups in use by Network Interfaces eni_client = boto3.client('ec2', region_name=args.region) eni_dict = eni_client.describe_network_interfaces() for i in eni_dict['NetworkInterfaces']: for j in i['Groups']: if j['GroupId'] not in security_groups_in_use: security_groups_in_use.append(j['GroupId']) # Security groups used by classic ELBs elb_client = boto3.client('elb', region_name=args.region) @@ -103,7 +105,7 @@ def lookup_by_id(sgid): print(u"Total number of Load Balancers evaluated: {0:d}".format(len(elb_dict['LoadBalancerDescriptions']) + len(elb2_dict['LoadBalancers']))) print(u"Total number of RDS Instances evaluated: {0:d}".format(len(rds_dict['DBInstances']))) print(u"Total number of Network Interfaces evaluated: {0:d}".format(len(eni_dict['NetworkInterfaces']))) print(u"Total number of Security Groups in-use evaluated: {0:d}".format(len(security_groups_in_use))) if args.delete: print(u"Total number of Unused Security Groups deleted: {0:d}".format(len(delete_candidates)))  - 
        
Tom Ryan revised this gist
Jun 16, 2017 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -29,7 +29,7 @@ def lookup_by_id(sgid): security_groups_dict = client.describe_security_groups() security_groups = security_groups_dict['SecurityGroups'] for groupobj in security_groups: if groupobj['GroupName'] == 'default' or groupobj['GroupName'].startswith('d-') or groupobj['GroupName'].startswith('AWS-OpsWorks-'): security_groups_in_use.append(groupobj['GroupId']) all_groups.append(groupobj['GroupId']) @@ -76,7 +76,7 @@ def lookup_by_id(sgid): delete_candidates = [] for group in all_groups: if group not in security_groups_in_use: delete_candidates.append(group) if args.delete:  - 
        
Tom Ryan revised this gist
Jun 13, 2017 . 1 changed file with 0 additions and 10 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -73,16 +73,6 @@ def lookup_by_id(sgid): for j in i['VpcSecurityGroups']: if j['VpcSecurityGroupId'] not in security_groups_in_use: security_groups_in_use.append(j['VpcSecurityGroupId']) delete_candidates = [] for group in all_groups:  - 
        
Tom Ryan revised this gist
Jun 13, 2017 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -108,12 +108,13 @@ def lookup_by_id(sgid): print("Activity Report") print("---------------") print(u"Total number of Security Groups evaluated: {0:d}".format(len(all_groups))) print(u"Total number of EC2 Instances evaluated: {0:d}".format(len(reservations))) print(u"Total number of Load Balancers evaluated: {0:d}".format(len(elb_dict['LoadBalancerDescriptions']) + len(elb2_dict['LoadBalancers']))) print(u"Total number of RDS Instances evaluated: {0:d}".format(len(rds_dict['DBInstances']))) print(u"Total number of Network Interfaces evaluated: {0:d}".format(network_interface_count)) print(u"Total number of Security Groups in-use evaluated: {0:d}".format(len(security_groups_in_use))) if args.delete: print(u"Total number of Unused Security Groups deleted: {0:d}".format(len(delete_candidates))) else:  - 
        
Tom Ryan revised this gist
Jun 6, 2017 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -108,16 +108,16 @@ def lookup_by_id(sgid): print("Activity Report") print("---------------") print(u"Total number of Security Groups in-use evaluated: {0:d}".format(len(security_groups_in_use))) print(u"Total number of EC2 Instances evaluated: {0:d}".format(len(reservations))) print(u"Total number of Load Balancers evaluated: {0:d}".format(len(elb_dict['LoadBalancerDescriptions']) + len(elb2_dict['LoadBalancers']))) print(u"Total number of RDS Instances evaluated: {0:d}".format(len(rds_dict['DBInstances']))) print(u"Total number of Network Interfaces evaluated: {0:d}".format(network_interface_count)) if args.delete: print(u"Total number of Unused Security Groups deleted: {0:d}".format(len(delete_candidates))) else: print(u"Total number of Unused Security Groups targeted for removal: {0:d}".format(len(delete_candidates))) # For each security group in the total list, if not in the "used" list, flag for deletion # If running with a "--delete" flag, delete the ones flagged.  - 
        
Tom Ryan revised this gist
Jun 6, 2017 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -115,9 +115,9 @@ def lookup_by_id(sgid): print(u"Total number of RDS Instances evaluated: {0:d}".format(len(rds_dict['DBInstances']))) print(u"Total number of Network Interfaces evaluated: {0:d}".format(network_interface_count)) if args.delete: print(u"Total number of unused security groups deleted: {0:d}".format(len(delete_candidates))) else: print(u"Total number of unused security groups targeted for removal: {0:d}".format(len(delete_candidates))) # For each security group in the total list, if not in the "used" list, flag for deletion # If running with a "--delete" flag, delete the ones flagged.  - 
        
Tom Ryan revised this gist
Jun 6, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -108,7 +108,7 @@ def lookup_by_id(sgid): print("Activity Report") print("---------------") print(u"Total number of Security Groups in use evaluated: {0:d}".format(len(security_groups_in_use))) print(u"Total number of EC2 Instances evaluated: {0:d}".format(len(reservations))) print(u"Total number of Load Balancers evaluated: {0:d}".format(len(elb_dict['LoadBalancerDescriptions']) + len(elb2_dict['LoadBalancers'])))  - 
        
Tom Ryan revised this gist
Jun 6, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -112,7 +112,7 @@ def lookup_by_id(sgid): print(u"Total number of EC2 Instances evaluated: {0:d}".format(len(reservations))) print(u"Total number of Load Balancers evaluated: {0:d}".format(len(elb_dict['LoadBalancerDescriptions']) + len(elb2_dict['LoadBalancers']))) print(u"Total number of RDS Instances evaluated: {0:d}".format(len(rds_dict['DBInstances']))) print(u"Total number of Network Interfaces evaluated: {0:d}".format(network_interface_count)) if args.delete: print(u"Total number of security groups deleted: {0:d}".format(len(delete_candidates)))  - 
        
Tom Ryan revised this gist
Jun 6, 2017 . No changes.There are no files selected for viewing
 - 
        
Tom Ryan revised this gist
Jun 6, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -72,7 +72,7 @@ def lookup_by_id(sgid): for i in rds_dict['DBInstances']: for j in i['VpcSecurityGroups']: if j['VpcSecurityGroupId'] not in security_groups_in_use: security_groups_in_use.append(j['VpcSecurityGroupId']) ## Security groups used by VPCs  - 
        
Tom Ryan revised this gist
Jun 6, 2017 . 1 changed file with 7 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -68,12 +68,12 @@ def lookup_by_id(sgid): # Security groups used by RDS rds_client = boto3.client('rds', region_name=args.region) rds_dict = rds_client.describe_db_instances() for i in rds_dict['DBInstances']: for j in i['VpcSecurityGroups']: if j['VpcSecurityGroupId'] not in security_groups_in_use: security_groups_in_use.append(j) ## Security groups used by VPCs #vpc_dict = client.describe_vpcs() @@ -112,6 +112,7 @@ def lookup_by_id(sgid): print(u"Total number of EC2 Instances evaluated: {0:d}".format(len(reservations))) print(u"Total number of Load Balancers evaluated: {0:d}".format(len(elb_dict['LoadBalancerDescriptions']) + len(elb2_dict['LoadBalancers']))) print(u"Total number of RDS Instances evaluated: {0:d}".format(len(rds_dict))) print(u"Total number of Network Interfaces evaluated: {0:d}".format(network_interface_count)) if args.delete: print(u"Total number of security groups deleted: {0:d}".format(len(delete_candidates)))  - 
        
lingmann revised this gist
Mar 10, 2017 . 1 changed file with 8 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -75,14 +75,14 @@ def lookup_by_id(sgid): if j not in security_groups_in_use: security_groups_in_use.append(j) ## Security groups used by VPCs #vpc_dict = client.describe_vpcs() #for i in vpc_dict['Vpcs']: # vpc_id = i['VpcId'] # vpc = ec2.Vpc(vpc_id) # for s in vpc.security_groups.all(): # if s.group_id not in security_groups_in_use: # security_groups_in_use.append(s.group_id) delete_candidates = [] for group in all_groups:  - 
        
pet0ruk revised this gist
Dec 5, 2016 . 1 changed file with 5 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -21,7 +21,8 @@ def lookup_by_id(sgid): parser.add_argument("-d", "--delete", help="delete security groups from AWS", action="store_true") args = parser.parse_args() client = boto3.client('ec2', region_name=args.region) ec2 = boto3.resource('ec2', region_name=args.region) all_groups = [] security_groups_in_use = [] # Get ALL security groups names @@ -50,23 +51,23 @@ def lookup_by_id(sgid): security_groups_in_use.append(n['GroupId']) # Security groups used by classic ELBs elb_client = boto3.client('elb', region_name=args.region) elb_dict = elb_client.describe_load_balancers() for i in elb_dict['LoadBalancerDescriptions']: for j in i['SecurityGroups']: if j not in security_groups_in_use: security_groups_in_use.append(j) # Security groups used by ALBs elb2_client = boto3.client('elbv2', region_name=args.region) elb2_dict = elb2_client.describe_load_balancers() for i in elb2_dict['LoadBalancers']: for j in i['SecurityGroups']: if j not in security_groups_in_use: security_groups_in_use.append(j) # Security groups used by RDS rds_client = boto3.client('rds', region_name=args.region) rds_dict = rds_client.describe_db_security_groups() for i in rds_dict['DBSecurityGroups']:  - 
        
sa-jbrooks revised this gist
Oct 3, 2016 . 1 changed file with 98 additions and 79 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,102 +1,121 @@ #!/usr/bin/env python import boto3 import argparse def lookup_by_id(sgid): sg = ec2.get_all_security_groups(group_ids=sgid) return sg[0].name # get a full list of the available regions client = boto3.client('ec2') regions_dict = client.describe_regions() region_list = [region['RegionName'] for region in regions_dict['Regions']] # parse arguments parser = argparse.ArgumentParser(description="Show unused security groups") parser.add_argument("-r", "--region", type=str, default="us-east-1", help="The default region is us-east-1. The list of available regions are as follows: %s" % sorted( region_list)) parser.add_argument("-d", "--delete", help="delete security groups from AWS", action="store_true") args = parser.parse_args() ec2 = boto3.resource('ec2') all_groups = [] security_groups_in_use = [] # Get ALL security groups names security_groups_dict = client.describe_security_groups() security_groups = security_groups_dict['SecurityGroups'] for groupobj in security_groups: if groupobj['GroupName'] == 'default': security_groups_in_use.append(groupobj['GroupId']) all_groups.append(groupobj['GroupId']) # Get all security groups used by instances instances_dict = client.describe_instances() reservations = instances_dict['Reservations'] network_interface_count = 0 for i in reservations: for j in i['Instances']: for k in j['SecurityGroups']: if k['GroupId'] not in security_groups_in_use: security_groups_in_use.append(k['GroupId']) # Security groups used by network interfaces for m in j['NetworkInterfaces']: network_interface_count += 1 for n in m['Groups']: if n['GroupId'] not in security_groups_in_use: security_groups_in_use.append(n['GroupId']) # Security groups used by classic ELBs elb_client = boto3.client('elb') elb_dict = elb_client.describe_load_balancers() for i in elb_dict['LoadBalancerDescriptions']: for j in i['SecurityGroups']: if j not in security_groups_in_use: security_groups_in_use.append(j) # Security groups used by ALBs elb2_client = boto3.client('elbv2') elb2_dict = elb2_client.describe_load_balancers() for i in elb2_dict['LoadBalancers']: for j in i['SecurityGroups']: if j not in security_groups_in_use: security_groups_in_use.append(j) # Security groups used by RDS rds_client = boto3.client('rds') rds_dict = rds_client.describe_db_security_groups() for i in rds_dict['DBSecurityGroups']: for j in i['EC2SecurityGroups']: if j not in security_groups_in_use: security_groups_in_use.append(j) # Security groups used by VPCs vpc_dict = client.describe_vpcs() for i in vpc_dict['Vpcs']: vpc_id = i['VpcId'] vpc = ec2.Vpc(vpc_id) for s in vpc.security_groups.all(): if s.group_id not in security_groups_in_use: security_groups_in_use.append(s.group_id) delete_candidates = [] for group in all_groups: if group not in security_groups_in_use and not group.startswith('AWS-OpsWorks-'): delete_candidates.append(group) if args.delete: print("We will now delete security groups identified to not be in use.") for group in delete_candidates: security_group = ec2.SecurityGroup(group) try: security_group.delete() except Exception as e: print(e) print("{0} requires manual remediation.".format(security_group.group_name)) else: print("The list of security groups to be removed is below.") print("Run this again with `-d` to remove them") for group in sorted(delete_candidates): print(" " + group) print("---------------") print("Activity Report") print("---------------") print(u"Total number of Security Groups evaluated: {0:d}".format(len(security_groups_in_use))) print(u"Total number of EC2 Instances evaluated: {0:d}".format(len(reservations))) print(u"Total number of Load Balancers evaluated: {0:d}".format(len(elb_dict['LoadBalancerDescriptions']) + len(elb2_dict['LoadBalancers']))) print(u"Total number of Network Interfaces evaluated: {0:d}".format(network_interface_count)) if args.delete: print(u"Total number of security groups deleted: {0:d}".format(len(delete_candidates))) else: print(u"Total number of security groups targeted for removal: {0:d}".format(len(delete_candidates))) # For each security group in the total list, if not in the "used" list, flag for deletion # If running with a "--delete" flag, delete the ones flagged.  - 
        
dritten revised this gist
Aug 22, 2014 . 1 changed file with 21 additions and 21 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,13 +1,13 @@ #!/usr/bin/env python import sys import boto import boto.ec2 import boto.ec2.elb import boto.rds import pprint import argparse def lookup_by_id(sgid): sg = ec2.get_all_security_groups(group_ids=sgid) return sg[0].name @@ -21,33 +21,32 @@ def lookup_by_id(sgid): counter=0 regions = boto.ec2.regions() for i in regions: #print regions[counter].name region_list.append(str(regions[counter].name)) counter=counter+1 parser = argparse.ArgumentParser(description="Show unused security groups") parser.add_argument("-r", "--region", type=str, default="us-east-1", help="The default region is us-east-1. The list of available regions are as follows: %s" % sorted(region_list)) parser.add_argument("-d", "--delete", help="delete security groups from AWS") args = parser.parse_args() pp = pprint.PrettyPrinter(indent=4) ec2 = boto.ec2.connect_to_region(args.region, aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY) allgroups = [] # Get ALL security groups names groups = ec2.get_all_security_groups() for groupobj in groups: allgroups.append(groupobj.name) # Get all instances security groups groups_in_use = ['default'] reservations = ec2.get_all_instances() for r in reservations: for ec2_group_list in r.groups: if ec2_group_list.name not in groups_in_use: groups_in_use.append(ec2_group_list.name) elb = boto.ec2.elb.connect_to_region(args.region, aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY) load_balancers = elb.get_all_load_balancers() @@ -73,7 +72,7 @@ def lookup_by_id(sgid): for group in allgroups: if group not in groups_in_use and not group.startswith('AWS-OpsWorks-'): delete_candidates.append(group) if args.delete: print "We will now delete security groups identified to not be in use." for group in delete_candidates: @@ -89,14 +88,15 @@ def lookup_by_id(sgid): print "Activity Report" print "---------------" print "Total number of Security Groups evaluated: %d" % (len(groups_in_use)) print "Total number of EC2 Instances evaluated: %d" % (len(reservations)) print "Total number of Load Balancers evaluated: %d" % (len(load_balancers)) print "Total number of RDS instances evaluated: %d" % (len(dbs)) print "Total number of Network Interfaces evaluated: %d" % (len(enis)) if args.delete: print "Total number of security groups deleted: %d" % (len(delete_candidates)) else: print "Total number of security groups targeted for removal: %d" % (len(delete_candidates)) # For each security group in the total list, if not in the "used" list, flag for deletion # If running with a "--delete" flag, delete the ones flagged.  - 
        
dritten revised this gist
Aug 21, 2014 . 1 changed file with 73 additions and 26 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,54 +2,101 @@ import sys import boto import boto.ec2 import boto.ec2.elb import boto.rds import pprint import argparse def lookup_by_id(sgid): sg = ec2.get_all_security_groups(group_ids=sgid) return sg[0].name # set credentials #ACCESS_KEY="<ACCESS_KEY>" #SECRET_KEY="<SECRET_KEY>" #get a full list of the available regions region_list=[] counter=0 regions = boto.ec2.regions() for i in regions: #print regions[counter].name region_list.append(str(regions[counter].name)) counter=counter+1 parser = argparse.ArgumentParser(description="Show unused security groups") parser.add_argument("-r", "--region", type=str, default="us-east-1", help="The default region is us-east-1. The list of available regions are as follows: %s" % sorted(region_list)) parser.add_argument("-d", "--delete", help="delete security groups from AWS") args = parser.parse_args() pp = pprint.PrettyPrinter(indent=4) ec2 = boto.ec2.connect_to_region(args.region, aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY) # Get ALL security groups names allgroups = [] groups = ec2.get_all_security_groups() for groupobj in groups: allgroups.append(groupobj.name) # Get all instances security groups groups_in_use = ['default'] reservations = ec2.get_all_instances() for r in reservations: for ec2_group_list in r.groups: if ec2_group_list.name not in groups_in_use: groups_in_use.append(ec2_group_list.name) elb = boto.ec2.elb.connect_to_region(args.region, aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY) load_balancers = elb.get_all_load_balancers() for load_balancer in load_balancers: if load_balancer.source_security_group.name not in groups_in_use: groups_in_use.append(load_balancer.source_security_group.name) rds = boto.rds.connect_to_region(args.region, aws_access_key_id=ACCESS_KEY, aws_secret_access_key=SECRET_KEY) dbs = rds.get_all_dbinstances() for db in dbs: if len(db.vpc_security_groups) > 0: sg_name = lookup_by_id(db.vpc_security_groups[0].vpc_group) if sg_name not in groups_in_use: groups_in_use.append(sg_name) enis = ec2.get_all_network_interfaces() for eni in enis: for eni_grp in eni.groups: if eni_grp.name not in groups_in_use: groups_in_use.append(eni_grp.name) delete_candidates = [] for group in allgroups: if group not in groups_in_use and not group.startswith('AWS-OpsWorks-'): delete_candidates.append(group) if args.delete: print "We will now delete security groups identified to not be in use." for group in delete_candidates: ec2.delete_security_group(group) else: print "The list of security groups to be removed is below." print "Run this again with `-d` to remove them" #pp.pprint(sorted(delete_candidates)) for group in sorted(delete_candidates): print " " + group print "---------------" print "Activity Report" print "---------------" print "Total of number of EC2 Instances evaluated %d" % (len(reservations)) print "Total of number of Load Balancers evaluated %d" % (len(load_balancers)) print "Total of number of RDS instances evaluated %d" % (len(dbs)) print "Total of number of Network Interfaces evaluated %d" % (len(enis)) if args.delete: print "Total of number of security groupsa deleted: %d" % (len(delete_candidates)) else: print "Total of number of security groups targeted for removal: %d" % (len(delete_candidates)) # For each security group in the total list, if not in the "used" list, flag for deletion # If running with a "--delete" flag, delete the ones flagged.  
NewerOlder