PROVISIONING AN HTTP API + Lambda Function WITH CLOUD FORMATION

Being in an development/engineering team you will be dealing with lot of things that might be building a new functionality or rebuilding an existing feature and when it comes up to scaling up the product as a developer managing and deploying the servers is the tedious task. So now a day most of the developer rely on Iac (Infrastructure as a Code and AWS cloudformation is one of them.

In this Post i will be discussing about Provisioning an HTTP API + Lambda Function using cloudformation. [ CloudFormation is an infrastructure automation platform for AWS that deploys AWS resources in a repeatable, testable and auditable manner ]

PREREQUISITES

  • aws account
  • aws cli installed on your local machine

CLOUD FORMATION TEMPLATE

Step 1: Create HTTP API Gateway The API Gateway service acts as routing medium to interact with API functions for a client.

Here !GetAtt intrinsic function returns the value of an attribute from a resource in the template.

Resources:
  HTTPAPI:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      Description: Example HTTP API
      Name: lambda-api
      ProtocolType: HTTP
      Target: !GetAtt MyLambdaFunction.Arn

Step 2 - creating Lambda Function with message "Hello world"

For Runtime in the place of nodejs12.x you can also use other language like python

The Handler: index.handler is the Lambda function handler method in your function code that processes events. When your function is invoked, Lambda runs the handler method. When the handler exits or returns a response, it becomes available to handle another event.

  MyLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: nodejs12.x
      Role: !GetAtt FunctionExecutionRole.Arn
      Handler: index.handler
      Code:
        ZipFile: |
          exports.handler = async (event) => {
              const response = {
                  statusCode: 200,
                  body: JSON.stringify('Hello world!'),
              };
              return response;
          };

Step 3 - Lambda Permission

The below code Lambda Permission enables the lambda to invoke from an api gateway that is defined in the template

APIInvokeLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref MyLambdaFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${MyAPI}/$default/$default

Step 4: Creating the Function Execution Role

Description: In the bellow mentioned template to IAM roles are declared so that only an authorised client can request to the function to get it executed.

Principal: Here Principal entity acts as IAM that has an authorisation to make a request for an operation on an AWS resource.

AWS Security Token Service (STS:AssumeRole) AssumeRolePolicy is provided in a role to help enabling trust relationship for other AWS services/AWS accounts to consume this role and gain permissions

 FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Outputs:
  InvokeURL:
    Value: !Sub https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com
AWSTemplateFormatVersion: '2010-09-09'
Description: |
  Example HTTP API, Lambda function, and permissions to invoke the Lambda integration.
  Because the template specifies a Target in AWS::ApiGatewayV2::Api, API Gateway uses quick create to create the API.
  Quick create produces an HTTP API with an integration, a default catch-all route, and a default stage which is configured to automatically deploy changes.
Resources:
  MyAPI:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      Description: Example HTTP API
      Name: lambda-api
      ProtocolType: HTTP
      Target: !GetAtt MyLambdaFunction.Arn
  MyLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: nodejs12.x
      Role: !GetAtt FunctionExecutionRole.Arn
      Handler: index.handler
      Code:
        ZipFile: |
          exports.handler = async (event) => {
              const response = {
                  statusCode: 200,
                  body: JSON.stringify('Hello from Lambda!'),
              };
              return response;
          };
  APIInvokeLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref MyLambdaFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${MyAPI}/$default/$default
  FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Outputs:
  InvokeURL:
    Value: !Sub https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com

For more templates refer to the github aws docs github.com/awsdocs/amazon-api-gateway-devel..

Did you find this article valuable?

Support shivasaichalla by becoming a sponsor. Any amount is appreciated!