From 1c8f765e833d96d2b61d608485a26f98bcdd285d Mon Sep 17 00:00:00 2001 From: Rich Mogull Date: Mon, 14 May 2018 12:10:04 -0700 Subject: [PATCH] Initial public commit --- .gitignore | 2 + README.md | 107 +++++++++++ count_resources.py | 429 +++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 3 + 4 files changed, 541 insertions(+) create mode 100644 count_resources.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 894a44c..885273e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ __pycache__/ *.py[cod] *$py.class +.DS_Store + # C extensions *.so diff --git a/README.md b/README.md index 084ec51..043bd41 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,109 @@ # resource-counter This command line tool counts the number of resources in different categories across Amazon regions. + +This is a simple Python app that will count resources across different regions and display them on the command line. It first shows the dictionary of the results for the monitored services on a per-region basis, then it shows totals across all regions in a friendlier format. It tries to use the most-efficient query mechanism for each resource in order to manage the impact of API activity. I wrote this to help me scope out assessments and know where resources are in a target account. + +The development plan is to upgrade the output (probably to CSV file) and to continue to add services. If you have a specific service you want to see added just add a request in the comments. + +The current list incluides: + +* Application and Network Load Balancers +* Autoscale Groups +* Classic Load Balancers +* CloudTrail Trails +* Cloudwatch Rules +* Config Rules +* Dynamo Tables +* Elastic IP Addresses +* Glacier Vaults +* IAM Groups +* Images +* Instances +* KMS Keys +* Lambda Functions +* Launch Configurations +* NAT Gateways +* Network ACLs +* IAM Policies +* RDS Instances +* IAM Roles +* S3 Buckets +* SAML Providers +* SNS Topics +* Security Groups +* Snapshots +* Subnets +* IAM Users +* VPC Endpoints +* VPC Peering Connection +* VPCs +* Volumes + +## Usage: + +To iunstall just copy it where you want it and instally the requirements: + + pip install -r ./requirements.txt + +This was written in Python 3.6 + +To run: + + python count_resources.py + +By default, it will use whatever AWS credentials are alerady configued on the system. You can also specify an access key/secret at runtime and this is not stored: + + Usage: count_resources.py [OPTIONS] + + Options: + --access TEXT AWS Access Key. Otherwise will use the standard credentials + path for the AWS CLI. + --secret TEXT AWS Secret Key + --profile TEXT If you have multiple credential profiles, use this option to + specify one. + --help Show this message and exit. + +## Sample Output: + +Establishing AWS session using the profile- dev +Current account ID: xxxxxxxxxx +Counting resources across regions. This will take a few minutes... + +Resources by region +{'ap-northeast-1': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 3, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'ap-northeast-2': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 2, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'ap-south-1': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 2, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'ap-southeast-1': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 3, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'ap-southeast-2': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 3, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'ca-central-1': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 2, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'eu-central-1': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 3, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'eu-west-1': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 3, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'eu-west-2': {'instances': 3, 'volumes': 3, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 3, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'eu-west-3': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 3, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'sa-east-1': {'instances': 0, 'volumes': 0, 'security_groups': 1, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 3, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'us-east-1': {'instances': 2, 'volumes': 2, 'security_groups': 19, 'snapshots': 0, 'images': 0, 'vpcs': 2, 'subnets': 3, 'peering connections': 0, 'network ACLs': 2, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 1, 'cloudtrail trails': 2, 'sns topics': 3, 'kms keys': 5, 'dynamo tables': 0, 'rds instances': 0}, 'us-east-2': {'instances': 0, 'volumes': 0, 'security_groups': 2, 'snapshots': 0, 'images': 0, 'vpcs': 1, 'subnets': 3, 'peering connections': 0, 'network ACLs': 1, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 0, 'dynamo tables': 0, 'rds instances': 0}, 'us-west-1': {'instances': 1, 'volumes': 3, 'security_groups': 14, 'snapshots': 1, 'images': 0, 'vpcs': 0, 'subnets': 0, 'peering connections': 0, 'network ACLs': 0, 'elastic IPs': 0, 'NAT gateways': 0, 'VPC Endpoints': 0, 'autoscale groups': 0, 'launch configurations': 0, 'classic load balancers': 0, 'application and network load balancers': 0, 'lambdas': 0, 'glacier vaults': 0, 'cloudwatch rules': 0, 'config rules': 0, 'cloudtrail trails': 1, 'sns topics': 0, 'kms keys': 1, 'dynamo tables': 0, 'rds instances': 0}, 'us-west-2': {'instances': 9, 'volumes': 29, 'security_groups': 76, 'snapshots': 171, 'images': 104, 'vpcs': 7, 'subnets': 15, 'peering connections': 1, 'network ACLs': 8, 'elastic IPs': 7, 'NAT gateways': 1, 'VPC Endpoints': 0, 'autoscale groups': 1, 'launch configurations': 66, 'classic load balancers': 1, 'application and network load balancers': 2, 'lambdas': 10, 'glacier vaults': 1, 'cloudwatch rules': 8, 'config rules': 1, 'cloudtrail trails': 1, 'sns topics': 6, 'kms keys': 7, 'dynamo tables': 1, 'rds instances': 0}} + +Resource totals across all regions +Application and Network Load Balancers : 2 +Autoscale Groups : 1 +Classic Load Balancers : 1 +CloudTrail Trails : 16 +Cloudwatch Rules : 8 +Config Rules : 2 +Dynamo Tables : 1 +Elastic IP Addresses : 7 +Glacier Vaults : 1 +Groups : 12 +Images : 104 +Instances : 15 +KMS Keys : 13 +Lambda Functions : 10 +Launch Configurations : 66 +NAT Gateways : 1 +Network ACLs : 22 +Policies : 15 +RDS Instances : 0 +Roles : 40 +S3 Buckets : 31 +SAML Providers : 1 +SNS Topics : 9 +Security Groups : 122 +Snapshots : 172 +Subnets : 51 +Users : 14 +VPC Endpoints : 0 +VPC Peering Connections : 1 +VPCs : 21 +Volumes : 37 + +Total resources: 796 + diff --git a/count_resources.py b/count_resources.py new file mode 100644 index 0000000..b1169c4 --- /dev/null +++ b/count_resources.py @@ -0,0 +1,429 @@ +import click +import boto3 +import sys +resource_counts = {} +resource_totals = {} + +@click.command() +@click.option('--access', help='AWS Access Key. Otherwise will use the standard credentials path for the AWS CLI.') +@click.option('--secret', help='AWS Secret Key') +@click.option('--profile', help='If you have multiple credential profiles, use this option to specify one.') +def controller(access, secret, profile): + global session + if access: + click.echo('Access Key specified') + if not secret: + click.echo('Secret key not specified. A secret key must be provided when the command line access key option is provided.') + else: + click.echo('Establishing AWS session using the provided access key...') + try: + session = boto3.session.Session(aws_access_key_id=access, aws_secret_access_key=secret) + except: + click.echo('Error establishing AWS connection. Likely bad credentials provided.') + sys.exit() + elif profile: + click.echo('Establishing AWS session using the profile- ' + profile) + try: + session = boto3.session.Session(profile_name=profile) + except: + click.echo('Error establishing AWS connection. Likely bad credentials provided.') + sys.exit() + else: + click.echo('Establishing AWS session using default path credentials...') + try: + session = boto3.session.Session() + except: + click.echo('Error establishing AWS connection. Likely bad credentials provided.') + sys.exit() + + # pull the account ID for use when needed for filtering + iam = session.resource('iam') + + account_id = iam.CurrentUser().arn.split(':')[4] + click.echo('Current account ID: ' + account_id) + + # Initialize dictionary to hold the counts. Pull the regions using EC2, since that is in every region. + # Then build out the master list of regions to then fill in the service counts + # Also build a separate dictionary for cross-region totals + + + region_list = session.get_available_regions('ec2') + for region in region_list: + resource_counts[region] = {} + + + # iterate through the various services to build the counts + click.echo('Counting resources across regions. This will take a few minutes...') + click.echo(' ') + ec2_counter(account_id) + autoscaling_counter() + balancer_counter() + s3_counter() + iam_counter() + lambda_counter() + glacier_counter() + cloudwatch_rules_counter() + config_counter() + cloudtrail_counter() + sns_counter() + kms_counter() + dynamo_counter() + rds_counter() + + # show results + click.echo('Resources by region') + click.echo(resource_counts) + click.echo(' ') + click.echo('Resource totals across all regions') + for key, value in sorted(resource_totals.items()): + click.echo("{} : {}".format(key, value)) + total = sum(resource_totals.values()) + click.echo('') + click.echo('Total resources: ' + str(total)) + +# ec2 = boto3.client('ec2', region_name='us-west-2') + +# ec2 = session.client('ec2', region_name='us-west-2') + + +def ec2_counter(account_id): + # get list of regions supported by EC2 endpoint + region_list = session.get_available_regions('ec2') + + # initialize cross region totals + total_instances = 0 + total_groups = 0 + total_volumes = 0 + total_snapshots = 0 + total_images = 0 + total_vpcs = 0 + total_subnets = 0 + total_peering_connections = 0 + total_acls = 0 + total_IPs = 0 + total_NAT = 0 + total_endpoints = 0 + + for region in region_list: + ec2 = session.resource('ec2', region_name=region) + ec2client = session.client('ec2', region_name=region) + + # build the collections to count + instance_iterator = ec2.instances.all() + volume_iterator = ec2.volumes.all() + security_group_iterator = ec2.security_groups.all() + snapshot_iterator = ec2.snapshots.filter(OwnerIds=[account_id]) + image_iterator = ec2.images.filter(Owners=[account_id]) + vpc_iterator = ec2.vpcs.all() + subnet_iterator = ec2.subnets.all() + vpc_peering_connection_iterator = ec2.vpc_peering_connections.all() + network_acl_iterator = ec2.network_acls.all() + vpc_address_iterator = ec2.vpc_addresses.all() + nat_gateways = ec2client.get_paginator('describe_nat_gateways') + nat_gateway_iterator = nat_gateways.paginate() + endpoints = ec2client.describe_vpc_endpoints() + + + # count resources + instance_counter = len(list(instance_iterator)) + group_counter = len(list(security_group_iterator)) + volume_counter = len(list(volume_iterator)) + snapshot_counter = len(list(snapshot_iterator)) + image_counter = len(list(image_iterator)) + vpc_counter = len(list(vpc_iterator)) + subnet_counter = len(list(subnet_iterator)) + peering_counter = len(list(vpc_peering_connection_iterator)) + acl_counter = len(list(network_acl_iterator)) + ip_counter = len(list(vpc_address_iterator)) + gateway_counter = 0 + for gateway in nat_gateway_iterator: + gateway_counter += len(gateway['NatGateways']) + endpoint_counter = len(endpoints['VpcEndpoints']) + + # add to the cross region totals + total_instances = total_instances + instance_counter + total_groups += group_counter + total_volumes += volume_counter + total_snapshots += snapshot_counter + total_images += image_counter + total_vpcs += vpc_counter + total_subnets += subnet_counter + total_peering_connections += peering_counter + total_acls += acl_counter + total_IPs += ip_counter + total_NAT += gateway_counter + total_endpoints += endpoint_counter + + # Add the counts to the per-region counter + resource_counts[region]['instances'] = instance_counter + resource_counts[region]['volumes'] = volume_counter + resource_counts[region]['security_groups'] = group_counter + resource_counts[region]['snapshots'] = snapshot_counter + resource_counts[region]['images'] = image_counter + resource_counts[region]['vpcs'] = vpc_counter + resource_counts[region]['subnets'] = subnet_counter + resource_counts[region]['peering connections'] = peering_counter + resource_counts[region]['network ACLs'] = acl_counter + resource_counts[region]['elastic IPs'] = ip_counter + resource_counts[region]['NAT gateways'] = gateway_counter + resource_counts[region]['VPC Endpoints'] = endpoint_counter + + + resource_totals['Instances'] = total_instances + resource_totals['Volumes'] = total_volumes + resource_totals['Security Groups'] = total_groups + resource_totals['Snapshots'] = total_snapshots + resource_totals['Images'] = total_images + resource_totals['VPCs'] = total_vpcs + resource_totals['Subnets'] = total_subnets + resource_totals['VPC Peering Connections'] = total_peering_connections + resource_totals['Network ACLs'] = total_acls + resource_totals['Elastic IP Addresses'] = total_IPs + resource_totals['NAT Gateways'] = total_NAT + resource_totals['VPC Endpoints'] = total_endpoints + +def iam_counter(): + iam = session.resource('iam', region_name='us-west-2') + + user_iterator = iam.users.all() + group_iterator = iam.groups.all() + role_iterator = iam.roles.all() + policy_iterator = iam.policies.filter(Scope='Local') + saml_provider_iterator = iam.saml_providers.all() + + total_users = len(list(user_iterator)) + total_groups = len(list(group_iterator)) + total_roles = len(list(role_iterator)) + total_policies = len(list(policy_iterator)) + total_saml = len(list(saml_provider_iterator)) + + resource_totals['Users'] = total_users + resource_totals['Groups'] = total_groups + resource_totals['Roles'] = total_roles + resource_totals['Policies'] = total_policies + resource_totals['SAML Providers'] = total_saml + +def autoscaling_counter(): + # get list of supported regions + region_list = session.get_available_regions('autoscaling') + + # initialize cross region totals + total_autoscaling_groups = 0 + total_launch_configurations = 0 + + # iterate through regions and count + for region in region_list: + client = session.client('autoscaling', region_name=region) + + # pull data using paginators + autoscaling = client.get_paginator('describe_auto_scaling_groups') + configurations = client.get_paginator('describe_launch_configurations') + autoscale_iterator = autoscaling.paginate() + configurations_iterator = configurations.paginate() + + # initialize region counts + autoscale_count = 0 + configuration_count = 0 + + for autoscale in autoscale_iterator: + autoscale_count += len(autoscale['AutoScalingGroups']) + for configuration in configurations_iterator: + configuration_count += len(configuration['LaunchConfigurations']) + + total_autoscaling_groups += autoscale_count + total_launch_configurations += configuration_count + + + resource_counts[region]['autoscale groups'] = autoscale_count + resource_counts[region]['launch configurations'] = configuration_count + + + resource_totals['Autoscale Groups'] = total_autoscaling_groups + resource_totals['Launch Configurations'] = total_launch_configurations + +def balancer_counter(): + # get list of supported regions + elb_region_list = session.get_available_regions('elb') + elbv2_region_list = session.get_available_regions('elbv2') + + # initalize cross region totals + elb_total = 0 + elbv2_total = 0 + + # First count up the classic ELBs + for region in elb_region_list: + elb = session.client('elb', region_name=region) + + # pull data using paginator + elb_paginator = elb.get_paginator('describe_load_balancers') + elb_iterator = elb_paginator.paginate() + + #initialize region count + elb_counter = 0 + + for balancer in elb_iterator: + elb_counter += len(balancer['LoadBalancerDescriptions']) + + elb_total += elb_counter + resource_counts[region]['classic load balancers'] = elb_counter + + # Now count up the application and network load balancers + for region in elbv2_region_list: + elb = session.client('elbv2', region_name=region) + + # pull data using paginator + elb_paginator = elb.get_paginator('describe_load_balancers') + elb_iterator = elb_paginator.paginate() + + #initialize region count + elb_counter = 0 + + for balancer in elb_iterator: + elb_counter += len(balancer['LoadBalancers']) + + elbv2_total += elb_counter + resource_counts[region]['application and network load balancers'] = elb_counter + resource_totals['Classic Load Balancers'] = elb_total + resource_totals['Application and Network Load Balancers'] = elbv2_total + +def s3_counter(): + total_buckets = 0 + # S3 gives you a full count no matter what the region setting + s3 = session.resource('s3', region_name='us-west-2') + bucket_iterator = s3.buckets.all() + bucket_counter = len(list(bucket_iterator)) + total_buckets += bucket_counter + # resource_counts[region]['s3 buckets'] = bucket_counter + resource_totals['S3 Buckets'] = total_buckets + +def lambda_counter(): + region_list = session.get_available_regions('lambda') + + total_functions = 0 + + for region in region_list: + aws_lambda = session.client('lambda', region_name=region) + function_counter = 0 + function_paginator = aws_lambda.get_paginator('list_functions') + function_iterator = function_paginator.paginate() + for function in function_iterator: + function_counter += len(function['Functions']) + total_functions += function_counter + resource_counts[region]['lambdas'] = function_counter + resource_totals['Lambda Functions'] = total_functions + +def glacier_counter(): + region_list = session.get_available_regions('glacier') + + total_vaults = 0 + + for region in region_list: + glacier = session.resource('glacier', region_name=region) + vault_iterator = glacier.vaults.all() + vault_counter = len(list(vault_iterator)) + total_vaults += vault_counter + resource_counts[region]['glacier vaults'] = vault_counter + resource_totals['Glacier Vaults'] = total_vaults + +def cloudwatch_rules_counter(): + region_list = session.get_available_regions('events') + + total_events = 0 + + for region in region_list: + cloudwatch = session.client('events', region_name=region) + rules = cloudwatch.list_rules() + events_counter = len(rules['Rules']) + total_events += events_counter + resource_counts[region]['cloudwatch rules'] = events_counter + resource_totals['Cloudwatch Rules'] = total_events + +def config_counter(): + region_list = session.get_available_regions('config') + + total_config_rules = 0 + + for region in region_list: + config = session.client('config', region_name=region) + config_rules_counter = 0 + config_rules_paginator = config.get_paginator('describe_config_rules') + config_rules_iterator = config_rules_paginator.paginate() + for rule in config_rules_iterator: + config_rules_counter += len(rule['ConfigRules']) + total_config_rules += config_rules_counter + resource_counts[region]['config rules'] = config_rules_counter + resource_totals['Config Rules'] = total_config_rules + +def cloudtrail_counter(): + region_list = session.get_available_regions('cloudtrail') + + total_trails = 0 + + for region in region_list: + cloudtrail = session.client('cloudtrail', region_name=region) + trails = cloudtrail.describe_trails() + trails_counter = len(trails['trailList']) + total_trails += trails_counter + resource_counts[region]['cloudtrail trails'] = trails_counter + resource_totals['CloudTrail Trails'] = total_trails + +def sns_counter(): + region_list = session.get_available_regions('sns') + + total_topics = 0 + + for region in region_list: + sns = session.resource('sns', region_name=region) + topic_iterator = sns.topics.all() + topic_counter = len(list(topic_iterator)) + total_topics += topic_counter + resource_counts[region]['sns topics'] = topic_counter + resource_totals['SNS Topics'] = total_topics + +def kms_counter(): + region_list = session.get_available_regions('kms') + + total_keys = 0 + + for region in region_list: + kms = session.client('kms', region_name=region) + keys_counter = 0 + kms_paginator = kms.get_paginator('list_keys') + kms_iterator = kms_paginator.paginate() + for key in kms_iterator: + keys_counter += len(key['Keys']) + total_keys += keys_counter + resource_counts[region]['kms keys'] = keys_counter + resource_totals['KMS Keys'] = total_keys + +def dynamo_counter(): + region_list = session.get_available_regions('dynamodb') + + total_tables = 0 + + for region in region_list: + dynamodb = session.resource('dynamodb', region_name=region) + table_iterator = dynamodb.tables.all() + table_counter = len(list(table_iterator)) + total_tables += table_counter + resource_counts[region]['dynamo tables'] = table_counter + resource_totals['Dynamo Tables'] = total_tables + +def rds_counter(): + region_list = session.get_available_regions('rds') + + total_dbinstances = 0 + + for region in region_list: + rds = session.client('rds', region_name=region) + dbinstances_counter = 0 + rds_paginator = rds.get_paginator('describe_db_instances') + rds_iterator = rds_paginator.paginate() + for instance in rds_iterator: + dbinstances_counter += len(instance['DBInstances']) + total_dbinstances += dbinstances_counter + resource_counts[region]['rds instances'] = dbinstances_counter + resource_totals['RDS Instances'] = total_dbinstances + +if __name__ == "__main__": + controller() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..526f3bd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +click +boto3 +botocore