AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > backend-stack Metadata: AWS::ServerlessRepo::Application: Name: serverless-face-rekognition Description: This will setup a custom facial recognition backend api using serverless stack like S3, Lambda, Rekognition, Dynamodb Author: Pankaj Agrawal SpdxLicenseId: MIT-0 LicenseUrl: LICENSE.txt ReadmeUrl: README.md Labels: ['reckognition', 'apigateway', 's3', 'cicd', 'devops'] HomePageUrl: https://github.com/aws-samples/serverless-webapp-mono-repo-ci-cd-java SemanticVersion: 1.0.0 SourceCodeUrl: https://github.com/aws-samples/serverless-webapp-mono-repo-ci-cd-java Globals: Api: Cors: AllowMethods: "'OPTIONS,GET'" AllowHeaders: "'Content-Type'" AllowOrigin: "'*'" EndpointConfiguration: EDGE TracingEnabled: True Function: Timeout: 10 Tracing: Active Environment: Variables: POWERTOOLS_METRICS_NAMESPACE: ServerlessApp POWERTOOLS_SERVICE_NAME: ImageService Resources: LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/" ManagedPolicyArns: - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy Policies: - PolicyName: LambdaExecutionRole PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: arn:aws:logs:*:*:* - Effect: Allow Action: - s3:GetObject Resource: !Join ["", [!Join [":", ["arn", "aws", "s3", "", "", !Join ["-", ["java", "backend", "bucket", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]]]], "/*"]] - Effect: Allow Action: - rekognition:IndexFaces Resource: "*" - Effect: Allow Action: - dynamodb:PutItem Resource: !Join [":", ["arn", "aws", "dynamodb", !Ref "AWS::Region", !Ref "AWS::AccountId", !Join ["-", ["table/face", "id", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]]]] BootstrapExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/service-role/" ManagedPolicyArns: - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy Policies: - PolicyName: AmazonRekognition PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - rekognition:CreateCollection - rekognition:DeleteCollection - rekognition:ListCollections Resource: "*" - PolicyName: AWSLambdaLogs PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: "arn:aws:logs:*:*:*" ImageRekognition: Type: AWS::Serverless::Function Properties: Role: !GetAtt LambdaExecutionRole.Arn Description: Triggered by S3, indexes faces against a collection in Amazon Rekognition CodeUri: BackendFunction Handler: com.webapp.function.IndexImageHandler::handleRequest AutoPublishAlias: live Runtime: java8.al2 Timeout: 10 MemorySize: 1536 Layers: - !Sub arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:2 Environment: Variables: CollectionId: !Join ["-", ["collection", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] TableName: !Join ["-", ["face", "id", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] POWERTOOLS_SERVICE_NAME: ImageRekognition LAMBDA_INSIGHTS_LOG_LEVEL: info Events: S3Event: Type: S3 Properties: Bucket: Ref: UploadBucket Events: s3:ObjectCreated:* Filter: S3Key: Rules: - Name: prefix Value: index/ RekognitionLambdaPermission: Type: "AWS::Lambda::Permission" Properties: Action: "lambda:invokeFunction" FunctionName: !GetAtt ImageRekognition.Arn Principal: "s3.amazonaws.com" SourceArn: !Join [":", ["arn", "aws", "s3", "", "", !Join ["-", ["java", "backend", "bucket", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]]]] SourceAccount: !Ref AWS::AccountId UploadBucket: Type: "AWS::S3::Bucket" DependsOn: - RekognitionLambdaPermission Properties: BucketName: !Join ["-", ["java", "backend", "bucket", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] CorsConfiguration: CorsRules: - AllowedHeaders: - "*" AllowedMethods: - GET - PUT - POST - DELETE - HEAD AllowedOrigins: - "*" LambdaCreateCollection: Type: AWS::Serverless::Function Properties: Description: Custom resource function to create Rekognition collection CodeUri: BackendFunction Handler: com.webapp.function.CreateCollectionHandler::handleRequest Runtime: java8.al2 Layers: - !Sub arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:2 Role: !GetAtt BootstrapExecutionRole.Arn AutoPublishAlias: live Timeout: 10 MemorySize: 1536 Tracing: PassThrough PopulateCreateCollection: Type: "Custom::CreateCollection" Version: "1.0" Properties: ServiceToken: !GetAtt LambdaCreateCollection.Arn CollectionName: !Join ["-", ["collection", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] DynamoDBTable: Type: AWS::Serverless::SimpleTable Properties: PrimaryKey: Name: RekognitionId Type: String ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 TableName: !Join ["-", ["face", "id", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] S3UploaderFunction: Type: AWS::Serverless::Function Properties: Description: Generate presigned url for S3 bucket and attach to API gateway CodeUri: BackendFunction Handler: com.webapp.function.ImageUploadHandler::handleRequest Runtime: java8.al2 MemorySize: 1536 AutoPublishAlias: live Layers: - !Sub arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:2 Environment: Variables: UploadBucket: !Ref UploadBucket POWERTOOLS_SERVICE_NAME: ImageUploadHandler LAMBDA_INSIGHTS_LOG_LEVEL: info Policies: - CloudWatchLambdaInsightsExecutionRolePolicy - S3CrudPolicy: BucketName: !Ref UploadBucket Events: HttpPost: Type: Api Properties: Path: '/upload-url' Method: get ImageSearch: Type: AWS::Serverless::Function Properties: Description: Take image for recognition CodeUri: BackendFunction Handler: com.webapp.function.RecognizeImageHandler::handleRequest Runtime: java8.al2 MemorySize: 1536 AutoPublishAlias: live Layers: - !Sub arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:2 Environment: Variables: CollectionName: !Join ["-", ["collection", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] TableName: !Join ["-", ["face", "id", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] LAMBDA_INSIGHTS_LOG_LEVEL: info Policies: - CloudWatchLambdaInsightsExecutionRolePolicy - RekognitionReadPolicy: CollectionId: !Join ["-", ["collection", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] - DynamoDBReadPolicy: TableName: !Join ["-", ["face", "id", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] Events: HttpPost: Type: Api Properties: Path: '/recognise' Method: post Outputs: BucketName: Value: !Ref UploadBucket Description: Name of the S3 bucket