A Step-by-Step Guide to Identifying Roles Without AWS IAM Permission Boundaries
Step 1: Understanding the Problem
AWS IAM (Identity & Access Management) Roles are a secure way to grant permissions to entities that you trust. However, without a permissions boundary, a role has the potential to escalate its privileges leading to more access than needed. To avoid this, our task is to identify such roles.
Step 2: Defining the Solution
To counter this problem, we are creating an AWS Lambda function that will:
Scrutinize every IAM role for permission boundaries.
Compile a JSON document listing roles missing these boundaries.
Store the JSON in an AWS S3 bucket.
Generate a pre-signed URL for secure access to the S3 object.
Send the pre-signed URL to your email using AWS SNS.
So we will get
/In conclusion, you will find a Terraform Git repository that automates the entire process.
Step 3: Setting up the Infrastructure
Creating an S3 bucket to store the JSON file.
Setting up SNS Topic and Subscription to enable email notifications.
Confirm the subscription that you will receive in your email.
Create a lambda function with python as runtime and attatch to it's execution role this policy.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "S3Actions", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:ListBucket", "s3:GetObject" ], "Resource": [ "arn:aws:s3:::<bucket-name>/*", "arn:aws:s3:::<bucket-name>" ] }, { "Sid": "IAMRoleActions", "Effect": "Allow", "Action": [ "iam:ListRoles", "iam:GetRole" ], "Resource": "*" }, { "Sid": "SNSTopicPublish", "Effect": "Allow", "Action": "sns:Publish", "Resource": "arn:aws:sns:<region>:<account-id>:<sns-topic>" } ] }
Don't forget to replace replace
<bucket-name>
,<region>
,<account-id>
and<sns-topic>
with your actual data.Setting up the Lambda function with the Python code that carries out the main task.
import boto3 import json from botocore.exceptions import NoCredentialsError # Function to generate presigned URL to access S3 objects def create_presigned_url(bucket_name, object_name, expiration=3600): # Initialize S3 client s3_client = boto3.client('s3') try: # Generate and return pre-signed URL response = s3_client.generate_presigned_url('get_object', Params={'Bucket': bucket_name, 'Key': object_name}, ExpiresIn=expiration) except NoCredentialsError: print("[Error] No AWS credentials found.") return None return response # Main function def lambda_handler(event, context): bucket_name = "<bucket-name>" object_name = "object_name" topic_arn = "<sns-topic>" # Initialize S3 and IAM clients s3 = boto3.client('s3') iam = boto3.client('iam') response = iam.list_roles() roles_no_boundary = [] # Loop through all IAM roles for role in response['Roles']: data = iam.get_role(RoleName=role['RoleName']) # Check if the role has a permission boundary try: data['Role']['PermissionsBoundary']['PermissionsBoundaryArn'] except KeyError: # If not, add it to the list roles_no_boundary.append({"ARN": role['Arn']}) json_data = json.dumps(roles_no_boundary) # Convert list to JSON # Upload JSON to S3 s3.put_object(Body=json_data, Bucket=bucket_name, Key=object_name) # Create pre-signed URL for the uploaded JSON url=create_presigned_url(bucket_name, object_name) # Initialize SNS client sns = boto3.client('sns') # Publish SNS message containing the pre-signed URL response = sns.publish( TopicArn=topic_arn, Message='Here is your pre-signed URL: ' + url, Subject='Your Presigned S3 URL' ) return { 'statusCode': 200, 'body': "JSON file has been successfully generated and uploaded to S3" }
Don't forget to replace replace
<bucket-name>
, and<sns-topic>
with your actual data.Run a default test in your Lambda, and you will receive the email shortly.
Step 4: Monitoring and Alerts
Monitoring and alerting are crucial for maintaining our Lambda function's health. A common issue is the 'Access Denied' error, indicating insufficient permissions for the AWS IAM Role.
To address this, we'll use Amazon CloudWatch. It monitors AWS resources, tracks metrics, and logs files. We'll set up CloudWatch to detect 'Access Denied' events and trigger an alert via SNS (Simple Notification Service).
The CloudWatch Logs Group is created by default when the lambda get executed (if she has sufficient permissions) so you go to the log group
Creating a Subscription Filter
Create a Subscription Filter with our priviously created Lambda function
Creating a Metric Filter
A metric filter will be used in combination with the subscription filter to convert filtered text into a numeric value that CloudWatch will continuously monitor.
Setting CloudWatch Alarm
Now that our metrics are in place, we can set up a CloudWatch alarm. This alarm will trigger whenever it detects 'Access Denied' entries.
Setting up SNS Topic and Subscription
When the alarm is triggered, it will send a message to an SNS Topic, which in turn triggers the external lambda function.
Conclusion
By following this guide, you can effectively identify AWS IAM roles without permission boundaries, ensuring tighter security and controlled access within your AWS environment. Implementing the outlined steps will help you set up a comprehensive monitoring and alerting system, allowing you to address potential issues proactively and maintain a robust security posture.
If you missed something, don't worry! You can automate the process using this awesome Terraform code.