Implementing Real-time Slack Alerts for IAM Key Expiration Using AWS Lambda

Santosh Garole
Globant
Published in
6 min readMar 14, 2024
Photo by mrpeker on Unsplash

In this article, we will explore how to set up an alert system for IAM (Identity Access Management) secret rotation using the AWS Lambda (Amazon Web Service) service. We have accomplished this task by leveraging AWS Boto and Python scripting. By AWS compliance standards, it is necessary to rotate the IAM user’s secret key and access key every 90 days. Failure to do so will result in non-compliance being displayed on our trust dashboards. Therefore, we must be promptly notified with a daily alert in case the underlying threshold is breached through the messaging platform employed for organizational communication. In our specific scenario, Slack is our chosen communication platform and alert monitoring platform. Consequently, we have opted to develop an AWS Lambda function using Python and boto3. This function will provide an alert as soon as our keys surpass the age of 70 days. Hence, we will have an additional 20 days to perform the necessary key rotation for each environment wherever they are used.

Prerequisites

Before proceeding with the setup, ensure that you have the following:

Create an IAM Role

Below are the steps for creating an IAM role:
1. Click the Create Role button and select the AWS service option for the trusted entity type. Similarly, select Lambda for common use cases, as shown below. Continue with the role creation by clicking on the Next button as shown below:

Create a role

2. Continue to add the role permissions as shown below image:

Role creation

First, search for the permission policies to be added to the search box. For example, we have added the policy IAMReadonlyAccess. Repeat this for all required permissions:

  • IAMReadOnlyAccess
  • AmazonS3ReadOnlyAccess
  • AWSLambdaBasicExecutionRole
  • AmazonEventBridgeSchedulerFullAccess

Writing a Python Script Using Boto

Below is a Python script that facilitates the verification of your IAM key’s age:

from urllib import response
from datetime import date
import requests
import boto3
import json
import sys
import random
import os

min_age = 70
max_age = 90
user_list = []
maxage_users = []
slackchannel = os.environ['slackchannel']
hook_url = os.environ['hook_url']
account_id = boto3.client("sts").get_caller_identity()["Account"]
vault_user = (f'vaultuser-{account_id}')
days_remain_all = []

def lambda_handler(event, context):
client = boto3.client('iam')
response = client.list_users()
for x in response['Users']:
if x['UserName'] != vault_user:
user_list.append(x['UserName'])

for username in user_list:
res = client.list_access_keys(UserName=username)
accesskeydate = res['AccessKeyMetadata'][0]['CreateDate'].date()
currentdate = date.today()
active_days = currentdate - accesskeydate
days_remain = max_age - (active_days.days)
if active_days.days > min_age:
maxage_users.append(username)
days_remain_all.append(days_remain)

slack_notif()

def slack_notif():
url = hook_url
message = (f'Found users "{maxage_users}" in account "{account_id}" User keys expires in: "{days_remain_all}" days')
title = (f"IAM Key Rotation:zap:")
slack_data = {
"username": "IAM_Key_Rotation",
"icon_emoji": ":satellite:",
"channel" : slackchannel,
"attachments": [
{
"color": "#9733EE",
"fields": [
{
"title": title,
"value": message,
"short": "false",
}
]
}
]
}
byte_length = str(sys.getsizeof(slack_data))
headers = {'Content-Type': "application/json", 'Content-Length': byte_length}
if maxage_users:
response = requests.post(url, data=json.dumps(slack_data), headers=headers)
if response.status_code != 200:
raise Exception(response.status_code, response.text)from datetime import date

To utilize this script, follow these steps:

  • Fork the provided code repository to your preferred platform.
  • Configure the script within your Lambda function’s settings.
  • Modify the environment variables in the script to align with your specific needs.

Creating a Lambda Function for Automation

In the search bar, enter Lambda to view the listed service, and click on Lambda. You will be able to see the option to create a new Lambda function. After clicking on the Create Function tab, you will be presented with the following window:

Lambda creation

In the first step, Select Author from scratch, as we already have a Python script written. The second step is to provide the lambda function name as per the requirement. Then select the Runtime version to Python 3.10 and architecture to x86_64. Next, choose the IAM role we created in the second step for this function and then click the Create Function tab:

Select the IAM role we created earlier

After successfully creating the Lambda function, proceed to configure the following environment variables within our Python script:

hook_url: Set the value to your Slack channel’s hook URL.
slackchannel: Set the value to your Slack channel's name.
Configure environment variables

Make sure you have the trigger setup as mentioned below. You can verify this in your Lambda function’s configuration by checking the Triggers tab, as illustrated below:

Verify the Lambda function’s trigger

Create a Scheduled Trigger as an EventBridge for the Lambda Function

We need to ensure that the Lambda function triggers automatically every day. To achieve this, we will set up an Amazon EventBridge trigger. To begin, navigate to the EventBridge service in the AWS Management Console. Click on the Create Rule button and follow steps as illustrated below:

Search for Amazon EventBridge in the console and click on Rules:

Create a scheduled trigger rule

Fill up the details for creating the rule, such as the rule’s name, the description, and the schedule on which you want the rule to be executed:

Configure the scheduled trigger rule

As shown in the example, we have selected a recurring schedule because we wanted to run this job every 12 hours:

Configure the schedule pattern

Select the time frame that fits your requirements. We have selected UTC as a time zone:

Configure the trigger’s time frame for execution

We have to select the execution target. For example, we have created this rule to trigger the Lambda function; hence, we have chosen AWS lambda Invoke API:

Selecting the target to trigger a Lambda function

Now, we have to select a particular Lambda function and copy the function’s code as shown below:

Configuring scheduled trigger for the lambda function

Testing the Output Using Lambda

After successfully creating the Lambda function and uploading your code following the above-mentioned steps, proceed with deploying the code. Once deployed, you can initiate a test run. This action should trigger a message to be sent to the designated Slack channel, as detailed in the step Displaying the results on Slack:

Testing lambda output

Displaying the Results on Slack

We have received the following alert as part of the above automation so that we can take care of rotation before the time:

Slack alert example

Conclusion

In this article, we have addressed a straightforward scenario: setting up an AWS Lambda Function to consistently trigger Slack alerts for IAM users’ keys that surpass 70 days in age. This enables us to proactively rotate the keys before they reach the 90-day mark. Our approach involves utilizing Boto and Python for the implementation and Amazon EventBridge to schedule the execution trigger. While the initial configuration involving various objects might appear complex, I encourage you to replicate the provided code and generate your scripts based on it. As you work with the foundational code, you will find subsequent configurations significantly more manageable. You are welcome to experiment with this foundation to streamline the process according to your specific requirements.

References

For additional insights, please visit these articles:

--

--