DEV Community

Cover image for ๐Ÿ’ธ How I Automated AWS Billing Control with Lambda, SNS & Boto3
AKASH S
AKASH S

Posted on

๐Ÿ’ธ How I Automated AWS Billing Control with Lambda, SNS & Boto3

Introduction

Have you ever worried about unexpected AWS billing due to resources running in the background? โ˜๏ธ๐Ÿ’ธ

In this blog, Iโ€™ll walk you through how I automated my AWS cost control by:

  • Setting up a Lambda function with Boto3
  • Using AWS SNS to trigger alerts
  • Creating a Billing Budget
  • Automatically stopping EC2 instances when billing crosses $0.01.

Step 1:Create SNS Topic to triger Lambda

  • Go to SNS > Topics
  • Click Create topic
  • Type: Standard
  • Name: BudgetAlertsTopic
  • Create topic
  • In "Subscriptions" tab โ†’ click Create subscription
  • Protocol: Email
  • Endpoint: Your email
  • Go to your email inbox โ†’ Confirm the subscription

Image description

Step 2:Create a Budget

Go to Billing > Budgets **> **Create Budget

  • Type: Cost Budget
  • Name: MyBillingBudget
  • Budget amount: $0.01
  • Scope: All services
  • Notifications:
  • Threshold: 100%
  • Send to: SNS topic BudgetAlertsTopic
  • Create budget

Image description

Step 3:Create Lambda Function to Stop EC2 + Block S3

  • Go to IAM > Roles > Create Role
  • Use Case: Lambda
  • Permissions โ†’ Create new custom policy with:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances",
        "ec2:StopInstances",
        "s3:ListBucket",
        "s3:PutPublicAccessBlock"
      ],
      "Resource": "*"
    }
  ]
}

Enter fullscreen mode Exit fullscreen mode
  • Name the role: LambdaBillingStopperRole

Step 4:Create Lambda Function

  • Go to Lambda > Create Function
  • Name: StopAWSResources
  • Runtime: Python 3.12
  • Role: Attach LambdaBillingStopperRole
import boto3

def lambda_handler(event, context):
    ec2 = boto3.client('ec2')
    s3 = boto3.client('s3')

    # Stop all EC2 instances
    instances = ec2.describe_instances(Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])
    for reservation in instances['Reservations']:
        for instance in reservation['Instances']:
            ec2.stop_instances(InstanceIds=[instance['InstanceId']])
            print(f"Stopped instance: {instance['InstanceId']}")

    # Block all S3 buckets
    buckets = s3.list_buckets()
    for bucket in buckets['Buckets']:
        s3.put_public_access_block(
            Bucket=bucket['Name'],
            PublicAccessBlockConfiguration={
                'BlockPublicAcls': True,
                'IgnorePublicAcls': True,
                'BlockPublicPolicy': True,
                'RestrictPublicBuckets': True
            }
        )
        print(f"Blocked bucket: {bucket['Name']}")

    return {
        'statusCode': 200,
        'body': 'EC2 stopped and S3 buckets locked.'
    }

Enter fullscreen mode Exit fullscreen mode
  • Paste this code in the function:

Image description

  • Deploy manually and save the code.

Image description

Step:5 Connect SNS to Lambda

  • Go to SNS > Topics > BudgetAlertsTopic
  • Click Create subscription
  • Protocol: AWS Lambda
  • Endpoint: Select your function StopAWSResources
  • Go to Lambda โ†’ Permissions โ†’ Add trigger โ†’ Choose SNS and select topic

Image description

Now, when budget hits 0.01 โ†’ SNS โ†’ triggers Lambda โ†’ EC2 stops + S3 blocks

  • We can check the status of EC2 after reaching the limt amount and it is stopped automatically.

Image description

  • We can also check via cloudwatch that is it stopped by our lamda function or not (for cross verifying)

Image description

  • We can see that our resources that it our EC2 is stopped by Lambda function in our latest Logstream.

  • So we did it..!๐Ÿ’ฅ

Stay tuned for more Deployment and Blogs..!๐Ÿซก๐Ÿ”ฅ

Top comments (0)