AWSTemplateFormatVersion: '2010-09-09'
Description: 'S3 Policy Change Monitoring Solution.This template creates resources to monitor and alert on S3 bucket policy changes.'

Resources:
  # 1. SNS Topic for notifications
  MonitoringTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Sub '${AWS::StackName}-s3-policy-changes'
      KmsMasterKeyId: !Ref SNSTopicKey
      Tags:
        - Key: Purpose
          Value: S3PolicyMonitoring

  # 2. SNS Topic Subscription
  EmailSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      TopicArn: !Ref MonitoringTopic
      Protocol: email
      Endpoint: !Ref EmailAddress

  # 3. KMS Key for SNS Topic encryption
  SNSTopicKey:
    Type: AWS::KMS::Key
    Properties:
      Description: 'KMS key for SNS topic encryption'
      EnableKeyRotation: true
      KeyPolicy:
        Version: '2012-10-17'
        Statement:
          - Sid: 'Allow SNS to use the key'
            Effect: Allow
            Principal:
              Service: 'sns.amazonaws.com'
            Action:
              - 'kms:GenerateDataKey*'
              - 'kms:Decrypt'
            Resource: '*'
          - Sid: 'AllowEventBridge'
            Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action:
              - 'kms:Decrypt'
              - 'kms:GenerateDataKey*'
            Resource: '*'
          - Sid: 'Allow key administration'
            Effect: Allow
            Principal:
              AWS: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:root'
            Action: 'kms:*'
            Resource: '*'

  # 4. EventBridge Rule for real-time monitoring
  S3PolicyChangeRule:
    Type: AWS::Events::Rule
    Properties:
      Name: !Sub 's3-changes-${AWS::AccountId}-${AWS::Region}'
      Description: 'Captures S3 bucket policy changes'
      EventPattern:
        source:
          - aws.s3
        detail-type:
          - 'AWS API Call via CloudTrail'
        detail:
          eventSource:
            - s3.amazonaws.com
          eventName:
            - PutBucketPolicy
            - DeleteBucketPolicy
            - PutBucketAcl
            - PutObjectAcl
      State: ENABLED
      Targets:
        - Arn: !Ref MonitoringTopic
          Id: 'SendToSNS'
          InputTransformer:
            InputPathsMap:
              "bucket": "$.detail.requestParameters.bucketName"
              "action": "$.detail.eventName"
              "key": "$.detail.requestParameters.key"
              "sourceIP": "$.detail.sourceIPAddress"
              "userArn": "$.detail.userIdentity.arn"
              "policy": "$.detail.requestParameters.policy"
              "errorCode": "$.detail.errorCode"
              "errorMessage": "$.detail.errorMessage"
              "eventTime": "$.detail.eventTime"
              "region": "$.detail.awsRegion"
              "requestId": "$.detail.requestID"
              "bucketPolicyStatement": "$.detail.requestParameters.bucketPolicy.Statement"
              "aclGrants": "$.detail.requestParameters.AccessControlPolicy.AccessControlList.Grant"
            InputTemplate: |
              {
                "bucket": <bucket>,
                "action": <action>,
                "key": <key>,
                "sourceIP": <sourceIP>,
                "userArn": <userArn>,
                "eventTime": <eventTime>,
                "error": {
                  "code": <errorCode>,
                  "message": <errorMessage>
                },
                "policyDetails": <policy>,
                "region": <region>,
                "requestId": <requestId>,
                "policyEffect": <bucketPolicyStatement>,
                "aclPermission": <aclGrants>
              }

  # 5. SNS Topic Policy
  TopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      Topics:
        - !Ref MonitoringTopic
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: 'AllowEventBridgePublish'
            Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: sns:Publish
            Resource: !Ref MonitoringTopic

Parameters:
  EmailAddress:
    Type: String
    Description: Email address to receive notifications

Outputs:
  TopicArn:
    Description: 'ARN of the SNS topic'
    Value: !Ref MonitoringTopic

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: "Notification Configuration"
        Parameters:
          - EmailAddress
    ParameterLabels:
      EmailAddress:
        default: "Notification Email Address"