This Python script gets a list of all regions, finds EC2 instances, RDS instances and ASG in them, and if there is no "prevent_stop" tag equal to "true" on the resource, then it stops this resource, and in the case of ASG it scaledown it to 0.
main.py:
import boto3 custom_ec2_filter = [ { 'Name': 'instance-state-name', 'Values': ['running', 'pending'] } ] # Get list of EC2 regions ec2 = boto3.client('ec2') regions = [region['RegionName'] for region in ec2.describe_regions()['Regions']] def main(event, context): for region in regions: print("Region: " + str(region)) # ASG print("Searching for ASG...") asg = boto3.client('autoscaling', region_name = region) asg_list = [asg_name['AutoScalingGroupName'] for asg_name in asg.describe_auto_scaling_groups()['AutoScalingGroups']] for asg_name in asg_list: api_response = asg.describe_auto_scaling_groups( AutoScalingGroupNames = [ asg_name, ] ) tags = (api_response["AutoScalingGroups"][0]["Tags"]) asg_scaledown = False if 'prevent_stop' not in [tag['Key'] for tag in tags]: asg_scaledown = True else: for tag in tags: if tag["Key"] == 'prevent_stop' and tag["Value"] != 'true': asg_scaledown = True if asg_scaledown == True: minSize = (api_response["AutoScalingGroups"][0]["MinSize"]) maxSize = (api_response["AutoScalingGroups"][0]["MaxSize"]) desiredCapacity = (api_response["AutoScalingGroups"][0]["DesiredCapacity"]) if minSize != 0 or maxSize != 0 or desiredCapacity != 0: print("Scalling down ASG: " + str(asg_name)) asg.update_auto_scaling_group( AutoScalingGroupName = asg_name, MinSize = 0, MaxSize = 0, DesiredCapacity = 0 ) # EC2 Instances print("Searching for running instances...") ec2 = boto3.resource('ec2', region_name = region) instances_list = ec2.instances.filter(Filters = custom_ec2_filter) for instance in instances_list: if 'prevent_stop' not in [tag['Key'] for tag in instance.tags]: print("Stopping instance: " + str(instance.id)) instance.stop() else: for tag in instance.tags: if tag["Key"] == 'prevent_stop' and tag["Value"] != 'true': print("Stopping instance: " + str(instance.id)) instance.stop() # RDS print("Searching for running RDS instances...") rds = boto3.client('rds', region_name = region) rds_list = [instance['DBInstanceIdentifier'] for instance in rds.describe_db_instances()['DBInstances']] for instance in rds_list: arn = rds.describe_db_instances(DBInstanceIdentifier = instance)['DBInstances'][0]['DBInstanceArn'] tags = rds.list_tags_for_resource(ResourceName = arn)['TagList'] stop_instance = False if 'prevent_stop' not in [tag['Key'] for tag in tags]: stop_instance = True else: for tag in tags: if tag["Key"] == 'prevent_stop' and tag["Value"] != 'true': stop_instance = True if stop_instance == True: instance_status = rds.describe_db_instances(DBInstanceIdentifier = instance)['DBInstances'][0]['DBInstanceStatus'] if instance_status != "stopping" and instance_status != "stopped": engine = rds.describe_db_instances(DBInstanceIdentifier = instance)['DBInstances'][0]['Engine'] print("Engine: " + str(engine)) if engine.startswith('aurora') == True: cluster_id = rds.describe_db_instances(DBInstanceIdentifier = instance)['DBInstances'][0]['DBClusterIdentifier'] print("Stopping Aurora cluster: " + str(cluster_id)) rds.stop_db_cluster(DBClusterIdentifier = cluster_id) else: print("Stopping RDS instances: " + str(instance)) rds.stop_db_instance(DBInstanceIdentifier = instance) print("----------------------------------------") if __name__ == '__main__': main()
List of required permissions to run (besides the "AWSLambdaExecute" policy):
- ec2:DescribeRegions
- ec2:DescribeInstances
- ec2:StopInstances
- rds:ListTagsForResource
- rds:DescribeDBInstances
- rds:StopDBInstance
- autoscaling:DescribeAutoScalingGroups
- autoscaling:UpdateAutoScalingGroup