Lab4/server/nested_templates/apigateway.yaml [4:758]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  Template to setup api gateway, apis, api keys and usage plan as part of bootstrap
Parameters:
  StageName:
    Type: String
  RegisterTenantLambdaExecutionRoleArn:
    Type: String
  TenantManagementLambdaExecutionRoleArn:
    Type: String
  RegisterTenantFunctionArn:
    Type: String
  ActivateTenantFunctionArn:
    Type: String
  GetTenantsFunctionArn:
    Type: String
  CreateTenantFunctionArn:
    Type: String
  GetTenantFunctionArn:
    Type: String
  DeactivateTenantFunctionArn:
    Type: String
  UpdateTenantFunctionArn:
    Type: String
  GetUsersFunctionArn:
    Type: String    
  GetUserFunctionArn:
    Type: String
  UpdateUserFunctionArn:
    Type: String
  DisableUserFunctionArn:
    Type: String
  CreateTenantAdminUserFunctionArn:
    Type: String
  CreateUserFunctionArn:
    Type: String
  DisableUsersByTenantFunctionArn:
    Type: String
  EnableUsersByTenantFunctionArn:
    Type: String
  AuthorizerFunctionArn:
    Type: String
  
Resources:
  ApiGatewayCloudWatchLogRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub apigateway-cloudwatch-publish-role-${AWS::Region}
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
            Action:
              - sts:AssumeRole
  ApiGatewayAttachCloudwatchLogArn:
    Type: AWS::ApiGateway::Account
    Properties:
      CloudWatchRoleArn: !GetAtt ApiGatewayCloudWatchLogRole.Arn

  AdminApiGatewayAccessLogs:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/api-gateway/access-logs-serverless-saas-admin-api
      RetentionInDays: 30
  AdminApiGatewayApi:
    Type: AWS::Serverless::Api
    Properties:
      MethodSettings:
        - DataTraceEnabled: False
          LoggingLevel: INFO
          MetricsEnabled: True
          ResourcePath: "/*"
          HttpMethod: "*"
      Auth:
        ResourcePolicy:
          CustomStatements:
            - Effect: Allow
              Principal: "*"
              Action: "execute-api:Invoke"
              Resource: ["execute-api:/*/*/*"]
            - Effect: Deny
              Principal: "*"
              Action: "execute-api:Invoke"
              Resource: 
                - !Join [
                   "",
                   [
                     "execute-api:/", !Ref StageName, "/POST/tenant"
                   ]
                  ] 
                - !Join [ "", [
                     "execute-api:/", !Ref StageName, "/POST/user/tenant-admin"
                   ]
                 ]                
              Condition:
                StringNotEquals:
                  aws:PrincipalArn:
                    - !Ref RegisterTenantLambdaExecutionRoleArn 
                    - !Ref TenantManagementLambdaExecutionRoleArn 
            - Effect: Deny
              Principal: "*"
              Action: "execute-api:Invoke"
              Resource: 
                - !Join [ "", [
                     "execute-api:/", !Ref StageName, "/PUT/users/disable"
                   ]
                 ]                
              Condition:
                StringNotEquals:
                  aws:PrincipalArn:
                    - !Ref TenantManagementLambdaExecutionRoleArn
            - Effect: Deny
              Principal: "*"
              Action: "execute-api:Invoke"
              Resource: 
                - !Join [ "", [
                     "execute-api:/", !Ref StageName, "/PUT/users/enable"
                   ]
                 ]                
              Condition:
                StringNotEquals:
                  aws:PrincipalArn:
                    - !Ref TenantManagementLambdaExecutionRoleArn            
      AccessLogSetting:
        DestinationArn: !GetAtt AdminApiGatewayAccessLogs.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: !Join ["", ["serverless-saas-admin-api-", !Ref "AWS::Region"]]
        basePath: !Join ["", ["/", !Ref StageName]]
        schemes:
          - https
        paths:
          /registration:
            post:
              summary: Register a new tenant
              description: Register a new tenant
              produces:
                - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri: !Join
                  - ""
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - !Ref RegisterTenantFunctionArn
                    - /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                   
          
          /tenant/activation/{tenantid}:
            put:
              security:
                - api_key: []
                - Authorizer: []
              summary: Activate an existing tenant
              description: Activate an existing tenant
              produces:
                - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri: !Join
                  - ""
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - !Ref ActivateTenantFunctionArn
                    - /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
          /tenants:
            get:
              summary: Returns all tenants
              description: Returns all tenants
              produces:
                - application/json
              responses: {}
              security:
                - api_key: []
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref GetTenantsFunctionArn
                    - /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                 
          /tenant:
            post:
              summary: Creates a tenant
              description: Creates a tenant
              produces:
                - application/json
              responses: {}
              security:
                - sigv4Reference: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref CreateTenantFunctionArn
                    - /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 
          
          /tenant/{tenantid}:
            get:
              summary: Returns a tenant
              description: Return a tenant by a tenant id
              produces:
                - application/json
              responses: {}
              security:   
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref GetTenantFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy        
            delete:              
              summary: Disables a tenant
              description: Disables a tenant by a tenant id
              produces:
                - application/json
              responses: {}
              security:   
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref DeactivateTenantFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            put:  
              summary: Updates a tenant
              description: Updates a tenant
              produces:
                - application/json
              responses: {}
              security:        
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref UpdateTenantFunctionArn
                    - /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     
            
          /user/{username}:
            get:
              summary: Returns a user
              description: Return a user by a user id
              produces:
                - application/json
              responses: {}
              security:     
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref GetUserFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy    
            put:              
              produces:
                - application/json
              responses: {}
              security:                
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref UpdateUserFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            delete:          
              summary: Diables a user
              description: Disable a user by a user id    
              produces:
                - application/json
              responses: {}
              security: 
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref DisableUserFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
          /user/tenant-admin:
            post:
              summary: Creates a tenant admin user
              description: Creates a tenant admin user
              produces:
                - application/json
              responses: {}
              security:
                - sigv4Reference: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref CreateTenantAdminUserFunctionArn
                    - /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       
          /user:
            post:
              summary: Create a user
              description: Create a user by a user id
              produces:
                - application/json
              responses: {}
              security:            
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref CreateUserFunctionArn
                    - /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 
          /users:
            get:
              summary: Get all users by tenantId
              description: Get all users by tenantId
              produces:
                - application/json
              responses: {}
              security:   
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref GetUsersFunctionArn
                    - /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         
          /users/disable:
            put:
              summary: disable users by tenant id
              description: disable users by tenant id
              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
              security:     
                - sigv4Reference: []
              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                
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref DisableUsersByTenantFunctionArn
                    - /invocations
                httpMethod: POST
                type: AWS
                requestParameters:
                  integration.request.header.X-Amz-Invocation-Type: '''Event'''
            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  
          /users/enable:
            put:
              summary: enable users by tenant id
              description: enable users by tenant id
              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
              security:     
                - sigv4Reference: []
              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                
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref EnableUsersByTenantFunctionArn
                    - /invocations
                httpMethod: POST
                type: AWS
                requestParameters:
                  integration.request.header.X-Amz-Invocation-Type: '''Event'''
                        
            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  
        components:
          securitySchemes:      
            sigv4Reference:
              type: "apiKey"
              name: "Authorization"
              in: "header"
              x-amazon-apigateway-authtype: "awsSigv4"  
            Authorizer:
              type: "apiKey"
              name: "Authorization"
              in: "header"
              x-amazon-apigateway-authtype: "custom"
              x-amazon-apigateway-authorizer:
                authorizerUri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref AuthorizerFunctionArn
                    - /invocations
                authorizerResultTtlInSeconds: 60
                type: "token"
      StageName: prod
  
  
Outputs:  
  AdminApiGatewayApi:
    Value: !Ref AdminApiGatewayApi
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



Solution/Lab4/server/nested_templates/apigateway.yaml [4:758]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  Template to setup api gateway, apis, api keys and usage plan as part of bootstrap
Parameters:
  StageName:
    Type: String
  RegisterTenantLambdaExecutionRoleArn:
    Type: String
  TenantManagementLambdaExecutionRoleArn:
    Type: String
  RegisterTenantFunctionArn:
    Type: String
  ActivateTenantFunctionArn:
    Type: String
  GetTenantsFunctionArn:
    Type: String
  CreateTenantFunctionArn:
    Type: String
  GetTenantFunctionArn:
    Type: String
  DeactivateTenantFunctionArn:
    Type: String
  UpdateTenantFunctionArn:
    Type: String
  GetUsersFunctionArn:
    Type: String    
  GetUserFunctionArn:
    Type: String
  UpdateUserFunctionArn:
    Type: String
  DisableUserFunctionArn:
    Type: String
  CreateTenantAdminUserFunctionArn:
    Type: String
  CreateUserFunctionArn:
    Type: String
  DisableUsersByTenantFunctionArn:
    Type: String
  EnableUsersByTenantFunctionArn:
    Type: String
  AuthorizerFunctionArn:
    Type: String
  
Resources:
  ApiGatewayCloudWatchLogRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub apigateway-cloudwatch-publish-role-${AWS::Region}
      Path: "/"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
            Action:
              - sts:AssumeRole
  ApiGatewayAttachCloudwatchLogArn:
    Type: AWS::ApiGateway::Account
    Properties:
      CloudWatchRoleArn: !GetAtt ApiGatewayCloudWatchLogRole.Arn

  AdminApiGatewayAccessLogs:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/api-gateway/access-logs-serverless-saas-admin-api
      RetentionInDays: 30
  AdminApiGatewayApi:
    Type: AWS::Serverless::Api
    Properties:
      MethodSettings:
        - DataTraceEnabled: False
          LoggingLevel: INFO
          MetricsEnabled: True
          ResourcePath: "/*"
          HttpMethod: "*"
      Auth:
        ResourcePolicy:
          CustomStatements:
            - Effect: Allow
              Principal: "*"
              Action: "execute-api:Invoke"
              Resource: ["execute-api:/*/*/*"]
            - Effect: Deny
              Principal: "*"
              Action: "execute-api:Invoke"
              Resource: 
                - !Join [
                   "",
                   [
                     "execute-api:/", !Ref StageName, "/POST/tenant"
                   ]
                  ] 
                - !Join [ "", [
                     "execute-api:/", !Ref StageName, "/POST/user/tenant-admin"
                   ]
                 ]                
              Condition:
                StringNotEquals:
                  aws:PrincipalArn:
                    - !Ref RegisterTenantLambdaExecutionRoleArn 
                    - !Ref TenantManagementLambdaExecutionRoleArn 
            - Effect: Deny
              Principal: "*"
              Action: "execute-api:Invoke"
              Resource: 
                - !Join [ "", [
                     "execute-api:/", !Ref StageName, "/PUT/users/disable"
                   ]
                 ]                
              Condition:
                StringNotEquals:
                  aws:PrincipalArn:
                    - !Ref TenantManagementLambdaExecutionRoleArn
            - Effect: Deny
              Principal: "*"
              Action: "execute-api:Invoke"
              Resource: 
                - !Join [ "", [
                     "execute-api:/", !Ref StageName, "/PUT/users/enable"
                   ]
                 ]                
              Condition:
                StringNotEquals:
                  aws:PrincipalArn:
                    - !Ref TenantManagementLambdaExecutionRoleArn            
      AccessLogSetting:
        DestinationArn: !GetAtt AdminApiGatewayAccessLogs.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: !Join ["", ["serverless-saas-admin-api-", !Ref "AWS::Region"]]
        basePath: !Join ["", ["/", !Ref StageName]]
        schemes:
          - https
        paths:
          /registration:
            post:
              summary: Register a new tenant
              description: Register a new tenant
              produces:
                - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri: !Join
                  - ""
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - !Ref RegisterTenantFunctionArn
                    - /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                   
          
          /tenant/activation/{tenantid}:
            put:
              security:
                - api_key: []
                - Authorizer: []
              summary: Activate an existing tenant
              description: Activate an existing tenant
              produces:
                - application/json
              responses: {}
              x-amazon-apigateway-integration:
                uri: !Join
                  - ""
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    - !Ref ActivateTenantFunctionArn
                    - /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
          /tenants:
            get:
              summary: Returns all tenants
              description: Returns all tenants
              produces:
                - application/json
              responses: {}
              security:
                - api_key: []
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref GetTenantsFunctionArn
                    - /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                 
          /tenant:
            post:
              summary: Creates a tenant
              description: Creates a tenant
              produces:
                - application/json
              responses: {}
              security:
                - sigv4Reference: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref CreateTenantFunctionArn
                    - /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 
          
          /tenant/{tenantid}:
            get:
              summary: Returns a tenant
              description: Return a tenant by a tenant id
              produces:
                - application/json
              responses: {}
              security:   
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref GetTenantFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy        
            delete:              
              summary: Disables a tenant
              description: Disables a tenant by a tenant id
              produces:
                - application/json
              responses: {}
              security:   
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref DeactivateTenantFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            put:  
              summary: Updates a tenant
              description: Updates a tenant
              produces:
                - application/json
              responses: {}
              security:        
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref UpdateTenantFunctionArn
                    - /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     
            
          /user/{username}:
            get:
              summary: Returns a user
              description: Return a user by a user id
              produces:
                - application/json
              responses: {}
              security:     
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref GetUserFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy    
            put:              
              produces:
                - application/json
              responses: {}
              security:                
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref UpdateUserFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
            delete:          
              summary: Diables a user
              description: Disable a user by a user id    
              produces:
                - application/json
              responses: {}
              security: 
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref DisableUserFunctionArn
                    - /invocations
                httpMethod: POST
                type: aws_proxy
          /user/tenant-admin:
            post:
              summary: Creates a tenant admin user
              description: Creates a tenant admin user
              produces:
                - application/json
              responses: {}
              security:
                - sigv4Reference: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref CreateTenantAdminUserFunctionArn
                    - /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       
          /user:
            post:
              summary: Create a user
              description: Create a user by a user id
              produces:
                - application/json
              responses: {}
              security:            
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref CreateUserFunctionArn
                    - /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 
          /users:
            get:
              summary: Get all users by tenantId
              description: Get all users by tenantId
              produces:
                - application/json
              responses: {}
              security:   
                - Authorizer: []
              x-amazon-apigateway-integration:
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref GetUsersFunctionArn
                    - /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         
          /users/disable:
            put:
              summary: disable users by tenant id
              description: disable users by tenant id
              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
              security:     
                - sigv4Reference: []
              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                
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref DisableUsersByTenantFunctionArn
                    - /invocations
                httpMethod: POST
                type: AWS
                requestParameters:
                  integration.request.header.X-Amz-Invocation-Type: '''Event'''
            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  
          /users/enable:
            put:
              summary: enable users by tenant id
              description: enable users by tenant id
              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
              security:     
                - sigv4Reference: []
              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                
                uri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref EnableUsersByTenantFunctionArn
                    - /invocations
                httpMethod: POST
                type: AWS
                requestParameters:
                  integration.request.header.X-Amz-Invocation-Type: '''Event'''
                        
            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  
        components:
          securitySchemes:      
            sigv4Reference:
              type: "apiKey"
              name: "Authorization"
              in: "header"
              x-amazon-apigateway-authtype: "awsSigv4"  
            Authorizer:
              type: "apiKey"
              name: "Authorization"
              in: "header"
              x-amazon-apigateway-authtype: "custom"
              x-amazon-apigateway-authorizer:
                authorizerUri: !Join
                  - ''
                  - - !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/
                    -  !Ref AuthorizerFunctionArn
                    - /invocations
                authorizerResultTtlInSeconds: 60
                type: "token"
      StageName: prod
  
  
Outputs:  
  AdminApiGatewayApi:
    Value: !Ref AdminApiGatewayApi
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



