Lab1/event-engine-assets/packaged.yaml [1:1030]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 'Lab1 - Basic Serverless Application'

Parameters:
  EEAssetsBucket:
    Description: "Region-specific assets S3 bucket name (e.g. ee-assets-prod-us-east-1)"
    Type: String
    Default: "aws-sam-cli-managed-default-samclisourcebucket-8tf6bmi4rdcx"
  EEAssetsKeyPrefix:
    Description: "S3 key prefix where this modules assets are stored. (e.g. modules/my_module/v1/)"
    Type: String
    Default: "serverless-saas/"
  StageName:
    Type: String
    Default: prod
    Description: Stage Name for the api

Globals:
  Function:
    Timeout: 29
    Layers:
    - Fn::Sub: arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:14
    Environment:
      Variables:
        LOG_LEVEL: DEBUG
  
Resources:
  ServerlessSaaSLayers:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: serverless-saas-workshoplab1
      Description: Utilities for project
      ContentUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}1b6d1796b5948e393749602691c77e44
      CompatibleRuntimes:
      - python3.8
      LicenseInfo: MIT
      RetentionPolicy: Retain
    Metadata:
      BuildMethod: python3.8
  ProductTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: productId
        AttributeType: S
      KeySchema:
      - AttributeName: productId
        KeyType: HASH
      BillingMode: PAY_PER_REQUEST
      TableName: Product-Lab1
  OrderTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: orderId
        AttributeType: S
      KeySchema:
      - AttributeName: orderId
        KeyType: HASH
      BillingMode: PAY_PER_REQUEST
      TableName: Order-Lab1
  ProductFunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: product-function-execution-role-lab1
      Path: /
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess
      Policies:
      - PolicyName: product-function-policy-lab1
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Action:
            - dynamodb:GetItem
            - dynamodb:UpdateItem
            - dynamodb:PutItem
            - dynamodb:DeleteItem
            - dynamodb:Query
            - dynamodb:Scan
            Resource:
            - Fn::GetAtt:
              - ProductTable
              - Arn
  GetProductFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.get_product
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  GetProductsFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.get_products
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  CreateProductFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.create_product
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  UpdateProductFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.update_product
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  DeleteProductFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.delete_product
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  OrderFunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: order-function-execution-role-lab1
      Path: /
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess
      Policies:
      - PolicyName: order-function-policy-lab1
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Action:
            - dynamodb:GetItem
            - dynamodb:UpdateItem
            - dynamodb:PutItem
            - dynamodb:DeleteItem
            - dynamodb:Query
            - dynamodb:Scan
            Resource:
            - Fn::GetAtt:
              - OrderTable
              - Arn
  GetOrdersFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.get_orders
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  GetOrderFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.get_order
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  CreateOrderFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.create_order
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  UpdateOrderFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.update_order
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  DeleteOrderFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.delete_order
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  ApiGatewayAccessLogs:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: /aws/api-gateway/access-logs-serverless-saas-workshop-lab1-api
      RetentionInDays: 30
  ApiGatewayApi:
    Type: AWS::Serverless::Api
    Properties:
      MethodSettings:
      - DataTraceEnabled: true
        LoggingLevel: INFO
        MetricsEnabled: true
        ResourcePath: /*
        HttpMethod: '*'
      AccessLogSetting:
        DestinationArn:
          Fn::GetAtt:
          - ApiGatewayAccessLogs
          - Arn
        Format: '{ "requestId":"$context.requestId", "ip": "$context.identity.sourceIp",
          "caller":"$context.identity.caller", "user":"$context.identity.user","requestTime":"$context.requestTime",
          "httpMethod":"$context.httpMethod","resourcePath":"$context.resourcePath",
          "status":"$context.status","protocol":"$context.protocol", "responseLength":"$context.responseLength"
          }'
      TracingEnabled: true
      DefinitionBody:
        openapi: 3.0.1
        info:
          title: serverless-saas-workshop-lab1
        basePath:
          Fn::Join:
          - ''
          - - /
            - Ref: StageName
        schemes:
        - https
        paths:
          /order/{id}:
            get:
              summary: Returns a order
              description: Return a order by a order id.
              produces:
              - application/json
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - GetOrderFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            put:
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - UpdateOrderFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            delete:
              summary: Deletes a order
              description: Deletes a order by a order id.
              produces:
              - application/json
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - DeleteOrderFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /orders:
            get:
              summary: Returns all orders
              description: Returns all orders.
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - GetOrdersFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /order:
            post:
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - CreateOrderFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /product/{id}:
            get:
              summary: Returns a product
              description: Return a product by a product id.
              produces:
              - application/json
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - GetProductFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            put:
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - UpdateProductFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            delete:
              summary: Deletes a product
              description: Deletes a product by a product id.
              produces:
              - application/json
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - DeleteProductFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /products:
            get:
              summary: Returns all products
              description: Returns all products.
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - GetProductsFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /product:
            post:
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - CreateProductFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
      StageName:
        Ref: StageName
  GetProductsLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - GetProductsFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  GetProductLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - GetProductFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  CreateProductLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - CreateProductFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  UpdateProductLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - UpdateProductFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  DeleteProductLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - DeleteProductFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  GetOrdersLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - GetOrdersFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  GetOrderLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - GetOrderFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  CreateOrderLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - CreateOrderFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  UpdateOrderLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - UpdateOrderFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  DeleteOrderLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - DeleteOrderFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  CloudFrontOriginAccessIdentity:
    Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: Origin Access Identity for CloudFront Distribution
  AppBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
  AppSiteReadPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket:
        Ref: AppBucket
      PolicyDocument:
        Statement:
        - Action: s3:GetObject
          Effect: Allow
          Resource:
            Fn::Sub: arn:aws:s3:::${AppBucket}/*
          Principal:
            CanonicalUser:
              Fn::GetAtt:
              - CloudFrontOriginAccessIdentity
              - S3CanonicalUserId
  ApplicationSite:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        CustomErrorResponses:
        - ErrorCode: 403
          ResponseCode: 200
          ResponsePagePath: /index.html
        - ErrorCode: 404
          ResponseCode: 200
          ResponsePagePath: /index.html
        DefaultCacheBehavior:
          AllowedMethods:
          - DELETE
          - GET
          - HEAD
          - OPTIONS
          - PATCH
          - POST
          - PUT
          Compress: true
          DefaultTTL: 3600
          ForwardedValues:
            Cookies:
              Forward: none
            QueryString: false
          MaxTTL: 86400
          MinTTL: 60
          TargetOriginId: lab1-tenantapp-s3origin
          ViewerProtocolPolicy: allow-all
        DefaultRootObject: index.html
        Enabled: true
        HttpVersion: http2
        Origins:
        - DomainName:
            Fn::GetAtt:
            - AppBucket
            - RegionalDomainName
          Id: lab1-tenantapp-s3origin
          S3OriginConfig:
            OriginAccessIdentity:
              Fn::Join:
              - ''
              - - origin-access-identity/cloudfront/
                - Ref: CloudFrontOriginAccessIdentity
        PriceClass: PriceClass_All
Outputs:
  APIGatewayURL:
    Description: API Gateway endpoint URL for API
    Value:
      Fn::Join:
      - ''
      - - Fn::Sub: https://${ApiGatewayApi}.execute-api.${AWS::Region}.amazonaws.com/
        - Ref: StageName
        - /
  ApplicationSite:
    Description: The name of the CloudFront url for Tenant Management site
    Value:
      Fn::GetAtt:
      - ApplicationSite
      - DomainName
  AppBucket:
    Description: The name of the bucket for uploading the Tenant Management site to
    Value:
      Ref: AppBucket
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



Solution/Lab1/event-engine-assets/packaged.yaml [1:1030]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 'Lab1 - Basic Serverless Application'

Parameters:
  EEAssetsBucket:
    Description: "Region-specific assets S3 bucket name (e.g. ee-assets-prod-us-east-1)"
    Type: String
    Default: "aws-sam-cli-managed-default-samclisourcebucket-8tf6bmi4rdcx"
  EEAssetsKeyPrefix:
    Description: "S3 key prefix where this modules assets are stored. (e.g. modules/my_module/v1/)"
    Type: String
    Default: "serverless-saas/"
  StageName:
    Type: String
    Default: prod
    Description: Stage Name for the api

Globals:
  Function:
    Timeout: 29
    Layers:
    - Fn::Sub: arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:14
    Environment:
      Variables:
        LOG_LEVEL: DEBUG
  
Resources:
  ServerlessSaaSLayers:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: serverless-saas-workshoplab1
      Description: Utilities for project
      ContentUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}1b6d1796b5948e393749602691c77e44
      CompatibleRuntimes:
      - python3.8
      LicenseInfo: MIT
      RetentionPolicy: Retain
    Metadata:
      BuildMethod: python3.8
  ProductTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: productId
        AttributeType: S
      KeySchema:
      - AttributeName: productId
        KeyType: HASH
      BillingMode: PAY_PER_REQUEST
      TableName: Product-Lab1
  OrderTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: orderId
        AttributeType: S
      KeySchema:
      - AttributeName: orderId
        KeyType: HASH
      BillingMode: PAY_PER_REQUEST
      TableName: Order-Lab1
  ProductFunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: product-function-execution-role-lab1
      Path: /
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess
      Policies:
      - PolicyName: product-function-policy-lab1
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Action:
            - dynamodb:GetItem
            - dynamodb:UpdateItem
            - dynamodb:PutItem
            - dynamodb:DeleteItem
            - dynamodb:Query
            - dynamodb:Scan
            Resource:
            - Fn::GetAtt:
              - ProductTable
              - Arn
  GetProductFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.get_product
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  GetProductsFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.get_products
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  CreateProductFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.create_product
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  UpdateProductFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.update_product
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  DeleteProductFunction:
    Type: AWS::Serverless::Function
    DependsOn: ProductFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}3f9284a8b1fb9547d59e56cc8560b94c
      Handler: product_service.delete_product
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - ProductFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: ProductService
          PRODUCT_TABLE_NAME:
            Ref: ProductTable
  OrderFunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: order-function-execution-role-lab1
      Path: /
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      ManagedPolicyArns:
      - arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy
      - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      - arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess
      Policies:
      - PolicyName: order-function-policy-lab1
        PolicyDocument:
          Version: 2012-10-17
          Statement:
          - Effect: Allow
            Action:
            - dynamodb:GetItem
            - dynamodb:UpdateItem
            - dynamodb:PutItem
            - dynamodb:DeleteItem
            - dynamodb:Query
            - dynamodb:Scan
            Resource:
            - Fn::GetAtt:
              - OrderTable
              - Arn
  GetOrdersFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.get_orders
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  GetOrderFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.get_order
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  CreateOrderFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.create_order
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  UpdateOrderFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.update_order
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  DeleteOrderFunction:
    Type: AWS::Serverless::Function
    DependsOn: OrderFunctionExecutionRole
    Properties:
      CodeUri: 
        Bucket: !Ref EEAssetsBucket
        Key: !Sub ${EEAssetsKeyPrefix}ac28465dbac64f71e4739d551119c420
      Handler: order_service.delete_order
      Runtime: python3.8
      Tracing: Active
      Role:
        Fn::GetAtt:
        - OrderFunctionExecutionRole
        - Arn
      Layers:
      - Ref: ServerlessSaaSLayers
      Environment:
        Variables:
          POWERTOOLS_SERVICE_NAME: OrderService
          ORDER_TABLE_NAME:
            Ref: OrderTable
  ApiGatewayAccessLogs:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: /aws/api-gateway/access-logs-serverless-saas-workshop-lab1-api
      RetentionInDays: 30
  ApiGatewayApi:
    Type: AWS::Serverless::Api
    Properties:
      MethodSettings:
      - DataTraceEnabled: true
        LoggingLevel: INFO
        MetricsEnabled: true
        ResourcePath: /*
        HttpMethod: '*'
      AccessLogSetting:
        DestinationArn:
          Fn::GetAtt:
          - ApiGatewayAccessLogs
          - Arn
        Format: '{ "requestId":"$context.requestId", "ip": "$context.identity.sourceIp",
          "caller":"$context.identity.caller", "user":"$context.identity.user","requestTime":"$context.requestTime",
          "httpMethod":"$context.httpMethod","resourcePath":"$context.resourcePath",
          "status":"$context.status","protocol":"$context.protocol", "responseLength":"$context.responseLength"
          }'
      TracingEnabled: true
      DefinitionBody:
        openapi: 3.0.1
        info:
          title: serverless-saas-workshop-lab1
        basePath:
          Fn::Join:
          - ''
          - - /
            - Ref: StageName
        schemes:
        - https
        paths:
          /order/{id}:
            get:
              summary: Returns a order
              description: Return a order by a order id.
              produces:
              - application/json
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - GetOrderFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            put:
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - UpdateOrderFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            delete:
              summary: Deletes a order
              description: Deletes a order by a order id.
              produces:
              - application/json
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - DeleteOrderFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /orders:
            get:
              summary: Returns all orders
              description: Returns all orders.
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - GetOrdersFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /order:
            post:
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - CreateOrderFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /product/{id}:
            get:
              summary: Returns a product
              description: Return a product by a product id.
              produces:
              - application/json
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - GetProductFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            put:
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - UpdateProductFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            delete:
              summary: Deletes a product
              description: Deletes a product by a product id.
              produces:
              - application/json
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - DeleteProductFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /products:
            get:
              summary: Returns all products
              description: Returns all products.
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - GetProductsFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
          /product:
            post:
              produces:
              - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Join:
                  - ''
                  - - Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - Fn::GetAtt:
                      - CreateProductFunction
                      - Arn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            options:
              consumes:
              - application/json
              produces:
              - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: '''DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'''
                      method.response.header.Access-Control-Allow-Headers: '''Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'''
                      method.response.header.Access-Control-Allow-Origin: '''*'''
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock
      StageName:
        Ref: StageName
  GetProductsLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - GetProductsFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  GetProductLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - GetProductFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  CreateProductLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - CreateProductFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  UpdateProductLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - UpdateProductFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  DeleteProductLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - DeleteProductFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  GetOrdersLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - GetOrdersFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  GetOrderLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - GetOrderFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  CreateOrderLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - CreateOrderFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  UpdateOrderLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - UpdateOrderFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  DeleteOrderLambdaApiGatewayExecutionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName:
        Fn::GetAtt:
        - DeleteOrderFunction
        - Arn
      Principal: apigateway.amazonaws.com
      SourceArn:
        Fn::Join:
        - ''
        - - 'arn:aws:execute-api:'
          - Ref: AWS::Region
          - ':'
          - Ref: AWS::AccountId
          - ':'
          - Ref: ApiGatewayApi
          - /*/*/*
  CloudFrontOriginAccessIdentity:
    Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: Origin Access Identity for CloudFront Distribution
  AppBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
  AppSiteReadPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket:
        Ref: AppBucket
      PolicyDocument:
        Statement:
        - Action: s3:GetObject
          Effect: Allow
          Resource:
            Fn::Sub: arn:aws:s3:::${AppBucket}/*
          Principal:
            CanonicalUser:
              Fn::GetAtt:
              - CloudFrontOriginAccessIdentity
              - S3CanonicalUserId
  ApplicationSite:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        CustomErrorResponses:
        - ErrorCode: 403
          ResponseCode: 200
          ResponsePagePath: /index.html
        - ErrorCode: 404
          ResponseCode: 200
          ResponsePagePath: /index.html
        DefaultCacheBehavior:
          AllowedMethods:
          - DELETE
          - GET
          - HEAD
          - OPTIONS
          - PATCH
          - POST
          - PUT
          Compress: true
          DefaultTTL: 3600
          ForwardedValues:
            Cookies:
              Forward: none
            QueryString: false
          MaxTTL: 86400
          MinTTL: 60
          TargetOriginId: lab1-tenantapp-s3origin
          ViewerProtocolPolicy: allow-all
        DefaultRootObject: index.html
        Enabled: true
        HttpVersion: http2
        Origins:
        - DomainName:
            Fn::GetAtt:
            - AppBucket
            - RegionalDomainName
          Id: lab1-tenantapp-s3origin
          S3OriginConfig:
            OriginAccessIdentity:
              Fn::Join:
              - ''
              - - origin-access-identity/cloudfront/
                - Ref: CloudFrontOriginAccessIdentity
        PriceClass: PriceClass_All
Outputs:
  APIGatewayURL:
    Description: API Gateway endpoint URL for API
    Value:
      Fn::Join:
      - ''
      - - Fn::Sub: https://${ApiGatewayApi}.execute-api.${AWS::Region}.amazonaws.com/
        - Ref: StageName
        - /
  ApplicationSite:
    Description: The name of the CloudFront url for Tenant Management site
    Value:
      Fn::GetAtt:
      - ApplicationSite
      - DomainName
  AppBucket:
    Description: The name of the bucket for uploading the Tenant Management site to
    Value:
      Ref: AppBucket
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



