
service: 'tcf-test-ctl'

provider:
  name: aws
  runtime: python3.7
  profile: 'tcf-test'
  stackName: 'tcf-test-ctl'
  region: 'af-south-1'
  stage: ${self:provider.profile}
  deploymentBucket:
    name: ${self:custom.ServerlessBucketName}
    serverSideEncryption: AES256
    blockPublicAccess: true

plugins:
  - serverless-deployment-bucket
  - serverless-parameters

custom:
  CustomerName: tcf
  StageName: test
  # Combination of profile and function name used as bucket name:
  ResourceName: serverless-framework # Only lowercase letters and numbers allowed. Used to populate bucket name.
  ServerlessBucketName: '${self:custom.ResourceName}-${self:provider.stage}-${self:provider.region}'
  FlowLogBucketName: '${self:custom.ResourceName}-${self:provider.stage}-${self:provider.region}-flowlog'

  # CloudFormation parameters templates

resources:

  # CloudFormation resource templates

  Resources:

    # Create KMS CloudTrail encryption key
    cloudtrailKey:
      Type: AWS::KMS::Key
      Properties:
        KeyPolicy:
          Version: '2012-10-17'
          Id: key-cloudtrail
          Statement:
            - Sid: 'Enable IAM User Permissions'
              Effect: 'Allow'
              Principal:
                AWS: !Join
                  - ''
                  - - 'arn:aws:iam::'
                    - !Ref 'AWS::AccountId'
                    - ':root'
              Action: 'kms:*'
              Resource: '*'
            - Sid: 'Allow CloudTrail to encrypt logs'
              Effect: 'Allow'
              Principal:
                Service:
                  - 'cloudtrail.amazonaws.com'
              Action: 'kms:GenerateDataKey*'
              Resource: '*'
              Condition:
                StringLike:
                  'kms:EncryptionContext:aws:cloudtrail:arn': !Sub 'arn:aws:cloudtrail:*:${AWS::AccountId}:trail/*'
            - Sid: 'Allow CloudTrail to describe key'
              Effect: 'Allow'
              Principal:
                Service:
                  - 'cloudtrail.amazonaws.com'
              Action: 'kms:DescribeKey'
              Resource: '*'
            - Sid: 'Allow principals in the account to decrypt log files'
              Effect: 'Allow'
              Principal:
                AWS: '*'
              Action:
                - 'kms:Decrypt'
                - 'kms:ReEncryptFrom'
              Resource: '*'
              Condition:
                StringEquals:
                  'kms:CallerAccount': !Sub '${AWS::AccountId}'
                StringLike:
                  'kms:EncryptionContext:aws:cloudtrail:arn': !Sub 'arn:aws:cloudtrail:*:${AWS::AccountId}:trail/*'
            - Sid: 'Allow alias creation during setup'
              Effect: 'Allow'
              Principal:
                AWS: '*'
              Action: 'kms:CreateAlias'
              Resource: '*'
              Condition:
                StringEquals:
                  'kms:ViaService': 'ec2.region.amazonaws.com'
                  'kms:CallerAccount': !Sub '${AWS::AccountId}'
            - Sid: 'Enable cross account log decryption'
              Effect: 'Allow'
              Principal:
                AWS: '*'
              Action:
                - 'kms:Decrypt'
                - 'kms:ReEncryptFrom'
              Resource: '*'
              Condition:
                StringEquals:
                  'kms:CallerAccount': !Sub '${AWS::AccountId}'
                StringLike:
                  'kms:EncryptionContext:aws:cloudtrail:arn': !Sub 'arn:aws:cloudtrail:*:${AWS::AccountId}:trail/*'
        Tags:
          - Key: Name
            Value: !Join
              - '-'
              - - '${self:custom.CustomerName}'
                - '${self:custom.StageName}'
                - 'cloudtrail'
                - 'key'

    cloudtrailKeyAlias:
      Type: AWS::KMS::Alias
      Properties:
        AliasName: alias/cloudtrail
        TargetKeyId:
          Ref: cloudtrailKey

    # Create KMS CloudTrail S3 bucket encryption key
    s3cloudtrailKey:
      Type: AWS::KMS::Key
      Properties:
        KeyPolicy:
          Version: '2012-10-17'
          Id: key-cloudtrails3
          Statement:
            - Sid: 'Enable IAM User Permissions'
              Effect: 'Allow'
              Principal:
                AWS: !Join
                  - ''
                  - - 'arn:aws:iam::'
                    - !Ref 'AWS::AccountId'
                    - ':root'
              Action: 'kms:*'
              Resource: '*'
            - Sid: 'Allow VPC Flow Logs to use the key'
              Effect: 'Allow'
              Principal:
                Service:
                  - 'delivery.logs.amazonaws.com'
              Action: 'kms:GenerateDataKey*'
              Resource: '*'
        Tags:
          - Key: Name
            Value: !Join
              - '-'
              - - '${self:custom.CustomerName}'
                - '${self:custom.StageName}'
                - 's3cloudtrail'
                - 'key'

    s3cloudtrailKeyAlias:
      Type: AWS::KMS::Alias
      Properties:
        AliasName: alias/cloudtrails3
        TargetKeyId:
          Ref: s3cloudtrailKey

    # Create CloudTrail encrypted S3 bucket for storage
    CloudTrailS3Bucket:
      DependsOn:
        - s3cloudtrailKey
        - s3cloudtrailKeyAlias
      Type: AWS::S3::Bucket
      DeletionPolicy: Retain
      Properties:
        BucketEncryption:
          ServerSideEncryptionConfiguration:
            - ServerSideEncryptionByDefault:
                KMSMasterKeyID: !Sub 'arn:aws:kms:${AWS::Region}:${AWS::AccountId}:${s3cloudtrailKeyAlias}'
                SSEAlgorithm: 'aws:kms'
        Tags:
          - Key: Name
            Value: !Join
              - '-'
              - - '${self:custom.CustomerName}'
                - '${self:custom.StageName}'
                - 'bucket'
                - 'CloudTrailS3'

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

    # Enable CloudTrail
    MyCloudTrail:
      DependsOn:
        - CloudTrailS3Bucket
        - CloudTrailBucketPolicy
        - cloudtrailKey
      Type: AWS::CloudTrail::Trail
      Properties:
        S3BucketName: !Ref CloudTrailS3Bucket
        IsLogging: true
        KMSKeyId: !GetAtt cloudtrailKey.Arn
        Tags:
          - Key: Name
            Value: !Join
              - '-'
              - - '${self:custom.CustomerName}'
                - '${self:custom.StageName}'
                - 'cloudtrail'
                - 'trail'
