Overview
This document provides a step-by-step guide to creating a Lambda function that sends notifications to Slack when:
- A new IAM user is created.
- A permission (policy) is attached to an IAM user.
Prerequisites
- AWS Account with necessary permissions to create and configure Lambda, IAM, CloudTrail, and CloudWatch Logs.
- Slack workspace with permissions to create a new app and generate an incoming webhook URL.
Architecture
IAM event -> CloudTrail -> CloudWatch Logs -> Lambda Function -> Slack
[Good Read: Step-by-Step Guide to Cloud Migration With DevOps ]
Step 1: Setup CloudTrail
- Go to CloudTrail Console:
- Navigate to the AWS Management Console.
- Go to the CloudTrail service.
2. Create or Configure a Trail:
- Create a new trail or use an existing one.
- Ensure that the trail is configured to log management events.
- Enable the trail to send logs to CloudWatch Logs.
Step 2: Setup CloudWatch Logs
- Create Log Group:
- Navigate to CloudWatch in the AWS Management Console.
- Create a new log group or use an existing one to receive CloudTrail logs
Step 3: Create Lambda Function
- Create a Lambda Function:
- Go to the AWS Lambda Console.
- Create a new Lambda function with a suitable name, runtime (Python 3.8+), and role with the necessary permissions.
2. Add the Following Code:
import json
import os
import base64
import gzip
import urllib3
webhook_url = os.environ.get('WEBHOOK_URL')
def send_slack_message(message):
http = urllib3.PoolManager()
payload = {
"blocks": message
}
encoded_payload = json.dumps(payload).encode('utf-8')
response = http.request(
'POST',
webhook_url,
body=encoded_payload,
headers={'Content-Type': 'application/json'},
)
return response.status
def create_slack_message(event_detail):
event_name = event_detail['eventName']
actor_name = event_detail['userIdentity']['userName']
if event_name == 'CreateUser':
user_name = event_detail['requestParameters']['userName']
title = "New IAM User Created"
message = f"A new IAM user `{user_name}` has been created by `{actor_name}`."
color = "#36a64f"
elif event_name in ['AttachUserPolicy', 'PutUserPolicy']:
user_name = event_detail['requestParameters']['userName']
policy_name = event_detail['requestParameters']['policyArn']
title = "Policy Attached to IAM User"
message = f"Policy `{policy_name}` has been attached to user `{user_name}` by `{actor_name}`."
color = "#FFA500"
slack_message = [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f":rotating_light: *{title}* :rotating_light:"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": f"*Event Name:*\n{event_name}"
},
{
"type": "mrkdwn",
"text": f"*User Name:*\n{user_name}"
},
{
"type": "mrkdwn",
"text": f"*Performed By:*\n{actor_name}"
}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": message
}
},
{
"type": "divider"
}
]
return slack_message
def parse_event(event):
if 'awslogs' in event:
log_data = event['awslogs']['data']
compressed_payload = base64.b64decode(log_data)
uncompressed_payload = gzip.decompress(compressed_payload)
log_events = json.loads(uncompressed_payload)['logEvents']
for log_event in log_events:
message = log_event['message']
log_entry = json.loads(message)
if log_entry['eventName'] in ['CreateUser', 'AttachUserPolicy', 'PutUserPolicy']:
slack_message = create_slack_message(log_entry)
send_slack_message(slack_message)
def lambda_handler(event, context):
try:
parse_event(event)
except Exception as e:
print(f"Error parsing event: {e}")
return {
'statusCode': 200,
'body': json.dumps('Notification sent!')
}
# Example test event
if __name__ == "__main__":
test_event = {
'awslogs': {
'data': base64.b64encode(gzip.compress(json.dumps({
'logEvents': [
{
'message': json.dumps({
'eventName': 'CreateUser',
'requestParameters': {
'userName': 'NewTestUser'
},
'userIdentity': {
'userName': 'AdminUser',
}
})
}
]
}).encode())).decode()
}
}
lambda_handler(test_event, None)
Set Environment variable
- Set the WEBHOOK_URL environment variable to the Slack webhook URL you created.
Step 4: Configure CloudWatch Logs Filter Pattern
- Create Metric Filter:
- Go to the CloudWatch Console.
- Select the log group that receives CloudTrail logs.
- Create a new metric filter with the following pattern:
- { ($.eventName = “CreateUser”) || ($.eventName = “AttachUserPolicy”) || ($.eventName = “PutUserPolicy”) }
- Provide a name for the filter and configure it.
Step 5: Add CloudWatch Logs Trigger to Lambda
- Add Trigger:
- Go to the Lambda Console.
- Select your Lambda function.
- In the “Function overview” section, click “Add trigger”.
- Select “CloudWatch Logs” as the trigger type.
- Choose the log group that contains the CloudTrail logs.
- Specify the filter pattern created earlier.
- Click “Add”.
Step 6: Test the Setup
- Generate Test Events:
- Create a new IAM user or attach a policy to an existing user to generate test events.
2. Verify Slack Notifications:
- Check your Slack channel to ensure notifications are being received as expected.
Comments
Post a Comment