Introduction
Amazon Web Services (AWS) Identity and Access Management (IAM) plays a critical role in securing your cloud infrastructure. Managing user access, permissions, and security best practices can be challenging, especially as your AWS environment scales. In this tutorial, we’ll explore how to leverage AWS Lambda to automate the analysis of IAM user configurations, providing insights into security posture and compliance.
Background….
IAM users are entities within your AWS account that can interact with AWS resources. Managing IAM users involves various tasks, such as ensuring multi-factor authentication (MFA) is enabled, monitoring access key usage, and reviewing attached policies. Manually performing these checks for each IAM user can be time-consuming and error-prone. Automating these tasks using Lambda can streamline the process and improve security posture.
import csv
import json
import io
import boto3
import datetime
iam_client = boto3.client('iam')
def check_access_keys(username):
response = iam_client.list_access_keys(UserName=username)
return len(response['AccessKeyMetadata']) > 0
def check_mfa(username):
try:
response = iam_client.list_mfa_devices(UserName=username)
return len(response['MFADevices']) > 0
except iam_client.exceptions.NoSuchEntityException:
return False
def check_console_login(username):
try:
iam_client.get_login_profile(UserName=username)
return True
except iam_client.exceptions.NoSuchEntityException:
return False
def get_last_console_login(username):
try:
response = iam_client.get_user(UserName=username)
password_last_used = response['User'].get('PasswordLastUsed')
return password_last_used
except iam_client.exceptions.NoSuchEntityException:
return None
def get_last_access_key_age(username):
response = iam_client.list_access_keys(UserName=username)
access_keys = response.get('AccessKeyMetadata', [])
if access_keys:
latest_access_key_creation = min(key['CreateDate'] for key in access_keys)
current_time = datetime.datetime.now(datetime.timezone.utc)
age = current_time - latest_access_key_creation
return age.days
else:
return None
def get_user_creation_time(username):
response = iam_client.get_user(UserName=username)
return response['User']['CreateDate']
def get_password_last_changed(username):
try:
response = iam_client.get_user(UserName=username)
return response['User'].get('PasswordLastUsed')
except iam_client.exceptions.NoSuchEntityException:
return None
def get_password_age(username):
password_last_changed = get_password_last_changed(username)
if password_last_changed is not None:
current_time = datetime.datetime.now(datetime.timezone.utc)
age = current_time - password_last_changed
return age.days
else:
return None
def process_user(user):
user_name = user['UserName']
user_creation_time = get_user_creation_time(user_name)
has_mfa = check_mfa(user_name)
has_console_login = check_console_login(user_name)
has_access_keys = check_access_keys(user_name)
last_console_login = get_last_console_login(user_name)
last_access_key_age = get_last_access_key_age(user_name)
password_age = get_password_age(user_name)
response_access_keys = iam_client.list_access_keys(UserName=user_name)
access_keys = response_access_keys.get('AccessKeyMetadata', [])
response_attached_policies = iam_client.list_attached_user_policies(UserName=user_name)
attached_policies = [
{"PolicyName": policy['PolicyName'], "PolicyDocument": get_default_policy_version(policy['PolicyArn'])}
for policy in response_attached_policies.get('AttachedPolicies', [])
]
return {
'UserName': user_name,
'User_creation_time': user_creation_time,
'HasMFA': has_mfa,
'HasConsoleLogin': has_console_login,
'HasAccessKeys': has_access_keys,
'LastConsoleLogin': last_console_login,
'ActiveAccessKeyAge': f"{last_access_key_age} days",
'PasswordAge': f"{password_age} days",
'AllPolicies': attached_policies
}
def get_default_policy_version(policy_arn):
try:
policy_details = iam_client.get_policy(PolicyArn=policy_arn)
default_version_id = policy_details['Policy']['DefaultVersionId']
policy_version = iam_client.get_policy_version(PolicyArn=policy_arn, VersionId=default_version_id)
return policy_version['PolicyVersion']['Document']
except iam_client.exceptions.NoSuchEntityException:
return None
def lambda_handler(event, context):
try:
# Get IAM Users
response = iam_client.list_users()
iam_users = response['Users']
users_with_details = []
# Process each user
for user in iam_users:
user_info = process_user(user)
users_with_details.append(user_info)
# Prepare JSON response
json_response = {
'statusCode': 200,
'body': {
'users': [
{
'UserName': user_info['UserName'],
'User_creation_time': str(user_info['User_creation_time']),
'HasMFA': str(user_info['HasMFA']),
'HasConsoleLogin': str(user_info['HasConsoleLogin']),
'HasAccessKeys': str(user_info['HasAccessKeys']),
'LastConsoleLogin': str(user_info['LastConsoleLogin']),
'ActiveAccessKeyAge': str(user_info['ActiveAccessKeyAge']),
'PasswordAge': str(user_info['PasswordAge']),
'AllPolicies': user_info['AllPolicies']
}
for user_info in users_with_details
]
},
'headers': {
'Content-Type': 'application/json'
}
}
return json_response
except Exception as e:
# Handle other exceptions if needed
return {
'statusCode': 500,
'body': {"error": str(e)},
'headers': {
'Content-Type': 'application/json'
}
}Lambda Function Overview
The Lambda function we’ll be building interacts with the IAM service to retrieve information about IAM users, their access, and security configurations. Here’s a high-level overview of what the Lambda function does:
- Retrieving IAM Users: The function retrieves a list of IAM users from the AWS IAM service using the
list_usersAPI. - Analyzing User Details: For each IAM user, the function analyzes various aspects of their configuration, including:
- MFA status
- Console login status
- Access key presence and age
- Password age
- Attached policies
- Processing User Data: User data is processed and organized into a structured format containing relevant details about each IAM user.
- Generating JSON Response: The function generates a JSON response containing the analyzed data for all IAM users.
Lambda Code Breakdown
The Lambda function is written in Python and utilizes the Boto3 SDK for interacting with AWS services. Here’s a breakdown of key components within the Lambda function:
- Functions like
check_mfa,check_console_login,check_access_keys, etc., are responsible for checking various aspects of IAM user configurations. - The
process_userfunction aggregates information about each IAM user into a structured format. - Error handling is implemented to gracefully handle exceptions and provide informative responses.

Conclusion
Automating IAM user analysis using AWS Lambda can significantly improve security and compliance within your AWS environment. By regularly monitoring user configurations, organizations can identify security gaps, enforce best practices, and ensure compliance with regulatory requirements. The Lambda function provided in this tutorial serves as a foundation for building more comprehensive IAM security automation solutions.
Empower your AWS IAM security with automation! Discover how to effortlessly analyze user configurations using AWS Lambda and Boto3. Enhance security, enforce best practices, and ensure compliance. Dive into our tutorial now and transform your IAM management!







