Как настроить Прокси на AWS API Gateway с помощью Cloudformation - PullRequest
0 голосов
/ 29 августа 2018

У меня есть лямбда-функция, которая будет обрабатывать запросы PUT и GET, используя Amazon API Gateway {proxy +} . Он работает правильно, когда все настройки устанавливаются вручную с помощью консоли Amazon. но я хочу автоматизировать его с помощью AWS Cloudformation.

Чтобы сообщить вам, я напишу шаги для установки {proxy+}:

1) создайте простую лямбда-функцию и вставьте в нее следующие строки кода:

import boto3

def lambda_handler(event, context):
    return {
        "statusCode": 200,
        "headers": {
            "Content-Type": 'text/html',
            "Access-Control-Allow-Origin": "*"
        },
        "body": "Hello Reza Amya, Your Lambda is working..!"
    }

2) перейти к Amazon API Gateway и нажать Create API.

3) выберите New API, заполните API name, выберите Edge optimized из списка для Endpoint Type, затем нажмите Create API

4) тогда ваш API создан, и вы должны быть на его странице Resources, если нет, перейдите на страницу Resources для созданного API.

5) из Actions выберите Create Resource

6) Выберите Configure as proxy resource (тогда он должен автоматически изменить другие поля, в противном случае введите proxy для Resource Name и {proxy+} для Resource Path), затем нажмите Create Resource

7) Выберите Lambda Function Proxy для Integration type, выберите лямбда-функцию из Lambda Function и нажмите Save

8) во всплывающем окне Add Permission to Lambda Function нажмите Ok

9) из Actions нажмите Deploy API

10) Выберите New Stage из списка для Deployment stage, затем введите имя для Stage name (для меня я набрал 'api') и нажмите Deploy

11) на stage на корневой странице развернутого API вы можете увидеть Invoke URL. щелкните по нему, и он откроет новую вкладку, связанную где-то вроде этого: https://xxxxxxxxx.execute -api.us-east-1.amazonaws.com / api /

12) добавьте простой сегмент в конец вашего URL следующим образом: https://xxxxxxxxx.execute -api.us-east-1.amazonaws.com / апи / тест

теперь вы должны увидеть ниже сообщение на странице вашего браузера:

Hello Reza Amya, Your Lambda is working..!

Теперь проблема в том, что я написал все эти шаги в файле Yaml:

AWSTemplateFormatVersion: 2010-09-09
Description: My Lambda Function
Parameters:
  S3Bucket:
    Description: S3 Bucket where the Lambda code is
    Type: String
  S3Key:
    Description: S3 Key where the Lambda code is
    Type: String
  S3ObjectVersion:
    Description: Version of the S3 Key to use
    Type: String

Resources:
  apiGateway:
    Type: "AWS::ApiGateway::RestApi"
    Properties:
      Name: "my-api"
      Description: "My API"
      EndpointConfiguration:
        Types:
          - EDGE

  Resource: 
    Type: AWS::ApiGateway::Resource
    Properties: 
      RestApiId: 
        Ref: "apiGateway"
      ParentId: 
        Fn::GetAtt: 
          - "apiGateway"
          - "RootResourceId"
      PathPart: "{proxy+}"

  ProxyMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      HttpMethod: ANY
      ResourceId: !Ref Resource
      RestApiId: !Ref apiGateway
      AuthorizationType: NONE
      RequestParameters:
        method.request.path.proxy: true
      Integration:
        CacheKeyParameters:
          - 'method.request.path.proxy'
        RequestParameters:
          integration.request.path.proxy: 'method.request.path.proxy'
        Type: AWS_PROXY
        IntegrationHttpMethod: ANY
        Uri: !Sub
          - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Arn}/invocations
          - Arn:
              Fn::GetAtt:
               - LambdaFunction
               - Arn
        PassthroughBehavior: WHEN_NO_MATCH
        IntegrationResponses:
          - StatusCode: 200 

  apiGatewayDeployment:
    Type: "AWS::ApiGateway::Deployment"
    DependsOn:
      - "ProxyMethod"
    Properties:
      RestApiId: !Ref "apiGateway"
      StageName: "dev"

  IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: 'sts:AssumeRole'

      Policies:
        - PolicyName: Logging
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: 'arn:aws:logs:*:*:*'
        - PolicyName: AccessToDynamoDB
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'dynamodb:CreateTable'
                  - 'dynamodb:DeleteItem'
                  - 'dynamodb:DeleteTable'
                  - 'dynamodb:GetItem'
                  - 'dynamodb:GetRecords'
                  - 'dynamodb:UpdateItem'
                  - 'dynamodb:UpdateTable'
                  - 'dynamodb:PutItem'
                  - 'dynamodb:UpdateTable'
                Resource: 'arn:aws:dynamodb:*:*:*'

  LambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        S3Bucket: {Ref: S3Bucket}
        S3Key: {Ref: S3Key}
        S3ObjectVersion: {Ref: S3ObjectVersion}
      Handler: main.lambda_handler
      MemorySize: 128
      Role: {'Fn::GetAtt': [IAMRole, Arn]}
      Runtime: python3.6
      Timeout: 300

  LambdaInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !GetAtt 
        - LambdaFunction
        - Arn
      Action: 'lambda:InvokeFunction'
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/*/*

Outputs:
  apiGatewayInvokeURL:
    Value: !Sub "https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGateway}"

  lambdaArn:
    Value: !GetAtt "LambdaFunction.Arn"

Приведенный выше файл Yaml создаст функцию Lambda и развернет API, но при попытке протестировать API будет отображаться нижеуказанная ошибка:

{"message": "Internal server error"}

Подскажите, пожалуйста, что не так и как я могу решить проблему?

1 Ответ

0 голосов
/ 29 августа 2018

Эта проблема связана с настройкой IntegrationHttpMethod. Хотя ваш метод APIGateway ANY, IntegrationHttpMethod всегда должен быть POST для AWS Lambda.

Это приведет к следующему объявлению метода.

  ProxyMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      HttpMethod: ANY
      ResourceId: !Ref Resource
      RestApiId: !Ref apiGateway
      AuthorizationType: NONE
      RequestParameters:
        method.request.path.proxy: true
      Integration:
        CacheKeyParameters:
          - 'method.request.path.proxy'
        RequestParameters:
          integration.request.path.proxy: 'method.request.path.proxy'
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Sub
          - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Arn}/invocations
          - Arn:
              Fn::GetAtt:
               - LambdaFunction
               - Arn
        PassthroughBehavior: WHEN_NO_MATCH
        IntegrationResponses:
          - StatusCode: 200 
...