It's a peacehell world.

こんな名前ですが情報技術について主に扱うブログです。

Lambda から DynamoDB GSI でクエリすると AccessDenied になる

🔥 事象

CDK Python でデプロイした Lambda で、GSI を使った query 実行時に AccessDenied になりました。

Lambda の Policy に dynamodb:Query 足してるのになんでやねんって感じ。

💡 解消方法

grantReadData で全ての読み取り権限を Lambda に付与することで解消できました。

⌨️ サンプル

例として野球チームの選手一覧からポジションと利き手で絞り込みたい場合をあげます。

監督も「左利きの投手」で query したいことでしょう。左の先発ピッチャーは重宝されますからね。

from aws_cdk import core
from aws_cdk.aws_iam import PolicyStatement
from aws_cdk.aws_lambda_python import PythonFunction
from aws_cdk.aws_lambda import Runtime
from aws_cdk.aws_dynamodb import (
    Table,
    Attribute,
    AttributeType,
    BillingMode,
    ProjectionType
)


class SampleStack(core.Stack):

    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        table_ = Table(
            self,
            'BaseballTeamMembers',
            billing_mode=BillingMode.PAY_PER_REQUEST,
            partition_key=Attribute(
                name='id', type=AttributeType.STRING),
            removal_policy=core.RemovalPolicy.DESTROY,
        )
        table_.add_global_secondary_index(
            index_name='PositionPitchingHandIndex',
            partition_key=Attribute(
                name='position',
                type=AttributeType.STRING),
            sort_key=Attribute(
                name='pitching-hand',
                type=AttributeType.STRING),
            projection_type=ProjectionType.ALL,
        )

        lambda_ = PythonFunction(
            self, 'ListMembersByPositionPitching',
            runtime=Runtime.PYTHON_3_8,
            entry='lambda',
            index='members.py',
            handler='handler',
            environment={
                'MEMBERS_TABLE_NAME': table_.table_name
            })
        lambda_.add_to_role_policy(
            PolicyStatement(
                resources=[table_.table_arn],
                actions=['dynamodb:Query']))
        table_.grant_read_data(lambda_)