AWSTemplateFormatVersion: '2010-09-09'
Description: 'FedRAMP Rev5 RSC Implementation - CloudTrail, Config, Alarms'

Parameters:
  AlertEmail:
    Type: String
    Description: Email address for security alerts
    AllowedPattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'

Resources:
  # FRR-RSC-03: IAM Access Analyzer
  AccessAnalyzer:
    Type: AWS::AccessAnalyzer::Analyzer
    Properties:
      AnalyzerName: FedRAMP-Account-Analyzer
      Type: ACCOUNT
      Tags:
        - Key: Purpose
          Value: FedRAMP-RSC-03
        - Key: Compliance
          Value: FedRAMP-Rev5

  # FRR-RSC-01: CloudTrail for Audit Logging
  CloudTrailBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub 'fedramp-cloudtrail-${AWS::AccountId}-${AWS::Region}'
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      VersioningConfiguration:
        Status: Enabled
      LifecycleConfiguration:
        Rules:
          - Id: DeleteOldLogs
            Status: Enabled
            ExpirationInDays: 2555  # 7 years
            NoncurrentVersionExpirationInDays: 90

  CloudTrailBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref CloudTrailBucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: AWSCloudTrailAclCheck
            Effect: Allow
            Principal:
              Service: cloudtrail.amazonaws.com
            Action: 's3:GetBucketAcl'
            Resource: !GetAtt CloudTrailBucket.Arn
          - Sid: AWSCloudTrailWrite
            Effect: Allow
            Principal:
              Service: cloudtrail.amazonaws.com
            Action: 's3:PutObject'
            Resource: !Sub '${CloudTrailBucket.Arn}/*'
            Condition:
              StringEquals:
                's3:x-amz-acl': 'bucket-owner-full-control'

  CloudTrailLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: /aws/cloudtrail/fedramp
      RetentionInDays: 365

  CloudTrailRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudtrail.amazonaws.com
            Action: 'sts:AssumeRole'
      Policies:
        - PolicyName: CloudTrailLogPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: !GetAtt CloudTrailLogGroup.Arn

  CloudTrail:
    Type: AWS::CloudTrail::Trail
    DependsOn:
      - CloudTrailBucketPolicy
    Properties:
      TrailName: FedRAMP-Audit-Trail
      S3BucketName: !Ref CloudTrailBucket
      IsLogging: true
      IsMultiRegionTrail: true
      IncludeGlobalServiceEvents: true
      EnableLogFileValidation: true
      CloudWatchLogsLogGroupArn: !GetAtt CloudTrailLogGroup.Arn
      CloudWatchLogsRoleArn: !GetAtt CloudTrailRole.Arn
      EventSelectors:
        - ReadWriteType: All
          IncludeManagementEvents: true
      Tags:
        - Key: Purpose
          Value: FedRAMP-RSC-01
        - Key: Compliance
          Value: FedRAMP-Rev5

  # FRR-RSC-01: Root Account Usage Alarm
  RootAccountAlarmTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: FedRAMP-Root-Account-Alerts
      DisplayName: FedRAMP Root Account Usage Alerts
      Subscription:
        - Endpoint: !Ref AlertEmail
          Protocol: email

  RootAccountMetricFilter:
    Type: AWS::Logs::MetricFilter
    Properties:
      FilterPattern: '{ $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" }'
      LogGroupName: !Ref CloudTrailLogGroup
      MetricTransformations:
        - MetricName: RootAccountUsageCount
          MetricNamespace: FedRAMP/Security
          MetricValue: '1'
          DefaultValue: 0

  RootAccountUsageAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: FedRAMP-Root-Account-Usage
      AlarmDescription: Alert when root account is used
      MetricName: RootAccountUsageCount
      Namespace: FedRAMP/Security
      Statistic: Sum
      Period: 300
      EvaluationPeriods: 1
      Threshold: 1
      ComparisonOperator: GreaterThanOrEqualToThreshold
      AlarmActions:
        - !Ref RootAccountAlarmTopic
      TreatMissingData: notBreaching

  # FRR-RSC-05: Config Recorder
  ConfigBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub 'fedramp-config-${AWS::AccountId}-${AWS::Region}'
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  ConfigRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: config.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/ConfigRole'
      Policies:
        - PolicyName: ConfigS3Policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 's3:GetBucketVersioning'
                  - 's3:PutObject'
                  - 's3:GetObject'
                Resource:
                  - !GetAtt ConfigBucket.Arn
                  - !Sub '${ConfigBucket.Arn}/*'

  ConfigRecorder:
    Type: AWS::Config::ConfigurationRecorder
    Properties:
      Name: FedRAMP-Config-Recorder
      RoleArn: !GetAtt ConfigRole.Arn
      RecordingGroup:
        AllSupported: true
        IncludeGlobalResourceTypes: true

  ConfigDeliveryChannel:
    Type: AWS::Config::DeliveryChannel
    Properties:
      Name: FedRAMP-Config-Delivery
      S3BucketName: !Ref ConfigBucket

  # FRR-RSC-05: Config Rules
  RootMFAEnabledRule:
    Type: AWS::Config::ConfigRule
    DependsOn: ConfigRecorder
    Properties:
      ConfigRuleName: root-account-mfa-enabled
      Description: Checks whether MFA is enabled for root account
      Source:
        Owner: AWS
        SourceIdentifier: ROOT_ACCOUNT_MFA_ENABLED

  IAMPasswordPolicyRule:
    Type: AWS::Config::ConfigRule
    DependsOn: ConfigRecorder
    Properties:
      ConfigRuleName: iam-password-policy
      Description: Checks IAM password policy meets requirements
      Source:
        Owner: AWS
        SourceIdentifier: IAM_PASSWORD_POLICY
      InputParameters:
        RequireUppercaseCharacters: true
        RequireLowercaseCharacters: true
        RequireSymbols: true
        RequireNumbers: true
        MinimumPasswordLength: 14
        PasswordReusePrevention: 24
        MaxPasswordAge: 90

  CloudTrailEnabledRule:
    Type: AWS::Config::ConfigRule
    DependsOn: ConfigRecorder
    Properties:
      ConfigRuleName: cloudtrail-enabled
      Description: Checks whether CloudTrail is enabled
      Source:
        Owner: AWS
        SourceIdentifier: CLOUD_TRAIL_ENABLED

  S3BucketPublicReadProhibitedRule:
    Type: AWS::Config::ConfigRule
    DependsOn: ConfigRecorder
    Properties:
      ConfigRuleName: s3-bucket-public-read-prohibited
      Description: Checks that S3 buckets do not allow public read access
      Source:
        Owner: AWS
        SourceIdentifier: S3_BUCKET_PUBLIC_READ_PROHIBITED

Outputs:
  CloudTrailBucket:
    Description: S3 bucket for CloudTrail logs
    Value: !Ref CloudTrailBucket
    Export:
      Name: !Sub '${AWS::StackName}-CloudTrailBucket'

  ConfigBucket:
    Description: S3 bucket for Config snapshots
    Value: !Ref ConfigBucket
    Export:
      Name: !Sub '${AWS::StackName}-ConfigBucket'

  AccessAnalyzer:
    Description: IAM Access Analyzer
    Value: !Ref AccessAnalyzer
    Export:
      Name: !Sub '${AWS::StackName}-AccessAnalyzer'

  RootAccountAlarmTopic:
    Description: SNS topic for root account alerts
    Value: !Ref RootAccountAlarmTopic
    Export:
      Name: !Sub '${AWS::StackName}-RootAlarmTopic'
