【Python】CDKでLambdaにDynamoDBのGSIにアクセス許可を付与する
あけましておめでとうございます! 今年もよろしくおねがいします 🙇
CDK で作った Lambda に DynamoDB の GSI(グローバルセカンダリインデックス)の権限をどうやって付加するか?という話です。
やりたいことは、ざっくり図にするとこんな感じです。
DynamoDB、Lambda、GSI を CDK でデプロイして GSI に Lambda から Scan を投げみるというデモです 👍
CDK では Lambda に GSI の許可を行ういい感じの機能が用意されていないので、ポリシー作ってアタッチするという力技になります 🙇
⚠ 記事を書き終える間近に気が付きました!
普通にバージョンアップで対応されてた 😅
https://github.com/aws/aws-cdk/pull/1564
古い内容の記事を書いていてもあれなので、泣く泣く記事の大部分を修正 😞
結果。記事にする必用もないくらい簡単なものになってしまった 😅
前提
※Dynamo の GSI の作り方等は、上記の過去記事を参照ください!今回は主に過去記事との差分を書いていきます!
では 作っていきましょう 👻
requirements.txt
DynamoDB と Lambda が必用です 👍
aws-cdk.core==1.72.0
aws-cdk.aws-lambda==1.72.0
aws-cdk.aws_dynamodb==1.72.0
スタックファイル
DynamoDB のテーブルと lambda を作って、lambda にテーブルの読み込み権限を与えます。こうすると、GSI にも読み込み権限が付与されます(泣)
from aws_cdk import aws_lambda, core
from aws_cdk.aws_dynamodb import Attribute, AttributeType, ProjectionType, Table
class DynamoTableGsiStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# =======> DynamoDB
gsi_name = "HogeGSI"
table = Table(
self,
"DynamoTableGsiTable",
partition_key=Attribute(name="pk", type=AttributeType.NUMBER),
sort_key=Attribute(name="sk", type=AttributeType.STRING),
removal_policy=core.RemovalPolicy.DESTROY,
)
table.add_global_secondary_index(
index_name=gsi_name,
partition_key=Attribute(name="gsi_pk", type=AttributeType.NUMBER),
sort_key=Attribute(name="gsi_sk", type=AttributeType.STRING),
projection_type=ProjectionType.KEYS_ONLY,
)
# =======> Lambda
lambda_ = aws_lambda.Function(
self,
"LambdaDynamoTableGsi",
code=aws_lambda.Code.asset("lambdas/dynamo_table_gsi"),
runtime=aws_lambda.Runtime.PYTHON_3_8,
handler="lambda_function.lambda_handler",
environment={"TABLE_NAME": table.table_name, "GSI_NAME": gsi_name},
)
table.grant_read_data(lambda_) # これがあればGSIに読み込み権限が付与される
Lambda
いつものおまけです 👍
import os
import boto3
dynamodb = boto3.client("dynamodb")
def lambda_handler(event, context):
return dynamodb.scan(TableName=os.getenv("TABLE_NAME"), IndexName=os.getenv("GSI_NAME"))["Items"]
デプロイ 🚀
$ cdk deploy dynamo-table-gsi-stack
動作確認
作ったテーブルと Lambda の名前を取得します。
$ aws dynamodb list-tables | grep dynamo-table-gsi-stack
$ aws lambda list-functions | grep dynamo-table-gsi-stack
今回はこんな(↓)名前でした。
dynamo-table-gsi-stack-DynamoTableGsiTable3CEEAFD7-1EZY6822T8XOK
dynamo-table-gsi-stack-LambdaDynamoTableGsiE0F0C0D-1LS4QF6WDEC9Y
以下のように確認してみました。
# リソース名を変数に入れてみる
$ TABLE_NAME=dynamo-table-gsi-stack-DynamoTableGsiTable3CEEAFD7-1EZY6822T8XOK
$ LAMBDA_NAME=dynamo-table-gsi-stack-LambdaDynamoTableGsiE0F0C0D-1LS4QF6WDEC9Y
# ダミーのデータをPUTしてみる
$ aws dynamodb put-item \
--table-name $TABLE_NAME \
--item '{"pk":{"N":"1234"},"sk":{"S":"hogehoge"},"gsi_pk":{"N":"987"},"gsi_sk":{"S":"hugohugo"},"dummy":{"S":"GSIでは取得されないパラメータ"}}'
# Lambdaを叩いてレスポンスを確認してみる
$ aws lambda invoke --function-name $LAMBDA_NAME --payload '{}' response.json
$ cat response.json
[{"gsi_pk": {"N": "987"}, "sk": {"S": "hogehoge"}, "pk": {"N": "1234"}, "gsi_sk": {"S": "hugohugo"}}]
動作確認完了 👍
デストロイ
$ cdk destroy dynamo-table-gsi-stack
まとめ
今回は CDK で Lambda と DynamoDB のテーブルと GSI を作って、Lambda に権限を付与する。ということをやってみました 👍
GSI への権限不要は、昔はポリシーを力技でアタッチする方法でしたが、今は Grant で普通に設定可能でした 😅