Athenaで別アカウントのS3をクエリーする最短手順
やりたいこと
別アカウントのS3バケットにあるデータをAthenaからクエリーしたい。
別アカウント側のGlueカタログ(Glueのクロスアカウントアクセス)は使わず、あくまで自アカウントのGlueカタログに別アカウントのS3バケットを登録して、検索を実行するのがゴール。
前提
- アカウントA:読み取られる側
- アカウントB:読み取る側
ステップバイステップ
アカウントAの準備
- S3バケットを作成し、テストデータを置く。
- バケット名は
athena-crossaccount-20210310
とする。 - テストデータはこちらの記事で使用したものを再利用する。
- バケット名は
- クロスアカウントアクセスを許可するため、バケットポリシーを設定する。
- アカウントBでこの後作成されるIAMロールに対してのみ許可する。ロール名は
AthenaCrossAccountRole
と仮定。
- アカウントBでこの後作成されるIAMロールに対してのみ許可する。ロール名は
(2021/6/2追記)
存在していないロールをバケットポリシーに入れることはできないので、この手順は正しくは「アカウントBの準備」でAthenaCrossAccountRole
を作成した後に実行するか、バケットポリシー保存直前で寸止めしておく必要があります。
(ご指摘いただいた@cols-wisteriaさん、ありがとうございました!)
バケットポリシー
{
"Version": "2012-10-17",
"Id": "Policy1495458089866",
"Statement": [
{
"Sid": "Policy_GetObject",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::2XXXXXXXXXX2:role/AthenaCrossAccountRole"
},
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::athena-crossaccount-20210310",
"arn:aws:s3:::athena-crossaccount-20210310/*"
]
}
]
}
アカウントBの準備
- クエリー結果保管バケットを作り、Athenaワークグループ"primary"(デフォルト)にセットする。
- ここでは
athena-query-result-4-sandbox
とした。
- ここでは
- Athenaでクエリーを実行するためのIAMポリシー
AthenaCrossAccountAccessPolicy
を作成する。-
AmazonAthenaFullAccess
というマネージドポリシーがあるので、これを参考に作る。 - ちなみに上記のマネージドポリシーは
s3:GetObject
権限がチュートリアル用バケットと(デフォルト仕様の)クエリー結果保管バケットにしかないので、そのままでは現場で使えない。他にもせっかく絞ったs3:ListBucket
が後段で全開放されてたりと若干つっこみどころの多いポリシーだが、ここでは細かいことは措いて先に進むことにする。
-
- IAMロール
AthenaCrossAccountRole
を作成し、上記ポリシーをアタッチする。- IAMロールではなくIAMユーザーにアタッチしてもよいが、今回は多少汎用性を高める必要があったのでロールとし、このロールにアカウントAからスイッチロールできるように設定(アカウントAをAssumeRoleの信頼元Principalに指定)した。
- 実際には、ロールの信頼元をEC2やLambdaに指定して、プログラマティックにAthenaを呼び出すイメージ。
Athena用ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"athena:*"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"glue:CreateDatabase",
"glue:DeleteDatabase",
"glue:GetDatabase",
"glue:GetDatabases",
"glue:UpdateDatabase",
"glue:CreateTable",
"glue:DeleteTable",
"glue:BatchDeleteTable",
"glue:UpdateTable",
"glue:GetTable",
"glue:GetTables",
"glue:BatchCreatePartition",
"glue:CreatePartition",
"glue:DeletePartition",
"glue:BatchDeletePartition",
"glue:UpdatePartition",
"glue:GetPartition",
"glue:GetPartitions",
"glue:BatchGetPartition"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket",
"s3:ListBucketMultipartUploads",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload",
"s3:CreateBucket",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::athena-query-result-4-sandbox",
"arn:aws:s3:::athena-query-result-4-sandbox/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::athena-crossaccount-20210310",
"arn:aws:s3:::athena-crossaccount-20210310/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"sns:ListTopics",
"sns:GetTopicAttributes"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"cloudwatch:PutMetricAlarm",
"cloudwatch:DescribeAlarms",
"cloudwatch:DeleteAlarms"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"lakeformation:GetDataAccess"
],
"Resource": [
"*"
]
}
]
}
- Glueデータベースを作成する。
- Glueデータベースは、Crawlerを使う場合もAthenaでDDLを実行する場合も、テーブルを格納するために等しく必要。
- ここでは
athena_crossaccount_20210310
とする。
- DDLを実行する。
- テーブルについては、CrawlerかDDL(あるいはCloudFormationか)のどちらかだけ必要。
- JSONLであればCrawlerで自動認識されるスキーマでほぼほぼ無修正で行けるはずだが、ここではAthena単体でどういう権限が必要かを切り分けたいので、あえてDDLで作成する。
- SerdeにはHiveとOpenXが選択可能だが、Glue Crawlerでは後者が使われていること、実際にクエリーしてみるとOpenXの方がエラーが少ないことから、ここではOpenXを選択。
CREATE EXTERNAL TABLE jsontest (
id int,
name string,
age int
)
ROW FORMAT serde 'org.openx.data.jsonserde.JsonSerDe'
with serdeproperties ( 'paths'='age, id, name' )
LOCATION 's3://athena-crossaccount-20210310/';
クエリー実行
ハマリポイント
- SerdeをHiveで作成すると、このデータセットではエラーとなった(nullが原因かも)。OpenXの方が融通利く模様。
- Glueカタログを介して外部テーブルを読みに行く以上、Glueサービスロールにもクロスアカウント権限が必要か?とも思ったが、Glue CrawlerやGlue Jobを使わない限りはそもそもそのロール使わないので、今回試したロールのみバケットポリシーで許可すればOKだった。
- 今回はAthena、というかAthenaの実行主体であるIAMロール(
AthenaCrossAccountRole
)は、クロスアカウントアクセスにassumeRoleを使ってない(あくまで検証上、アカウントBにスイッチする際にassumeRoleしているだけで、クロスアカウントのクエリー自体はS3のリソースベースポリシーを介して、ロールをスイッチすることなく実行されている)。assumeRoleを用いるパターンだと、sts:AssumeRoleの付与やリソース/プリンシパル縛りなど、これはこれで細々とした設定が必要になる。はず。
Author And Source
この問題について(Athenaで別アカウントのS3をクエリーする最短手順), 我々は、より多くの情報をここで見つけました https://qiita.com/itsuki3/items/ef9c12c67df888369c11著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .