Check ID: cloudwatch_log_metric_filter_for_s3_bucket_policy_changes
Provider: AWS
Service: cloudwatch
Severity: MEDIUM
Categories: logging
Resource type: AwsCloudWatchAlarm

What this check verifies

CloudTrail logs are assessed for a CloudWatch metric filter matching S3 bucket configuration changes (ACL, policy, CORS, lifecycle, replication; e.g., PutBucketPolicy, DeleteBucketPolicy) and for an associated CloudWatch alarm.

Risk

Without alerting on S3 policy and ACL changes, unauthorized modifications can go unnoticed, weakening confidentiality and integrity. Misuse could expose buckets publicly, grant write/delete access, or alter replication paths, enabling data exfiltration and destructive actions.

Recommendation

Establish and maintain metric filters and alarms for S3 bucket policy, ACL, CORS, lifecycle, and replication changes. Route alerts to monitored channels and integrate with SIEM. Enforce least privilege, require change reviews, and use defense in depth to prevent and quickly detect unsafe bucket policy changes.

Remediation

# CloudWatch metric filter for S3 bucket policy changes
resource "aws_cloudwatch_log_metric_filter" "<example_resource_name>" {
  name           = "<example_resource_name>"
  log_group_name = "<example_resource_name>"
  # Critical: detects S3 bucket policy changes from CloudTrail logs
  pattern = "{($.eventSource=s3.amazonaws.com) && (($.eventName=PutBucketAcl) || ($.eventName=PutBucketPolicy) || ($.eventName=PutBucketCors) || ($.eventName=PutBucketLifecycle) || ($.eventName=PutBucketReplication) || ($.eventName=DeleteBucketPolicy) || ($.eventName=DeleteBucketCors) || ($.eventName=DeleteBucketLifecycle) || ($.eventName=DeleteBucketReplication))}"

  metric_transformation {
    name      = "<example_resource_name>"
    namespace = "<example_resource_name>"
    value     = "1"
  }
}

# Alarm on the metric filter
resource "aws_cloudwatch_metric_alarm" "<example_resource_name>" {
  alarm_name          = "<example_resource_name>"
  metric_name         = "<example_resource_name>"  # Critical: matches metric filter
  namespace           = "<example_resource_name>"  # Critical: matches metric filter
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = 1
  period              = 300
  statistic           = "Sum"
  threshold           = 1
}

References

Where this check fires

This check runs on every scheduled scan against your AWS account. Findings appear at Cloud Security → Findings filterable by Check ID = cloudwatch_log_metric_filter_for_s3_bucket_policy_changes. To re-evaluate after a fix, hit Run now on the account’s schedule under Cloud Security → Schedules — the next scan re-checks this control and marks the finding fixed or keeps it persistent.
← Back to AWS checks