2

I have an AWS SAM application and I want to add Lambda Authorizer to some of my routes in my current API Gateway.

All of the template.yaml samples have the same template for authorizers:

protectedApi:
 Type: AWS::Serverless::HttpApi
 Auth: 
   Authorizers:
     LambdaAuthorizer:
       AuthorizerPayloadFormatVersion: 2.0
       FunctionArn: ...
       FunctionInvokeRole: ...
       Identity:
        Headers:
         - Authorization

However, this does not create the authorizer in the same API id, it creates a completely new API. All my routes, integrations are gone. Also, new API has a different invoke URL

I also tried to manually add the authorizer through the API management screen, but then the authorizer definition and its integrations disappear after sometime. ( I dont know why )

Does anyone have an idea on how I can add authorizer to my current API gateway using template.yaml? What is the correct format?

Or how can I prevent integration disappearing when added manually?

Thanks

Riddick
  • 41
  • 4

1 Answers1

1

One way I would recommend to solve the issue of API stages and indeed APIs themselves being replaced unexpectedly is to use a Custom Domain name as an abstraction layer. This requires you to have a domain you own and can control which maps to an AWS API Gateway custom domain name (which can easily be provisioned in your template.yaml) which then maps to your API.

(Just as an aside I might also suggest not to make changes directly to your stack via the AWS console (unless essential & then ideally also reflected in the template.yaml) as you may get into 'Drift state' in that your template.yaml and stack have changed, AWS may not know how to resolve these diffs next time you come to deploy changes which may remove some resources in an attempt to resolve the diffs. You are doing this correctly currently via IaC (Infrastructure as Code) and AWS SAM is AWS's recommended method)

The AWS API Gateway custom domain name provisions a load-balancer under the hood which presents a static endpoint which your DNS can point to, AWS manages the mapping of the custom domain name to the API resources, so it doesn't matter if AWS then needs to replace any resources this is mapped to, so you have created an abstraction layer for safety against this issue.

Some more info on custom domain names: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html

So, the flow will be:

sub-domain on a domain you control -> API Gateway custom domain name -> AWS API Gateway -> lambdas (handling routes)

An example sub-domain under your main Co domain might be: https://some-service-name-api.your-co-website.com or https://api.your-co-website.com/some-api-path (with alternative path mapping)

To map your domain name -> your AWS Custom Domain name resource you will need to create a CNAME record in your Company DNS (eg in route 53 or wherever it is managed).

In order let AWS know you can control that domain (and provide SSL for https) you will need to create a Certificate in AWS Cert Mgr in the same region as your API. You will then be able to add that Cert in your domain DNS as a CNAME to validate you can control the domain

The steps in full:

  1. Create a certificate in the same region as your stack (do this via the AWS Console for ease). You will need the top level domain and also add any sub-domains you might want to include to that cert. Note - it will say 'Pending validation' until you complete step 2.
  2. Add the CNAME and CNAME value for the Cert you have just created (may require multiple for sub-domains) as a CNAME record(s) to prove you control the domain, it will look for example like: name: _6c7353b72be1c1b5d262839c123456789.your-domain.com value: _0833d6c57a7a5b8123456789.zzhfktmlwt.acm-validations.aws (when done correctly the 'Pending Validation' on the record will change to 'Success', then you can move to Step 3.
  3. Add the below (with updated names where required of course!) to your template.yaml and deploy the stack
  4. Once the stack is deployed, goto API gateway and Custom Domain Names, find the newly created custom domain name and you will see the API Gateway domain name (load-balancer name) name that has been provisioned. Add a CNAME record for your sub-domain.your-domain.com -> API Gateway custom domain name
Resources:
  protectedApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: your-stage-name
      Auth:
        # DefaultAuthorizer: NONE
        DefaultAuthorizer: AWS_IAM
        Authorizers:
          LambdaAuthorizer:
            FunctionPayloadType: REQUEST
            FunctionArn: !GetAtt LambdaAuthorizer.Arn
            Identity:
              Headers:
                - Authorization

  CustomDomainName:
    Type: AWS::ApiGateway::DomainName
    Properties:
      RegionalCertificateArn: arn:aws:acm:eu-west-2:621234567874:certificate/12345678
      DomainName: my-api.your-domain.com
      SecurityPolicy: TLS_1_2
      EndpointConfiguration:
        Types:
          - REGIONAL
      Tags:
        - Key: PROJECT
          Value: "Example auth API with custom domain name"
        - Key: PROVISIONEDBY
          Value: "SAM/ CLOUDFORMATION"
    DependsOn:
      - protectedApi # this ensures that your API is provisioned first

  PathMappings:
    Type: AWS::ApiGateway::BasePathMapping
    Properties:
      DomainName: !Ref CustomDomainName
      RestApiId: !Ref protectedApi
      Stage: your-stage-name

You should now be able to make amendments safely, and your endpoint always remain fixed eg https://my-api.your-domain.com/some-route

Leigh Mathieson
  • 1,658
  • 2
  • 17
  • 25