AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: Amazon S3 Find and Forget API Globals: Function: Runtime: python3.9 Timeout: 180 Layers: !Ref CommonLayers Environment: Variables: AllowOrigin: !If - DefaultAccessControlOrigin - !Ref WebUIOrigin - !Ref AccessControlAllowOriginOverride ConfigParam: !Ref ConfigParameter DeletionQueueTable: !Ref DeletionQueueTableName DataMapperTable: !Ref DataMapperTableName GSIBucketCount: "1" JobTable: !Ref JobTableName JobTableDateGSI: !Ref JobTableDateGSI LogLevel: !Ref LogLevel Metadata: cfn-lint: config: ignore_checks: - W8001 # Bug in cfn-lint not detecting that the Condition is actually in use. Parameters: AccessControlAllowOriginOverride: Type: String ConfigParameter: Type: String CognitoUserPoolArn: Type: String CommonLayers: Type: CommaDelimitedList Description: Common layers supplied to all functions DataMapperTableName: Description: Table name for DataMapper Table Type: String DeletionQueueTableName: Description: Table name for Deletion Queue Table Type: String EnableAccessLogging: Description: Whether to enable access logs Type: String JobTableDateGSI: Description: Date ordered GSI for Jobs Table Type: String JobTableName: Description: Table name for Jobs Table Type: String LogLevel: Type: String Default: INFO AllowedValues: - CRITICAL - FATAL - ERROR - WARNING - INFO - DEBUG - NOTSET WebUIOrigin: Type: String DeployCognito: Type: String Conditions: EnableAccessLogging: !Equals [!Ref EnableAccessLogging, "true"] DefaultAccessControlOrigin: !Equals [!Ref AccessControlAllowOriginOverride, "false"] ShouldDeployCognito: !Equals [!Ref DeployCognito, "true"] Resources: Api: Type: AWS::Serverless::Api Properties: OpenApiVersion: '3.0.1' StageName: Prod MethodSettings: !If - EnableAccessLogging - - LoggingLevel: INFO DataTraceEnabled: false ResourcePath: '/*' HttpMethod: '*' - !Ref AWS::NoValue DefinitionBody: openapi: "3.0.1" info: title: "Amazon S3 Find And Forget API" version: "1.0" servers: - url: "https://your-apigw-id.execute-api.region.amazonaws.com/{basePath}" variables: basePath: default: "Prod" tags: - name: DataMapper description: Operations related to data mappers - name: DeletionQueue description: Operations related to the deletion queue - name: Jobs description: Operations related to jobs - name: Settings description: Operations related to solution settings paths: /v1/queue: get: summary: Lists deletion queue items tags: - DeletionQueue operationId: "listDeletionQueueMatches" security: - Authorizer: [] parameters: - '$ref': '#/components/parameters/StartAtQS' - '$ref': '#/components/parameters/PageSizeQS' responses: '200': description: OK content: application/json: schema: type: "object" title: "DeletionQueue" properties: MatchIds: type: "array" description: "The list of Match IDs currently in the queue" items: $ref: '#/components/schemas/DeletionQueueItem' NextStart: type: "string" nullable: true default: "" description: "The watermark to use when requesting the next page of results" x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetDeletionQueue.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" delete: summary: Starts a job for the items in the deletion queue tags: - DeletionQueue operationId: "startDeletionJob" security: - Authorizer: [] responses: '202': description: "Job Started" content: application/json: schema: $ref: '#/components/schemas/Job' '422': $ref: '#/components/responses/InvalidRequest' x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ProcessQueue.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" patch: summary: "Adds an item to the deletion queue (Deprecated: use PATCH /v1/queue/matches)" deprecated: true tags: - DeletionQueue operationId: "addItemToDeletionQueue" security: - Authorizer: [] responses: '201': description: "Created" content: application/json: schema: $ref: '#/components/schemas/DeletionQueueItem' '422': $ref: '#/components/responses/InvalidRequest' requestBody: description: "Request body containing details of the Match to add to the Deletion Queue" content: application/json: schema: $ref: '#/components/schemas/CreateDeletionQueueItem' required: true x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${EnqueueDeletion.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" /v1/queue/matches: delete: summary: Removes one or more items from the deletion queue tags: - DeletionQueue operationId: "deleteMatches" security: - Authorizer: [] responses: '204': description: OK requestBody: description: "Request body containing a list of Matches to be deleted" content: application/json: schema: title: "ListOfMatchDeletions" required: - "Matches" type: "object" properties: Matches: type: "array" description: "The list of Match IDs to remove from the deletion queue" items: title: "MatchDeletion" required: - "DeletionQueueItemId" type: "object" properties: DeletionQueueItemId: type: "string" description: "The Deletion Queue Item ID to remove from the deletion queue" required: true x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${CancelDeletion.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" patch: summary: Adds one or more items to the deletion queue tags: - DeletionQueue operationId: "addItemsToDeletionQueue" security: - Authorizer: [] responses: '201': description: "Created" content: application/json: schema: title: "ListOfDeletionQueueItem" required: - "Matches" type: "object" properties: Matches: type: "array" description: "List of Deletion Queue Item objects" items: $ref: '#/components/schemas/DeletionQueueItem' '422': $ref: '#/components/responses/InvalidRequest' requestBody: description: "Request body containing details of the Matches to add to the Deletion Queue" content: application/json: schema: title: "ListOfCreateDeletionQueueItems" required: - "Matches" type: "object" properties: Matches: type: "array" description: "List of Deletion Queue Items" items: $ref: '#/components/schemas/CreateDeletionQueueItem' required: true x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${EnqueueDeletions.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" /v1/jobs: get: summary: Lists all jobs tags: - Job operationId: "listJobs" security: - Authorizer: [] parameters: - '$ref': '#/components/parameters/StartAtQS' - '$ref': '#/components/parameters/PageSizeQS' responses: '200': description: "OK" content: application/json: schema: title: "ListOfJobs" type: "object" properties: Jobs: type: "array" description: "The list of jobs" items: $ref: '#/components/schemas/JobSummary' NextStart: type: "integer" nullable: true default: 0 description: "The watermark to use when requesting the next page of results" x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ListJobs.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" /v1/jobs/{job_id}: parameters: - '$ref': '#/components/parameters/JobId' get: summary: Returns the details of a job tags: - Job operationId: "getJob" security: - Authorizer: [] responses: '200': description: "OK" content: application/json: schema: $ref: '#/components/schemas/Job' x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetJob.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" /v1/jobs/{job_id}/events: parameters: - '$ref': '#/components/parameters/JobId' get: summary: Lists all events for a job tags: - Job operationId: "getJobEvents" security: - Authorizer: [] parameters: - '$ref': '#/components/parameters/StartAtQS' - '$ref': '#/components/parameters/PageSizeQS' - in: "query" name: "filter" required: "false" schema: oneOf: - type: "string" - type: "array" items: type: "string" pattern: "^(EventName)([=])([a-zA-Z0-9]+)$" pattern: "^(EventName)([=])([a-zA-Z0-9]+)$" description: > Filters to apply in the format [key][operator][value]. If multiple filters are supplied, they will applied on an **AND** basis. Supported keys: EventName. Supported Operators: = responses: '200': description: "OK" content: application/json: schema: title: "ListOfJobEvents" type: "object" properties: JobEvents: type: "array" description: "The list of job events" items: $ref: '#/components/schemas/JobEvent' NextStart: type: "integer" nullable: true default: 0 description: "The watermark to use when requesting the next page of results" x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ListJobEvents.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" /v1/data_mappers: get: summary: Lists data mappers tags: - DataMapper operationId: "listDataMappers" security: - Authorizer: [] parameters: - '$ref': '#/components/parameters/StartAtQS' - '$ref': '#/components/parameters/PageSizeQS' responses: '200': description: OK content: application/json: schema: title: "ListOfDataMappers" type: "object" properties: DataMappers: type: "array" description: "The list of data mappers" items: $ref: '#/components/schemas/DataMapper' NextStart: type: "string" nullable: true default: "" description: "The watermark to use when requesting the next page of results" x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetDataMappers.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" /v1/data_mappers/{data_mapper_id}: parameters: - '$ref': '#/components/parameters/DataMapperId' get: summary: Returns the details of a data mapper tags: - DataMapper operationId: "getDataMapper" security: - Authorizer: [] responses: '200': description: "OK" content: application/json: schema: $ref: '#/components/schemas/DataMapper' x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetDataMapper.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" put: summary: Creates or modifies a data mapper tags: - DataMapper operationId: "putDataMapper" security: - Authorizer: [] responses: '201': description: "OK" content: application/json: schema: $ref: '#/components/schemas/DataMapper' requestBody: description: "Request body containing details of the Data Mapper to create or modify" content: application/json: schema: $ref: '#/components/schemas/DataMapper' required: true x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PutDataMapper.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" delete: summary: Removes a data mapper tags: - DataMapper operationId: "deleteDataMapper" security: - Authorizer: [] responses: '204': description: OK x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DeleteDataMapper.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" /v1/settings: get: summary: Gets the solution settings tags: - Settings operationId: "getSettings" security: - Authorizer: [] responses: '200': description: "OK" content: application/json: schema: $ref: '#/components/schemas/Settings' x-amazon-apigateway-integration: uri: Fn::Sub: "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ListSettings.Arn}/invocations" passthroughBehavior: "when_no_match" httpMethod: "POST" type: "aws_proxy" components: parameters: DataMapperId: in: "path" name: "data_mapper_id" required: "true" schema: type: "string" description: "Data Mapper ID path parameter" JobId: in: "path" name: "job_id" required: "true" schema: type: "string" description: "Job ID path parameter" PageSizeQS: in: "query" name: "page_size" required: "false" schema: type: "integer" minimum: 1 maximum: 1000 description: "Page size query string parameter. Min: 1. Max: 1000" StartAtQS: in: "query" name: "start_at" required: "false" schema: type: "string" default: 0 description: "Start at watermark query string parameter" schemas: DataMapper: description: "A Data Mapper object" required: - "Columns" - "QueryExecutor" - "QueryExecutorParameters" - "RoleArn" type: "object" properties: DataMapperId: type: "string" description: "The ID of the data mapper" Format: type: "string" description: "The format of the dataset" enum: - "json" - "parquet" default: "parquet" QueryExecutor: type: "string" description: "The query executor used to query your dataset" enum: - "athena" Columns: minItems: 1 type: "array" description: "Columns to query for MatchIds the dataset" items: type: "string" QueryExecutorParameters: type: "object" description: "Details of the query executor parameters to use when the QueryExecutor is set to 'athena'" properties: DataCatalogProvider: description: "The data catalog provider which contains the database table with metadata about your S3 data lake" enum: - "glue" type: "string" Database: description: "The database in the data catalog which contains the metatadata table" type: "string" Table: description: "The table in the data catalog database containing the metatadata for your data lake" type: "string" PartitionKeys: description: "The partition keys to use on each query. This allows to control the number and the size of the queries. When omitted, all the table partitions are used." type: "array" items: type: "string" required: - "Database" - "Table" RoleArn: type: "string" description: "Role ARN to assume when performing operations in S3 for this data mapper. The role must have the exact name 'S3F2DataAccessRole'." pattern: '^arn:(aws[a-zA-Z-]*)?:iam::\d{12}:role\/S3F2DataAccessRole$' DeleteOldVersions: type: "boolean" description: "Toggles deleting all non-latest versions of an object after a new redacted version is created" default: "true" IgnoreObjectNotFoundExceptions: type: "boolean" description: "Toggles ignoring Object Not Found errors during deletion" default: "false" DeletionQueueItem: description: "A Deletion Queue Item object" type: "object" required: - "DeletionQueueItemId" - "Type" - "MatchId" - "CreatedAt" - "DataMappers" properties: DeletionQueueItemId: type: "string" description: "The Deletion Queue Item unique identifier" Type: type: "string" description: "MatchId Type" default: "Simple" enum: - "Simple" - "Composite" MatchId: oneOf: - type: "string" - type: "array" items: type: "object" required: - "Column" - "Value" properties: Column: type: "string" description: "Column Identifier" Value: type: "string" description: "Value for the given column" description: "The Match ID to remove from the deletion queue" CreatedAt: type: "integer" description: "Deletion queue item creation date as Epoch timestamp" DataMappers: type: "array" description: "The list of data mappers to apply to this Match ID" items: type: "string" CreateDeletionQueueItem: description: "A request to create a Deletion Queue Item" required: - "MatchId" type: "object" properties: Type: type: "string" description: "MatchId Type" enum: - "Simple" - "Composite" default: "Simple" MatchId: oneOf: - type: "string" - type: "array" items: type: "object" required: - "Column" - "Value" properties: Column: type: "string" description: "Column Identifier" Value: type: "string" description: "Value for the given column" description: "The Match ID to remove from the deletion queue" DataMappers: type: "array" description: "The list of data mappers to apply to this Match ID" default: ["*"] items: type: "string" JobSummary: description: "A Job summary object" type: "object" required: - "Id" - "JobStatus" - "CreatedAt" properties: Id: type: "string" description: "The Job ID" JobStatus: type: "string" description: "The Job status. When a job is first created, it will remain in queued till the workflow starts" default: "QUEUED" enum: - "QUEUED" - "RUNNING" - "FORGET_COMPLETED_CLEANUP_IN_PROGRESS" - "COMPLETED" - "COMPLETED_CLEANUP_FAILED" - "FAILED" - "FIND_FAILED" - "FORGET_FAILED" - "FORGET_PARTIALLY_FAILED" CreatedAt: type: "integer" description: "Job creation date as Epoch timestamp" default: JobStartTime: type: "integer" description: "Job start date as Epoch timestamp" JobFinishTime: type: "integer" description: "Job finish date as Epoch timestamp" TotalObjectUpdatedCount: type: "integer" description: "Total number of successfully updated objects" default: 0 TotalObjectUpdateSkippedCount: type: "integer" description: "Total number of skipped objects" default: 0 TotalObjectUpdateFailedCount: type: "integer" description: "Total number of objects which could not be successfully updated" default: 0 TotalObjectRollbackFailedCount: type: "integer" description: "Total number of objects which could not be successfully rolled back after detecting an integrity conflict" default: 0 TotalQueryCount: type: "integer" description: "Total number of queries executed during the find phase" default: 0 TotalQueryFailedCount: type: "integer" description: "Total number of unsuccessfully executed queries during the find phase" default: 0 TotalQueryScannedInBytes: type: "integer" description: "Total amount of data scanned during the find phase" default: 0 TotalQuerySucceededCount: type: "integer" description: "Total number of successfully executed queries during the find phase" default: 0 TotalQueryTimeInMillis: type: "integer" description: "Total time spent by the query executor for this job" default: 0 Job: description: "A Job object" type: "object" required: - "Id" - "JobStatus" - "CreatedAt" - "AthenaConcurrencyLimit" - "AthenaQueryMaxRetries" - "DeletionTasksMaxNumber" - "ForgetQueueWaitSeconds" - "QueryExecutionWaitSeconds" - "QueryQueueWaitSeconds" - "Sk" - "Type" - "GSIBucket" properties: Id: type: "string" description: "The Job ID" JobStatus: type: "string" description: "The Job status. When a job is first created, it will remain in queued till the workflow starts" default: "QUEUED" enum: - "QUEUED" - "RUNNING" - "FORGET_COMPLETED_CLEANUP_IN_PROGRESS" - "COMPLETED" - "COMPLETED_CLEANUP_FAILED" - "FAILED" - "FIND_FAILED" - "FORGET_FAILED" - "FORGET_PARTIALLY_FAILED" CreatedAt: type: "integer" description: "Job creation date as Epoch timestamp" default: JobStartTime: type: "integer" description: "Job start date as Epoch timestamp" JobFinishTime: type: "integer" description: "Job finish date as Epoch timestamp" AthenaConcurrencyLimit: type: "integer" description: "Athena concurrency setting for this job" AthenaQueryMaxRetries: type: "integer" description: "Max number of retries to each Athena query after a failure" DeletionTasksMaxNumber: type: "integer" description: "Max Fargate tasks setting for this job" ForgetQueueWaitSeconds: type: "integer" description: "Forget queue wait setting for this job" QueryExecutionWaitSeconds: type: "integer" description: "Query execution wait setting for this job" QueryQueueWaitSeconds: type: "integer" description: "Query queue worker wait setting for this job" TotalObjectUpdatedCount: type: "integer" description: "Total number of successfully updated objects" default: 0 TotalObjectUpdateSkippedCount: type: "integer" description: "Total number of skipped objects" default: 0 TotalObjectUpdateFailedCount: type: "integer" description: "Total number of objects which could not be successfully updated" default: 0 TotalObjectRollbackFailedCount: type: "integer" description: "Total number of objects which could not be successfully rolled back after detecting an integrity conflict" default: 0 TotalQueryCount: type: "integer" description: "Total number of queries executed during the find phase" default: 0 TotalQueryFailedCount: type: "integer" description: "Total number of unsuccessfully executed queries during the find phase" default: 0 TotalQueryScannedInBytes: type: "integer" description: "Total amount of data scanned during the find phase" default: 0 TotalQuerySucceededCount: type: "integer" description: "Total number of successfully executed queries during the find phase" default: 0 TotalQueryTimeInMillis: type: "integer" description: "Total time spent by the query executor for this job" default: 0 Expires: type: "integer" description: "Expiry date when the item will be deleted as Epoch time" Sk: type: "string" description: "Internal field used as part of DynamoDB single table design" Type: type: "string" enum: - "Job" description: "Internal field used as part of DynamoDB single table design" GSIBucket: type: "string" description: "Internal field used as part of DynamoDB single table design" JobEvent: description: "A Job Event object" type: "object" properties: Id: type: "string" description: "The Job ID" CreatedAt: type: "integer" description: "Job creation date as Epoch timestamp" default: EventName: type: "string" description: "The Job Event name" EventData: type: "object" description: "Free form field containing data about the event. Structure varies based on the event" EmitterId: type: "string" description: "The identifier for the service or service instance which emitted the event" example: "StepFunctions" Expires: type: "integer" description: "Expiry date when the item will be deleted as Epoch time" Sk: type: "string" description: "Internal field used as part of DynamoDB single table design" Type: type: "string" enum: - "Job" description: "Internal field used as part of DynamoDB single table design" Settings: description: "A Settings object" type: "object" properties: AthenaConcurrencyLimit: type: "integer" description: "Athena concurrency setting for this job" AthenaQueryMaxRetries: type: "integer" description: "Max number of retries to each Athena query after a failure" DeletionTasksMaxNumber: type: "integer" description: "Max Fargate tasks setting for this job" ForgetQueueWaitSeconds: type: "integer" description: "Forget queue wait setting for this job" QueryExecutionWaitSeconds: type: "integer" description: "Query execution wait setting for this job" QueryQueueWaitSeconds: type: "integer" description: "Query queue worker wait setting for this job" required: - "AthenaConcurrencyLimit" - "AthenaQueryMaxRetries" - "DeletionTasksMaxNumber" - "ForgetQueueWaitSeconds" - "QueryExecutionWaitSeconds" - "QueryQueueWaitSeconds" Error: description: "A standard error object" type: "object" properties: Message: description: "Error message" type: "string" required: - "Message" responses: InvalidRequest: description: "Error response for invalid requests" content: application/json: schema: $ref: '#/components/schemas/Error' securitySchemes: Authorizer: type: "apiKey" name: "Authorization" in: "header" x-amazon-apigateway-authtype: !If [ShouldDeployCognito, "cognito_user_pools", "awsSigv4"] x-amazon-apigateway-authorizer: !If - ShouldDeployCognito - providerARNs: - Ref: CognitoUserPoolArn type: "cognito_user_pools" - !Ref AWS::NoValue x-amazon-apigateway-request-validator: All x-amazon-apigateway-request-validators: All: validateRequestParameters: true validateRequestBody: true EndpointConfiguration: REGIONAL Cors: AllowMethods: "'*'" AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" AllowOrigin: !If - DefaultAccessControlOrigin - !Sub "'${WebUIOrigin}'" - !Sub "'${AccessControlAllowOriginOverride}'" GatewayResponses: DEFAULT_4XX: ResponseTemplates: "application/json": '{ "Message": $context.error.messageString }' ResponseParameters: Headers: Access-Control-Allow-Methods: "'*'" Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" Access-Control-Allow-Origin: !If - DefaultAccessControlOrigin - !Sub "'${WebUIOrigin}'" - !Sub "'${AccessControlAllowOriginOverride}'" BAD_REQUEST_BODY: StatusCode: 422 ResponseTemplates: "application/json": '{ "Message": $context.error.messageString }' ResponseParameters: Headers: Access-Control-Allow-Methods: "'*'" Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" Access-Control-Allow-Origin: !If - DefaultAccessControlOrigin - !Sub "'${WebUIOrigin}'" - !Sub "'${AccessControlAllowOriginOverride}'" BAD_REQUEST_PARAMETERS: StatusCode: 422 ResponseTemplates: "application/json": '{ "Message": $context.error.messageString }' ResponseParameters: Headers: Access-Control-Allow-Methods: "'*'" Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" Access-Control-Allow-Origin: !If - DefaultAccessControlOrigin - !Sub "'${WebUIOrigin}'" - !Sub "'${AccessControlAllowOriginOverride}'" DEFAULT_5XX: ResponseTemplates: "application/json": '{ "Message": $context.error.messageString }' ResponseParameters: Headers: Access-Control-Allow-Methods: "'*'" Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'" Access-Control-Allow-Origin: !If - DefaultAccessControlOrigin - !Sub "'${WebUIOrigin}'" - !Sub "'${AccessControlAllowOriginOverride}'" ## Queue EnqueueDeletion: Type: AWS::Serverless::Function Properties: Handler: handlers.enqueue_handler CodeUri: ../backend/lambdas/queue/ Events: Get: Type: Api Properties: Path: /v1/queue Method: PATCH RestApiId: !Ref Api Policies: - DynamoDBCrudPolicy: TableName: !Ref DeletionQueueTableName EnqueueDeletions: Type: AWS::Serverless::Function Properties: Handler: handlers.enqueue_batch_handler CodeUri: ../backend/lambdas/queue/ Events: Get: Type: Api Properties: Path: /v1/queue/matches Method: PATCH RestApiId: !Ref Api Policies: - DynamoDBCrudPolicy: TableName: !Ref DeletionQueueTableName GetDeletionQueue: Type: AWS::Serverless::Function Properties: Handler: handlers.get_handler CodeUri: ../backend/lambdas/queue/ Events: Get: Type: Api Properties: Path: /v1/queue Method: GET RestApiId: !Ref Api Policies: - DynamoDBCrudPolicy: TableName: !Ref DeletionQueueTableName CancelDeletion: Type: AWS::Serverless::Function Properties: Handler: handlers.cancel_handler CodeUri: ../backend/lambdas/queue/ Events: Get: Type: Api Properties: Path: /v1/queue/matches Method: DELETE RestApiId: !Ref Api Policies: - DynamoDBReadPolicy: TableName: !Ref JobTableName - DynamoDBCrudPolicy: TableName: !Ref DeletionQueueTableName ProcessQueue: Type: AWS::Serverless::Function Properties: Handler: handlers.process_handler CodeUri: ../backend/lambdas/queue/ MemorySize: 512 Events: Get: Type: Api Properties: Path: /v1/queue Method: DELETE RestApiId: !Ref Api Policies: - DynamoDBCrudPolicy: TableName: !Ref DeletionQueueTableName - DynamoDBCrudPolicy: TableName: !Ref JobTableName - Statement: - Action: "ssm:GetParameter" Effect: "Allow" Resource: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${ConfigParameter}" # DataMappers PutDataMapper: Type: AWS::Serverless::Function Properties: Handler: handlers.put_data_mapper_handler CodeUri: ../backend/lambdas/data_mappers/ Events: Put: Type: Api Properties: Path: /v1/data_mappers/{data_mapper_id} Method: PUT RestApiId: !Ref Api Policies: - Statement: - Action: - "glue:BatchGetPartition" - "glue:GetDatabase*" - "glue:GetPartition*" - "glue:GetTable*" Effect: "Allow" Resource: - !Sub "arn:${AWS::Partition}:glue:*:*:catalog*" - !Sub "arn:${AWS::Partition}:glue:*:*:database*" - !Sub "arn:${AWS::Partition}:glue:*:*:table*" - !Sub "arn:${AWS::Partition}:glue:*:*:partition*" - DynamoDBCrudPolicy: TableName: !Ref DataMapperTableName GetDataMapper: Type: AWS::Serverless::Function Properties: Handler: handlers.get_data_mapper_handler CodeUri: ../backend/lambdas/data_mappers/ Events: Get: Type: Api Properties: Path: /v1/data_mappers/{data_mapper_id} Method: GET RestApiId: !Ref Api Policies: - DynamoDBReadPolicy: TableName: !Ref DataMapperTableName GetDataMappers: Type: AWS::Serverless::Function Properties: Handler: handlers.get_data_mappers_handler CodeUri: ../backend/lambdas/data_mappers/ Events: Get: Type: Api Properties: Path: /v1/data_mappers Method: GET RestApiId: !Ref Api Policies: - DynamoDBCrudPolicy: TableName: !Ref DataMapperTableName DeleteDataMapper: Type: AWS::Serverless::Function Properties: Handler: handlers.delete_data_mapper_handler CodeUri: ../backend/lambdas/data_mappers/ Events: Get: Type: Api Properties: Path: /v1/data_mappers/{data_mapper_id} Method: DELETE RestApiId: !Ref Api Policies: - DynamoDBReadPolicy: TableName: !Ref JobTableName - DynamoDBCrudPolicy: TableName: !Ref DataMapperTableName # Jobs GetJob: Type: AWS::Serverless::Function Properties: Handler: handlers.get_job_handler CodeUri: ../backend/lambdas/jobs/ Events: Get: Type: Api Properties: Path: /v1/jobs/{job_id} Method: GET RestApiId: !Ref Api Policies: - DynamoDBReadPolicy: TableName: !Ref JobTableName ListJobs: Type: AWS::Serverless::Function Properties: Handler: handlers.list_jobs_handler CodeUri: ../backend/lambdas/jobs/ Events: List: Type: Api Properties: Path: /v1/jobs Method: GET RestApiId: !Ref Api Policies: - DynamoDBReadPolicy: TableName: !Ref JobTableName ListJobEvents: Type: AWS::Serverless::Function Properties: Handler: handlers.list_job_events_handler CodeUri: ../backend/lambdas/jobs/ Events: List: Type: Api Properties: Path: /v1/jobs/{job_id}/events Method: GET RestApiId: !Ref Api Policies: - DynamoDBReadPolicy: TableName: !Ref JobTableName # Settings ListSettings: Type: AWS::Serverless::Function Properties: Handler: handlers.list_settings_handler CodeUri: ../backend/lambdas/settings/ Events: List: Type: Api Properties: Path: /v1/settings Method: GET RestApiId: !Ref Api Policies: - Statement: - Action: "ssm:GetParameter" Effect: "Allow" Resource: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter${ConfigParameter}" Outputs: AccessControlAllowOriginHeader: Description: Access-Control-Allow-Origin header sent from API endpoints Value: !If - DefaultAccessControlOrigin - !Ref WebUIOrigin - !Ref AccessControlAllowOriginOverride ApiArn: Value: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${Api}/${Api.Stage}/*/* ApiUrl: Description: API endpoint URL for Prod environment Value: !Sub https://${Api}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${Api.Stage}/ PutDataMapperRole: Description: Role used by the PutDataMapper API Value: !Ref PutDataMapperRole