Skip to content

Instantly share code, notes, and snippets.

@snixon
Forked from TomRyan-321/security-group-cleanup.py
Last active August 25, 2022 18:08
Show Gist options
  • Save snixon/059b0a0edf87e9a34d020bb2c9546874 to your computer and use it in GitHub Desktop.
Save snixon/059b0a0edf87e9a34d020bb2c9546874 to your computer and use it in GitHub Desktop.

Revisions

  1. snixon revised this gist Jul 13, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion security-group-cleanup.py
    Original 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, group, security_group.group_name])
    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)
  2. snixon revised this gist Dec 5, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion security-group-cleanup.py
    Original 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(group["GroupId"])
    tag_excluded_sgs.append(groupobj["GroupId"])
    all_groups.append(groupobj["GroupId"])

    total_groups = len(all_groups)
  3. snixon revised this gist Jul 3, 2019. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions security-group-cleanup.py
    Original 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
  4. snixon revised this gist Jul 3, 2019. No changes.
  5. snixon revised this gist Jul 3, 2019. 1 changed file with 271 additions and 110 deletions.
    381 changes: 271 additions & 110 deletions security-group-cleanup.py
    Original 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)

    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()

    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
    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'])

    # 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_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)
    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_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.delete:
    print("We will now delete security groups identified to not be in use.")
    for group in delete_candidates:
    security_group = ec2.SecurityGroup(group)
    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_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(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(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)))
    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.
    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")
  6. Tom Ryan revised this gist Jun 30, 2017. 1 changed file with 0 additions and 9 deletions.
    9 changes: 0 additions & 9 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,9 +0,0 @@
    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
  7. Tom Ryan revised this gist Jun 19, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions README.md
    Original 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>
    security-group-cleanup.py -r region

    Evaluate and delete all unused sec groups in a region:

    security-group-cleanup.py -r <region> -d
    security-group-cleanup.py -r region -d
  8. Tom Ryan revised this gist Jun 19, 2017. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original 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
  9. Tom Ryan revised this gist Jun 19, 2017. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original 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
  10. Tom Ryan revised this gist Jun 19, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original 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
    security-group-cleanup.py -r <region> -d
  11. Tom Ryan revised this gist Jun 19, 2017. No changes.
  12. Tom Ryan revised this gist Jun 19, 2017. No changes.
  13. Tom Ryan renamed this gist Jun 19, 2017. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  14. Tom Ryan revised this gist Jun 19, 2017. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions readme.md
    Original 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
  15. Tom Ryan revised this gist Jun 19, 2017. 1 changed file with 10 additions and 8 deletions.
    18 changes: 10 additions & 8 deletions security-group-cleanup.py
    Original 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 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_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(network_interface_count))
    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)))
  16. Tom Ryan revised this gist Jun 16, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions security-group-cleanup.py
    Original 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':
    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 and not group.startswith('AWS-OpsWorks-'):
    if group not in security_groups_in_use:
    delete_candidates.append(group)

    if args.delete:
  17. Tom Ryan revised this gist Jun 13, 2017. 1 changed file with 0 additions and 10 deletions.
    10 changes: 0 additions & 10 deletions security-group-cleanup.py
    Original 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'])


    ## 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:
  18. Tom Ryan revised this gist Jun 13, 2017. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion security-group-cleanup.py
    Original 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 in-use evaluated: {0:d}".format(len(security_groups_in_use)))
    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:
  19. Tom Ryan revised this gist Jun 6, 2017. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions security-group-cleanup.py
    Original 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 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)))
    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)))
    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.
  20. Tom Ryan revised this gist Jun 6, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions security-group-cleanup.py
    Original 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 security groups deleted: {0:d}".format(len(delete_candidates)))
    print(u"Total number of unused 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)))
    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.
  21. Tom Ryan revised this gist Jun 6, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion security-group-cleanup.py
    Original 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 evaluated: {0:d}".format(len(security_groups_in_use)))
    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'])))
  22. Tom Ryan revised this gist Jun 6, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion security-group-cleanup.py
    Original 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)))
    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)))
  23. Tom Ryan revised this gist Jun 6, 2017. No changes.
  24. Tom Ryan revised this gist Jun 6, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion security-group-cleanup.py
    Original 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)
    security_groups_in_use.append(j['VpcSecurityGroupId'])


    ## Security groups used by VPCs
  25. Tom Ryan revised this gist Jun 6, 2017. 1 changed file with 7 additions and 6 deletions.
    13 changes: 7 additions & 6 deletions security-group-cleanup.py
    Original 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_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)
    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)))
  26. lingmann revised this gist Mar 10, 2017. 1 changed file with 8 additions and 8 deletions.
    16 changes: 8 additions & 8 deletions security-group-cleanup.py
    Original 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)
    ## 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:
  27. pet0ruk revised this gist Dec 5, 2016. 1 changed file with 5 additions and 4 deletions.
    9 changes: 5 additions & 4 deletions security-group-cleanup.py
    Original 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()

    ec2 = boto3.resource('ec2')
    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')
    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')
    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')
    rds_client = boto3.client('rds', region_name=args.region)
    rds_dict = rds_client.describe_db_security_groups()

    for i in rds_dict['DBSecurityGroups']:
  28. @sa-jbrooks sa-jbrooks revised this gist Oct 3, 2016. 1 changed file with 98 additions and 79 deletions.
    177 changes: 98 additions & 79 deletions security-group-cleanup.py
    Original file line number Diff line number Diff line change
    @@ -1,102 +1,121 @@
    #!/usr/bin/env python

    import sys
    import boto
    import boto.ec2
    import boto.ec2.elb
    import boto.rds
    import pprint
    import boto3
    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
    # 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")
    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()

    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 = []

    ec2 = boto3.resource('ec2')
    all_groups = []
    security_groups_in_use = []
    # 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()
    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)
    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 allgroups:
    if group not in groups_in_use and not group.startswith('AWS-OpsWorks-'):
    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."
    print("We will now delete security groups identified to not be in use.")
    for group in delete_candidates:
    ec2.delete_security_group(group)
    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"
    #pp.pprint(sorted(delete_candidates))
    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(" " + group)

    print "---------------"
    print "Activity Report"
    print "---------------"
    print("---------------")
    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))
    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 "Total number of security groups deleted: %d" % (len(delete_candidates))
    print(u"Total number of security groups deleted: {0:d}".format(len(delete_candidates)))
    else:
    print "Total number of security groups targeted for removal: %d" % (len(delete_candidates))
    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.
    # 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.
  29. @dritten dritten revised this gist Aug 22, 2014. 1 changed file with 21 additions and 21 deletions.
    42 changes: 21 additions & 21 deletions security-group-cleanup.py
    Original 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
    #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 = []
    # 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)

    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 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))
    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 of number of security groupsa deleted: %d" % (len(delete_candidates))
    print "Total number of security groups deleted: %d" % (len(delete_candidates))
    else:
    print "Total of number of security groups targeted for removal: %d" % (len(delete_candidates))
    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.
  30. @dritten dritten revised this gist Aug 21, 2014. 1 changed file with 73 additions and 26 deletions.
    99 changes: 73 additions & 26 deletions security-group-cleanup.py
    Original 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

    del_flag = ''
    if len(sys.argv) > 1:
    del_flag = sys.argv[1]

    pp = pprint.PrettyPrinter(indent=4)
    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="<security key>"
    #ACCESS_KEY="<ACCESS_KEY>"
    #SECRET_KEY="<SECRET_KEY>"

    ec2 = boto.connect_ec2(ACCESS_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)

    allgroups = []
    # Get ALL security groups names
    allgroups = []
    groups = ec2.get_all_security_groups()
    for groupobj in groups:
    allgroups.append(groupobj.name)
    # pp.pprint(sorted(allgroups))

    # Get [running|stopped] instances security groups
    groups_in_use = []
    for state in ['running','stopped']:
    reservations = ec2.get_all_instances(filters={'instance-state-name': state})
    for r in reservations:
    for inst in r.instances:
    if inst.groups[0].name not in groups_in_use:
    groups_in_use.append(inst.groups[0].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:
    if group not in groups_in_use and not group.startswith('AWS-OpsWorks-'):
    delete_candidates.append(group)

    if del_flag == '--delete':
    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)
    print "We have deleted %d groups." % (len(delete_candidates))
    else:
    print "The list of security groups to be removed is below."
    print "Run this again with `--delete` to remove them"
    pp.pprint(sorted(delete_candidates))
    print "Total of %d groups targeted for removal." % (len(delete_candidates))

    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.
    # If running with a "--delete" flag, delete the ones flagged.