
service: 'tcf-prod-ec2'

provider:
  name: aws
  runtime: python3.7
  profile: 'tcf-prod'
  stackName: 'tcf-prod-ec2'
  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: prod
  # 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}'

  # CloudFormation parameters templates
  parameters:
    paramCustomerName:
      Description: Enter the Customer Name, used to tag everything
      Type: String
      Default: '${self:custom.CustomerName}'

    ## EC2
    InstanceType:
      Description: WebServer EC2 instance type
      Type: String
      Default: t3.micro
      AllowedValues:
        - t3.micro
      ConstraintDescription: must be a valid EC2 instance type.

    KeyName:
      Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
      Type: 'AWS::EC2::KeyPair::KeyName'
      ConstraintDescription: must be the name of an existing EC2 KeyPair.
      Default: tcf-prod-ec2-key-01

    AmazonImageID:
      Description: The ID of the Amazon machine image (AMI) - Windows Server 2019
      Type: String
      Default: ami-0799fd71a56e64aa8

resources:

  # CloudFormation resource templates

  #Conditions:

  Resources:

  ## EC2

    # Create a managed policy for S3 access

    # S3AccessPolicy:
    #   Type: AWS::IAM::ManagedPolicy
    #   Properties:
    #     Description: Policy for S3 access
    #     Path: /
    #     PolicyDocument:
    #       Version: "2012-10-17"
    #       Statement:
    #         - Effect: Allow
    #           Action: 's3:ListAllMyBuckets'
    #           Resource: '*'
    #         - Effect: Allow
    #           Action: 's3:ListBucket'
    #           Resource: 'arn:aws:s3:::*'
    #         - Effect: Allow
    #           Action: 's3:GetObject'
    #           Resource: 'arn:aws:s3:::*/*'
    #         - Effect: Allow
    #           Action: 's3:PutObject'
    #           Resource: 'arn:aws:s3:::*/*'


    # Create role for EC2 instance and attach policies

    EC2AccessRole:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal:
                Service:
                  - "ec2.amazonaws.com"
              Action:
                - "sts:AssumeRole"
        Path: "/"
        Policies:
          - PolicyName: root
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - "ec2:CreateTags"
                    - "ec2:DescribeVolumes"
                  Resource: '*'
        ManagedPolicyArns:
          # - !Ref S3AccessPolicy
          - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        Tags:
          - Key: Name
            Value: !Join
              - '-'
              - - '${self:custom.CustomerName}'
                - '${self:custom.StageName}'
                - 'iam'
                - 'role'
                - 'EC2Access'

    # Create EC2 Instance Profile and attach the role

    EC2InstanceProfile:
      Type: AWS::IAM::InstanceProfile
      Properties:
        InstanceProfileName: '${self:custom.ResourceName}-${self:provider.stage}-ec2-instance-profile'
        Path: /
        Roles:
          - !Ref EC2AccessRole

    # Create Security Group for the EC2

    EC2SecurityGroup:
      Type: 'AWS::EC2::SecurityGroup'
      Properties:
        GroupDescription: Enable SSH access (default)
        # SecurityGroupIngress:
        #   - IpProtocol: tcp
        #     FromPort: 22
        #     ToPort: 22
        #     CidrIp: 0.0.0.0/0
#            SourceSecurityGroupId:
        VpcId:
          Fn::ImportValue: !Sub '${self:custom.CustomerName}-${self:custom.StageName}-VPC'
        Tags:
          - Key: Name
            Value: !Join
              - '-'
              - - '${self:custom.CustomerName}'
                - '${self:custom.StageName}'
                - 'EC2'
                - 'SecurityGroup'

    # Create KMS EC2 encryption key

    ec2Key:
      Type: AWS::KMS::Key
      Properties:
        EnableKeyRotation: true
        KeyPolicy:
          Version: '2012-10-17'
          Id: key-ec2
          Statement:
            - Sid: 'Enable IAM User Permissions'
              Effect: 'Allow'
              Principal:
                AWS: !Join
                  - ''
                  - - 'arn:aws:iam::'
                    - !Ref 'AWS::AccountId'
                    - ':root'
              Action: 'kms:*'
              Resource: '*'
        Tags:
          - Key: Name
            Value: !Join
              - '-'
              - - '${self:custom.CustomerName}'
                - '${self:custom.StageName}'
                - 'KMS-Key'
                - 'ec2'

    # KMS RDS encryption key alias

    ec2Alias:
      Type: AWS::KMS::Alias
      Properties:
        AliasName: alias/ec2
        TargetKeyId:
          Ref: ec2Key

    # Create EC2 instance

    EC2Instance1:
      Type: AWS::EC2::Instance
      Properties:
        InstanceType: !Ref InstanceType
        SubnetId:
          Fn::ImportValue: !Sub '${self:custom.CustomerName}-${self:custom.StageName}-PrivateSubnetA1'
        SecurityGroupIds:
          - !Ref EC2SecurityGroup
        IamInstanceProfile: !Ref EC2InstanceProfile
        KeyName: !Ref KeyName
        ImageId: !Ref AmazonImageID
        Monitoring: 'true'
        DisableApiTermination: 'true'
        PropagateTagsToVolumeOnCreation: 'true'
        "BlockDeviceMappings": [
          {
            "DeviceName": "/dev/sda1",
            "Ebs": {
              "VolumeType": "gp3",
              "VolumeSize": "30",
              "Iops": "3000",
              "DeleteOnTermination": "true",
              "Encrypted": "true",
              "KmsKeyId": !Ref ec2Key
            }
          }
        ]
        Tags:
          - Key: Name
            Value: !Join
              - '-'
              - - '${self:custom.CustomerName}'
                - '${self:custom.StageName}'
                - 'EC2Instance'
                - '1'
          - Key: backup
            Value: daily

    # Assign an EIP to EC2

    MyEIP:
      Type: AWS::EC2::EIP
      Properties:
        InstanceId: !Ref EC2Instance1
        Tags:
          - Key: 'Name'
            Value: !Join
              - '-'
              - - '${self:custom.CustomerName}'
                - '${self:custom.StageName}'
                - 'eip'
                - 'EC2Instance'

  ## Outputs

  Outputs:
    exportEc2InstanceId:
      Description: '${self:custom.CustomerName}-${self:custom.StageName} - Ec2 Instance Id'
      Export:
        Name: '${self:custom.CustomerName}-${self:custom.StageName}-Ec2InstanceId'
      Value: !Ref EC2Instance1

#-----------------------------------------------------------------------#
