Skip to content

AWS Amplify で DynamoDB の属性へのアクセスを制限する

Updated:

背景

Lambdaから操作できるDynamoDBの属性を制限する。

手順

1. Lambda にアクセス権付与

DynamoDBへのアクセスを許可していない場合は次のコマンドを実行してアクセス権を付与する。

amplify update function

2. Lambda のアクセス権変更

オーバーライドは不要。 xxxx-cloudformation-template.jsonlambdaexecutionpolicy を編集する。 Statementを次のように変更する。

"lambdaexecutionpolicy": {
  "DependsOn": [
    "LambdaExecutionRole"
  ],
  "Type": "AWS::IAM::Policy",
  "Properties": {
    "PolicyName": "lambda-execution-policy",
    "Roles": [
      {
        "Ref": "LambdaExecutionRole"
      }
    ],
    "PolicyDocument": {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
          ],
          "Resource": {
            // 省略
          }
        },
        {
          "Effect": "Allow",
          "Action": [
            "dynamodb:GetItem",
            "dynamodb:BatchGetItem",
            "dynamodb:Query",
            "dynamodb:PutItem",
            "dynamodb:UpdateItem",
            "dynamodb:DeleteItem",
            "dynamodb:BatchWriteItem"
          ],
          "Resource": [
            {
              "Ref": "xxx" // 要変更
            },
            {
              "Fn::Join": [
                "/",
                [
                  {
                    "Ref": "xxx" // 要変更
                  },
                  "index/*"
                ]
              ]
            }
          ],
          "Condition": {
            "ForAllValues:StringEquals": {
              "dynamodb:Attributes": [
                "attribute1", // 属性名
                "attribute2" // 属性名
              ]
            },
            "StringEqualsIfExists": {
              "dynamodb:Select": "SPECIFIC_ATTRIBUTES"
            }
          }
        }
      ]
    }
  }
}

動作例(getItem)

許可されていないattribute3を取得する。

const params = {
  TableName,
  Key: marshall({
    attribute1,
  }),
  AttributesToGet: ["attribute1", "attribute2", "attribute3"],
};

try {
  const { Item } = await client.getItem(params);
  return Item !== undefined ? unmarshall(Item) : undefined;
} catch (error) {
  logger.error("getItem", { error });
}

AccessDeniedException が発生する。

{
  "level": "ERROR",
  "message": "getItem",
  "service": "dynamodbAttributeTest",
  "timestamp": "2024-02-17T21:29:26.278Z",
  "xray_trace_id": "1-65ce8234-57b78d1c570ea8a670ab9c74",
  "error": {
      "name": "AccessDeniedException",
      "location": "/var/task/node_modules/@smithy/smithy-client/dist-cjs/index.js:838",
      "message": "User: arn:aws:sts::xxx:assumed-role/xxx-dev/xxx-dev is not authorized to perform: dynamodb:GetItem on resource: arn:aws:dynamodb:ap-northeast-1:xxx:table/xxx-dev because no identity-based policy allows the dynamodb:GetItem action",
      "stack": "AccessDeniedException: xxx"
    }
}

動作例(putItem)

許可されていないattribute3を登録する。

const params = {
  TableName: TABLE,
  Item: marshall({
    attribute1,
    attribute2,
    attribute3,
  }),
};

try {
  await client.putItem(params);
} catch (error) {
  logger.error("putItem", { error });
}

AccessDeniedException が発生する。

{
    "level": "ERROR",
    "message": "putItem",
    "service": "dynamodbAttributeTest",
    "timestamp": "2024-02-17T21:41:39.466Z",
    "xray_trace_id": "1-65ce8512-1abcacdb3c34edad1eff499f",
    "error": {
        "name": "AccessDeniedException",
        "location": "/var/task/node_modules/@smithy/smithy-client/dist-cjs/index.js:838",
        "message": "User: arn:aws:sts::xxx:assumed-role/xxx-dev/xxx-dev is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:ap-northeast-1:xxx:table/xxx-dev because no identity-based policy allows the dynamodb:PutItem action",
        "stack": "AccessDeniedException: xxx"
    }
}

参考