---
AWSTemplateFormatVersion: 2010-09-09
Description: "This template creates AWS CodePipeline and other CICD resources for Identity Center automation solution (qs-1t52at7re)"
Parameters:
  RepositoryName:
    Description: 'The name of CodeCommit repository that has been created for this solution'
    Type: String
    Default: <Replace-With-Your-Own-Value, Eg my-ic-repo>
  RepoBranch:
    Description: The name of branch that will trigger the CodePipeline run.
    Type: String
    Default: <Replace-With-Your-Own-Value, Eg main>
  ICMappingBucketName:
    Type: String
    Description: >-
      The same bucket name will be used in the automation and s3 stack. This S3
      bucket stores the permission sets and mapping files. Specify the same name you have specified in identity-center-stacks-parameters.json
    Default: <Replace-With-Your-Own-Value, Eg ic-s3-automation-sample-bucket>

Resources:
  PipelineArtifactStoreBucket:
    Type: 'AWS::S3::Bucket'
    DeletionPolicy: Delete
    Properties:
      BucketName: !Sub 'ic-pipeline-artifact-bucket-${AWS::AccountId}'
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  PipelineArtifactStoreBucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      Bucket: !Ref PipelineArtifactStoreBucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: DenyInsecureConnections
            Effect: Deny
            Principal: '*'
            Action: 's3:*'
            Resource: !Join
              - ''
              - - !GetAtt
                  - PipelineArtifactStoreBucket
                  - Arn
                - /*
            Condition:
              Bool:
                'aws:SecureTransport': false
          - Sid: DenyOther
            Effect: Deny
            Principal: '*'
            Action:
             - "s3:GetObject"
             - "s3:GetObjectVersion"
             - "s3:PutObject"
            Resource: !Join
              - ''
              - - !GetAtt
                  - PipelineArtifactStoreBucket
                  - Arn
                - /*
            Condition:
              StringNotEquals:
                'aws:PrincipalArn':
                  - !GetAtt CodePipelineServiceRole.Arn
                  - !GetAtt CodeBuildRole.Arn

  AWSCodePipeline:
    Type: 'AWS::CodePipeline::Pipeline'
    Properties:
      ArtifactStore:
        Location: !Ref PipelineArtifactStoreBucket
        Type: S3
      RoleArn: !GetAtt CodePipelineServiceRole.Arn
      Name: Identity-Center-Automation-Solution
      Stages:
        - Name: Source
          Actions:
            - Name: CodeCommitUpdate
              ActionTypeId:
                Category: Source
                Owner: AWS
                Version: '1'
                Provider: CodeCommit
              Configuration:
                RepositoryName: !Ref RepositoryName
                BranchName: !Ref RepoBranch
              OutputArtifacts:
                - Name: SourceArtifacts
              RunOrder: 1
        - Name: ProvisionS3Bucket
          Actions:
            - Name: CreateCFNParameterFiles
              InputArtifacts:
                - Name: SourceArtifacts
              ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: '1'
              Configuration:
                ProjectName: !Ref CreateParameterFiles
              RunOrder: 1
              OutputArtifacts:
                - Name: UpdatedSourceArtifacts
            - Name: BuildS3Stack
              ActionTypeId:
                Category: Deploy
                Owner: AWS
                Version: '1'
                Provider: CloudFormation
              Configuration:
                ActionMode: CREATE_UPDATE
                StackName: IdentityCenter-S3-Bucket-Stack
                Capabilities: CAPABILITY_IAM
                TemplateConfiguration: UpdatedSourceArtifacts::ic-s3-parameters.json
                TemplatePath: UpdatedSourceArtifacts::identity-center-s3-bucket.template
                RoleArn: !GetAtt CodeBuildRole.Arn
              InputArtifacts:
                - Name: UpdatedSourceArtifacts
              RunOrder: 2
            - Name: CreateLambdaZipCode
              InputArtifacts:
                - Name: UpdatedSourceArtifacts
              ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: '1'
              Configuration:
                ProjectName: !Ref CodeBuildProjectS3Upload
              RunOrder: 3
        - Name: BuildICTemplate
          Actions:
            - Name: BuildICTemplate
              ActionTypeId:
                Category: Deploy
                Owner: AWS
                Version: '1'
                Provider: CloudFormation
              InputArtifacts:
                - Name: UpdatedSourceArtifacts
              Configuration:
                ActionMode: CREATE_UPDATE
                StackName: IdentityCenter-Automation-Stack
                Capabilities: 'CAPABILITY_IAM,CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND'
                TemplateConfiguration: UpdatedSourceArtifacts::ic-automation-parameters.json
                TemplatePath: UpdatedSourceArtifacts::identity-center-automation.template
                RoleArn: !GetAtt CodeBuildRole.Arn
              RunOrder: 1
            - Name: SyncMappingFiles
              InputArtifacts:
                - Name: UpdatedSourceArtifacts
              ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: '1'
              Configuration:
                ProjectName: !Ref UploadMappingFiles
              RunOrder: 2
        - Name: ReviewAndExecute
          Actions:
            - Name: Approval
              ActionTypeId:
                Category: Approval
                Owner: AWS
                Version: '1'
                Provider: Manual
              Configuration:
                CustomData: Please check the S3 Objects before triggering the deployment
              RunOrder: 1
            - Name: TriggerLambdaAutomation
              ActionTypeId:
                Category: Invoke
                Owner: AWS
                Provider: Lambda
                Version: '1'
              Configuration:
                FunctionName: "ic-permissionsets-enabler"
              RunOrder: 2

  CodePipelineServiceRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: ICSamplePipelineRole
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - codepipeline.amazonaws.com
        Version: 2012-10-17
      Path: /
      Policies:
        - PolicyName: Pipeline-Service-Policy-Example
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 'codecommit:CancelUploadArchive'
                  - 'codecommit:GetBranch'
                  - 'codecommit:GetCommit'
                  - 'codecommit:GetUploadArchiveStatus'
                  - 'codecommit:UploadArchive'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'codedeploy:CreateDeployment'
                  - 'codedeploy:GetApplicationRevision'
                  - 'codedeploy:GetDeployment'
                  - 'codedeploy:GetDeploymentConfig'
                  - 'codedeploy:RegisterApplicationRevision'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'codebuild:BatchGetBuilds'
                  - 'codebuild:StartBuild'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'lambda:InvokeFunction'
                  - 'lambda:ListFunctions'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'iam:PassRole'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'cloudformation:*'
                  - 'cloudwatch:*'
                  - 's3:*'
                  - 'sns:*'
                Resource: '*'

#
  CreateParameterFiles:
    Type: 'AWS::CodeBuild::Project'
    Properties:
      Name: CreateCFNParameterFiles
      Description: Use input json file to create the CFN parameter files for both CFN stack.
      ServiceRole: !GetAtt CodeBuildRole.Arn
      Artifacts:
        Type: CODEPIPELINE
      Environment:
        Type: LINUX_CONTAINER
        ComputeType: BUILD_GENERAL1_SMALL
        Image: 'aws/codebuild/standard:5.0'
      Source:
        Type: CODEPIPELINE
        BuildSpec: src/codebuild/buildspec-param.yml
      SourceVersion: !Sub 'refs/heads/${RepoBranch}'
      TimeoutInMinutes: 10
#

  CodeBuildProjectS3Upload:
    Type: 'AWS::CodeBuild::Project'
    Properties:
      Name: BuildandUploadLambdaFiles
      Description: Compress Lambda python scripts and sync the zip files to Identity Center secure S3 bucket.
      ServiceRole: !GetAtt CodeBuildRole.Arn
      Artifacts:
        Type: NO_ARTIFACTS
      Environment:
        Type: LINUX_CONTAINER
        ComputeType: BUILD_GENERAL1_SMALL
        Image: 'aws/codebuild/standard:5.0'
        EnvironmentVariables:
          - Name: S3_BUCKET_NAME
            Type: PLAINTEXT
            Value: !Join
              - '-'
              - - !Ref ICMappingBucketName
                - !Sub ${AWS::AccountId}
                - !Sub ${AWS::Region}
      Source:
        Type: CODECOMMIT
        Location: !Sub >-
          https://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/${RepositoryName}
        BuildSpec: src/codebuild/buildspec-zipfiles.yml
      SourceVersion: !Sub 'refs/heads/${RepoBranch}'
      TimeoutInMinutes: 10

  UploadMappingFiles:
    Type: 'AWS::CodeBuild::Project'
    Properties:
      Name: UploadMappingFilestoS3
      Description: >-
        The Lambda functions are ready. This will sync the latest Identity Center mapping
        defination files to s3.
      ServiceRole: !GetAtt CodeBuildRole.Arn
      Artifacts:
        Type: NO_ARTIFACTS
      Environment:
        Type: LINUX_CONTAINER
        ComputeType: BUILD_GENERAL1_SMALL
        Image: 'aws/codebuild/standard:5.0'
        EnvironmentVariables:
          - Name: S3_BUCKET_NAME
            Type: PLAINTEXT
            Value: !Join
              - '-'
              - - !Ref ICMappingBucketName
                - !Sub ${AWS::AccountId}
                - !Sub ${AWS::Region}
      Source:
        Type: CODECOMMIT
        Location: !Sub >-
          https://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/${RepositoryName}
        BuildSpec: src/codebuild/buildspec-mapping.yml
      SourceVersion: !Sub 'refs/heads/${RepoBranch}'
      TimeoutInMinutes: 10

  CodeBuildRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: ICAutoPipelineCodeBuildRole
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - codebuild.amazonaws.com
                - cloudformation.amazonaws.com
        Version: 2012-10-17
      Path: /
      #https://docs.aws.amazon.com/codebuild/latest/userguide/auth-and-access-control-permissions-reference.html
      Policies:
        - PolicyName: CodeBuildAccess
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 'cloudwatch:*'
                  - 'events:DeleteRule'
                  - 'events:DescribeRule'
                  - 'events:PutRule'
                  - 'events:PutTargets'
                  - 'events:RemoveTargets'
                  - 'iam:CreateRole'
                  - 'iam:DeleteRole'
                  - 'iam:DeleteRolePolicy'
                  - 'iam:GetRole'
                  - 'iam:GetRolePolicy'
                  - 'iam:PassRole'
                  - 'iam:PutRolePolicy'
                  - 'kms:*'
                  - 'lambda:AddPermission'
                  - 'lambda:CreateFunction'
                  - 'lambda:DeleteFunction'
                  - 'lambda:GetFunction'
                  - 'lambda:RemovePermission'
                  - 'lambda:UpdateFunction*'
                  - 'logs:*'
                  - 's3:*'
                  - 'sns:*'
                  - 'dynamodb:CreateTable'
                  - 'dynamodb:DescribeTable'
                  - 'dynamodb:UpdateTable'
                  - 'dynamodb:DeleteTable'
                Resource: '*'