【AWS】CloudformationでAPI GatewayとLambdaでHello World

1. 使用するサービス

(AWS)

  • Cloudformation
  • Lambda

2. 概要

API GatewayとLambdaを使った構成を簡単にCloudformationで実装出来るテンプレートを載せます。CORSにも対応しているのでS3の静的ウェブサイトからの通信にも対応してます。

3. 実装

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Outputs the API

Parameters:

  Project:
    Description: "Project Name"
    Default: "demo"
    Type: String

  Stage:
    Description: "Environment stage"
    Default: dev
    Type: String
    AllowedValues: [dev, staging, prod]
Resources:

  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: !Sub "${Project}-${Stage}-HelloWorldFunction"
      Handler: index.handler
      Runtime: python3.8
      CodeUri: ./hello
      Role: !GetAtt HelloWorldRole.Arn

  HelloWorldRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${Project}-${Stage}-HelloWorldRole" 
      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
        
      MaxSessionDuration: 3600
      Path: "/"

  HelloWorldFunctionApiPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      FunctionName: !Ref HelloWorldFunction

  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Body:
        info:
          version: '1.0'
          title: !Sub "${Project}-${Stage}-API"
        paths:
          /hello:
            get:
              produces:
              - "application/json"
              responses:
                "200":
                  description: "200 response"
                  schema:
                    $ref: "#/definitions/Empty"
                  headers:
                    Access-Control-Allow-Origin:
                      type: "string"
                      
              x-amazon-apigateway-integration:
                uri: !Sub >-
                  arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloWorldFunction.Arn}/invocations
                responses:
                  default:
                    statusCode: "200"
                    responseParameters:
                      method.response.header.Access-Control-Allow-Origin: "'*'"
                passthroughBehavior: "when_no_match"
                httpMethod: "POST"
                contentHandling: "CONVERT_TO_TEXT"
                type: "aws"
            options:
              consumes:
              - "application/json"
              produces:
              - "application/json"
              responses:
                "200":
                  description: "200 response"
                  schema:
                    $ref: "#/definitions/Empty"
                  headers:
                    Access-Control-Allow-Origin:
                      type: "string"
                    Access-Control-Allow-Methods:
                      type: "string"
                    Access-Control-Allow-Headers:
                      type: "string"
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: "200"
                    responseTemplates:
                      application/json: |
                        {}
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'"
                      method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
                      method.response.header.Access-Control-Allow-Origin: "'*'"
                requestTemplates:
                  application/json: "{\"statusCode\": 200}"
                passthroughBehavior: "when_no_match"
                type: "mock"
              
        definitions:
          Empty:
            type: object
            title: Empty Schema
        x-amazon-apigateway-gateway-responses:
          UNAUTHORIZED:
            statusCode: 401
            responseParameters:
              gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
            responseTemplates:
              application/json: "{\"message\":$context.error.messageString}" 
              
        swagger: '2.0'


  ApiGatewayDeploy:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId: !Ref RestApi
      Description: "apigateway deployment you need to change Title when you modify Apigateway to deploy"
      StageName: !Ref Stage

4. おわりに

上記のテンプレートで簡単なAPI GatewayとLambdaの実装ができます。CORSの元URLの記載など、細かい部分の修正は必須ですが、とりあえず実装して試してみたいって場合には十分かと思います。