# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Amazon Software License (the "License"). # You may not use this file except in compliance with the License. # A copy of the License is located at # # http://www.apache.org/licenses/LICENSE-2.0 # # or in the "license" file accompanying this file. This file is distributed # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either # express or implied. See the License for the specific language governing # permissions and limitations under the License. Description: "(SO0084) - The AWS CloudFormation template for deployment of the document-understanding-solution. Version %%VERSION%%" Parameters: Email: Description: User email address Type: String AllowedPattern: (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]) KendraEnabled: Description: Amazon Kendra is added as an additional capability and can be used for exploring features such as Semantic Search, Adding FAQs and Access Control Lists. Type: String Default: "true" AllowedValues: - "true" - "false" ReadOnlyMode: Description: You will only be able to analyze the pre-loaded documents. You will not be able to upload documents from the web application UI. Type: String Default: "false" AllowedValues: - "true" - "false" CodeCommitRepository: Description: Enter the repository name that will be created Type: String AllowedPattern: "[a-zA-Z0-9-]+" Default: document-understanding-reference-architecture Version: Description: Solution Version Type: String Default: "%%VERSION%%" Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Pipeline Configuration Parameters: - CodeCommitRepository - Label: default: Solution Feature Configuration Parameters: - Version - Email ParameterLabels: CodeCommitRepository: default: CodeCommit Repository Name WebApp: default: Web Console Version: default: Solution Version Mappings: BuildEnv: Images: Standard5: "aws/codebuild/standard:5.0" CDK: StackName: "DUS" ClientStackName: "DUSClient" Metrics: SendAnonymousUsage: "true" SourceCode: Source: S3Bucket: "%%BUCKET_NAME%%" Version: "%%VERSION%%" SolutionName: "%%SOLUTION_NAME%%" KeyPrefix: "%%SOLUTION_NAME%%/%%VERSION%%" Resources: # CICD resources [start] DevOutputBucket: Type: AWS::S3::Bucket DeletionPolicy: Retain Properties: PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True Metadata: cfn_nag: rules_to_suppress: - id: W35 reason: "validated and does not require access logging to be configured." - id: W41 reason: "validated and does not require to encrypt the bucket." - id: W51 reason: "The dev output bucket does not require bucket policy because the bucket is only accessed by CodeBuild and CodePipeline." DocumentUnderstandingRepo: Type: AWS::CodeCommit::Repository DeletionPolicy: Retain Properties: RepositoryName: !Ref CodeCommitRepository RepositoryDescription: document understanding reference architecture ArtifactS3Bucket: Type: AWS::S3::Bucket DeletionPolicy: Retain Properties: PublicAccessBlockConfiguration: BlockPublicAcls: True BlockPublicPolicy: True IgnorePublicAcls: True RestrictPublicBuckets: True VersioningConfiguration: Status: Enabled Metadata: cfn_nag: rules_to_suppress: - id: W35 reason: "validated and does not require access logging to be configured." - id: W41 reason: "validated and does not require to encrypt the bucket." - id: W51 reason: "The artifact bucket does not require bucket policy because the bucket is only accessed by CodeBuild and CodePipeline." DevCodePipeline: Type: AWS::CodePipeline::Pipeline DependsOn: CICDCustomResource Properties: Name: !Sub ${CodeCommitRepository} RoleArn: !Sub ${CodePipelineRole.Arn} ArtifactStore: Type: S3 Location: !Ref ArtifactS3Bucket Stages: - Name: Source Actions: - Name: CodeCommit ActionTypeId: Category: Source Owner: AWS Version: "1" Provider: CodeCommit OutputArtifacts: - Name: SourceApp Configuration: RepositoryName: !Ref CodeCommitRepository BranchName: master PollForSourceChanges: false - Name: Deploy Actions: - Name: CDKDeploy InputArtifacts: - Name: SourceApp ActionTypeId: Category: Build Owner: AWS Version: "1" Provider: CodeBuild Configuration: ProjectName: !Ref CodeBuildCDK # CICD resources [end] CodeBuildCDK: Type: AWS::CodeBuild::Project Properties: Name: !Sub ${CodeCommitRepository}-CDK Description: "CDK project to deploy custom components for document understanding" ServiceRole: !Sub ${CodeBuildRole.Arn} EncryptionKey: !Sub arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/s3 Source: Type: CODEPIPELINE BuildSpec: | version: 0.2 phases: install: runtime-versions: nodejs: 14 ruby: 2.7 commands: - echo "This buildspec is based on image - aws/codebuild/amazonlinux2-x86_64-standard:4.0" - n 16 - node --version - echo "Installing jq package" - wget -O jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 - chmod +x ./jq - cp jq /usr/bin - echo "Installing pip" - curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py - python get-pip.py - echo "Installing moto for running tests" - pip install moto==2.3.2 - npm install -g cdk@1.203.0 - cdk --version - npm install -g typescript - tsc --version - echo "Installing Yarn" - curl -o- -L https://yarnpkg.com/install.sh | bash - echo "Injecting values for Deploy Type, Region, Email, Version, and boto/pdf lambda code S3 location to the project" - sed -i -e "s/SOURCE_BUCKET/$SOURCE_BUCKET-$AWS_REGION/g" ./source/lib/cdk-textract-stack.ts - sed -i -e "s/CODE_VERSION/$VERSION/g" ./source/lib/cdk-textract-stack.ts - sed -i -e "s/SOLUTION_NAME/$SOLUTION_NAME/g" ./source/lib/cdk-textract-stack.ts - sed -i -e "s/\"email\":.*/\"email\":\ \"$USER_EMAIL\",/g" "./source/package.json" - sed -i -e "s/\"region\":.*/\"region\":\ \"$AWS_REGION\"/g" "./source/package.json" - sed -i -e "s/\"isROMode\":.*/\"isROMode\":\ \"$READ_ONLY_MODE\",/g" "./source/package.json" - sed -i -e "s/\"enableKendra\":.*/\"enableKendra\":\ \"$KENDRA_ENABLED\",/g" "./source/package.json" - sed -i -e "s/\"stackname\":.*/\"stackname\":\ \"$MAIN_STACK_NAME\",/g" "./source/package.json" - sed -i -e "s/\"cicd\":.*/\"cicd\":\ \"true\",/g" "./source/package.json" build: commands: - cd ./source - echo "Installing all dependencies" - yarn - echo "----- Deploying complete solution -----" - yarn deploy-all artifacts: files: - '**/*' Environment: ComputeType: BUILD_GENERAL1_MEDIUM Image: !FindInMap [BuildEnv, Images, Standard5] Type: LINUX_CONTAINER EnvironmentVariables: - Name: BUILD_OUTPUT_BUCKET Value: !Ref DevOutputBucket - Name: MAIN_STACK_NAME Value: !FindInMap [BuildEnv, CDK, StackName] - Name: SOURCE_BUCKET Value: !FindInMap [SourceCode, Source, S3Bucket] - Name: VERSION Value: !FindInMap [SourceCode, Source, Version] - Name: USER_EMAIL Value: !Ref Email - Name: SOLUTION_NAME Value: !FindInMap [SourceCode, Source, SolutionName] - Name: KENDRA_ENABLED Value: !Ref KendraEnabled - Name: READ_ONLY_MODE Value: !Ref ReadOnlyMode Artifacts: Name: CodeBuild-CDK-output Type: CODEPIPELINE # CodeBuild projects [end] # CICD helper resources [start] CICDHelper: Type: "AWS::Lambda::Function" Metadata: cfn_nag: rules_to_suppress: - id: W58 reason: "Customer resource needs no additional permission to log to Cloudwatch" - id: W92 reason: "Impossible for us to define the correct concurrency for clients" - id: W89 reason: "No VPC used in this solution, therefore no need to deploy lambda inside a VPC" Properties: Description: "Document Understanding Solution CICD helper" Code: S3Bucket: !Join [ "-", [ !FindInMap ["SourceCode", "Source", "S3Bucket"], Ref: "AWS::Region", ], ] S3Key: !Join [ "/", [ !FindInMap ["SourceCode", "Source", "KeyPrefix"], "document-understanding-cicd.zip", ], ] Handler: index.handler Runtime: nodejs16.x Role: !GetAtt CICDHelperRole.Arn Timeout: 900 MemorySize: 2048 Environment: Variables: CODE_BUCKET: !Join [ "", [ !FindInMap ["SourceCode", "Source", "S3Bucket"], "-", !Ref "AWS::Region", ], ] CODE_KEY: !FindInMap ["SourceCode", "Source", "KeyPrefix"] CODE_SOURCE: "document-understanding-solution.zip" CODECOMMIT_REPO: !Sub ${DocumentUnderstandingRepo.Name} LOGGING_LEVEL: 2 CICDCustomResource: Type: "Custom::CreateCommit" DependsOn: CICDHelperPolicy Properties: ServiceToken: !GetAtt CICDHelper.Arn CDKManifestGenerator: Type: "Custom::ManifestGenerator" DependsOn: CICDCustomResource Properties: ServiceToken: !GetAtt CICDHelper.Arn Email: !Ref Email VERSION: !Ref Version ANONYMOUS_METRICS: !FindInMap [BuildEnv, Metrics, SendAnonymousUsage] CICDDeleteStack: Type: "Custom::DeleteStack" DependsOn: CICDHelperPolicy Properties: ServiceToken: !GetAtt CICDHelper.Arn STACK_NAME: !FindInMap [BuildEnv, CDK, StackName] CLIENT_STACK_NAME: !FindInMap [BuildEnv, CDK, ClientStackName] CDK_TOOLKIT_STACK_NAME: DocumentUnderstandingCDKToolkit # Custom resource [end] # IAM resources [start] CICDHelperRole: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Principal: Service: - "lambda.amazonaws.com" Action: - "sts:AssumeRole" Path: "/" CICDHelperPolicy: Type: "AWS::IAM::Policy" Metadata: cfn_nag: rules_to_suppress: - id: W13 reason: "Reviewed, actions split per service, and which cannot be applied at resource level. Because of CDK deployment we do not know the exact resource ARN" - id: F5 reason: "Reviewed, need permissions to delete various IAM resources" - id: W12 reason: "Resource level permissions are not supported by those services" Properties: PolicyName: cicdhelperpolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: "Allow" Action: - "logs:CreateLogGroup" - "logs:CreateLogStream" - "logs:PutLogEvents" - "logs:DescribeLogGroups" Resource: - !Join [ "", [ "arn:", !Ref "AWS::Partition", ":logs:", Ref: "AWS::Region", ":", !Ref "AWS::AccountId", ":log-group:/aws/lambda/", !Ref CICDHelper, ":*", ], ] - Effect: "Allow" Action: - "logs:PutResourcePolicy" Resource: - "*" # PutResourcePolicy requires access to "*" resources - Effect: "Allow" Action: - "codecommit:CreateCommit" - "codecommit:PutFile" - "codecommit:GetBranch" Resource: - !Sub ${DocumentUnderstandingRepo.Arn} - Effect: "Allow" Action: - "apigateway:Delete*" Resource: - !Sub "arn:${AWS::Partition}:apigateway:${AWS::Region}::*" - Effect: "Allow" Action: - "cloudformation:DeleteStack" - "cloudformation:Describe*" - "cloudformation:Delete*" Resource: - !Sub "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:*" - Effect: "Allow" Action: - "cognito-idp:AdminDeleteUser" - "cognito-idp:DeleteUser" - "cognito-idp:DeleteUserPool" - "cognito-idp:DeleteUserPoolClient" Resource: - !Sub "arn:${AWS::Partition}:cognito-idp:${AWS::Region}:${AWS::AccountId}:*" - Effect: "Allow" Action: - "cognito-identity:DeleteIdentityPool" - "cognito-identity:SetIdentityPoolRoles" Resource: - !Sub "arn:${AWS::Partition}:cognito-identity:${AWS::Region}:${AWS::AccountId}:*" - Effect: "Allow" Action: - "dynamodb:DeleteTable" - "dynamodb:Describe*" Resource: - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:*" - Effect: "Allow" Action: - "es:DeleteElasticsearchDomain" - "es:DescribeElasticsearchDomain" Resource: - !Sub "arn:${AWS::Partition}:es:${AWS::Region}:${AWS::AccountId}:domain/*" - Effect: "Allow" Action: - "iam:Delete*" - "iam:Describe*" - "iam:DetachRolePolicy" Resource: - !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:*" - Effect: "Allow" Action: - "lambda:GetEventSourceMapping" - "lambda:DeleteFunction" - "lambda:InvokeFunction" - "lambda:RemovePermission" - "lambda:DeleteLayerVersion" - "lambda:DeleteEventSourceMapping" Resource: - !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:*" - Effect: "Allow" Action: - "lambda:GetEventSourceMapping" - "lambda:DeleteEventSourceMapping" Resource: "*" # lambda permissions do not work without access to "*" resources - Effect: "Allow" Action: - "sns:DeleteTopic" - "sns:GetTopicAttributes" - "sns:Unsubscribe" Resource: - !Sub "arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:*" - Effect: "Allow" Action: - "sqs:SetQueueAttributes" - "sqs:DeleteQueue" Resource: - !Sub "arn:${AWS::Partition}:sqs:${AWS::Region}:${AWS::AccountId}:*" - Effect: "Allow" Action: - "s3:DeleteBucketPolicy" - "s3:DeleteBucket" Resource: - !Sub "arn:${AWS::Partition}:s3:::*" - Effect: "Allow" Action: - "cloudfront:Get*" - "cloudfront:GetCloudFrontOriginAccessIdentityConfig" - "cloudfront:Delete*" - "cloudfront:UpdateDistribution" Resource: # Cloudfront permissions do not work without access to "*" resources - "*" - Effect: "Allow" Action: - "s3:GetObject" Resource: - !Join [ "", [ "arn:", !Ref "AWS::Partition", ":s3:::", !FindInMap ["SourceCode", "Source", "S3Bucket"], "-", !Ref "AWS::Region", "/", !FindInMap ["SourceCode", "Source", "KeyPrefix"], "/document-understanding-solution.zip", ], ] Roles: - Ref: "CICDHelperRole" CodePipelineRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: | { "Statement": [{ "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": "codepipeline.amazonaws.com" } }] } Policies: - PolicyName: !Sub ${CodeCommitRepository}-codepipeline PolicyDocument: !Sub | { "Statement": [ { "Action": [ "s3:GetBucketVersioning" ], "Resource": [ "arn:${AWS::Partition}:s3:::${ArtifactS3Bucket}" ], "Effect": "Allow" }, { "Action": [ "s3:PutObject", "s3:GetObject", "S3:GetObjectVersion" ], "Resource": [ "arn:${AWS::Partition}:s3:::${ArtifactS3Bucket}/*" ], "Effect": "Allow" }, { "Action": [ "codecommit:BatchGetRepositories", "codecommit:UploadArchive", "codecommit:Get*", "codecommit:List*", "codecommit:GitPull" ], "Resource": "arn:${AWS::Partition}:codecommit:${AWS::Region}:${AWS::AccountId}:${CodeCommitRepository}", "Effect": "Allow" }, { "Action": [ "codebuild:BatchGetBuilds", "codebuild:StartBuild" ], "Resource": [ "arn:${AWS::Partition}:codebuild:${AWS::Region}:${AWS::AccountId}:project/${CodeBuildCDK}" ], "Effect": "Allow" } ] } CodeBuildRole: Type: AWS::IAM::Role Properties: Path: / AssumeRolePolicyDocument: | { "Version": "2012-10-17", "Statement": [{ "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": "codebuild.amazonaws.com" } }] } Policies: - PolicyName: !Sub ${CodeCommitRepository}-codebuild PolicyDocument: !Sub | # Cognito, ec2 (vpc), cloudfront, kms, lambda permissions do not work without access to "*" resources { "Statement": [ { "Effect": "Allow", "Resource": [ "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*" ], "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:DeleteLogStream", "logs:PutLogEvents", "logs:Describe*", "logs:PutRetentionPolicy", "logs:PutResourcePolicy" ] }, { "Effect": "Allow", "Resource": [ "arn:${AWS::Partition}:s3:::*" ], "Action": [ "s3:DeleteBucket", "s3:CreateBucket", "s3:DeleteBucketPolicy", "s3:CreateBucketPolicy", "s3:GetBucketPolicy", "s3:PutBucketPolicy", "s3:DeleteObject", "s3:PutObject", "s3:GetObject", "s3:GetObjectAcl", "s3:ListBucket", "s3:PutBucketLogging", "s3:GetBucketLocation", "s3:SetBucketEncryption", "s3:GetBucketAcl", "s3:PutBucketAcl", "s3:GetEncryptionConfiguration", "s3:PutBucketTagging", "s3:PutEncryptionConfiguration", "s3:PutPublicAccessBlock", "s3:GetPublicAccessBlock", "s3:GetAccountPublicAccessBlock", "s3:GetBucketPublicAccessBlock", "s3:PutAccountPublicAccessBlock", "s3:PutBucketPublicAccessBlock", "s3:GetBucketCORS", "s3:PutBucketCORS", "s3:GetBucketWebsite", "s3:PutBucketWebsite", "s3:PutLifecycleConfiguration", "s3:GetLifecycleConfiguration", "s3:PutBucketOwnershipControls" ] }, { "Effect": "Allow", "Resource": "arn:${AWS::Partition}:apigateway:${AWS::Region}::*", "Action": [ "apigateway:Post", "apigateway:Get*", "apigateway:Put", "apigateway:Patch", "apigateway:Create", "apigateway:Delete" ] }, { "Effect": "Allow", "Resource": "*", "Action": [ "cloudfront:CreateCloudFrontOriginAccessIdentity", "cloudfront:DeleteCloudFrontOriginAccessIdentity", "cloudfront:GetCloudFrontOriginAccessIdentityConfig", "cloudfront:GetCloudFrontOriginAccessIdentity" ] }, { "Effect": "Allow", "Resource": "arn:${AWS::Partition}:cloudfront::${AWS::AccountId}:distribution/*", "Action": [ "cloudfront:CreateDistribution", "cloudfront:DeleteDistribution", "cloudfront:TagResource", "cloudfront:GetDistribution", "cloudfront:UpdateDistribution" ] }, { "Effect": "Allow", "Resource": "arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:*", "Action": [ "cloudformation:GetTemplate", "cloudformation:DescribeStacks", "cloudformation:DescribeStackEvents", "cloudformation:CreateChangeSet", "cloudformation:ExecuteChangeSet", "cloudformation:DescribeChangeSet", "cloudformation:CreateStack", "cloudformation:Delete*", "cloudformation:List*" ] }, { "Effect": "Allow", "Resource": "*", "Action": [ "cognito-idp:AdminCreateUser", "cognito-idp:AdminDeleteUser", "cognito-idp:CreateUserPool", "cognito-idp:CreateUserPoolClient", "cognito-idp:DeleteIdentityProvider", "cognito-idp:DeleteUser", "cognito-idp:DeleteUserPool", "cognito-idp:DeleteUserPoolClient", "cognito-idp:Describe*", "cognito-idp:Get*", "cognito-idp:List*", "cognito-identity:CreateIdentityPool", "cognito-identity:DeleteIdentityPool", "cognito-identity:SetIdentityPoolRoles" ] }, { "Effect": "Allow", "Resource": "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:*", "Action": [ "dynamodb:CreateTable", "dynamodb:DeleteTable", "dynamodb:DescribeTable", "dynamodb:DescribeLimits", "dynamodb:ListTables", "dynamodb:ListStreams", "dynamodb:DescribeStream" ] }, { "Effect": "Allow", "Resource": "*", "Action": [ "ec2:AssociateRouteTable", "ec2:DisassociateRouteTable", "ec2:CreateNatGateway", "ec2:DeleteNatGateway", "ec2:AuthorizeSecurityGroupEgress", "ec2:AuthorizeSecurityGroupIngress", "ec2:allocateAddress", "ec2:releaseAddress", "ec2:CreateRoute", "ec2:DeleteRoute", "ec2:RevokeSecurityGroupIngress", "ec2:RevokeSecurityGroupEgress", "ec2:CreateInternetGateway", "ec2:DeleteInternetGateway", "ec2:AttachInternetGateway", "ec2:DetachInternetGateway", "ec2:CreateVpc", "ec2:AssociateSubnetCidrBlock", "ec2:AssociateVpcCidrBlock", "ec2:CreateSecurityGroup", "ec2:CreateSubnet", "ec2:DeleteVpc", "ec2:DeleteSecurityGroup", "ec2:DeleteSubnet", "ec2:Describe*", "ec2:describe*", "ec2:createTags", "ec2:ModifyVpcAttribute", "ec2:CreateRouteTable", "ec2:DeleteRouteTable", "ec2:ModifySubnetAttribute" ] }, { "Effect": "Allow", "Resource": "arn:${AWS::Partition}:es:${AWS::Region}:${AWS::AccountId}:domain/*", "Action": [ "es:Describe*", "es:CreateElasticsearchDomain", "es:CreateElasticsearchServiceRole", "es:DeleteElasticsearchDomain", "es:DeleteElasticsearchServiceRole", "es:List*", "es:UpdateElasticsearchDomainConfig" ] }, { "Effect": "Allow", "Resource": "arn:${AWS::Partition}:iam::${AWS::AccountId}:*", "Action": [ "iam:PassRole", "iam:CreateRole", "iam:DeleteRole", "iam:List*", "iam:Get*", "iam:AttachRolePolicy", "iam:PutRolePolicy", "iam:DeleteRolePolicy", "iam:DetachRolePolicy", "iam:CreateServiceLinkedRole", "iam:DeleteServiceLinkedRole" ] }, { "Effect": "Allow", "Resource": "*", "Action": [ "kms:CreateKey", "kms:DisableKey", "kms:EnableKeyRotation", "kms:DisableKeyRotation", "kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey", "kms:Describe*", "kms:GetKeyPolicy", "kms:PutKeyPolicy", "kms:CreateGrant", "kms:RetireGrant", "kms:RevokeGrant" ] }, { "Effect": "Allow", "Resource": "*", "Action": [ "lambda:CreateEventSourceMapping", "lambda:AddPermission", "lambda:CreateFunction", "lambda:DeleteEventSourceMapping", "lambda:DeleteFunction", "lambda:AddLayerVersionPermission", "lambda:DeleteLayerVersion", "lambda:PublishLayerVersion", "lambda:Get*", "lambda:List*", "lambda:PutFunctionConcurrency", "lambda:InvokeFunction" ] }, { "Effect": "Allow", "Resource": "arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:*", "Action": [ "sns:AddPermission", "sns:CreateTopic", "sns:DeleteTopic", "sns:GetTopicAttributes", "sns:ListSubscriptions", "sns:ListTopics", "sns:RemovePermission", "sns:SetTopicAttributes", "sns:SetSubscriptionAttributes", "sns:Subscribe", "sns:Unsubscribe", "sns:TagResource" ] }, { "Action": [ "sqs:AddPermission", "sqs:CreateQueue", "sqs:DeleteQueue", "sqs:GetQueueAttributes", "sqs:GetQueueUrl", "sqs:ListQueues", "sqs:SetQueueAttributes" ], "Resource": "arn:${AWS::Partition}:sqs:${AWS::Region}:${AWS::AccountId}:*", "Effect": "Allow" }, { "Action": [ "states:CreateActivity", "states:DeleteActivity", "states:CreateStateMachine", "states:DeleteStateMachine", "states:Describe*", "states:TagResource", "states:UntagResource" ], "Resource": "arn:${AWS::Partition}:states:${AWS::Region}:${AWS::AccountId}:stateMachine:*", "Effect": "Allow" } ] } AmazonCloudWatchEventRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - events.amazonaws.com Action: sts:AssumeRole Path: / Policies: - PolicyName: cwe-pipeline-execution PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: codepipeline:StartPipelineExecution Resource: !Join [ "", [ "arn:", !Ref "AWS::Partition", ":codepipeline:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":", !Ref DevCodePipeline, ], ] # IAM resources [start] # CloudWatch resources [start] AmazonCloudWatchEventRule: Type: AWS::Events::Rule Properties: EventPattern: source: - aws.codecommit detail-type: - "CodeCommit Repository State Change" resources: - !Join [ "", [ "arn:", !Ref "AWS::Partition", ":codecommit:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":", !Ref CodeCommitRepository, ], ] detail: event: - referenceCreated - referenceUpdated referenceType: - branch referenceName: - master Targets: - Arn: !Join [ "", [ "arn:", !Ref "AWS::Partition", ":codepipeline:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":", !Ref DevCodePipeline, ], ] RoleArn: !GetAtt AmazonCloudWatchEventRole.Arn Id: codepipeline-document-understanding Outputs: SolutionPipeline: Description: "Pipeline created for this solution." Value: !Sub ${CodeCommitRepository} PipelineBuildImage: Description: "Image used to build this pipeline" Value: !FindInMap [BuildEnv, Images, Standard5] PipelineS3Artifacts: Description: "Bucket for CodePipeline to store build artifacts" Value: !Ref ArtifactS3Bucket DistArtifactBucket: Description: "Bucket prefix that custom CFN templates will reference for artifacts (template will append [region-name] to this prefix)" Value: !Ref DevOutputBucket