AWSTemplateFormatVersion: '2010-09-09'

Description: |
  (SO0077) - This Guidance for Multi-Omics and Multi-Modal Data Integration and Analysis on AWS creates a scalable environment in AWS to prepare genomic, clinical, mutation, expression and imaging data for large-scale analysis and perform interactive queries against a data lake. This solution demonstrates how to 1)Provision Amazon Omics resources to ingest, store and query genomics data, 2) provision serverless data ingestion pipelines for multi-modal data preparation and cataloging, 3) visualize and explore clinical data through an interactive interface, and 4) run interactive analytic queries against a multi-modal data lake. Version v3.0.0.

Mappings:
  Send:
    AnonymousUsage:
      Data: Yes
  SourceCode:
    General:
      S3Bucket: '%%BUCKET_NAME%%'
      KeyPrefix: '%%SOLUTION_NAME%%/%%VERSION%%'

Parameters:
  Project:
    Type: String
    Description: >
      The project name for this solution. The project name will be used to prefix resources created by this solution. The solution Glue database name and Athena workgroup name will be the project name. Project names should be unique to a project.
    AllowedPattern: "[a-zA-Z0-9-]{3,24}"
    ConstraintDescription: >
      Project name should be unique, 3-24 characters in length, and only have alphanumeric characters and hyphens ([a-zA-Z0-9-]{3,32}).
    Default: GenomicsAnalysis

Resources:
  Setup:
    Type: Custom::Setup
    DependsOn:
      - CodeBuild
    Version: 1.0
    Properties:
      ServiceToken: !Sub ${SetupLambda.Arn}
      CodeBuildProjectName: !Sub ${CodeBuild}

  SetupLambda:
    Type: AWS::Lambda::Function
    DependsOn:
      - SetupLambdaRole
    Properties:
      Handler: lambda.handler
      Runtime: python3.8
      FunctionName: !Sub ${Project}Setup
      Code:
        S3Bucket: !Join ["-", [!FindInMap ["SourceCode", "General", "S3Bucket"], Ref: "AWS::Region"]]
        S3Key: !Join ["", [!FindInMap ["SourceCode", "General", "KeyPrefix"], "/SolutionSetup.zip"]]
      Role: !Sub ${SetupLambdaRole.Arn}
      Timeout: 600
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W58
            reason: Bug in CfnNag.
          - id: W89
            reason: Lambda only used on setup.
          - id: W92
            reason: No need for concurrent execution.
  SetupLambdaRole:
    Type: AWS::IAM::Role
    DependsOn:
      - CodeBuild
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
      Path: /
      Policies:
        - PolicyName: LogsAccess
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource:
                  - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${Project}*
        - PolicyName: CodeBuildAccess
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - codebuild:BatchGetProjects
                  - codebuild:BatchGetBuilds
                  - codebuild:StartBuild
                Resource:
                  - !Sub ${CodeBuild.Arn}
        - PolicyName: EventsAccess
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - events:DeleteRule
                  - events:PutRule
                  - events:PutTargets
                  - events:RemoveTargets
                Resource:
                  - !Sub arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/Setup*
        - PolicyName: LambdaAccess
          PolicyDocument:
            Statement:
              - Effect: Allow
                Action:
                  - lambda:AddPermission
                  - lambda:RemovePermission
                Resource:
                  - !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${Project}*

  CodeBuildRole:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Version: 2012-10-17
          Statement:
            - Action:
                - sts:AssumeRole
              Effect: Allow
              Principal:
                Service:
                  - codebuild.amazonaws.com
        Path: /
        Policies:
          - PolicyName: CloudFormationAccess
            PolicyDocument:
              Statement:
                - Action:
                    - cloudformation:CreateStack
                    - cloudformation:DescribeStacks
                    - cloudformation:DescribeStackResource
                    - cloudformation:DescribeStackResources
                    - cloudformation:UpdateStack
                    - cloudformation:DeleteStack
                    - cloudformation:UpdateTerminationProtection
                  Effect: Allow
                  Resource: !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${Project}*
          - PolicyName: LogsAccess
            PolicyDocument:
              Statement:
                - Effect: Allow
                  Action:
                    - logs:CreateLogGroup
                    - logs:CreateLogStream
                    - logs:PutLogEvents
                  Resource:
                    - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${Project}*
          - PolicyName: IAMAccess
            PolicyDocument:
              Statement:
                - Effect: Allow
                  Action:
                    - iam:CreateRole
                    - iam:DeleteRole
                    - iam:PutRolePolicy
                    - iam:DeleteRolePolicy
                    - iam:AttachRolePolicy
                    - iam:DetachRolePolicy
                    - iam:UpdateAssumeRolePolicy
                    - iam:PassRole
                    - iam:GetRole
                    - iam:GetInstanceProfile
                    - iam:CreateInstanceProfile
                    - iam:DeleteInstanceProfile
                    - iam:AddRoleToInstanceProfile
                    - iam:RemoveRoleFromInstanceProfile
                  Resource:
                    - !Sub arn:aws:iam::${AWS::AccountId}:role/${Project}*
                    - !Sub arn:aws:iam::${AWS::AccountId}:instance-profile/${Project}*
                    - !Sub arn:aws:iam::${AWS::AccountId}:role/aws-quicksight-service-role-v0
          - PolicyName: CodeBuildAccess
            PolicyDocument:
              Statement:
                - Effect: Allow
                  Action:
                    - codebuild:CreateProject
                    - codebuild:UpdateProject
                    - codebuild:ListProjects
                    - codebuild:BatchGetProjects
                    - codebuild:DeleteProject
                  Resource:
                    - !Sub arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/${Project}*
          - PolicyName: CodePipelineAccess
            PolicyDocument:
              Statement:
                - Effect: Allow
                  Action:
                    - codepipeline:CreatePipeline
                    - codepipeline:GetPipeline
                    - codepipeline:UpdatePipeline
                    - codepipeline:DeletePipeline
                    - codepipeline:GetPipelineState
                    - codepipeline:ListPipelineExecutions
                  Resource:
                    - !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${Project}*
          - PolicyName: CodeCommitAccess
            PolicyDocument:
              Statement:
                - Effect: Allow
                  Action:
                    - codecommit:CreateBranch
                    - codecommit:CreateRepository
                    - codecommit:GetRepository
                    - codecommit:DeleteRepository
                    - codecommit:CreateCommit
                    - codecommit:GitPush
                    - codecommit:GitPull
                    - codecommit:DeleteBranch
                  Resource:
                    - !Sub arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${Project}*
                - Effect: Allow
                  Action:
                    - codecommit:ListRepositories
                  Resource: '*'
          - PolicyName: EventsAccess
            PolicyDocument:
              Statement:
                - Effect: Allow
                  Action:
                    - events:DescribeRule
                    - events:PutRule
                    - events:DeleteRule
                    - events:PutTargets
                    - events:RemoveTargets
                  Resource:
                    - !Sub arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/*
          - PolicyName: GlueAccess
            PolicyDocument:
              Statement:
                - Effect: Allow
                  Action:
                    - glue:StartCrawler
                    - glue:GetCrawlers
                    - glue:StartWorkflowRun
                  Resource: '*'
          - PolicyName: LambdaAccess
            PolicyDocument:
              Statement:
                - Effect: Allow
                  Action:
                    - lambda:GetFunction
                    - lambda:CreateFunction
                    - lambda:DeleteFunction
                    - lambda:InvokeFunction
                  Resource:
                    - !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${Project}*
          - PolicyName: S3Access
            PolicyDocument:
              Statement:
                - Effect: Allow
                  Action:
                    - s3:GetObject
                  Resource:
                    !Join
                      - ''
                      - - 'arn:aws:s3:::'
                        - !Join
                            - '-'
                            - - !FindInMap ["SourceCode", "General", "S3Bucket"]
                              - Ref: "AWS::Region"
                        - '/*'
                - Effect: Allow
                  Action:
                    - s3:ListBucket
                  Resource:
                    !Join
                      - ''
                      - - 'arn:aws:s3:::'
                        - !Join
                            - '-'
                            - - !FindInMap ["SourceCode", "General", "S3Bucket"]
                              - Ref: "AWS::Region"

                - Effect: Allow
                  Action:
                    - s3:PutObjectAcl
                    - s3:GetObject
                    - s3:PutObject
                    - s3:DeleteObject
                    - s3:ListBucket
                    - s3:CreateBucket
                    - s3:DeleteBucket
                    - s3:PutEncryptionConfiguration
                    - s3:PutBucketPublicAccessBlock
                    - s3:PutBucketLogging
                    - s3:PutBucketAcl
                    - s3:PutBucketOwnershipControls
                  Resource:
                    - arn:aws:s3:::*pipe*
                    - arn:aws:s3:::*pipe*/*
                - Effect: Allow
                  Action:
                    - s3:CreateBucket
                    - s3:DeleteBucket
                    - s3:ListBucket
                    - s3:PutEncryptionConfiguration
                    - s3:PutBucketPublicAccessBlock
                    - s3:PutBucketLogging
                    - s3:PutBucketAcl
                    - s3:PutObject
                    - s3:PutObjectAcl
                    - s3:PutBucketOwnershipControls
                  Resource:
                    - arn:aws:s3:::*pipe*
                    - arn:aws:s3:::*pipe*/*

      Metadata:
        cfn_nag:
          rules_to_suppress:
            - id: W11
              reason: Star required for codecommit:ListRepositories and Glue actions.
  
  CodeBuild:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Sub ${Project}Setup
      Artifacts:
        Type: NO_ARTIFACTS
      Source:
        Type: NO_SOURCE
        BuildSpec: !Sub |
          version: 0.2
          phases:
            install:
              commands:
                - git config --global user.name automated_user
                - git config --global user.email automated_email
                - git config --global credential.helper '!aws codecommit credential-helper $@'
                - git config --global credential.UseHttpPath true
                - aws s3 cp s3://$ARTIFACT_BUCKET/$ARTIFACT_KEY_PREFIX/Solution.zip .
                - unzip Solution.zip
                - ./$SOLUTION_ACTION.sh
      Environment:
        ComputeType: BUILD_GENERAL1_SMALL
        EnvironmentVariables:
          - Name: SOLUTION_ACTION
            Value: setup
          - Name: PROJECT_NAME
            Value: !Ref Project
          - Name: ARTIFACT_BUCKET
            Value: !Join ["-", [!FindInMap ["SourceCode", "General", "S3Bucket"], Ref: "AWS::Region"]]
          - Name: ARTIFACT_KEY_PREFIX
            Value: !FindInMap ["SourceCode", "General", "KeyPrefix"]
        Image: aws/codebuild/standard:6.0
        Type: LINUX_CONTAINER
      ServiceRole: !Sub ${CodeBuildRole}
      TimeoutInMinutes: 60
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W32
            reason: Customer can enable encryption if desired.
