Automatically tag AWS EC2 Instances with the “Owner” tag upon creation
No no, You created this, Look at this tag!
Context
This is a guide on how to create a lambda function which will automatically tag EC2 instances upon creation with the Creator’s email ID and send them a Slack message.
Inspired by : Automatically tag new AWS resources based on identity or role
Basic Idea of this Project
A Flowchart — Since I love Canva and A picture is worth a thousand words or something.
In Words:
UserA is an IAM user and that user’s organisation email is usera.something@example.com. In order to map the IAM user to his/her, we add a tag to the UserA as “Owner” = “usera.something@example.com”
UserA creates an EC2 > This is identified by the CloudWatch Events Rule we have configured to listen EC2:RunInstances events. > CloudWatch Events rule triggers a Lambda function. > This Lambda function receives the CloudTrail resource creation event as an argument and parses that data to collect the list of new EC2 instance attributes, creation date, IAM role name. > Script checks for the existing tags attached to the newly created EC2s > If the “Owner” tag is already configured then no need to override it. Else, the script will identify the UserA as the IAM user who created the resource and will find the UserA’s email ID from IAM tags and attach them to the EC2. > There are a few other mandatory tags as well. Script will check for their presence and will curate a Slack message and will send to the IAM user if the mandatory tags are missing.
Steps:
- First we need to add Tags to all the IAM users. These tags will be inherited when we add tags to the resources created by that specific user.
You can use AWS CLI for this.
ie: aws iam tag-user — user-name kalanaw — tags ‘{“Key”: “Owner”, “Value”:”kalanaw@example.com”}’
ie: In below example, we can configure the lambda script to add Owner and Team tag to all the EC2s created by that IAM user, kalanaw.
- Our lambda needs to read tags, read Cloudtrail data, write to Cloudwatch logs and other AWS Service permissions. Hence we need an execution role to run the script.
- Sample IAM Policy to attach to the lambda script. Create a Lambda based IAM role and attach the below policy.
Important: Replace “YouraccountID” with your actual AWS Account ID.
- Then we can write the Lambda Script.
Lambda > Create function > Author from Scratch > Add a name > Runtime is Python 3.9 > Change default execution role > Use the IAM Role we created earlier.
Keep the rest with default values. - Sample Lambda Script here, You need to edit company email domain, list of mandatory tags, Slack message body if needed. If you have ideas to upgrade the script, have concerns please do not hesitate to send a Pull request or comment down.
Important: In order to send Slack alerts you need to create a Slack bot and get the “Bot User OAuth Token” and add that as an Environment Variable in your Lambda Script.
ie: SLACK_BOT_TOKEN=eduae-wfqd3ee-ejWE-FHREFH-UR-HFQDEF - Since we will be using slack-sdk we will have to import slack-sdk to lambda since it is not packed in Lambda by default. The most scalable solution is creating a lambda layer with slack-sdk and adding that layer to our lambda function. In this way we can reuse this layer for any other lambda function unlike using a Zipped deployment package.
- In order to get the Event details (EC2 Creation Event) we have to create a Multi Region CloudTrail Trail. We do not have to create a brand new trail for this as we can reuse an existing Trail. If there already is a Trail do not create a new one. (The requirement is to have a multi region CloudTrail trail within the account)
CloudTrail > Dashboard > Create trail
Use any Trail name, name won’t be used anywhere. You can use a new S3 bucket or use an existing one. Won’t make a difference. You can use any option for Encryption as well.
- This lambda script needs to be executed every time an EC2 created. To achieve that we can use Cloudwatch EventRules. Keep the default values for the rest.
- Now we do have lambda, CloudTrail Trail. Next step is combining these two. We use CloudWatch Event Rules for that.
- Create a rule in CloudWatch Events to trigger on the Amazon EC2 RunInstances API action. For information, see Creating a CloudWatch Events Rule That Triggers on an AWS API Call Using AWS CloudTrail in the Amazon CloudWatch Events User Guide. Use the following settings for the rule:
- For Event source, choose Event Pattern.
- For Service Name, choose EC2.
- For Event Type, choose AWS API Call via CloudTrail.
- Choose Specific operation(s), and then enter RunInstances.
- For Targets, choose the Lambda function we created earlier.
Now everything should work as expected. Start an EC2 with “Owner” Tag, without “Owner” tag and see whether everything works as expected. If you are facing any issue comment down below!
Cheers,