AWSTemplateFormatVersion: '2010-09-09'
Description: Creates resources for Mashery Enriched Call Log Export delivery
Parameters:
  IAMRoleExternalId:
    Description: Value of ExternalId for Role Assumption
    Type: String
    Default: changeme
  CreateBucket:
    Description: Create a new Bucket for Mashery ECLE. If supplying your own bucket in BucketArn set this value to False.
    Type: String
    Default: true
    AllowedValues:
      - true
      - false
  BucketNamePrefix:
    Description: Prefix of the bucket to create. Default is mashery-ecle with account and region suffix (e.g mashery-ecle-0123456789-us-east-1)
    Type: String
    Default: mashery-ecle
  ExistingBucketName:
    Description: If using pre-existing bucket, provide the name for it. CreateBucket must be set to false.
    Type: String
  KMSKeyAdministrators:
    Description: Comma delimited List of principals which will be Key Administrators of the CMK. This must include the user/role creating the stack.
    Type: String
  KMSDecryptPrincipals:
    Description: Comma delimited List of principals to be granted ability to Decrypt with CMK
    Type: String
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
    - Label:
        default: S3 Bucket Configuration
      Parameters:
        - CreateBucket
        - BucketNamePrefix
        - ExistingBucketName
      ParameterLabels:
        CreateBucket:
            default: Whether to Create the S3 Bucket
        BucketNamePrefix:
            default: Name of an existing S3 Bucket
        ExistingBucketName:
            default: If using pre-existing bucket, provide the name for it. CreateBucket must be set to false.
    - Label:
        default: IAM Configuration
      Parameters:
        - IAMRoleExternalId
      ParameterLabels:
        IAMRoleExternalId:
          default: ExternalId for IAM Role
    - Label:
        default: KMS Configuration
      Parameters:
        - KMSKeyAdministrators
        - KMSDecryptPrincipals
      ParameterLabels:
        KMSKeyAdministrators:
          default: List of principals which will be Key Administrators of the CMK
        KMSDecryptPrincipals:
          default: List of principals to be granted ability to Decrypt with CMK
Conditions:
  CreateBucketTrue: !Equals [ !Ref CreateBucket, true ]
Resources:
  ECLEIAMRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "mashery-ecle-writer-${AWS::Region}"
      Description: Mashery ECLE Writer
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - "arn:aws:iam::809167139867:role/spark_ecle"
                - "arn:aws:iam::809167139867:role/platform_api_worker"
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                sts:ExternalId: !Ref IAMRoleExternalId
  ECLEIAMPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: !Sub "mashery-ecle-writer-${AWS::Region}"
      Roles:
        - !Ref ECLEIAMRole
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: AllowRoleKMS
            Effect: Allow
            Action:
              - kms:Encrypt
              - kms:Decrypt
              - kms:GenerateDataKey*
            Resource: !GetAtt ECLECMK.Arn
          - Sid: DeleteS3
            Effect: Allow
            Action:
              - s3:DeleteObject
            Resource: !If [CreateBucketTrue, !Sub "${S3Bucket.Arn}/validate/*", !Sub "arn:aws:s3:::${ExistingBucketName}/validate/*"]
          - Sid: PutS3
            Effect: Allow
            Action:
              - s3:PutObject
              - s3:PutObjectAcl
              - s3:GetObject
              - s3:DeleteObject
              - s3:ListMultipartUploadParts
              - s3:AbortMultipartUpload
            Resource: !If [CreateBucketTrue, !Sub "${S3Bucket.Arn}/*", !Sub "arn:aws:s3:::${ExistingBucketName}/*"]
          - Sid: BucketResourceActions
            Effect: Allow
            Action:
              - s3:ListBucket
              - s3:GetBucketLocation
              - s3:ListBucketMultipartUploads
            Resource: !If [CreateBucketTrue, !Sub "${S3Bucket.Arn}", !Sub "arn:aws:s3:::${ExistingBucketName}"]
  ECLECMK:
    Type: AWS::KMS::Key
    DependsOn: ECLEIAMRole
    Properties:
      Description: "Mashery ECLE Writer Key"
      Enabled: True
      EnableKeyRotation: True
      KeyPolicy:
        Version: '2012-10-17'
        Id: key-policy
        Statement:
          - Sid: Allow administration of the key
            Effect: Allow
            Principal:
              AWS: !Split [ "," ,!Ref KMSKeyAdministrators]
            Action: kms:*
            Resource: '*'
          - Sid: Allow attachment of persistent resources
            Effect: Allow
            Principal:
              AWS: !GetAtt ECLEIAMRole.Arn
            Resource: '*'
            Action:
              - kms:Encrypt
              - kms:GenerateDataKey*
              - kms:Decrypt
            Condition:
              StringEquals:
                "kms:ViaService": !Sub "s3.${AWS::Region}.amazonaws.com"
          - Sid: Allow decrypt access to specific principals
            Effect: Allow
            Principal:
              AWS: !Split [ "," , !Ref KMSDecryptPrincipals]
            Action:
              - kms:Decrypt
            Resource: '*'
            Condition:
              StringEquals:
                "kms:ViaService": !Sub "s3.${AWS::Region}.amazonaws.com"
  ECLECMKAlias:
    Type: AWS::KMS::Alias
    DependsOn: ECLECMK
    Properties:
      AliasName: alias/mashery_ecle_writer
      TargetKeyId: !Ref ECLECMK
  S3Bucket:
    Type: AWS::S3::Bucket
    Condition: CreateBucketTrue
    DependsOn: ECLECMK
    Properties:
      BucketName: !Sub "${BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}"
      AccessControl: 'Private'
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: aws:kms
              KMSMasterKeyID: !Ref ECLECMK
  S3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Statement:
          -
            Sid: "DenyIncorrectEncryptionHeader"
            Action:
              - "s3:PutObject"
            Effect: "Deny"
            Resource: !Sub "arn:aws:s3:::${BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}/*"
            Principal: "*"
            Condition:
              StringNotEquals:
                s3:x-amz-server-side-encryption: "aws:kms"
          -
            Sid: "DenyUnEncryptedObjectUploads"
            Action:
              - "s3:PutObject"
            Effect: "Deny"
            Resource: !Sub "arn:aws:s3:::${BucketNamePrefix}-${AWS::AccountId}-${AWS::Region}/*"
            Principal: "*"
            Condition:
              "Null":
                s3:x-amz-server-side-encryption: "true"
Outputs:
  S3BucketName:
    Description: S3 Bucket Name
    Value: !If [CreateBucketTrue, !Ref S3Bucket, !Ref ExistingBucketName]
  CMKArn:
    Description: CMK Arn
    Value: !GetAtt ECLECMK.Arn
  IAMRoleArn:
    Description: IAM Role Arn
    Value: !GetAtt ECLEIAMRole.Arn
  ExternalId:
    Description: ExternalId for Role Assumption
    Value: !Ref IAMRoleExternalId