今回のゴール
- プライベートサブネットからインターネットを経由せずに直接DynamoDBにアクセスしたい
- 社内のコンプライアンス上インターネットを経由しないでDynamoDBと通信したい
等の要件はよくあると思います。
そこで今回はVPCエンドポイント経由でDynamoDBを使用できるように設定していきます。
DynamoDBの作成
[テーブル名]:test-vpcendpoint
[パーティションキー]:id

Lambdaの作成
セキュリティーグループの作成
Lambda関数にアタッチするセキュリティーグループを作成します。
 [セキュリティグループ名]:sg_test_lambda
[説明]:access to dynamodb 
[VPC]:VPCを選択

IAMポリシーの作成
下記のポリシー(Allow_DynamoDB_test-vpcendpoint)を作成しました。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "dynamodb:PutItem",
                "dynamodb:DescribeTable",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:UpdateItem"
            ],
            "Resource": "arn:aws:dynamodb:ap-northeast-1:(your account ID):table/test-vpcendpoint"
        }
    ]
}
Lambdaの作成
[関数名]:vpc-endpoint-test
[ランタイム]:Python 3.9

ロールにポリシーのアタッチ
自動作成されたIAMロールに先ほど作成したポリシー( Allow_DynamoDB_test-vpcendpoint )をアタッチします。
今回はVPCにLambdaでアクセスできるように設定しますので、AWS管理ポリシーの”AWSLambdaVPCAccessExecutionRole”をアタッチします。
この設定をしないと、後で行うLamdbdのVPC設定時に、
“The provided execution role does not have permissions to call CreateNetworkInterface on EC2”
とエラーがでて登録できません。
LambdaのVPC設定
LambdaがVPCにアクセスできるよう設定します。
Lambda関数を選択して、[設定]-[VPC]画面からVPC情報を登録していきます。
[VPC]、[サブネット]を入力して、[セキュリティーグループ]に先ほど作成したセキュリティーグループ( sg_test_lambda )を選択します。

エンドポイントの作成
DynamoDBのサービスを選択して、VPCとルートテーブルを選択します。

確認
Lambda関数のコード
1件のレコードを登録する下記のコードで検証しました。
import boto3
import json
dynamodb = boto3.client('dynamodb')
def lambda_handler(event, context):
    
    dynamodb.put_item(
        TableName = 'test-vpcendpoint',
        Item = {"id": {"S": "1" }}
        )
        
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }
エンドポイントがある状態
デフォルトゲートウェイがインターネットゲートウェイ・NATゲートウェイに向いていない状態でLamdbaを実行します。
インターネットに接続できない状態でも成功となりました。
{
  "statusCode": 200,
  "body": "\"Hello from Lambda!\""
}
エンドポイントが無い状態
エンドポイントのルートテーブルの管理より、対象のルートテーブルを外した状態でLambdaを実行します。
タイムアウトのエラーとなりました。
{
  "errorMessage": "2021-10-21T06:27:57.633Z 93b7fe05-0465-4ce4-9815-781acff17825 Task timed out after 3.00 seconds"
}
