🛡️ Introduction
In today’s cloud-first world, Identity and Access Management (IAM) is your AWS account’s first line of defense. Yet, it’s common for IAM passwords and access keys to remain active well beyond their intended lifespan — posing serious security risks. Manually tracking and rotating these credentials is tedious and error-prone.
This post walks you through building a fully automated IAM expiry notification system using AWS Lambda, Amazon SNS, and Amazon EventBridge. The setup continuously scans IAM users, detects credentials past expiration, and sends real-time alerts to help you stay secure — all with zero manual effort.
🎯 Purpose
The goal of this automation is to enhance your AWS security posture by proactively monitoring IAM user credentials — specifically passwords and access keys — and alerting administrators when they exceed a predefined age threshold.
This ensures regular credential rotation, enforces security best practices, and reduces the risk of unauthorized access due to stale or forgotten IAM credentials.
📌 Scope
This automation covers:
🔍 Scanning all IAM users in the AWS account
⏰ Detecting expired access keys and outdated passwords
📢 Sending automated notifications via Amazon SNS (e.g., email alerts)
🗓️ Scheduling periodic checks using Amazon EventBridge
⚙️ Running everything in a serverless AWS Lambda function — no manual intervention after deployment
⚠️ Note: This solution focuses purely on monitoring and alerting. It does not deactivate or delete keys automatically — giving administrators control over remediation.
🏗️ Architecture Overview
The architecture of this solution is simple, serverless, and fully automated — designed to run on a schedule without any manual triggers. It leverages three core AWS services that work together to monitor IAM credentials and send expiry notifications.
⚙️ How It Works
1. Amazon EventBridge (Scheduler):
- Triggers the Lambda function automatically at a predefined interval (e.g., daily).
- Ensures continuous monitoring of IAM credentials without human intervention.
2. AWS Lambda (Logic Engine):
Executes the core logic to:
Fetch all IAM users in the AWS account.
Retrieve each user’s password and access key metadata.
Calculate the age of credentials.
Compare against a defined threshold (e.g., 85 days).
Identifies users with credentials nearing or past expiry.
3.Amazon SNS (Notification System):
- Sends out real-time notifications (email or other subscribed endpoints).
- Alerts administrators or security teams when credentials exceed the threshold.
🧠 Workflow Summary
- EventBridge triggers the Lambda function on schedule.
- Lambda queries IAM to fetch user credentials and calculates their age.
- If a password or key is older than the threshold, Lambda compiles the details.
- Lambda publishes the alert message to an SNS topic.
- SNS sends an email or message to the subscribed recipients.
This lightweight design ensures high reliability, zero maintenance, and no additional infrastructure cost, making it ideal for organizations of any size that want to enhance IAM security visibility.
⚙️ Implementation Steps
Step 1: Create an SNS Topic
We’ll start by setting up an Amazon SNS topic — this will act as the notification channel for sending expiry alerts via email (or any other supported protocol).
🧭 Steps:
1.Navigate to SNS in the AWS Console
Open the AWS Management Console and search for SNS (Simple Notification Service).
2.Create a New Topic
Click on “Create topic” to begin the setup.
3.Select Topic Type
Choose Standard as the topic type and provide a descriptive name.
4.Create the Topic
Scroll down and click “Create topic” at the bottom-right corner of the page.
5.Add a Subscription
Once the topic is created, click on “Create subscription.”
6.Configure the Subscription
- Topic ARN: Select the topic you just created.
- Protocol: Choose *Email *(you can also use SMS, Lambda, or HTTP endpoints).
- Endpoint: Enter your email address (or the recipient’s email).
7.Confirm the Subscription
- Check your email inbox for a confirmation message from AWS.
- Click “Confirm subscription” in the email to activate it.
After confirmation, the SNS topic will be ready to receive messages and forward them as email alerts to the subscribed recipients.
Step 2: Create the Lambda Function
Next, we’ll set up the AWS Lambda function that performs the actual check for IAM password and access key expiry, and sends notifications via SNS.
🧭 Steps:
1.Navigate to Lambda in the AWS Console
Open the AWS Lambda service from the console.
2.Create a New Function
Click “Create function” to begin setup.
3.Configure Basic Settings
- Choose Author from scratch.
- Provide a name.
- Select Python latest runtime.
- Choose x86_64 as the architecture.
4.Assign Permissions
Lambda needs an execution role with specific IAM permissions to fetch IAM data and publish notifications to SNS.
Create a new IAM Role
with the following policy and attach it to your Lambda function:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"sns:Publish",
"iam:GetAccessKeyLastUsed",
"iam:ListUsers",
"iam:GetUser",
"iam:ListAccessKeys",
"iam:GetAccountPasswordPolicy",
"iam:GenerateCredentialReport",
"iam:GetCredentialReport"
],
"Resource": "*"
}
]
}
5.Create the Function
Click “Create function” to finalize setup.
6.Add the Code
- Once the function is created, open it in the console.
- In the code editor, replace the default code with the following Python script:
import boto3
import datetime
import csv
import io
from dateutil import parser
sns_client = boto3.client('sns')
iam_client = boto3.client('iam')
SNS_TOPIC_ARN = 'Paste your SNS Topic ARN Here'
def lambda_handler(event, context):
iam_client.generate_credential_report()
report_response = iam_client.get_credential_report()
report_csv = report_response['Content'].decode('utf-8')
csv_reader = csv.DictReader(io.StringIO(report_csv))
max_password_age = 90
expired_items = []
now = datetime.datetime.now(datetime.timezone.utc)
for row in csv_reader:
username = row['user']
if username in ['<root_account>', '']:
continue
user_creation_time = row['user_creation_time']
password_last_changed = row['password_last_changed']
# ✅ Password check
if password_last_changed not in ['not_supported', 'N/A']:
pwd_changed_dt = parser.isoparse(password_last_changed)
password_age_days = (now - pwd_changed_dt).days
if password_age_days > max_password_age:
expired_items.append({
'UserName': username,
'Type': 'Password',
'UserCreationTime': user_creation_time,
'PasswordLastChanged': pwd_changed_dt.strftime('%Y-%m-%d %H:%M:%S'),
'Age': password_age_days
})
# ✅ Access key check
try:
access_keys = iam_client.list_access_keys(UserName=username)['AccessKeyMetadata']
for key in access_keys:
if key['Status'] == 'Active':
key_id = key['AccessKeyId']
key_created_dt = key['CreateDate']
key_age_days = (now - key_created_dt).days
if key_age_days > max_password_age:
try:
usage = iam_client.get_access_key_last_used(AccessKeyId=key_id)
last_used = usage.get('AccessKeyLastUsed', {}).get('LastUsedDate')
last_used_str = last_used.strftime('%Y-%m-%d %H:%M:%S') if last_used else "Never Used"
except Exception:
last_used_str = "Unknown"
expired_items.append({
'UserName': username,
'Type': 'AccessKey',
'AccessKeyId': key_id,
'UserCreationTime': user_creation_time,
'AccessKeyCreationTime': key_created_dt.strftime('%Y-%m-%d %H:%M:%S'),
'AccessKeyLastUsed': last_used_str,
'Age': key_age_days
})
except Exception as e:
print(f"Error listing keys for user {username}: {e}")
# ✅ Send SNS notification
if expired_items:
message = "The following IAM credentials are older than the allowed max password age:\n\n"
for item in expired_items:
if item['Type'] == 'Password':
message += (
f"User: {item['UserName']}, User Creation Time: {item['UserCreationTime']}, "
f"Password Last Changed: {item['PasswordLastChanged']}, Age: {item['Age']} days\n"
)
else:
message += (
f"User: {item['UserName']}, User Creation Time: {item['UserCreationTime']}, "
f"AccessKeyId: {item['AccessKeyId']}, Access Key Creation Time: {item['AccessKeyCreationTime']}, "
f"Access Key Last Used: {item['AccessKeyLastUsed']}, Age: {item['Age']} days\n"
)
sns_client.publish(
TopicArn=SNS_TOPIC_ARN,
Subject="IAM User and Access Keys Credentials Expiry Alert",
Message=message
)
else:
sns_client.publish(
TopicArn=SNS_TOPIC_ARN,
Subject="IAM User and Access Keys Compliance Notification",
Message="All IAM user passwords and access keys are compliant (within 90 days)."
)
return {
'statusCode': 200,
'body': 'Lambda function executed successfully!'
}
7.Deploy and Test
Click “Deploy”, then “Test” to execute the function.
- Verify the function runs successfully.
- You should receive an SNS email notification indicating whether any IAM credentials have expired.
Step 3: Create an Amazon EventBridge Scheduler
The final step is to automate the Lambda function’s execution using Amazon EventBridge Scheduler. This ensures that the IAM credential checks run on a regular basis without manual triggers.
🧭Steps:
1.Open EventBridge in the AWS Console
Navigate to Amazon EventBridge from the AWS Management Console.
2.Access the Scheduler
In the left-hand menu, click on “Schedules.”
3.Create a New Schedule
Click “Create schedule” to start configuring your recurring rule.
4.Configure Schedule Details
- Name: Provide scheduler name
- Description: Add a short description for reference.
- Schedule Group: Select Default.
-
Schedule Pattern:
Occurrence: Recurring schedule
Time zone: select based on timezone
Schedule type: Cron-based schedule
Cron expression: Example —cron(0 10 ? * 6 *)
This runs the Lambda function every Saturday at 10:00 AM.
Flexible time window: Off
5.Set the Target Service
- Under Target, choose AWS Lambda function.
- Select the Lambda function you created in the previous step.
6.Assign Required Permissions
- EventBridge needs permission to invoke the Lambda function.
- Use an existing IAM role or create a new one that allows lambda:InvokeFunction.
7.Review and Create
Click Next, review your configuration, and then select “Create schedule.”
Your EventBridge Scheduler is now live and will automatically trigger the Lambda function on the defined schedule — keeping your IAM credential monitoring continuous and effortless.
✅ Conclusion
By automating IAM user password and access key expiry notifications using AWS Lambda, Amazon EventBridge, and Amazon SNS, you can proactively maintain account security without manual oversight. This serverless approach ensures timely alerts, reduces the risk of credential misuse, and keeps your AWS environment compliant with best practices — all while staying simple, scalable, and cost-effective.
Top comments (0)