オブジェクトACLの影響でGlue Crawlerのクロスアカウントのアクセスがうまくいかない

オブジェクトACLの影響でGlue Crawlerのクロスアカウントのアクセスがうまくいかない

Clock Icon2025.02.28

こんにちは、データ事業本部のキタガワです。
今回は、Glue Crawlerを使用してS3バケットのデータをクローリングする際に直面した問題とその対処法についてお話しします。

問題の概要

Glue Crawlerで特定のS3バケットのデータをクローリングしようとしました。
前提条件は以下の通りです。

  • クロスアカウントでのアクセス
  • サンプルファイルを受領し、Crawlerのあるアカウント内で閉じた検証を行った際には問題なくクローリングが完了し、結果としてのテーブル生成を確認済み

しかし、見落としていた条件として、対象のS3バケットはオブジェクトACLが有効かつオブジェクト所有者がオブジェクトライターになっていました。
このオブジェクトACLの影響で、バケットの所有者とオブジェクトの所有者が異なる状態になっており、バケットポリシーだけではオブジェクトにアクセスする権限の付与ができていませんでした。
その結果、Crawlerが正常終了するものの、生成物が出てこない状態になってしまいました。

事の経緯

仮にS3バケットがあるアカウントをAccountA、CrawlerがあるアカウントをAccountBとします。
また、AccountAのS3バケットにオブジェクトをPUTしたアカウントをAccountCとします。

AccountAのS3バケットにAccountBのCrawler用IAMロールが参照できるようなバケットポリシーを、またAccountBのCrawler用IAMロールにAccountAのS3バケットが参照できるようなポリシーをそれぞれ追加しました。
これはブログ[1]にも記載があるようなシンプルなものです。
Crawler用IAMロールには s3:ListBuckets3:GetObjectを付与しました。
この設定自体に間違いはありませんでした。

次にCrawlerをS3パスを指定し実行したところ、結果として生成されるはずのGlue Data Catalogのテーブルが生成されないという現象に遭遇しました。
試しに別のS3パスを指定してみると、こちらは正常に動作しました。
同じバケットでも参照できるオブジェクトとできないオブジェクトがあるという状況です。
詳しく調べたところ、Crawler用IAMロールではListBucketは成功しているものの、GetObjectで失敗しているようでした。
状況を簡単に図に表すと以下のようになります。

alt text

この状況では、オブジェクトへのアクセス権限がないことを示すAccessDeniedエラーが発生していました。

原因

先にも述べたとおり、オブジェクトACLが有効になっており、バケットの所有者とオブジェクトの所有者が異なる状態になっていたことが原因です。
この状態のオブジェクトにはバケットポリシーが効かない[2]ため、同じバケットにあるオブジェクトでも、あるオブジェクトは参照できて別のオブジェクトは参照できないという現象が起きます。

対処法

根本的にはオブジェクトACLを無効化するのがベストプラクティスです。
2021年にはAWS公式から非推奨扱いになっています[3]
とはいえ、昔からあるバケットだとまだオブジェクトACLが設定されている場合もあり、本番環境で稼働しているバケットの設定を簡単に変えられるわけでもありません。
では、どうしたら良いのでしょうか。

暫定的な対処として、オブジェクト所有者がバケット所有者にアクセス許可を付与し、バケット所有者は自分のアカウントのユーザーに許可を委任することができます。
ただし、この時クロスアカウントでの委任はサポートされていません[4]
また、AccountAにバケット参照用のIAMロールを作成し、AccountBのユーザーやサービスからAssumeRoleしてもらう方法もありますが、今回のシナリオではCrawlerがそもそもAssumeRoleできないため選択肢になりません。

他に考えられる方法としては、

  • オブジェクトを別のバケットにコピーし、そちらを参照する
  • オブジェクトのACLを変更する

がありますが、どれも追加の開発や継続的なメンテナンスが必要になる可能性があります。
この時はCrawlerの対象をバケットとオブジェクトの所有者が一致しているデータに限定することで対応することにしました。

まとめ

すぐに対応はできなくても、S3バケットのACLは無効化し、バケットの所有者とオブジェクトの所有者を一致させるように徐々に移行していきましょう。
バケットのACLが必要となるのは限定的な状況のみ[5]です。
移行には以下のブログが参考になります。

移行には前提条件の確認、PUTクライアントの特定・改修、既存バケットと新規バケットの対応など、状況に即した対応すべきことがたくさんあります。
できるところから少しずつでも進めていくことをお勧めします。

脚注
  1. Glueクローラーのデータソースとして別AWSアカウントのS3バケットを指定したい | DevelopersIO ↩︎

  2. Amazon S3 のバケットポリシー - Amazon Simple Storage Service:バケットに添付された許可は、バケット所有者が所有するバケットのすべてのオブジェクトに適用されます。これらの許可は、他の AWS アカウント が所有するオブジェクトには適用されません。 ↩︎

  3. 【アップデート】S3でACLを無効化できるようになりました #reinvent | DevelopersIO ↩︎

  4. 例 4 - バケット所有者が所有権のないオブジェクトへのクロスアカウントアクセス許可を付与する - Amazon Simple Storage Service:クロスアカウントの委任はサポートされていないため、バケット所有者アカウントは他の AWS アカウント にアクセス許可を委任できません。 ↩︎

  5. S3 のオブジェクト ACL を有効化にするケースまとめ | DevelopersIO:現状では、CloudFront のアクセスログを S3 に保存する場合、または、AWS Backup の S3 バックアップのリカバリポイントの復元先の S3 バケット以外で、特別な事情がない限りは、ACL を無効化することが望ましいと考えられます。 ↩︎

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.