Bhavesh Achhada
Bhavesh Achhada

Reputation: 323

How to disable Api-Key auth from specific endpoints using OpenAPI definition body of aws sam AWS::APIGATEWAY::RESTAPI

I have a serverless application which uses the AWS::APIGATEWAY::RESTAPI, The endpoints of this RestAPI are used as an trigger of a lambda function. I have an OpenAPI file to define the API. I have given the basic structure of my template below.

MyRestApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Ref Stage
      Auth:
        AddDefaultAuthorizerToCorsPreflight: false
        ApiKeyRequired: true
        DefaultAuthorizer: TokenAuthorizer
        Authorizers:
          TokenAuthorizer:
            FunctionArn: !GetAtt TokenAuthorizerFunction.Arn
      Cors:
        AllowMethods: "'*'"
        AllowHeaders: "'*'"
        AllowOrigin: "'*'"
        AllowCredentials: "'*'"
      Mode: overwrite
      DefinitionBody:
        openapi: '3.0'
        info:
          version: '2022-11-08'
          title: MyRestApi
        paths:
          /hello:
            post:
              cors: true
              produces:
                - application/json
              consumes:
                - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Headers:
                      type: "string"
                    Access-Control-Allow-Methods:
                      type: "string"
                    Access-Control-Allow-Origin:
                      type: "string"
                    Content-Length:
                      type: string
                    Content-Type:
                      type: string
                '400':
                  description: 400 response
                '500':
                  description: 500 response
              x-amazon-apigateway-integration:
                type: aws
                responses:
                  '4\d{2}':
                    statusCode: '400'
                  default:
                    statusCode: '200'
                    responseTemplates:
                      application/json: $util.parseJson($input.json('$.body'))
                    responseParameters:
                      method.response.header.Content-Type: integration.response.header.Content-Type
                      method.response.header.Content-Length: integration.response.header.Content-Length
                      method.response.header.Access-Control-Allow-Headers: integration.response.header.Access-Control-Allow-Headers
                      method.response.header.Access-Control-Allow-Methods: integration.response.header.Access-Control-Allow-Methods
                      method.response.header.Access-Control-Allow-Origin: integration.response.header.Access-Control-Allow-Origin
                  '5\d{2}':
                    statusCode: '500'
                    responseTemplates:
                      application/json: $util.parseJson($input.json('$.body'))
                requestTemplates:
                  application/json: |
                    {
                      "httpMethod": "$context.httpMethod",
                      "body" : "$util.escapeJavaScript($input.json('$'))",
                      "headers": {
                          #foreach($header in $input.params().header.keySet())
                          "$header": "$util.escapeJavaScript($input.params().header.get($header))" #if($foreach.hasNext),#end
                    
                          #end,
                          "paramA": "$context.authorizer.paramA",
                          "paramB": "$context.authorizer.paramB"
                        },
                      "queryStringParameters": {
                          #foreach($param in $input.params().querystring.keySet())
                          "$param": "$util.escapeJavaScript($input.params().querystring.get($param))" #if($foreach.hasNext),#end
                    
                          #end
                        },
                      "path": "$context.resourcePath",
                      "pathParams": {
                        #foreach($param in $input.params().path.keySet())
                        "$param": "$util.escapeJavaScript($input.params().path.get($param))" #if($foreach.hasNext),#end
                    
                        #end
                      },
                      "requestContext":{
                        "identity": {
                          "sourceIp": "$context.identity.sourceIp"
                        }
                      }
                    }
                httpMethod: POST
                uri: !Join [ "", [ !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:", !Ref MyLambdaFunction, "/invocations" ] ]
            options:
              cors: true
              produces:
                - application/json
              consumes:
                - application/json
              responses:
                '200':
                  description: 200 response
                  schema:
                    $ref: '#/definitions/Empty'
                  headers:
                    Access-Control-Allow-Headers:
                      type: "string"
                    Access-Control-Allow-Methods:
                      type: "string"
                    Access-Control-Allow-Origin:
                      type: "string"
                    Content-Length:
                      type: string
                    Content-Type:
                      type: string
                '400':
                  description: 400 response
                '500':
                  description: 500 response
              security:
                - NONE: []
              x-amazon-apigateway-integration:
                type: aws
                responses:
                  '4\d{2}':
                    statusCode: '400'
                  default:
                    statusCode: '200'
                    responseTemplates:
                      application/json: $util.parseJson($input.json('$.body'))
                    responseParameters:
                      method.response.header.Content-Type: integration.response.header.Content-Type
                      method.response.header.Content-Length: integration.response.header.Content-Length
                      method.response.header.Access-Control-Allow-Headers: integration.response.header.Access-Control-Allow-Headers
                      method.response.header.Access-Control-Allow-Methods: integration.response.header.Access-Control-Allow-Methods
                      method.response.header.Access-Control-Allow-Origin: integration.response.header.Access-Control-Allow-Origin
                  '5\d{2}':
                    statusCode: '500'
                    responseTemplates:
                      application/json: $util.parseJson($input.json('$.body'))
                requestTemplates:
                  application/json: |
                    {
                      "httpMethod": "$context.httpMethod",
                      "body" : "$util.escapeJavaScript($input.json('$'))",
                      "headers": {
                          #foreach($header in $input.params().header.keySet())
                          "$header": "$util.escapeJavaScript($input.params().header.get($header))" #if($foreach.hasNext),#end

                          #end,
                          "role": "$context.authorizer.role",
                          "username": "$context.authorizer.username"
                        },
                      "queryStringParameters": {
                          #foreach($param in $input.params().querystring.keySet())
                          "$param": "$util.escapeJavaScript($input.params().querystring.get($param))" #if($foreach.hasNext),#end

                          #end
                        },
                      "path": "$context.resourcePath",
                      "pathParams": {
                        #foreach($param in $input.params().path.keySet())
                        "$param": "$util.escapeJavaScript($input.params().path.get($param))" #if($foreach.hasNext),#end

                        #end
                      },
                      "requestContext":{
                        "identity": {
                          "sourceIp": "$context.identity.sourceIp"
                        }
                      }
                    }
                httpMethod: POST
                uri: !Join [ "", [ !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:", !Ref MyLambdaFunction, "/invocations" ] ]

I want to remove both TokenAuthorizer and API-Key auth from options method.

  1. I tried adding security field to the options method.

    security:
      - NONE: []
    

    But this only removed the tokenauthorizer, api-key auth is not removed.

  2. I tried removing the global DefaultAuthorizer and ApiKeyRequired from the RestApi section and tried adding to openapi only to the post method, but it didn't add any type of auth to the post method. Example given below.

To the openapi global field

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
    TokenAuthorizer:
      type: apiKey
      in: header
      name: Authorization
      x-amazon-apigateway-authorizer:
        type: token
        identitySource: method.request.header.Authorization
        authorizerUri: !Join [ "", [ !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:", !Ref TokenAuthorizerFunction, "/invocations" ] ]

and to the post method:

security:
  - ApiKeyAuth: []
    TokenAuthorizer:  []

Upvotes: 0

Views: 614

Answers (1)

Andi F.
Andi F.

Reputation: 776

Maybe this helps

ApiGatewayWithDefaultAuthorizer:
  Type: AWS::Serverless::Api
  Properties:
    ...
    Auth:
      DefaultAuthorizer: MyCognitoAuth
      Authorizers:
        MyCognitoAuth:
          UserPoolArn: !GetAtt UserPool.Arn
          Identity:
            Header: Authorization

[...]

LambdaFunction
  Type: AWS::Serverless::Function
  ...
  Properties:
    Events:
      Type: Api
        Properties:
          Path: /path/with/no/authenticator
          Method: get
          Auth:
            Authorizer: NONE
          RestApiId:
            Ref: ApiGatewayWithDefaultAuthorizer

Upvotes: 0

Related Questions