Serverless-application-model: When using an inline swagger, api+method+path authorizers do not get added

Created on 31 Oct 2018  路  2Comments  路  Source: aws/serverless-application-model

Description:
My expectation was that when using the Auth functionality in SAM against an API and Function, when no default
authorizer is configured then the Authorizer would be assigned against the Functions path

I've also noticed that when using a Default Authorizer, all methods on the API get the Authorizer assigned, configuring
NONE authorizer against an API Event does not prevent the authorizer getting assigned.

Steps to reproduce the issue:

Given a SAM Template that includes a an inline swagger document, an Authorizer and Auth configured on the DELETE and
POST events

template.yaml

---
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Runtime: python3.6
    MemorySize: 128
    Timeout: 15


Resources:
  Create:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: example
      Handler: service.example
      Events:
        Create:
          Type: Api
          Properties:
            Method: post
            Path: /
            RestApiId: !Ref API
            Auth:
              Authorizer: ExampleAuth

  List:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: example
      Handler: service.example
      Events:
        Create:
          Type: Api
          Properties:
            Method: get
            Path: /
            RestApiId: !Ref API

  Delete:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: example
      Handler: service.example
      Events:
        AddTenant:
          Type: Api
          Properties:
            Method: delete
            Path: /{id}
            RestApiId: !Ref API
            Auth:
              Authorizer: ExampleAuth

  Retrieve:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: example
      Handler: service.example
      Events:
        AddTenant:
          Type: Api
          Properties:
            Method: post
            Path: /{id}
            RestApiId: !Ref API

  Auth:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: example
      Handler: service.example

  API:
    Type: AWS::Serverless::Api
    Properties:
      Name: ExampleAPI
      EndpointConfiguration: REGIONAL
      StageName: v1
      Auth:
        Authorizers:
          ExampleAuth:
            FunctionPayloadType: TOKEN
            FunctionArn: !GetAtt Auth.Arn
            Identity:
              Header: Authorization
              ValidationExpression: Bearer.*
              ReauthorizeEvery: 0
      DefinitionBody:
        swagger: "2.0"
        info:
          title: Example
          version: "1"
        parameters:
          id:
            name: id
            in: path
            required: true
            type: string
        paths:
          /:
            post:
              parameters:
                - in: body
                  name: item
                  schema:
                    type: object
              responses:
                "201":
                  description: Created
              x-amazon-apigateway-integration:
                type: aws_proxy
                httpMethod: POST
                passthroughBehavior: when_no_match
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Create.Arn}/invocations
            get:
              responses:
                "200":
                  description: Got
              x-amazon-apigateway-integration:
                type: aws_proxy
                httpMethod: POST
                passthroughBehavior: when_no_match
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${List.Arn}/invocations
          /{id}:
            get:
              parameters:
                - $ref: '#/parameters/id'
              responses:
                "200":
                  description: Got
              x-amazon-apigateway-integration:
                type: aws_proxy
                httpMethod: POST
                passthroughBehavior: when_no_match
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Retrieve.Arn}/invocations
            delete:
              parameters:
                - $ref: '#/parameters/id'
              responses:
                "200":
                  description: Deleted
              x-amazon-apigateway-integration:
                type: aws_proxy
                httpMethod: POST
                passthroughBehavior: when_no_match
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Delete.Arn}/invocations

example/service.py

def example(event, context):
    print(event)
    return 200

example/__init__.py

__version__ = "1.0.0"

Deploy this SAM Template

sam package --template-file template.yaml --s3-bucket "${S3_BUCKET}" > template-export.yaml
sam deploy --template-file template-export.yaml --stack-name "${STACK_NAME}" --capabilities CAPABILITY_IAM

Observed result:
No Authorizers are assigned to any of the methods
image
image

Expected result:
My expectation was that the GET Methods on the path / and /{id} would not have an authorizer assigned, but POST / and DELETE /{id} do not have authorizer assigned

priorit2-important typbug

Most helpful comment

We plan on adding a feature to merge your defined Swagger with the generated Swagger from SAM. This should resolve this issue also.

All 2 comments

We plan on adding a feature to merge your defined Swagger with the generated Swagger from SAM. This should resolve this issue also.

A workaround exists where if the name of the Authorizer defined in the SAM template matches the name of a securityDefinitions in the swagger document, AND the endpoint refers to that named security definition, then the correct authorizer will be assigned to the endpoint.

This is often what is desired, because if you have security requirements for the endpoint, you probably want to define them (as best you can) in the swagger doc.

SAM snippet below:

  myApi:
    Type: AWS::Serverless::Api
    Properties:
      EndpointConfiguration: REGIONAL
      StageName: master
      DefinitionBody:
        swagger: '2.0'
        info:
          title: Test
          version: 1.0.0
          description: Only a test
        schemes:
        - https
        paths:
          "/sayHello":
            get:
              operationId: hello
              description: Says "Hello"
              produces:
              - text/html
              responses:
                '200':
                  description: OK
                default:
                  description: Error
              security:
              - keyAuth: [] # refers to security definition in this swagger doc
              x-amazon-apigateway-integration:
                uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Function.Arn}/invocations
                httpMethod: POST
                type: aws_proxy
        securityDefinitions:
          keyAuth: #matches name of Auth/Authorizer defined on the Api
            description: Authentication will be performed using a custom authenticator
            type: apiKey
            name: Authorization
            in: header
      Auth:
        Authorizers:
          keyAuth: # Name of this authorizer; becomes the name of the authorizer in API Gateway console
            Identity:
              Headers:
              - Authorization
              ReauthorizeEvery: 600
            FunctionPayloadType: REQUEST
            FunctionArn: !Ref CustomAuthArn

The result of the above is that the authorizer is created with expected properties in the API, and the endpoint is configured to use that authorizer.

Untested are the effects of setting the Serverless::Function/Events/Auth/Authorizer to NONE or setting the DefaultAuthorizer property on the Serverless::Api/Auth/Authorizers

Was this page helpful?
0 / 5 - 0 ratings