IAM Policy Changes Alarm Should Be Enabled
More Info:
AWS IAM policy configuration changes should be monitored using CloudWatch alarms.
Risk Level
High
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- AWS Well Architected Framework
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS AWS
- CIS Critical Security Controls v8
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- Cloudanix Best Practice
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- HIPAA
- HITRUST CSF
- ISO 27001
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIS2 Directive
- NIST CSF
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- PCI
- SOC2
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Using Console
-
Configure CloudTrail to Deliver Logs to CloudWatch Logs:
- Go to the AWS Management Console.
- Open the CloudTrail service.
- Select your trail.
- Click on "Edit".
- In the "CloudWatch Logs" section, select an existing log group or create a new one.
- Click "Save changes".
-
Create Metric Filter and Alarm:
- Go to the CloudWatch service in the AWS Management Console.
- In the left-hand navigation pane, choose "Logs" and then select the log group you configured in CloudTrail.
- Click on "Create metric filter".
- Define a filter pattern that matches IAM policy changes. For example, you might use a pattern like
{ $.eventSource = "iam.amazonaws.com" && $.eventName = "AttachRolePolicy" }. - Click "Assign metric".
- Give your metric a name like
IAMPolicyChangesEventCountorIAMPolicyEventCount. - Click "Create filter".
- Once your filter is created, you can set up an alarm based on this metric.
Using CLI
-
Create Metric Filter:
aws logs put-metric-filter \--log-group-name "YOUR_LOG_GROUP_NAME" \--filter-name "IAMPolicyChangesFilter" \--filter-pattern '{ $.eventSource = "iam.amazonaws.com" && $.eventName = "AttachRolePolicy" }' \--metric-transformations "metricName=IAMPolicyChangesEventCount,metricNamespace=CloudTrailMetrics,metricValue=1"or
aws logs put-metric-filter \--log-group-name "YOUR_LOG_GROUP_NAME" \--filter-name "IAMPolicyChangesFilter" \--filter-pattern '{ $.eventSource = "iam.amazonaws.com" && $.eventName = "AttachRolePolicy" }' \--metric-transformations "metricName=IAMPolicyEventCount,metricNamespace=CloudTrailMetrics,metricValue=1"Replace
"YOUR_LOG_GROUP_NAME"with the name of your CloudTrail log group. -
Create CloudWatch Alarm (optional): Use the
put-metric-alarmcommand to create an alarm based on the metric you created.
Using Python
Set an alarm for "IAMPolicyChangesEventCount" Metric
import boto3
cloudwatch_logs = boto3.client('logs')
cloudwatch = boto3.client('cloudwatch')
# Create Metric Filter
response = cloudwatch_logs.put_metric_filter(
logGroupName='YOUR_LOG_GROUP_NAME',
filterName='IAMPolicyChangesFilter',
filterPattern='{ $.eventSource = "iam.amazonaws.com" && $.eventName = "AttachRolePolicy" }',
metricTransformations=[
{
'metricName': 'IAMPolicyChangesEventCount',
'metricNamespace': 'CloudTrailMetrics',
'metricValue': 1
}
]
)
# Create CloudWatch Alarm (optional)
# You can use cloudwatch.put_metric_alarm() to create an alarm based on the metric
Or set an alarm for "IAMPolicyEventCount" Metric
import boto3
cloudwatch_logs = boto3.client('logs')
cloudwatch = boto3.client('cloudwatch')
# Create Metric Filter
response = cloudwatch_logs.put_metric_filter(
logGroupName='YOUR_LOG_GROUP_NAME',
filterName='IAMPolicyChangesFilter',
filterPattern='{ $.eventSource = "iam.amazonaws.com" && $.eventName = "AttachRolePolicy" }',
metricTransformations=[
{
'metricName': 'IAMPolicyEventCount',
'metricNamespace': 'CloudTrailMetrics',
'metricValue': 1
}
]
)
# Create CloudWatch Alarm (optional)
# You can use cloudwatch.put_metric_alarm() to create an alarm based on the metric
Replace "YOUR_LOG_GROUP_NAME" with the name of your CloudTrail log group.
These steps should help you set up the IAMPolicyChangesEventCount or IAMPolicyEventCount metric in CloudWatch using the AWS Console, AWS CLI, or Python script. Remember to adjust the configuration according to your specific use case and environment.
Using Terraform
# SNS topic for IAM policy change notifications
resource "aws_sns_topic" "iam_policy_changes_notifications" {
name = "iam-policy-changes-notifications"
}
# Subscription for email notifications
resource "aws_sns_topic_subscription" "iam_policy_changes_email" {
topic_arn = aws_sns_topic.iam_policy_changes_notifications.arn
protocol = "email"
# Replace with the email address that should receive alerts
endpoint = "IAM_POLICY_CHANGES_ALERT_EMAIL@example.com"
}
# Metric filter on the CloudTrail log group to count IAM policy change events
resource "aws_cloudwatch_log_metric_filter" "iam_policy_changes" {
name = "IAMPolicyChanges"
log_group_name = "CLOUDTRAIL_LOG_GROUP_NAME" # Replace with your CloudTrail CloudWatch Logs log group name
pattern = "{($.eventName=DeleteGroupPolicy)||($.eventName=DeleteRolePolicy)||($.eventName=DeleteUserPolicy)||($.eventName=PutGroupPolicy)||($.eventName=PutRolePolicy)||($.eventName=PutUserPolicy)||($.eventName=CreatePolicy)||($.eventName=DeletePolicy)||($.eventName=CreatePolicyVersion)||($.eventName=DeletePolicyVersion)||($.eventName=AttachRolePolicy)||($.eventName=DetachRolePolicy)||($.eventName=AttachUserPolicy)||($.eventName=DetachUserPolicy)||($.eventName=AttachGroupPolicy)||($.eventName=DetachGroupPolicy)}"
metric_transformation {
name = "IAMPolicyEventCount"
namespace = "CloudTrailMetrics"
value = "1"
}
}
# CloudWatch alarm for IAM policy changes
resource "aws_cloudwatch_metric_alarm" "iam_policy_changes" {
alarm_name = "IAMPolicyChangesAlarm"
alarm_description = "Alarm for IAM policy changes"
namespace = "CloudTrailMetrics"
metric_name = "IAMPolicyEventCount"
statistic = "Sum"
period = 300
threshold = 1
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
alarm_actions = [
aws_sns_topic.iam_policy_changes_notifications.arn,
]
actions_enabled = true
depends_on = [
aws_cloudwatch_log_metric_filter.iam_policy_changes,
]
}
Substitute:
CLOUDTRAIL_LOG_GROUP_NAMEwith your CloudTrail log group name (fromCloudWatchLogsLogGroupArn).IAM_POLICY_CHANGES_ALERT_EMAIL@example.comwith the destination email; the recipient must confirm the SNS subscription from the email they receive.
This creates new monitoring resources (SNS topic, subscription, metric filter, and alarm) and does not force replacement of existing ones.
To verify, terraform plan should show these resources with + create and no ~ update or - destroy for existing CloudWatch alarms.