[アップデート] 別アカウントのAmazon DynamoDB Streamsをイベントソースマッピングとして設定し、別アカウントからAWS Lambdaを実行できるようになりました

[アップデート] 別アカウントのAmazon DynamoDB Streamsをイベントソースマッピングとして設定し、別アカウントからAWS Lambdaを実行できるようになりました

AWS LambdaがAmazon DynamoDB Streamsに対してクロスアカウントアクセスできるようになりました。
2026.02.02

AWS Lambda関数のトリガーとして、別アカウントのAmazon DynamoDB Streamsが指定できるようになったぞ

おのやんです。

AWS Lambda(以下、Lambda)が、Amazon DynamoDB(以下、DynamoDB)Streamsからのクロスアカウントアクセスをサポートするようになりました。

https://aws.amazon.com/jp/about-aws/whats-new/2026/01/aws-lambda-cross-account-access-dynamodb-streams/

今回は、こちらのアップデートの内容についてまとめ、実際に検証していきたいと思います。

アップデート内容のおさらい

今まで、Lambda関数は同じAWSアカウント内のDynamoDB Streamsしかイベントソースとして使用できませんでした。ですので、別アカウントにDynamoDB Streamsのデータを送信する場合はAmazon EventBridgeやAmazon Data Firehoseなどを噛ませる必要がありました。DynamoDB StreamsのデータをLambda経由で別アカウントに送信する類似の構成は、過去に弊社ブログでもご紹介しています。

https://dev.classmethod.jp/articles/dynamodb-streams-sqs-cross-account-eventbridge/

今回のアップデートにより、別のAWSアカウントにあるlambda関数のイベントソースとしてDynamoDB Streamsを設定できるようになります。

クロスアカウントアクセスを有効にするには、DynamoDB Streamsにリソースベースのポリシーを設定し、別アカウントのLambda関数からのアクセスを許可、その後にLambda関数のイベントソースマッピングとして、別アカウントのDynamoDB Streamsを指定します。

こちらの機能は、すべてのAWSリージョンと、AWS GovCloud (US) リージョンで利用可能です。

実際にやってみた

それでは、実際にクロスアカウントでDynamoDB StreamsとLambdaを連携させてみましょう。

今回は、2つのAWSアカウントを準備して試してみます。アカウントA(111111111111)にはDynamoDBテーブルとStreamsを配置します。アカウントB(222222222222)にはLambda関数を配置します。また、これらの操作はap-northeast-1(東京リージョン)で実施します。

上記の構成にて、アカウントAのDynamoDBに変更があったときに、アカウントBのLambdaが起動される構成を作ります。

スクリーンショット 2026-02-01 17.09.59

アカウントAでDynamoDBテーブルを作成

まず、アカウントAでDynamoDBテーブルを作成し、Streamsを有効化します。

aws dynamodb create-table \
    --table-name CrossAccountTest \
    --attribute-definitions AttributeName=id,AttributeType=S \
    --key-schema AttributeName=id,KeyType=HASH \
    --billing-mode PAY_PER_REQUEST \
    --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
    --region ap-northeast-1

アカウントAにて、DynamoDBテーブルが作成されていますね。

スクリーンショット 2026-02-01 15.31.31

テーブルが作成されたら、Stream ARNを確認しておきます。

aws dynamodb describe-table \
    --table-name CrossAccountTest \
    --region ap-northeast-1 \
    --query 'Table.LatestStreamArn' \
    --output text

こちらは後ほど使用しますので、メモしておきます。

arn:aws:dynamodb:ap-northeast-1:111111111111:table/CrossAccountTest/stream/2026-02-01T06:30:25.829

アカウントBでLambda関数を作成

次に、アカウントBでLambda関数を作成します。今回はPython 3.13で簡単なログ出力関数を作成します。

まず、Lambda実行用のIAM信頼ポリシーをJSONファイルに記述します。

trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

こちらのポリシーを使って、IAMロールを作成します。

aws iam create-role \
    --role-name lambda-dynamodb-cross-account-role \
    --assume-role-policy-document file://trust-policy.json

こちらのIAMロールに、AWSLambdaDynamoDBExecutionRoleのマネージドポリシーをアタッチします。

aws iam attach-role-policy \
    --role-name lambda-dynamodb-cross-account-role \
    --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaDynamoDBExecutionRole

作成したロールのARNをメモしておきます。

aws iam get-role \
    --role-name lambda-dynamodb-cross-account-role \
    --query 'Role.Arn' \
    --output text
arn:aws:iam::222222222222:role/lambda-dynamodb-cross-account-role

次に、Lambda関数のコードを準備します。この際、さきほどメモしてIAMロールのARNを記載します。

lambda_function.py
import json
from typing import Any, Dict

def lambda_handler(event: Dict[str, Any], context: Any) -> Dict[str, Any]:
    print('Received event:', json.dumps(event, indent=2, ensure_ascii=False))

    for record in event['Records']:
        print(f"EventID: {record['eventID']}")
        print(f"EventName: {record['eventName']}")
        print(f"DynamoDB: {json.dumps(record['dynamodb'], indent=2, ensure_ascii=False)}")

    return {'statusCode': 200, 'body': 'Success'}

このコードをZIPで圧縮し、デプロイします。

$ zip function.zip lambda_function.py

$ aws lambda create-function \
    --function-name CrossAccountDynamoDBHandler \
    --runtime python3.13 \
    --role arn:aws:iam::222222222222:role/lambda-dynamodb-cross-account-role \
    --handler lambda_function.lambda_handler \
    --zip-file fileb://function.zip \
    --region ap-northeast-1

Lambda関数がデプロイできました。

スクリーンショット 2026-02-01 17.12.01

アカウントAでDynamoDB Streamsのリソースベースポリシーを設定

次に、アカウントAのDynamoDB Streamsに、アカウントBのLambda関数がアクセスできるリソースベースのポリシーを設定します。この際、さきほどメモしてDynamoDB StreamsとIAMロールのARNを記述します。

aws dynamodb put-resource-policy \
    --resource-arn arn:aws:dynamodb:ap-northeast-1:111111111111:table/CrossAccountTest/stream/2026-02-01T06:30:25.829 \
    --policy '{
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::222222222222:role/lambda-dynamodb-cross-account-role"
          },
          "Action": [
            "dynamodb:DescribeStream",
            "dynamodb:GetRecords",
            "dynamodb:GetShardIterator"
          ],
          "Resource": "arn:aws:dynamodb:ap-northeast-1:111111111111:table/CrossAccountTest/stream/2026-02-01T06:30:25.829"
        }
      ]
    }' \
    --region ap-northeast-1

クロスアカウントアクセスする際の、DynamoDBのリソースベースのポリシーについては、こちらをご参照ください。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/rbac-examples.html#rbac-examples-cross-account

こちらの操作にて、DynamoDB Streamsのリソースベースのポリシーが設定できました。

スクリーンショット 2026-02-01 16.00.10

このポリシーにより、アカウントBのLambda実行ロールがアカウントAのDynamoDB Streamsを読み取れるようになります。

アカウントBでイベントソースマッピングを作成

次に、アカウントBのLambda関数のトリガーとして、アカウントAのDynamoDB Streamsを設定します。ここでも、先ほどメモしたDynamoDB StreamsのARNを使用します。

aws lambda create-event-source-mapping \
    --function-name CrossAccountDynamoDBHandler \
    --event-source-arn arn:aws:dynamodb:ap-northeast-1:111111111111:table/CrossAccountTest/stream/2026-02-01T06:30:25.829 \
    --starting-position LATEST \
    --region ap-northeast-1

アカウントBのLambda関数のトリガーとして、アカウントAのDynamoDB Streamsを設定できました。

スクリーンショット 2026-02-01 16.02.48

イベントソースマッピングが作成されると、アカウントBのLambdaがアカウントAのDynamoDB Streamsをポーリングし始めます。

動作確認

それでは、アカウントAのDynamoDBに実際にデータを挿入して、クロスアカウントで動作するか確認してみましょう。

aws dynamodb put-item \
    --table-name CrossAccountTest \
    --item '{"id": {"S": "test-001"}, "name": {"S": "Test User"}, "email": {"S": "test@example.com"}}' \
    --region ap-northeast-1

DynamoDBにデータが挿入されました。

スクリーンショット 2026-02-01 16.05.25

アカウントBのLambda関数のCloudWatch Logsを確認すると、DynamoDBのイベント情報が書かれたログが確認できました!

スクリーンショット 2026-02-01 16.11.46

コマンドでも、こんな感じでログを取得できました。

$ aws logs tail /aws/lambda/CrossAccountDynamoDBHandler --follow --region ap-northeast-1

2026-02-01T07:03:58.084000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 INIT_START Runtime Version: python:3.13.v77       Runtime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:2c989696daccfc69ccb5167bebf22a3274048af875cacc431bdb8442374348aa
2026-02-01T07:03:58.217000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 START RequestId: 3f79919b-70f1-4c3a-8db6-144abc39ab55 Version: $LATEST
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 Received event: {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "Records": [
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "eventID": "8adc758361089d9e8b12b0a1cc6338ea",
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "eventName": "INSERT",
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "eventVersion": "1.1",
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "eventSource": "aws:dynamodb",
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "awsRegion": "ap-northeast-1",
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "dynamodb": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "ApproximateCreationDateTime": 1769929437.0,
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "Keys": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "id": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "S": "test-001"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 }
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 },
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "NewImage": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "name": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "S": "Test User"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 },
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "id": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "S": "test-001"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 },
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "email": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "S": "test@example.com"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 }
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 },
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "SequenceNumber": "109600002442871503720585",
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "SizeBytes": 54,
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "StreamViewType": "NEW_AND_OLD_IMAGES"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 },
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "eventSourceARN": "arn:aws:dynamodb:ap-northeast-1:111111111111:table/CrossAccountTest/stream/2026-02-01T06:30:25.829"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 }
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 ]
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 }
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 EventID: 8adc758361089d9e8b12b0a1cc6338ea
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 EventName: INSERT
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 DynamoDB: {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "ApproximateCreationDateTime": 1769929437.0,
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "Keys": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "id": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "S": "test-001"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 }
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 },
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "NewImage": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "name": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "S": "Test User"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 },
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "id": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "S": "test-001"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 },
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "email": {
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "S": "test@example.com"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 }
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 },
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "SequenceNumber": "109600002442871503720585",
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "SizeBytes": 54,
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 "StreamViewType": "NEW_AND_OLD_IMAGES"
2026-02-01T07:03:58.218000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 }
2026-02-01T07:03:58.220000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 END RequestId: 3f79919b-70f1-4c3a-8db6-144abc39ab55
2026-02-01T07:03:58.223000+00:00 2026/02/01/[$LATEST]0d610dcf62874d3e9980e597d1b3d770 REPORT RequestId: 3f79919b-70f1-4c3a-8db6-144abc39ab55    Duration: 2.28 ms       Billed Duration: 132 ms Memory Size: 128 MB     Max Memory Used: 38 MB  Init Duration: 129.19 ms

アカウントを分離している環境だと特に嬉しい

AWS Lambdaが別アカウントのDynamoDB Streamsをイベントソースとして使えるようになりました。特に複数のアカウントを事業部別などで管理している環境ですと、別アカウントのDynamoDB Streamsから直接Lambdaを呼び出せるので、非常に便利です。

マルチアカウント構成でDynamoDBとLambdaを使っている場合はぜひ活用してみてください。では!

この記事をシェアする

FacebookHatena blogX

関連記事