【ITニュース解説】Secure Data Sharing: AWS Lambda Writing to S3 Across Accounts

2025年09月03日に「Dev.to」が公開したITニュース「Secure Data Sharing: AWS Lambda Writing to S3 Across Accounts」について初心者にもわかりやすいように丁寧に解説しています。

作成日: 更新日:

ITニュース概要

AWSの別アカウント間でデータを安全に共有する方法を解説する。あるアカウントのLambdaから、別のS3バケットへ安全にデータを書き込むには、LambdaのIAMロールとS3バケットポリシーの適切な設定が必要だ。具体的な設定手順を示す。

ITニュース解説

現代のITシステム開発では、セキュリティと管理の効率性を高めるため、複数のAWSアカウントを使い分ける「マルチアカウント環境」が一般的である。AWSアカウントとは、利用者が所有するコンピューティングリソースやデータストレージなどを管理するための独立した仮想的な境界を指す。このマルチアカウント環境では、一つのアカウントで動くサービスが、別の独立したアカウントに存在するデータストレージへアクセスする必要が生じることがある。本解説では、AWS Lambdaというサービスを用いて、あるAWSアカウントから別のAWSアカウントに存在するS3バケットへ、データを安全に書き込む方法について詳細を説明する。

通常、AWSアカウントは互いに厳しく分離されており、デフォルトでは別アカウントのリソースに直接アクセスできない。これはセキュリティを保つ上で非常に重要であるが、システムによっては異なるアカウント間でデータを連携させる機能が求められる。例えば、データ処理を行うLambda関数を開発用のアカウントに置き、処理後の重要なデータを本番環境のアカウントにあるS3バケットに保存するといったケースである。このような状況で、安全かつ確実にクロスアカウントアクセスを実現するための設定が不可欠となる。

この課題を解決するためには、AWSの「IAM (Identity and Access Management)」サービスと「S3バケットポリシー」という二つの主要なセキュリティ機能を利用する。IAMは、AWSリソースへのアクセスをきめ細かく制御する仕組みであり、「誰が(プリンシパル)」、「何に(リソース)」対して、「どのような操作を(アクション)」できるかを定義する。IAMロールは、特定のサービスやユーザーに一時的な権限を与える「役割」であり、本解説ではAWS Lambdaにこの役割を与える。一方、S3バケットポリシーは、S3バケット自体に設定するルールで、どのプリンシパル(実体)がこのバケットにアクセスできるかをバケット側から明示的に許可するものである。これら二つの設定を組み合わせることで、強固なセキュリティを保ちつつクロスアカウントアクセスを実現する。

具体的なシナリオとしては、以下の二つのアカウントが登場する。 アカウントA(仮に「1111111111」と表記)は、データを処理するAWS Lambda関数をホストする。 アカウントB(仮に「2222222222」と表記)は、データを保存するS3バケット「account_b_bucket」を所有する。 目標は、アカウントAのLambda関数が、アカウントBにあるS3バケットへ安全にオブジェクト(ファイル)をアップロードすることである。

この目標を達成するために、三つの主要な設定が必要となる。まず、アカウントAにおけるIAMロールの設定である。 最初に「account_a_lambda_role」というIAMロールをアカウントAに作成する。これは、Lambda関数がS3バケットにアクセスする際に一時的に引き受ける「役割」となる。このロールには、アカウントBのS3バケット「account_b_bucket」に対してオブジェクトの読み込み(s3:GetObject)と書き込み(s3:PutObject)を許可する「カスタムポリシー」をアタッチする。このポリシーは、どのアクションをどこのリソースに対して許可するかを明確に定義し、具体的には"Resource": ["arn:aws:s3:::account_b_bucket/*"]でターゲットのS3バケット内の全てのオブジェクトを対象とする。 次に、このIAMロールに「信頼ポリシー」をアタッチする。これは、どのサービスがこのロールを引き受けることを許可するかを定義するものである。Lambda関数がこのロールを使用するため、"Principal": { "Service": "lambda.amazonaws.com" }という記述で、AWS Lambdaサービスがこのロールを引き受けることを許可する。これにより、Lambda関数は指定された権限で動作できるようになる。

次に、アカウントBにおけるS3バケットポリシーの設定である。 S3バケット側(アカウントB)でも、アカウントAからのアクセスを明示的に許可する必要がある。アカウントBのS3バケット「account_b_bucket」に対して「バケットポリシー」を設定する。このバケットポリシーは、アカウントAの「arn:aws:iam::1111111111:role/account_a_lambda_role」という特定のIAMロールが、このS3バケットに対してオブジェクトの読み書き(s3:GetObject, s3:PutObject)を行うことを許可する内容である。具体的には、"Principal": { "AWS": ["arn:aws:iam::1111111111:role/account_a_lambda_role"] }という記述で、アカウントAの特定のIAMロールからのアクセスを許可する。これにより、アカウントBのS3バケットは、アカウントAのLambda関数が引き受けた役割からのアクセスを信頼し、受け入れる準備が整う。

これらの設定が完了すると、Lambda関数は次のような流れでS3バケットにアクセスする。まず、アカウントAでデプロイされたLambda関数が何らかのトリガーで起動される。起動されたLambda関数は、自身の実行ロールとして指定されている「account_a_lambda_role」を引き受ける。このロールにアタッチされたポリシーにより、Lambda関数はアカウントBのS3バケットに対する特定の操作が許可されていることを確認する。次に、Lambda関数がアカウントBのS3バケットに対してアクセス要求を行う。アカウントBのS3バケットは、自身のバケットポリシーを参照し、そのアクセス要求がアカウントAの「account_a_lambda_role」からのものであることを確認する。バケットポリシーでこのロールからのアクセスが許可されているため、S3バケットはアクセスを受け入れ、Lambda関数は安全にオブジェクトを書き込むことができる。

提供されたPythonのサンプルコードは、このクロスアカウントS3アクセスを実行するLambda関数の具体的な実装例である。このコードでは、AWSのサービスを操作するためのライブラリである「boto3」を使用する。boto3.client("s3")という記述でS3サービスへのクライアントを作成し、S3バケットへの操作を可能にする。os.environ["TARGET_BUCKET"]は、Lambda関数の環境変数からターゲットとなるS3バケット名を取得しており、コードを変更せずに設定を変更できる柔軟性を提供する。コードは、現在の時刻を元にアップロードするファイル名とファイル内容を生成し、s3_client.put_object()メソッドを使って、指定されたS3バケットにファイルをアップロードする。このメソッドでは、Bucket引数でターゲットバケット名を、Key引数でアップロードするファイル名を、Body引数でファイル内容(バイト形式にエンコード)を指定する。ファイルのアップロードが成功した場合はステータスコード200と成功メッセージを返し、エラーが発生した場合はステータスコード500とエラーメッセージを返すことで、処理結果を伝える。このコードは、前述のIAMロールとS3バケットポリシーの設定が正しく行われていることを前提として動作する。

このように、IAMロールにアタッチする権限ポリシーと信頼ポリシー、そしてS3バケットに設定するバケットポリシーを適切に組み合わせることで、異なるAWSアカウント間での安全なデータ共有を実現できる。この方法は、各AWSアカウントの独立したセキュリティ境界を保ちながら、システム全体としての連携を可能にする。このクロスアカウントアクセスのパターンは、Lambda関数だけでなく、EC2インスタンスやECSタスクといった他のAWSサービスにも応用可能であり、クラウド環境におけるセキュリティと柔軟なシステム設計を実現するための重要な基盤技術である。

【ITニュース解説】Secure Data Sharing: AWS Lambda Writing to S3 Across Accounts | いっしー@Webエンジニア