---
AWSTemplateFormatVersion: 2010-09-09

Description: Aqua Workshop Module 1 - DevSecOps


Parameters:

  EksClusterName:
    Type: String
    Description: The name of the EKS cluster created
    Default: aqua
    MinLength: 1
    MaxLength: 100
    ConstraintDescription: You must enter the EKS cluster name

  # TODO: Update this to final repo name
  GitSourceRepo:
    Type: String
    Description: GitHub source repository - must contain a Dockerfile and buildspec.yml in the base
    Default: amazon-eks-devsecops
    MinLength: 1
    MaxLength: 100
    ConstraintDescription: You must enter a GitHub repository name

  GitBranch:
    Type: String
    Default: master
    Description: GitHub git repository branch - change triggers a new build
    MinLength: 1
    MaxLength: 100
    ConstraintDescription: You must enter a GitHub repository branch name

  GitHubToken:
    Type: String
    NoEcho: true
    Description: GitHub API token - see https://github.com/blog/1509-personal-api-tokens
    MinLength: 3
    MaxLength: 100
    ConstraintDescription: You must enter a GitHub personal access token

  GitHubUser:
    Type: String
    Description: GitHub username or organization
    MinLength: 3
    MaxLength: 100
    ConstraintDescription: You must enter a GitHub username or organization

  CodeBuildDockerImage:
    Type: String
    Default: aws/codebuild/standard:4.0
    Description: Default AWS CodeBuild Docker optimized image
    MinLength: 3
    MaxLength: 100
    ConstraintDescription: You must enter a CodeBuild Docker image

  KubectlRoleName:
    Type: String
    Default: AquaWorkshopCodeBuildKubectlRole
    Description: IAM role used by kubectl to interact with EKS cluster
    MinLength: 3
    MaxLength: 100
    ConstraintDescription: You must enter a kubectl IAM role

  AquaURL:
    Type: String
    Description: URL for the Aqua Web console
    MinLength: 3
    MaxLength: 100
    ConstraintDescription: You must enter a the Aqua console URL

  AquaConsolePassword:
    NoEcho: 'true'
    Description: >-
      Enter the password for the Aqua Console. 
    Type: String
    MinLength: '8'
    MaxLength: '128'


Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: GitHub
        Parameters:
          - GitHubUser
          - GitHubToken
          - GitSourceRepo
          - GitBranch
      - Label:
          default: CodeBuild
        Parameters:
          - CodeBuildDockerImage
      - Label:
          default: IAM
        Parameters:
          - KubectlRoleName
      - Label:
          default: EKS
        Parameters:
          - EksClusterName
      - Label:
          default: Aqua
        Parameters:
          - AquaURL
          - AquaConsolePassword
    ParameterLabels:
      GitHubUser:
        default: Username
      GitHubToken:
        default: Access token
      GitSourceRepo:
        default: Repository
      GitBranch:
        default: Branch
      CodeBuildDockerImage:
        default: Docker image
      KubectlRoleName:
        default: kubectl IAM role
      EksClusterName:
        default: EKS cluster name
      AquaURL:
        default: Aqua Console URL
      AquaConsolePassword:
        default: Aqua Console password


Resources:

  AquaConsoleSecret:
    Type: AWS::SecretsManager::Secret
    Properties: 
      Description: Aqua Console password
      Name: !Join 
        - '/'
        - - !Ref EksClusterName
          - aquaconsole-password
      SecretString: 
        !Ref AquaConsolePassword

  EcrDockerRepository:
    Type: AWS::ECR::Repository
    DeletionPolicy: Retain

  CodePipelineArtifactBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain

  CodePipelineServiceRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: codepipeline.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: codepipeline-access
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Resource: "*"
                Effect: Allow
                Action:
                  - codebuild:StartBuild
                  - codebuild:BatchGetBuilds
                  - codecommit:GetBranch
                  - codecommit:GetCommit
                  - codecommit:UploadArchive
                  - codecommit:GetUploadArchiveStatus
                  - codecommit:CancelUploadArchive
                  - iam:PassRole
              - Resource: !Sub arn:aws:s3:::${CodePipelineArtifactBucket}/*
                Effect: Allow
                Action:
                  - s3:PutObject
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:GetBucketVersioning
    DependsOn: CodePipelineArtifactBucket

  CodeBuildServiceRole:
    Type: AWS::IAM::Role
    Properties:
      Path: /
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Resource: !Sub arn:aws:iam::${AWS::AccountId}:role/${KubectlRoleName}
                Effect: Allow
                Action:
                  - sts:AssumeRole
              - Resource: '*'
                Effect: Allow
                Action:
                  - eks:Describe*
              - Resource: '*'
                Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
              - Resource: '*'
                Effect: Allow
                Action:
                  - ecr:GetAuthorizationToken
              - Resource: '*'
                Effect: Allow
                Action:
                  - ec2:CreateNetworkInterface
                  - ec2:DescribeDhcpOptions
                  - ec2:DescribeNetworkInterfaces
                  - ec2:DeleteNetworkInterface
                  - ec2:DescribeSubnets
                  - ec2:DescribeSecurityGroups
                  - ec2:DescribeVpcs
                  - ec2:CreateNetworkInterfacePermission
              - Resource: !Sub arn:aws:s3:::${CodePipelineArtifactBucket}/*
                Effect: Allow
                Action:
                  - s3:GetObject
                  - s3:PutObject
                  - s3:GetObjectVersion
              - Resource: !Sub arn:aws:ecr:${AWS::Region}:${AWS::AccountId}:repository/${EcrDockerRepository}
                Effect: Allow
                Action:
                  - ecr:GetDownloadUrlForLayer
                  - ecr:BatchGetImage
                  - ecr:BatchCheckLayerAvailability
                  - ecr:PutImage
                  - ecr:InitiateLayerUpload
                  - ecr:UploadLayerPart
                  - ecr:CompleteLayerUpload
              - Resource: !Ref AquaConsoleSecret
                Effect: Allow
                Action:
                  - "secretsmanager:GetSecretValue"

  CodeBuildProject:
    Type: AWS::CodeBuild::Project
    Properties:
      Artifacts:
        Type: CODEPIPELINE
      Source:
        Type: CODEPIPELINE
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        Type: LINUX_CONTAINER
        Image: !Ref CodeBuildDockerImage
        PrivilegedMode: true
        EnvironmentVariables:
          - Name: REPOSITORY_URI
            Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${EcrDockerRepository}
          - Name: REPOSITORY_NAME
            Value: !Ref GitSourceRepo
          - Name: REPOSITORY_BRANCH
            Value: !Ref GitBranch
          - Name: EKS_CLUSTER_NAME
            Value: !Ref EksClusterName
          - Name: EKS_KUBECTL_ROLE_ARN
            Value: !Sub arn:aws:iam::${AWS::AccountId}:role/${KubectlRoleName}
          - Name: AQUA_URL
            Value: !Ref AquaURL
          - Name: AQUA_USER
            Value: 'administrator'
          - Name: AQUA_PASSWORD
            Type: SECRETS_MANAGER
            Value: !Ref AquaConsoleSecret
      Name: !Ref AWS::StackName
      ServiceRole: !GetAtt CodeBuildServiceRole.Arn

  CodePipelineGitHub:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      RoleArn: !GetAtt CodePipelineServiceRole.Arn
      ArtifactStore:
        Type: S3
        Location: !Ref CodePipelineArtifactBucket
      Stages:
        - Name: Source
          Actions:
            - Name: App
              ActionTypeId:
                Category: Source
                Owner: ThirdParty
                Version: 1
                Provider: GitHub
              Configuration:
                Owner: !Ref GitHubUser
                Repo: !Ref GitSourceRepo
                Branch: !Ref GitBranch
                OAuthToken: !Ref GitHubToken
              OutputArtifacts:
                - Name: App
              RunOrder: 1
        - Name: Build
          Actions:
            - Name: Build
              ActionTypeId:
                Category: Build
                Owner: AWS
                Version: 1
                Provider: CodeBuild
              Configuration:
                ProjectName: !Ref CodeBuildProject
              InputArtifacts:
                - Name: App
              OutputArtifacts:
                - Name: BuildOutput
              RunOrder: 1
    DependsOn: CodeBuildProject
