3
votes

I am trying to build an AWS CloudFormation template to create an API Gateway,
When I manually created the API Gateway, I use stage variables to use different AWS Functions for different stages.

eg. I have a Stage Variables called adminLogin,
The values of adminLogin will be -
dev_adminLogin when the API Gateway's stage is dev
stage_adminLogin when the API Gateway's stage is stage

API Gateway's Resource integration request -
enter image description here

Stage Variable mapping -
enter image description here

CloudFormation template snippet -

test:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: 'test'
      Body:
        swagger: "2.0"
        info:
          version: "2019-04-11T02:29:18Z"
          title: "Test"
        basePath: !Ref "testEnv"
        schemes:
          - "https"
        paths:
          /admin/login:
            post:
              consumes:
                - "application/json"
              produces:
                - "application/json"
              responses:
                '200':
                  description: "200 response"
                  schema:
                    $ref: "#/definitions/Empty"
              x-amazon-apigateway-integration:
                #uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${stageVariables.adminLogin}/invocations"
                uri: !Join [
                    '', [
                      'arn:',
                      'aws:',
                      'apigateway:',
                      !Ref "AWS::Region",
                      ':lambda:',
                      'path/2015-03-31/functions/',
                      '${stageVariables.adminLogin}',
                      '/invocations'
                    ]
                  ]
                responses:
                  default:
                    statusCode: "200"
                passthroughBehavior: "when_no_templates"
                httpMethod: "POST"
                contentHandling: "CONVERT_TO_TEXT"
                type: "aws_proxy"

I am getting the following error when I run the cloudformation template -

Errors found during import: Unable to put integration on 'POST' for resource at path '/admin/login': Invalid lambda function 
(Service: AmazonApiGateway; 
Status Code: 400; 
Error Code: BadRequestException; 

The issue is definately with the uri property,
I tried both -

uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${stageVariables.adminLogin}/invocations"

and

uri: !Join ['', ['arn:','aws:','apigateway:',!Ref "AWS::Region",':lambda:','path/2015-03-31/functions/','${!stageVariables.adminLogin}','/invocations']]

Reference -
1. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apitgateway-method-integration.html#cfn-apigateway-method-integration-uri
2. https://docs.aws.amazon.com/apigateway/latest/developerguide/amazon-api-gateway-using-stage-variables.html

1

1 Answers

1
votes

The Lambda function should be mentioned using Lambda ARN (not just Lambda function name)

ex:

uri: "arn:aws:apigateway:REGION:lambda:path/2015-03-31/functions/arn:aws:lambda:REGION:ACCOUNTID:function:dev_adminLogin/invocations"

Putting it together in cloudformation as follows should work

                uri: !Join
                      - ''
                      - - 'arn:aws:apigateway:'
                        - !Ref "AWS::Region"
                        - ':lambda:path/2015-03-31/functions/arn:aws:lambda:'
                        - !Ref "AWS::Region"
                        - ':'
                        - !Ref "AWS::AccountId"
                        - ':function:${stageVariables.adminLogin}/invocations'

Also remember to add lambda permission(for both dev_adminLogin and stage_adminLogin), otherwise apigateway won't be able to invoke lambda and would receive 5XX error

Using CLI:

aws lambda add-permission  --function-name "arn:aws:lambda:REGION:ACCOUNTID:function:dev_adminLogin"    --source-arn "arn:aws:execute-api:REGION:ACCOUNTID:API_ID/*/POST/admin/login"    --principal apigateway.amazonaws.com    --statement-id stmt1    --action lambda:InvokeFunction

aws lambda add-permission  --function-name "arn:aws:lambda:REGION:ACCOUNTID:function:stage_adminLogin"    --source-arn "arn:aws:execute-api:REGION:ACCOUNTID:API_ID/*/POST/admin/login"    --principal apigateway.amazonaws.com    --statement-id stmt2    --action lambda:InvokeFunction

Ref: https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html