---
AWSTemplateFormatVersion: 2010-09-09
Parameters:

    DisplayName:
        Type: String
        Default: lc-classified-codepipeline
        Description: Name for this service; used in the code repository and pipeline names
    SourceOwnerName:
      Description: Source repository owner name
      Type: String
      Default: axel-springer-kugawana
      ConstraintDescription: Specify the Organisation
    SourceRepoName:
      Description: Source repository name
      Type: String
      Default: cbm_lc-classified
      ConstraintDescription: Only specify the repo name
    Environment:
      Description: Environment
      Type: String
      Default: dev
      AllowedValues:
      - dev
      - dev2
      - rec
      - rec2
      - prod
    TagBloc:
      Description: Tag bloc metier
      Type: String
      Default: classified
    TagApp:
      Description: Tag application
      Type: String
      Default: lcpab
    TagComp:
      Description: Tag composant
      Type: String
      Default: classified
    OAuthToken:
      Description: Personal Access Token for GitHUB
      Type: String
      Default: 9f517344135844faf2fd0ccacb0ea19f353cd5b5

Mappings:
  EnvironmentMap:
    dev:
      SourceRepoBranch: dev
    dev2:
      SourceRepoBranch: dev2
    rec:
      SourceRepoBranch: master
    rec2:
      SourceRepoBranch: rec2
    prod:
      SourceRepoBranch: master
      
Conditions:
  IsProdCondition: !Or [!Equals [ !Ref Environment, prod ],!Equals [ !Ref Environment, demo ]]

Resources:
    #########
    # Build #
    #########
    CodeBuildRole:
      Type: "AWS::IAM::Role"
      Properties:
        RoleName: !Join ['-', [!Ref 'DisplayName', 'codebuild', !Ref 'Environment']]
        AssumeRolePolicyDocument:
          Statement:
          - Effect: Allow
            Principal:
              Service:
              - codebuild.amazonaws.com
              - cloudformation.amazonaws.com
              - codedeploy.amazonaws.com
              - ec2.amazonaws.com
            Action:
            - sts:AssumeRole
        Path: "/"
        Policies:
        - PolicyName: !Join ['-', [!Ref DisplayName, "codebuild-build-policy", !Ref Environment]]
          PolicyDocument:
            Statement:
            - Effect: Allow
              Action:
              - s3:*
              Resource:
              - !Join ['', ['arn:aws:s3:::applications.', !Ref 'Environment']]
              - !Join ['', ['arn:aws:s3:::applications.', !Ref 'Environment', '/*']]
              - !Join ['', ['arn:aws:s3:::log-cloudfront.', !Ref 'Environment']]
              - !Join ['', ['arn:aws:s3:::log-cloudfront.', !Ref 'Environment', '/*']]
            - Effect: Allow
              Action:
              - s3:*
              Resource:
              - !Join ['', ['arn:aws:s3:::assets.lacentrale.', !Ref 'Environment', '/*']]
            - Effect: Allow
              Action:
              - logs:*
              Resource:
              - !Join ['', ['arn:aws:logs:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId' , ':log-group:/aws/codebuild/*' ]]
              - !Join ["", ["arn:aws:logs:", !Ref "AWS::Region",":", !Ref "AWS::AccountId",":", "log-group:/aws/lambda/lc-classified-", !Ref Environment,"-*:*"]]
            - Effect: "Allow"
              Action:
              - "logs:Describe*"
              Resource: "*"                 
        - PolicyName: !Join ['-', [!Ref DisplayName, "codebuild-deploy-policy", !Ref Environment]]
          PolicyDocument:
            Statement:
            - Action:
              - cloudformation:*
              Resource: 
              - !Join ["", ["arn:aws:cloudformation:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":stack/lc-classified-", !Ref Environment, "/*"]]
              - !Join ["", ["arn:aws:cloudformation:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":stack/lc-classified-cloudfront-", !Ref Environment, "/*"]]
              - !Join ["", ["arn:aws:cloudformation:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":stack/lc-classified-resource-", !Ref Environment, "/*"]]
              Effect: Allow
            - Action:
              - cloudformation:ValidateTemplate
              Resource: "*"
              Effect: Allow
            - Action:
              - iam:*
              Resource: !Join ["", ["arn:aws:iam::", !Ref "AWS::AccountId", ":role/lc-classified*", !Ref Environment, "*"]]
              Effect: Allow
            - Action:
              - codedeploy:*
              Resource:
              - !Join ["", ["arn:aws:codedeploy:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":application:", "lc-classified-", !Ref Environment, "*"]]
              - !Join ["", ["arn:aws:codedeploy:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":deploymentgroup:", "lc-classified-", !Ref Environment, "*"]]
              - !Join [":", ["arn:aws:codedeploy", !Ref "AWS::Region", !Ref "AWS::AccountId", "deploymentconfig", "*"]]
              Effect: Allow        
            - Action:
              - lambda:*
              Effect: Allow
              Resource: !Join ["", ["arn:aws:lambda:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":function:lc-classified-", !Ref Environment, "*"]]
            - Action:
              - "lambda:CreateEventSourceMapping"
              - "lambda:Get*"
              Effect: Allow
              Resource: "*"            
            - Action:
              - lambda:InvokeFunction
              Resource: "arn:aws:lambda:*:*:function:CodeDeployHook_*"
              Effect: Allow
            - Action:
              - apigateway:*
              Resource:
              - !Join [":", ["arn:aws:apigateway", !Ref "AWS::Region", ":/restapis"]]
              - !Join [":", ["arn:aws:apigateway", !Ref "AWS::Region", ":/restapis/*"]]
              - !Join [":", ["arn:aws:apigateway", !Ref "AWS::Region", ":/tags"]]
              - !Join [":", ["arn:aws:apigateway", !Ref "AWS::Region", ":/tags/*"]]
              Effect: Allow
            - Action:
              - cloudwatch:DescribeAlarms
              - sns:Publish
              Resource: "*"
              Effect: Allow
        - PolicyName: !Join ['-', [!Ref DisplayName, "cloudfront-policy", !Ref Environment]]
          PolicyDocument:
            Statement:
            - Action:
              - acm:ListCertificates
              - cloudfront:*
              - iam:ListServerCertificates
              - waf:ListWebACLs
              - waf:GetWebACL
              Resource: "*"
              Effect: Allow
        - PolicyName: !Join ['-', [!Ref DisplayName, "route53-policy", !Ref Environment]]
          PolicyDocument:
            Statement:
            - Action:
              - route53:*
              Resource: "*"
              Effect: Allow
        - PolicyName: !Join ['-', [!Ref DisplayName, "waf-policy", !Ref Environment]]
          PolicyDocument:
            Statement:
            - Action:
              - waf:Get*
              - waf:Create*
              - waf:Update*
              Resource: "*"
              Effect: Allow
              
    CodePipelineRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: !Join ['-', [!Ref 'DisplayName', !Ref 'Environment']]
        AssumeRolePolicyDocument:
          Statement:
          - Effect: Allow
            Principal:
              Service:
              - codepipeline.amazonaws.com
            Action:
            - sts:AssumeRole
        Path: "/"
        Policies:
        - PolicyName: !Join ['-', [!Ref DisplayName, "codepipeline-sns-policy", !Ref Environment]]
          PolicyDocument:
            Statement:
            - Effect: Allow
              Action:
              - sns:Publish
              Resource:
              - !Join ['', ['arn:aws:sns:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId' , ':lcpab_manual_approval_', !Ref 'Environment' ]]
        - PolicyName: !Join ['-', [!Ref DisplayName, "codepipeline-s3-policy", !Ref Environment]]
          PolicyDocument:
            Statement:
            - Effect: Allow
              Action:
              - s3:PutObject
              - s3:GetObject
              - s3:GetObjectVersion
              - s3:ListBucket
              Resource:
              - !Join ['', ['arn:aws:s3:::applications.', !Ref 'Environment']]
              - !Join ['', ['arn:aws:s3:::applications.', !Ref 'Environment', '/*']]
        - PolicyName: !Join ['-', [!Ref DisplayName, "codepipeline-codebuild-policy", !Ref Environment]]
          PolicyDocument:
            Statement:
            - Effect: "Allow"
              Action:
              - "codebuild:StartBuild"
              - "codebuild:BatchGetBuilds"
              Resource:
              - !Join ['', ['arn:aws:codebuild:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId' , ':project/', !Ref 'CodeBuildServerless' ]]
              - !Join ['', ['arn:aws:codebuild:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId' , ':build/', !Ref 'CodeBuildServerless', ':*' ]]
              - !Join ['', ['arn:aws:codebuild:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId' , ':project/', !Ref 'CodeBuildResource' ]]
              - !Join ['', ['arn:aws:codebuild:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId' , ':build/', !Ref 'CodeBuildResource', ':*' ]]
              - !Join ['', ['arn:aws:codebuild:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId' , ':project/', !Ref 'CodeBuildExpose' ]]
              - !Join ['', ['arn:aws:codebuild:', !Ref 'AWS::Region', ':', !Ref 'AWS::AccountId' , ':build/', !Ref 'CodeBuildExpose', ':*' ]]
        - PolicyName: !Join ['-', [!Ref DisplayName, "codepipeline-apigateway-policy", !Ref Environment]]
          PolicyDocument:
            Statement:
            - Effect: "Allow"
              Action:
              - "apigateway:*"
              Resource:
              - !Join [":", ["arn:aws:apigateway", !Ref "AWS::Region", ":/tags"]]
              - !Join [":", ["arn:aws:apigateway", !Ref "AWS::Region", ":/tags/*"]]

    CodeBuildResource:
      Type: AWS::CodeBuild::Project
      Properties:
        Name: !Sub '${DisplayName}_build_Resource-${Environment}'
        Source:
          Type: CODEPIPELINE
          BuildSpec: "aws/codebuild/buildspec.resource.yml"
        Artifacts:
            Type: CODEPIPELINE
        Environment: 
            Type: LINUX_CONTAINER
            ComputeType: BUILD_GENERAL1_SMALL
            Image: !Sub 'aws/codebuild/python:3.6.5'
            EnvironmentVariables:
              - Name: ENV
                Value: !Ref Environment
        ServiceRole: !GetAtt CodeBuildRole.Arn
        Tags:
          - Key: Name
            Value: !Sub '${DisplayName}-${Environment}'
          - Key: Env
            Value: !Ref Environment
          - Key: Bloc
            Value: !Ref TagBloc
          - Key: Comp
            Value: !Ref TagComp
          - Key: App
            Value: !Ref TagApp
          - Key: Managed_By
            Value: CloudFormation

    CodeBuildServerless:
      Type: "AWS::CodeBuild::Project"
      Properties:
        Artifacts:
          Type: CODEPIPELINE
        Cache:
          Type: S3
          Location: !Join ['', ['arn:aws:s3:::applications.', !Ref 'Environment', '/codebuild/cache']]
        Environment:
          Type: LINUX_CONTAINER
          ComputeType: BUILD_GENERAL1_SMALL
          Image: !Sub ${AWS::AccountId}.dkr.ecr.eu-west-1.amazonaws.com/ci-containers/lc-classified:latest
          EnvironmentVariables:
          - Name: ENV
            Value: !Ref Environment
        Name: !Sub '${DisplayName}_build_Serverless-${Environment}'
        ServiceRole: !Ref CodeBuildRole
        Source:
          Type: CODEPIPELINE
          BuildSpec: "aws/codebuild/buildspec.serverless.yml"
        Tags:
          - Key: Name
            Value: !Sub '${DisplayName}-${Environment}'
          - Key: Env
            Value: !Ref Environment
          - Key: Bloc
            Value: !Ref TagBloc
          - Key: Comp
            Value: !Ref TagComp
          - Key: App
            Value: !Ref TagApp
          - Key: Managed_By
            Value: CloudFormation

    CodeBuildExpose:
      Type: AWS::CodeBuild::Project
      Properties:
        Name: !Sub '${DisplayName}_build_Expose-${Environment}'
        Source:
          Type: CODEPIPELINE
          BuildSpec: "aws/codebuild/buildspec.expose.yml"
        Artifacts:
            Type: CODEPIPELINE
        Environment: 
            Type: LINUX_CONTAINER
            ComputeType: BUILD_GENERAL1_SMALL
            Image: !Sub 'aws/codebuild/python:3.6.5'
            EnvironmentVariables:
              - Name: ENV
                Value: !Ref Environment
        ServiceRole: !GetAtt CodeBuildRole.Arn
        Tags:
          - Key: Name
            Value: !Sub '${DisplayName}-${Environment}'
          - Key: Env
            Value: !Ref Environment
          - Key: Bloc
            Value: !Ref TagBloc
          - Key: Comp
            Value: !Ref TagComp
          - Key: App
            Value: !Ref TagApp
          - Key: Managed_By
            Value: CloudFormation
    
    #############
    # Pipeline  #
    #############
  
    PipelineExecutionRole:
      Type: AWS::IAM::Role
      Properties:
          Path: '/managed/'      
          AssumeRolePolicyDocument:
              Version: '2012-10-17'
              Statement:
                - 
                  Action: 'sts:AssumeRole'
                  Effect: Allow
                  Principal:
                    Service: 
                      - codepipeline.amazonaws.com
          Policies:
              - 
                PolicyName: CodePipelinePassRoleAccess
                PolicyDocument:
                  Version: '2012-10-17'
                  Statement:
                      - 
                        Action: 'iam:PassRole'
                        Effect: Allow
                        Resource: !GetAtt CodeBuildRole.Arn
              - 
                PolicyName: CodePipelineS3ArtifactAccess
                PolicyDocument:
                  Version: '2012-10-17'
                  Statement:
                      - 
                        Action:
                          - 's3:GetObject'
                          - 's3:GetObjectVersion'
                          - 's3:GetBucketVersioning'
                          - 's3:PutObject'
                        Effect: Allow
                        Resource: 
                          - !Join ['', ['arn:aws:s3:::applications.', !Ref 'Environment']]
                          - !Join ['', ['arn:aws:s3:::applications.', !Ref 'Environment', '/*']]
              - 
                PolicyName: CodePipelineBuildAccess
                PolicyDocument:
                  Version: '2012-10-17'
                  Statement:
                      - 
                        Action:
                          - 'codebuild:StartBuild'
                          - 'codebuild:StopBuild'
                          - 'codebuild:BatchGetBuilds'
                        Effect: Allow
                        Resource: 
                          - !GetAtt CodeBuildResource.Arn
                          - !GetAtt CodeBuildServerless.Arn
                          - !GetAtt CodeBuildExpose.Arn

    Pipeline:
        Type: AWS::CodePipeline::Pipeline
        Properties:
          ArtifactStore: 
            Location: !Join ['', ['applications.', !Ref 'Environment']]
            Type: S3
          Name: !Sub ${DisplayName}-${Environment}
          RoleArn: 
            Fn::GetAtt: [ CodePipelineRole, Arn ]
          Stages:
            - Name: Source
              Actions:
                - Name: Source
                  ActionTypeId:
                    Category: Source
                    Owner: ThirdParty
                    Version: "1"
                    Provider: GitHub
                  Configuration:
                    Owner: !Ref SourceOwnerName
                    Repo: !Ref SourceRepoName
                    Branch: !FindInMap [EnvironmentMap, !Ref Environment, SourceRepoBranch]
                    PollForSourceChanges: true
                    OAuthToken: !Ref OAuthToken
                  OutputArtifacts:
                  - Name: SourceZip
                  RunOrder: 1

            - !If
              - IsProdCondition
              - Name: "Manual_Approval"
                Actions:
                  - 
                    Name: Approval
                    ActionTypeId:
                      Category: Approval
                      Owner: AWS
                      Provider: Manual
                      Version: "1"
                    Configuration: 
                      NotificationArn: arn:aws:sns:eu-west-1:395174950964:lcpab_manual_approval_prod
              - !Ref AWS::NoValue

            - Name: "Resource"
              Actions:
                - 
                  Name: CodeBuildResource
                  ActionTypeId:
                    Category: Build
                    Owner: AWS
                    Provider: CodeBuild
                    Version: "1"
                  Configuration:
                    ProjectName: !Ref CodeBuildResource
                  InputArtifacts:
                    - Name: SourceZip
                  OutputArtifacts:
                    - Name: BuiltZipResource
            - Name: "Serverless"
              Actions:
                - 
                  Name: CodeBuildServerless
                  ActionTypeId:
                    Category: Build
                    Owner: AWS
                    Provider: CodeBuild
                    Version: "1"
                  Configuration:
                    ProjectName: !Ref CodeBuildServerless
                  InputArtifacts:
                    - Name: SourceZip
                  OutputArtifacts:
                    - Name: BuiltZipServerless
            - Name: "Expose"
              Actions:
                - 
                  Name: CodeBuildExpose
                  ActionTypeId:
                    Category: Build
                    Owner: AWS
                    Provider: CodeBuild
                    Version: "1"
                  Configuration:
                    ProjectName: !Ref CodeBuildExpose
                  InputArtifacts:
                    - Name: SourceZip
                  OutputArtifacts:
                    - Name: BuiltZipExpose
