HOWTO: Use EventBridge to trigger a Lambda function written in Python to tag EC2 instances

In this tutorial, we will learn to tag AWS EC2 instances when they are created using Lambda function, written in Python. We will create a rule in EventBridge to trigger a Lambda function whenever a user creates a new AWS EC2 instance. The Lambda function will tag new EC2 instances with the name of the user that created it.

Tags are custom metadata that you can attach to your resources for a variety of purposes, such as cost allocation in your billingsecurity authorization using attribute-based access control, or to support your other categorization needs. These tags makes it very easy to categorize your resources for easier tracking in the future.

By having this dynamic automation in place, organizations can easily track who created what resources. 

Once the resources are tagged, we can create additional views in Resource Explorer and generate a list of all resources created by a specific user based on this tag value. How to use AWS Resource Explorer is covered in my previous post here.

In the next post, I will automate most of the steps below using CloudFormation template instead of using AWS Management console.

Services Used:

  • Amazon VPC
  • Amazon EventBridge
  • AWS Lambda
  • Amazon CloudWatch
  • AWS CloudTrail

Prerequisites

  • IAM Identity Center user with appropriate permissions. Please refer to my previous post here on how to configure users. 

Steps

  1. Create a VPC for a test environment with only one public subnet
  2. Create a lambda function to tag EC2 instances when they are created
  3. Set up the Test for the Lambda function. This test event creates a log group in CloudWatch, so whenever the function runs it logs in the CloudWatch logs
  4. Create a CloudTrail trail. Please refer to my previous post here.
  5. Create Amazon EventBridge rule which is triggered when EC2 instance is created
  6. Provide permissions to Lambda function to execute the create tag on EC2 instances
  7. Deploy the Lambda function
  8. Create test EC2 instances to trigger the EventBridge which will trigger the Lambda function
  9. Validate the tags on the EC2 instances and view them in Resource Explorer
  10. Clean up resources: Delete all the resources so you are not charged

Step 1: Create a VPC for test environment

Create a VPC with limited subnets and restricted security group. Here I have created a VPC with one public subnet in one availability zone.

Change the security group from allowing all traffic to only SSH traffic from your IP address

Default inbound rules allows all traffic (below)

Change to allow only SSH traffic (below)

Step 2: Create a Lambda function

On the Lambda console, click the Create function and make the following selections:
Author from scratch
Function Name: <your function name> e.g.maghilda_tagResourceCreation
Runtime: Python 3.12

The following default source code will be generated

Step 3: Set up the Test for the Lambda function

Run the Test to make sure that the boilerplate code runs. This test also creates the log group under the CloudWatch

This will create the AWS CloudWatch log group and stream

Step 4: Create a CloudTrail Trail

EventBridge requires CloudTrail Trail to exist as it uses the CloudTrail API. To set up CloudTrail trail with S3, please review my post here.

Step 5: Create Amazon EventBridge

Amazon EventBridge Event Bus is a serverless event bus that helps you receive, filter, transform, route, and deliver events. Create a Rule in Amazon EventBridge to trigger Lambda function when an EC2 instance is created (RunInstance)

Under Event Pattern, make the following selections:
Event source : AWS sevices
AWS service: EC2
Event type: AWS API Call via CloudTrail
Event Type Specification 1: Specific operation(s). Enter RunInstances
The Event pattern will be built on the right in json as seen below

Under Select target(s), make the following entries:
Target 1: AWS service
Select a target: Lambda function
Function: select your Lambda function e.g, maghilda_tagResourceCreation

Once the EventBridge rule is created, it will show as a trigger on the Lambda console as follows.

Step 6: Provide Permissions to the Lambda function to execute Create Tag method

Complete writing the Python function as follows. The print(event) will provide you with the json structure to select userName and instanceId. In this case, I am using SSO credentials which are under session context.sessionIssuer arrays.

import json
import boto3
 
ec2 = boto3.client('ec2')
 
def lambda_handler(event, context):
    #print(event)
    
    #user name; please note that this may differ based on the structure of your IAM user
    userName = event['detail']['userIdentity']['sessionContext']['sessionIssuer']['userName']
    
    #instance id
    instanceId = event['detail']['responseElements']['instancesSet']['items'][0]['instanceId']
    
    ec2.create_tags(
        Resources=[
            instanceId,
        ],
        Tags=[
            {
                'Key': 'CreatedBy',
                'Value': userName
            },
        ]
    )
    print("completed executing tag lambda function")
    return

Provide permissions for your Lambda function to create tags. Modify the permissions associated with the Lambda Execution Role under Configuration Tab -> Permissions.

Click on the Role name above and add policy to CreateTags on all EC2 resources.

The completed policy will look like below

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "ec2:CreateTags",
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:us-east-1:791114689129:*"
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:us-east-1:791114689129:log-group:/aws/lambda/maghilda_tagResourceCreation:*"
        }
    ]
}

Step 7: Deploy the Lambda function

Click Deploy to deploy the Lambda function

Step 8: Create test EC2 instances

Step 9: Validate the tags and see all the tagged resources in Resource Explorer

Under the Instances Tags tab, you will notice the new key value pair of CreateBy and the userName

Validate the CloudWatch logs

In the Resource Explorer, run the query to find all resources tagged with the createdby and username. I had created two test instances and they are listed below. Please check my previous post here.

Step 10: Clean up resources

Make sure to clean up the following resources we created for this tutorial

  • Stop and terminate instances
  • Delete CloudTrail trail
  • Delete CloudWatch Log Group
  • Delete S3 bucket created for CloudTrail Trail
  • Delete VPC
  • Delete Lambda function
  • Delete EventBridge rule

References