AWSTemplateFormatVersion: 2010-09-09
Description: Create Prowler S3 Bucket for Prowler Reports

Parameters:
  AwsOrgId:
    Type: String
    Description: >
      Enter AWS Organizations ID.
      This is used to restrict permissions to least privilege.
    AllowedPattern: ^o-[a-z0-9]{10,32}$
    ConstraintDescription: The Org Id must be a 12 character string starting with o- and followed by 10 lower case alphanumeric characters.
    Default: o-abcde12345
  S3Prefix:
    Type: String
    Description: >
      Enter S3 Bucket Name Prefix (in lowercase).
      Bucket will be named: prefix-awsaccount-awsregion (i.e., prowler-123456789012-us-east-1)
    AllowedPattern: ^[a-z0-9][a-z0-9-]{1,33}[a-z0-9]$
    ConstraintDescription: >
      Max 35 characters, as "-awsaccount-awsregion" will be added, and max name is 63 characters.
      Can't start or end with dash.  Can use numbers and lowercase letters.
    Default: prowler

Resources:
  ProwlerS3:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${S3Prefix}-${AWS::AccountId}-${AWS::Region}
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: "AES256"
      AccessControl: Private
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      VersioningConfiguration:
        Status: Enabled
      Tags:
        - Key: App
          Value: Prowler
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W35
            reason: "This S3 Bucket is only being used by the AWS Organization to download/upload prowler reports."

  ProwlerS3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref ProwlerS3
      PolicyDocument:
        Statement:
          - Sid: AllowGetPutListObject
            Effect: Allow
            Principal: "*"
            Action:
              - s3:GetObject
              - s3:PutObject
              - s3:ListBucket
              - s3:PutObjectAcl
            Resource:
              - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3}
              - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3}/*
            Condition:
              StringEquals:
                aws:PrincipalOrgId: !Ref AwsOrgId
          - Sid: DenyNonSSLRequests
            Effect: Deny
            Action: s3:*
            Resource:
              - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3}
              - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3}/*
            Principal: "*"
            Condition:
              Bool:
                aws:SecureTransport: false
          - Sid: DenyIncorrectEncryptionHeader
            Effect: Deny
            Principal: "*"
            Action: s3:PutObject
            Resource:
              - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3}/*
            # Allow uploads with No Encryption, as S3 Default Encryption still applies.
            # If Encryption is set, only allow uploads with AES256.
            Condition:
              "Null":
                s3:x-amz-server-side-encryption: false
              StringNotEquals:
                s3:x-amz-server-side-encryption: AES256
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: F16
            reason: "This S3 Bucket Policy has a condition that only allows access to the AWS Organization."


Outputs:
  ProwlerS3:
    Description: S3 Bucket for Prowler Reports
    Value: !Ref ProwlerS3
  ProwlerS3Account:
    Description: AWS Account Number where Prowler S3 Bucket resides.
    Value: !Ref AWS::AccountId
