ぺーぺーSEのブログ

備忘録・メモ用サイト。

AWSコマンドラインインターフェース(AWS CLI)でAPI Gateway+AWS Lambdaを構築してみる(その2)

下記の記事ではAPI GatewayをHTTPのGETメソッドで作成したが、この記事ではHTTPのPOSTメソッドで作成する。

tanakakns.hatenablog.com

API Gateway + AWS LambdaをAWS CLIで構築して、POSTメソッドでテストするところまで行う。
以下の順で行う。

  1. AWS Lambdaの作成
  2. API Gatewayの作成
    1. APIの作成
    2. リソース(パス)の作成
    3. HTTPメソッドの作成
  3. AWS LambdaとAPI Gatewayの連携設定
    1. APIのリソースとLambdaの関連付け
    2. AWS LambdaからAPI Gatewayへのレスポンスを作成
    3. API GatewayメソッドにLambda関数の実行権限付与
    4. API Gatewayメソッドのレスポンスを作成
  4. 設定したAPI Gateway + AWS Lambdaのテスト
  5. APIのデプロイ
  6. APIの確認

以降の作成手順ではいろいろと流出するとマズいID周りは以下のようにマスクしています。

  • AWSアカウントID
    • [account-id]
  • 実行ロール
    • [exec-role-name]
  • 作成したAPIのID(rest-api-id)
    • [rest-api-id]
  • 作成したAPIのルートパスのID
    • [rest-api-root-path-id]
  • APIに追加するパス(cliPathSample)のID
    • [rest-api-cliPathSample-path-id]
  • デプロイのID
    • [deployment-id]
  • その他
    • xxx

1.AWS Lambdaの作成

AWS LambdaにLambda関数を作成する。
Lambda関数名は「cliLambdaSample」、ランタイムは「java8」で作成する。
実行のロールについてはあらかじめ作成しておいて、「aws iam list-roles」コマンドで表示されたものから選ぶ。

aws lambda create-function^
 --function-name cliLambdaSample^
 --runtime       java8^
 --role          arn:aws:iam::[account-id]:role/[exec-role-name]^
 --handler       org.sample.handler.PersonHandler::postPerson^
 --zip-file      fileb://LambdaSample-1.0-SNAPSHOT.jar
{
    "CodeSha256": "xxx",
    "FunctionName": "cliLambdaSample",
    "CodeSize": 506959,
    "MemorySize": 128,
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample",
    "Version": "$LATEST",
    "Role": "arn:aws:iam::[account-id]:role/[exec-role-name]",
    "Timeout": 3,
    "LastModified": "2016-02-03T11:33:17.027+0000",
    "Handler": "org.sample.handler.PersonHandler::postPerson",
    "Runtime": "java8",
    "Description": ""
}

作成したLambda関数の確認。

aws lambda get-function^
 --function-name cliLambdaSample
{
    "Code": {
        "RepositoryType": "S3",
        "Location": "https://awslambda-ap-ne-1-tasks.s3-ap-northeast-1.amazonaws.com/snapshots/[account-id]/cliLambdaSample-xxx"
    },
    "Configuration": {
        "Version": "$LATEST",
        "CodeSha256": "xxx",
        "FunctionName": "cliLambdaSample",
        "MemorySize": 128,
        "CodeSize": 506959,
        "FunctionArn": "arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample",
        "Handler": "org.sample.handler.PersonHandler::postPerson",
        "Role": "arn:aws:iam::[account-id]:role/[exec-role-name]",
        "Timeout": 3,
        "LastModified": "2016-02-03T11:33:17.027+0000",
        "Runtime": "java8",
        "Description": ""
    }
}

2.API Gatewayの作成

2.1.APIの作成

API GatewayAPIを作成する。

aws apigateway create-rest-api^
 --name cliApiSample
{
    "name": "cliApiSample",
    "id": "[rest-api-id]",
    "createdDate": 1454499448
}

作成したAPIの確認。

aws apigateway get-resources^
 --rest-api-id [rest-api-id]
{
    "items": [
        {
            "path": "/",
            "id": "[rest-api-root-path-id]"
        }
    ]
}

作成したAPIにはルートパスのリソースが作成されていることがわかる。

2.2.リソース(パス)の作成

作成したAPIに対してパスを追加する。
親(parent-id)はAPIのルートパスリソースを指定する。

aws apigateway create-resource^
 --rest-api-id [rest-api-id]^
 --parent-id   [rest-api-root-path-id]^
 --path-part   cliPathSample
{
    "path": "/cliPathSample",
    "pathPart": "cliPathSample",
    "id": "[rest-api-cliPathSample-path-id]",
    "parentId": "[rest-api-root-path-id]"
}

作成したリソースを確認コマンド。

aws apigateway get-resource^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]
{
    "path": "/cliPathSample",
    "pathPart": "cliPathSample",
    "id": "[rest-api-cliPathSample-path-id]",
    "parentId": "[rest-api-root-path-id]"
}

2.3.APIメソッドを作成

APIの「/cliPathSample」リソースに対してPOSTメソッドを作成する。

aws apigateway put-method^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST^
 --authorization-type NONE
{
    "apiKeyRequired": false,
    "httpMethod": "POST",
    "authorizationType": "NONE"
}

作成したメソッドの確認。

aws apigateway get-method^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST
{
    "apiKeyRequired": false,
    "httpMethod": "POST",
    "authorizationType": "NONE"
}

3.AWS LambdaとAPI Gatewayの連携設定

3.1.APIのリソースとLambdaの関連付け

cliPathSampleリソースとLambda関数を作成したHTTPのPOSTメソッドで関連付ける。
ただし、API GatewayからAWS LambdaへはPOSTで連携することに注意。
また、uri
「arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/[Lambda関数のARN]/invocations」
の形式で指定する。
「2015-03-31」という日付はおそらくAWS CLIに「aws lambda」コマンド実装されたリリース日(Release: AWS CLI 1.8.12)。

aws apigateway put-integration^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST^
 --type AWS^
 --integration-http-method POST^
 --uri arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample/invocations
{
    "httpMethod": "POST",
    "cacheKeyParameters": [],
    "type": "AWS",
    "uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample/invocations",

    "cacheNamespace": "[rest-api-cliPathSample-path-id]"
}

作成した連携設定を確認。

aws apigateway get-integration^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST
{
    "httpMethod": "POST",
    "cacheKeyParameters": [],
    "type": "AWS",
    "uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample/invocations",

    "cacheNamespace": "[rest-api-cliPathSample-path-id]"
}

3.2.AWS LambdaからAPI Gatewayへのレスポンスを作成

POSTのHTTPレスポンスをステータス200のときはJSONで設定。

aws apigateway put-integration-response^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST^
 --status-code 200^
 --response-templates {\"application/json\":\"\"}
{
    "statusCode": "200",
    "responseTemplates": {
        "application/json": null
    }
}

作成したレスポンスを確認。

aws apigateway get-integration-response^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST^
 --status-code 200
{
    "statusCode": "200",
    "responseTemplates": {
        "application/json": null
    }
}

1つ上のレイヤでも確認。

aws apigateway get-integration^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST
{
    "httpMethod": "POST",
    "integrationResponses": {
        "200": {
            "responseTemplates": {
                "application/json": null
            },
            "statusCode": "200"
        }
    },
    "cacheKeyParameters": [],
    "type": "AWS",
    "uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample/invocations",

    "cacheNamespace": "[rest-api-cliPathSample-path-id]"
}

3.3.API GatewayメソッドにLambda関数の実行権限付与

cliPathSampleリソースのPOSTメソッドに対してLambda関数の実行権限を付与する。
statement-idは32桁で適当に作成。(ここでは、12345678901234567890123456789012)
source-arnは
「arn:aws:execute-api:ap-northeast-1:[account-id]:[rest-api-id]/[ステージ名]/[HTTPメソッド]/[リソース名]
の形式。

aws lambda add-permission^
 --function-name cliLambdaSample^
 --statement-id 12345678901234567890123456789012^
 --action lambda:InvokeFunction^
 --principal apigateway.amazonaws.com^
 --source-arn arn:aws:execute-api:ap-northeast-1:[account-id]:[rest-api-id]/test/POST/cliPathSample
{
    "Statement": "{
        \"Condition\":{
            \"ArnLike\":{
                \"AWS:SourceArn\":\"arn:aws:execute-api:ap-northeast-1:[account-id]:[rest-api-id]/*/POST/cliPathSample\"
            }
        },
        \"Action\":[
            \"lambda:InvokeFunction\"
        ],
        \"Resource\":\"arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample\",
        \"Effect\":\"Allow\",
        \"Principal\":{
            \"Service\":\"apigateway.amazonaws.com\"
        },
        \"Sid\":\"12345678901234567890123456789012\"
    }"
}

設定した実行権限の確認。

aws lambda get-policy^
 --function-name cliLambdaSample
{
    "Policy": "{
        \"Version\":\"2012-10-17\",
        \"Statement\":[
            {
                \"Condition\":{
                    \"ArnLike\":{
                        \"AWS:SourceArn\":\"arn:aws:execute-api:ap-northeast-1:[account-id]:[rest-api-id]/*/POST/cliPathSample\"
                    }
                },
                \"Action\":\"lambda:InvokeFunction\",
                \"Resource\":\"arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample\",
                \"Effect\":\"Allow\",
                \"Principal\":{
                    \"Service\":\"apigateway.amazonaws.com\"
                },
                \"Sid\":\"12345678901234567890123456789012\"
            }
        ],
        \"Id\":\"default\"
    }"
}

3.4.API Gatewayメソッドのレスポンスを作成

aws apigateway put-method-response^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST^
 --status-code 200^
 --response-models {\"application/json\":\"Empty\"}
{
    "responseModels": {
        "application/json": "Empty"
    },
    "statusCode": "200"
}

作成したレスポンスの確認。

aws apigateway get-method^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST
{
    "apiKeyRequired": false,
    "httpMethod": "POST",
    "methodIntegration": {
        "integrationResponses": {
            "200": {
                "responseTemplates": {
                    "application/json": null
                },
                "statusCode": "200"
            }
        },
        "cacheKeyParameters": [],
        "uri": "arn:aws:apigateway:ap-northeast-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample/invocations",
        "httpMethod": "POST",
        "cacheNamespace": "[rest-api-cliPathSample-path-id]",
        "type": "AWS"
    },
    "methodResponses": {
        "200": {
            "responseModels": {
                "application/json": "Empty"
            },
            "statusCode": "200"
        }
    },
    "authorizationType": "NONE"
}

4.設定したAPI Gateway + AWS Lambdaのテスト

aws apigateway test-invoke-method^
 --rest-api-id [rest-api-id]^
 --resource-id [rest-api-cliPathSample-path-id]^
 --http-method POST^
 --path-with-query-string ""^
 --body {\"name\":\"Jiro\",\"age\":18}
{
    "status": 200,
    "body": "{\"message\":\"Accepted the person post request.\"}",
    "log": "Execution log for request test-request\n
            Wed Feb 03 12:35:55 UTC 2016 : Starting execution for request: test-invoke-request\n
            Wed Feb 03 12:35:55 UTC 2016 : API Key: test-invoke-api-key\n
            Wed Feb 03 12:35:55 UTC 2016 : Method request path: {}\n
            Wed Feb 03 12:35:55 UTC 2016 : Method request query string: {}\n
            Wed Feb 03 12:35:55 UTC 2016 : Method request headers: {}\n
            Wed Feb 03 12:35:55 UTC 2016 : Method request body before transformations: {\"name\":\"Jiro\",\"age\":18}\n
            Wed Feb 03 12:35:55 UTC 2016 : Endpoint request URI: https://lambda.ap-northeast-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:ap-northeast-1:[account-id]:function:cliLambdaSample/invocations\n
            Wed Feb 03 12:35:55 UTC 2016 : Endpoint request headers: {Authorization=xxx,
                                                                      X-Amz-Date=20160203T123555Z,
                                                                      X-Amz-Source-Arn=arn:aws:execute-api:ap-northeast-1:[account-id]:[rest-api-id]/null/POST/cliPathSample,
                                                                      Accept=application/json,
                                                                      User-Agent=AmazonAPIGateway_[rest-api-id],
                                                                      Host=lambda.ap-northeast-1.amazonaws.com,
                                                                      X-Amz-Content-Sha256=xxx,
                                                                      Content-Type=application/json}\n
            Wed Feb 03 12:35:55 UTC 2016 : Endpoint request body after transformations: {\"name\":\"Jiro\",\"age\":18}\n
            Wed Feb 03 12:35:57 UTC 2016 : Endpoint response body before transformations: {\"message\":\"Accepted the person post request.\"}\n
            Wed Feb 03 12:35:57 UTC 2016 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0,
                                                                       x-amzn-RequestId=xxx,
                                                                       Connection=keep-alive,
                                                                       Content-Length=47,
                                                                       Date=Wed, 03 Feb 2016 12:35:56GMT,
                                                                       Content-Type=application/json}\n
            Wed Feb 03 12:35:57 UTC 2016 : Method response body after transformations: {\"message\":\"Accepted the person post request.\"}\n
            Wed Feb 03 12:35:57 UTC 2016 : Method response headers: {Content-Type=application/json}\n
            Wed Feb 03 12:35:57 UTC 2016 : Successfully completed execution\n
            Wed Feb 03 12:35:57 UTC 2016 : Method completed with status: 200\n",
    "latency": 1517,
    "headers": {
        "Content-Type": "application/json"
    }
}

5.APIのデプロイ

作成したAPIを公開してアクセスURIを取得する。

aws apigateway create-deployment^
 --rest-api-id [rest-api-id]^
 --stage-name test^
 --stage-description ""^
 --description ""
{
    "id": "[deployment-id]",
    "createdDate": 1454501432
}

デプロイを確認。
ただし、下記のコマンドは1つのAPIに対してすべてのデプロイを表示する。

aws apigateway get-deployments^
 --rest-api-id [rest-api-id]
{
    "items": [
        {
            "id": "[deployment-id]",
            "createdDate": 1454501432
        }
    ]
}

1つのデプロイを指定して内容を確認。

aws apigateway get-deployment^
 --rest-api-id [rest-api-id]^
 --deployment-id [deployment-id]
{
    "id": "[deployment-id]",
    "createdDate": 1454501432
}

APIのステージ名を取得する。
ただし、下記のコマンドは1つのAPIに対してすべてのステージを表示する。

aws apigateway get-stages^
 --rest-api-id [rest-api-id]
{
    "item": [
        {
            "stageName": "test",
            "cacheClusterEnabled": false,
            "cacheClusterStatus": "NOT_AVAILABLE",
            "deploymentId": "[deployment-id]",
            "lastUpdatedDate": 1454501432,
            "createdDate": 1454501432,
            "methodSettings": {}
        }
    ]
}

1つのステージを指定して内容を確認。

aws apigateway get-stage^
 --rest-api-id [rest-api-id]^
 --stage-name test
{
    "stageName": "test",
    "cacheClusterEnabled": false,
    "cacheClusterStatus": "NOT_AVAILABLE",
    "deploymentId": "[deployment-id]",
    "lastUpdatedDate": 1454501432,
    "createdDate": 1454501432,
    "methodSettings": {}
}

6.APIの確認

以上の手順で作成したAPIURIは以下のようになる。

https://[rest-api-id].execute-api.[リージョン名].amazonaws.com/[ステージ名][リソースのパス]

ここの例では、

https://[rest-api-id].execute-api.ap-northeast-1.amazonaws.com/test/cliPathSample

となる。