AWSTemplateFormatVersion: 2010-09-09
Description: GenomicsAnalysisPipe
Parameters:
ResourcePrefix:
Type: String
Default: GenomicsAnalysis
ResourcePrefixLowercase:
Type: String
Default: genomicsanalysis
Resources:
SourceEvent:
Type: AWS::Events::Rule
DependsOn:
- CodePipeline
- SourceEventRole
Properties:
Description: Rule for Amazon CloudWatch Events to detect changes to the source
repository and trigger pipeline execution
EventPattern:
detail:
event:
- referenceCreated
- referenceUpdated
referenceName:
- master
referenceType:
- branch
detail-type:
- CodeCommit Repository State Change
resources:
- !Sub ${Repo.Arn}
source:
- aws.codecommit
Name: !Sub ${Repo}-Pipeline-Trigger
State: ENABLED
Targets:
- Arn: !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${CodePipeline}
Id: ProjectPipelineTarget
RoleArn: !Sub ${SourceEventRole.Arn}
CodeBuildCopyResourcesProject:
Type: AWS::CodeBuild::Project
DependsOn:
- BuildBucket
- CodeBuildRole
- ResourcesBucket
Properties:
Name: !Sub ${ResourcePrefix}CopyResources
Description: !Sub ${ResourcePrefix}CopyResources
Artifacts:
Type: CODEPIPELINE
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/standard:4.0
EnvironmentVariables:
- Name: RESOURCES_BUCKET
Value: !Sub ${ResourcesBucket}
ServiceRole: !Sub ${CodeBuildRole.Arn}
Source:
Type: CODEPIPELINE
BuildSpec: copyresources_buildspec.yml
Metadata:
cfn_nag:
rules_to_suppress:
- id: W32
reason: Artifact outputs are encrypted by default.
CodeBuildOmicsResourcesProject:
Type: AWS::CodeBuild::Project
DependsOn:
- BuildBucket
- CodeBuildRole
- ResourcesBucket
Properties:
Name: !Sub ${ResourcePrefix}OmicsResources
Description: !Sub ${ResourcePrefix}OmicsResources
Artifacts:
Type: CODEPIPELINE
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux2-x86_64-standard:2.0
EnvironmentVariables:
- Name: RESOURCES_BUCKET
Value: !Sub ${ResourcesBucket}
ServiceRole: !Sub ${CodeBuildRole.Arn}
Source:
Type: CODEPIPELINE
BuildSpec: omicsresources_buildspec.yml
Metadata:
cfn_nag:
rules_to_suppress:
- id: W32
reason: Artifact outputs are encrypted by default.
Repo:
DeletionPolicy: Retain
Type: AWS::CodeCommit::Repository
Properties:
RepositoryName: !Sub ${ResourcePrefix}
RepositoryDescription: !Sub ${ResourcePrefix}
CodePipeline:
Type: AWS::CodePipeline::Pipeline
DependsOn:
- CodeBuildCopyResourcesProject
- CodePipelineRole
- Repo
Properties:
ArtifactStore:
Location: !Ref BuildBucket
Type: S3
Name: !Sub ${ResourcePrefix}CodePipeline
RoleArn: !GetAtt CodePipelineRole.Arn
Stages:
- Name: Source
Actions:
- Name: CodeCommitRepo
ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeCommit
Version: 1
Configuration:
BranchName: master
RepositoryName: !Sub ${ResourcePrefix}
PollForSourceChanges: false
OutputArtifacts:
- Name: SourceStageOutput
- Name: Build
Actions:
- Name: CopyResources
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
RunOrder: 1
Configuration:
ProjectName: !Sub ${ResourcePrefix}CopyResources
InputArtifacts:
- Name: SourceStageOutput
OutputArtifacts:
- Name: QuicksightTemplate
- Name: OmicsResources
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
RunOrder: 1
Configuration:
ProjectName: !Sub ${ResourcePrefix}OmicsResources
InputArtifacts:
- Name: SourceStageOutput
- Name: CreateStack
Actions:
- Name: CreateGenomicsStack
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: 1
Configuration:
StackName: !Sub ${ResourcePrefix}-Genomics
ActionMode: CREATE_UPDATE
Capabilities: CAPABILITY_NAMED_IAM
RoleArn: !Sub ${CloudFormationRole.Arn}
TemplatePath: !Sub SourceStageOutput::code_cfn.yml
ParameterOverrides: !Sub |
{
"ResourcePrefix" : "${ResourcePrefix}",
"ResourcePrefixLowercase" : "${ResourcePrefixLowercase}",
"ResourcesBucket" : "${ResourcesBucket}",
"DataLakeBucket": "${DataLakeBucket}",
"DatabaseAdministrator": "${CloudFormationRole.Arn}"
}
InputArtifacts:
- Name: SourceStageOutput
OutputArtifacts: []
RunOrder: 3
- Name: CreateImagingStack
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: 1
Configuration:
StackName: !Sub ${ResourcePrefix}-Imaging
ActionMode: CREATE_UPDATE
Capabilities: CAPABILITY_NAMED_IAM
RoleArn: !Sub ${CloudFormationRole.Arn}
TemplatePath: !Sub SourceStageOutput::TCIA_etl.yaml
ParameterOverrides: !Sub |
{
"ResourcePrefix": "${ResourcePrefix}",
"ResourcePrefixLowercase" : "${ResourcePrefixLowercase}",
"DatabaseName": "${ResourcePrefixLowercase}",
"ResourcesBucket" : "${ResourcesBucket}",
"DataLakeBucket": "${DataLakeBucket}",
"ExistingBucket": "Yes"
}
InputArtifacts:
- Name: SourceStageOutput
OutputArtifacts: []
RunOrder: 4
- Name: CreateOmicsStack
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: 1
Configuration:
StackName: !Sub ${ResourcePrefix}-Omics
ActionMode: CREATE_UPDATE
Capabilities: CAPABILITY_NAMED_IAM
RoleArn: !Sub ${CloudFormationRole.Arn}
TemplatePath: !Sub SourceStageOutput::omics_cfn.yml
ParameterOverrides: !Sub |
{
"OmicsResourcesS3Bucket" : "${ResourcesBucket}",
"OmicsDataS3Bucket" : "${DataLakeBucket}",
"OmicsResourcePrefix": "${ResourcePrefix}Omics"
}
InputArtifacts:
- Name: SourceStageOutput
OutputArtifacts: []
RunOrder: 4
- Name: SaveQuicksightStack
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: S3
Version: 1
Configuration:
BucketName: !Ref ResourcesBucket
Extract: true
InputArtifacts:
- Name: QuicksightTemplate
OutputArtifacts: []
RunOrder: 5
CloudFormationRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Principal:
Service:
- cloudformation.amazonaws.com
Policies:
- PolicyName: CloudFormationRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- iam:CreateRole
- iam:DeleteRole
- iam:PutRolePolicy
- iam:GetRolePolicy
- iam:DeleteRolePolicy
- iam:AttachRolePolicy
- iam:DetachRolePolicy
- iam:UpdateAssumeRolePolicy
- iam:PassRole
- iam:GetRole
Resource:
- !Sub arn:aws:iam::${AWS::AccountId}:role/${ResourcePrefix}*
- Effect: Allow
Action:
- glue:CreateJob
- glue:UpdateJob
- glue:DeleteJob
- glue:GetJob
Resource: '*'
- Effect: Allow
Action:
- glue:CreateSecurityConfiguration
- glue:GetSecurityConfiguration
- glue:DeleteSecurityConfiguration
Resource: '*'
- Effect: Allow
Action:
- glue:CreateWorkflow
- glue:DeleteWorkflow
- glue:UpdateWorkflow
Resource: '*'
- Effect: Allow
Action:
- glue:GetDataCatalogEncryptionSettings
- glue:PutDataCatalogEncryptionSettings
- glue:DeleteDataCatalogEncryptionSettings
Resource:
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:catalog
- Effect: Allow
Action:
- glue:GetDatabases
- glue:SearchTables
- iam:ListUsers
- iam:ListRoles
Resource: '*'
- Effect: Allow
Action:
- glue:CreateDatabase
- glue:UpdateDatabase
- glue:DeleteDatabase
- glue:GetDatabase
- glue:GetCrawler
- glue:CreateCrawler
- glue:UpdateCrawler
- glue:DeleteCrawler
- glue:StopCrawler
- glue:StopTrigger
- glue:GetTrigger
- glue:CreateTrigger
- glue:DeleteTrigger
- glue:UpdateTrigger
Resource:
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:catalog
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:database/${ResourcePrefixLowercase}
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:table/${ResourcePrefixLowercase}/*
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:userDefinedFunction/${ResourcePrefixLowercase}/*
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:crawler/${ResourcePrefixLowercase}*
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:trigger/${ResourcePrefixLowercase}*
- Effect: Allow
Action:
- glue:CreateTable
- glue:UpdateTable
- glue:DeleteTable
- glue:GetTable
- glue:GetTables
- glue:GetPartitions
Resource:
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:catalog
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:database/${ResourcePrefixLowercase}
- !Sub arn:aws:glue:${AWS::Region}:${AWS::AccountId}:table/${ResourcePrefixLowercase}/*
- Effect: Allow
Action:
- lambda:CreateFunction
- lambda:DeleteFunction
- lambda:GetFunctionConfiguration
- lambda:GetFunction
- lambda:InvokeFunction
- lambda:ListTags
- lambda:TagResource
- lambda:UntagResource
- lambda:UpdateFunctionCode
- lambda:UpdateFunctionConfiguration
Resource:
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${ResourcePrefix}*
- Effect: Allow
Action:
- lambda:PublishLayerVersion
- lambda:DeleteLayerVersion
- lambda:GetLayerVersion
Resource:
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:layer:OmicsApiModels
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:layer:OmicsApiModels:*
- Effect: Allow
Action:
- athena:GetWorkGroup
- athena:CreateWorkGroup
- athena:DeleteWorkGroup
Resource:
- !Sub arn:aws:athena:${AWS::Region}:${AWS::AccountId}:workgroup/${ResourcePrefixLowercase}-${AWS::Region}
- Effect: Allow
Action:
- kms:CreateKey
- kms:GenerateDataKey
Resource: '*'
- Effect: Allow
Action:
- lakeformation:GrantPermissions
- lakeformation:ListPermissions
- lakeformation:BatchGrantPermissions
- lakeformation:RevokePermissions
- lakeformation:BatchRevokePermissions
Resource: !Sub arn:aws:lakeformation:${AWS::Region}:${AWS::AccountId}:catalog:${AWS::AccountId}
- Effect: Allow
Action:
- s3:CreateBucket
- s3:DeleteBucket
- s3:GetObject
Resource:
- !Sub ${BuildBucket.Arn}
- !Sub ${BuildBucket.Arn}/*
- !Sub ${ResourcesBucket.Arn}
- !Sub ${ResourcesBucket.Arn}/*
- Effect: Allow
Action:
- s3:GetObject
Resource:
- !Sub ${ResourcesBucket.Arn}/artifacts/*
- arn:aws:s3:::aws-genomics-static-us-east-1/*
- Effect: Allow
Action:
- sagemaker:CreateNotebookInstanceLifecycleConfig
- sagemaker:DescribeNotebookInstanceLifecycleConfig
- sagemaker:UpdateNotebookInstanceLifecycleConfig
- sagemaker:DeleteNotebookInstanceLifecycleConfig
- sagemaker:CreateNotebookInstance
- sagemaker:UpdateNotebookInstance
- sagemaker:StartNotebookInstance
- sagemaker:DescribeNotebookInstance
- sagemaker:DeleteNotebookInstance
- sagemaker:StopNotebookInstance
Resource:
- !Sub arn:aws:sagemaker:${AWS::Region}:${AWS::AccountId}:notebook-instance-lifecycle-config/${ResourcePrefixLowercase}*
- !Sub arn:aws:sagemaker:${AWS::Region}:${AWS::AccountId}:notebook-instance/${ResourcePrefixLowercase}*
- Effect: Deny
Action:
- lakeformation:GetDataLakeSettings
- lakeformation:PutDataLakeSettings
Resource: '*'
Metadata:
cfn_nag:
rules_to_suppress:
- id: W11
reason: Glue does not support resource-level permissions for these actions.
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: CodeBuildAccess
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Resource:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ResourcePrefix}*
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
- s3:PutObject
Resource:
- !Sub ${BuildBucket.Arn}/*
- !Sub ${ResourcesBucket.Arn}/*
- Effect: Allow
Action:
- s3:ListBucket
Resource:
- !Sub ${ResourcesBucket.Arn}
- !Sub ${DataLakeBucket.Arn}
- Effect: Allow
Action:
- s3:PutObject
- s3:PutObjectAcl
Resource:
- !Sub ${ResourcesBucket.Arn}
- !Sub ${ResourcesBucket.Arn}/*
- !Sub ${DataLakeBucket.Arn}
- !Sub ${DataLakeBucket.Arn}/*
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- codepipeline.amazonaws.com
Path: /
Policies:
- PolicyName: CloudFormationAccess
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- cloudformation:CreateStack
- cloudformation:UpdateStack
- cloudformation:DescribeStacks
Effect: Allow
Resource:
- !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${ResourcePrefix}-Genomics/*
- !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${ResourcePrefix}-Imaging/*
- !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${ResourcePrefix}-Omics/*
- PolicyName: IamAccess
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- iam:PassRole
Effect: Allow
Resource: !GetAtt CodeBuildRole.Arn
- PolicyName: IamAccessCF
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- iam:PassRole
Effect: Allow
Resource: !Sub ${CloudFormationRole.Arn}
- PolicyName: S3Access
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:GetObjectVersion
- s3:GetBucketVersioning
- s3:DeleteObject
- s3:PutObject
Resource:
- !Sub ${BuildBucket.Arn}
- !Sub ${BuildBucket.Arn}/*
- !Sub ${ResourcesBucket.Arn}
- !Sub ${ResourcesBucket.Arn}/*
- PolicyName: CodeBuildAccess
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- codebuild:StartBuild
- codebuild:BatchGetBuilds
Effect: Allow
Resource:
- !GetAtt CodeBuildCopyResourcesProject.Arn
- !GetAtt CodeBuildOmicsResourcesProject.Arn
- PolicyName: CodeCommitAccess
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- codecommit:UploadArchive
- codecommit:GetBranch
- codecommit:GetCommit
- codecommit:GetUploadArchiveStatus
Resource: !GetAtt Repo.Arn
SourceEventRole:
Type: AWS::IAM::Role
DependsOn: CodePipeline
Description: IAM role to allow Amazon CloudWatch Events to trigger AWS CodePipeline
execution
Properties:
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service:
- events.amazonaws.com
Sid: 1
Policies:
- PolicyName: CloudWatchEventPolicy
PolicyDocument:
Statement:
- Action:
- codepipeline:StartPipelineExecution
Effect: Allow
Resource:
- !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${CodePipeline}*
BuildBucket:
Type: AWS::S3::Bucket
Properties:
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerPreferred
LoggingConfiguration:
DestinationBucketName: !Ref LogsBucket
LogFilePrefix: templates_logs/
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Metadata:
cfn_nag:
rules_to_suppress:
- id: W51
reason: Bucket policy is not needed.
DataLakeBucket:
Type: AWS::S3::Bucket
Properties:
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerPreferred
LoggingConfiguration:
DestinationBucketName: !Ref LogsBucket
LogFilePrefix: templates_logs/
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Metadata:
cfn_nag:
rules_to_suppress:
- id: W51
reason: Bucket policy is not needed.
ResourcesBucket:
Type: AWS::S3::Bucket
Properties:
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerPreferred
LoggingConfiguration:
DestinationBucketName: !Ref LogsBucket
LogFilePrefix: templates_logs/
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Metadata:
cfn_nag:
rules_to_suppress:
- id: W51
reason: Bucket policy is not needed.
LogsBucket:
DeletionPolicy: Retain
Type: AWS::S3::Bucket
Properties:
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerPreferred
AccessControl: LogDeliveryWrite
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Metadata:
cfn_nag:
rules_to_suppress:
- id: W35
reason: This is the pipeline and solution log bucket and does not require access logging to be configured.
- id: W51
reason: Bucket policy is not needed.
Outputs:
LogsBucket:
Value: !Ref LogsBucket
BuildBucket:
Value: !Ref BuildBucket
RepoName:
Description: RepoName
Value: !Sub ${Repo.Name}
RepoHttpUrl:
Description: RepoCloneCommand
Value: !Sub ${Repo.CloneUrlHttp}
ResourcesBucket:
Value: !Ref ResourcesBucket
DataLakeBucket:
Value: !Ref DataLakeBucket
Export:
Name: !Sub ${ResourcePrefix}-DataLakeBucket
DataLakeBucketArn:
Value: !GetAtt DataLakeBucket.Arn
Export:
Name: !Sub ${ResourcePrefix}-DataLakeBucketArn
ResourcePrefixLowercase:
Value: !Ref ResourcePrefixLowercase
Export:
Name: !Sub ${ResourcePrefix}-ResourcePrefixLowercase
# aws cloudformation update-stack --stack-name ${PROJECT_NAME:-GenomicsAnalysis}-Pipeline --template-body file://pipe_cfn.yml --capabilities CAPABILITY_NAMED_IAM --output text --parameters ParameterKey=ResourcePrefix,ParameterValue=${PROJECT_NAME:-GenomicsAnalysis} ParameterKey=ResourcePrefixLowercase,ParameterValue=$(echo ${PROJECT_NAME:-GenomicsAnalysis} | tr '[:upper:]' '[:lower:]'); aws cloudformation wait stack-update-complete --stack-name ${PROJECT_NAME:-GenomicsAnalysis}-Pipeline