目次
あるAWSアカウントのRedshiftから別のAWSアカウントのS3のデータを参照できるよう、AWSアカウントをまたいでRedshift Spectrumの設定をする機会がありました。
以下の記事を参考にやりたいことが実現できるか検証しました。
【参考】
AWS Glue と Amazon S3 に対する Amazon Redshift Spectrum のアカウント間アクセスを作成するにはどうすればよいですか?
https://repost.aws/ja/knowledge-center/redshift-cross-account-glue-s3
やりたいこと
- アカウント1のRedshiftからRedshift Spectrumを通してアカウント2のデータを参照したい。
- アカウント2は2つあるデータカタログのテーブルのうち、「test1_db」のデータのみアカウント1に参照を許可したい。
- アカウント1からテーブル「test2_db」の存在が見えるのはOKだが、「test2_db」のデータは参照できないようにしたい。
前提条件
- アカウント1にRedshiftクラスターが構築済みであること。
- アカウント2のS3バケットが作成済みで、参照先データとしてcsvファイルが配置されていること。csvファイルの配置パスは以下の通りとする。
- s3://spectrum-test-xxxxx/test1_db/sample.csv
- s3://spectrum-test-xxxxx/test2_db/sample.csv - アカウント2のGlue Data Catalogにデータベース1つとテーブルが2つ作成済みであること
- spectrum-test(データベース)
- test1_db(テーブル):ロケーションはs3://spectrum-test-xxxxx/test1_db/
- test2_db(テーブル):ロケーションはs3://spectrum-test-xxxxx/test2_db/
設定のポイント
やりたいことを実現するために、以下5カ所の設定を行います。
検証
1.アカウント1にRedshiftとの信頼関係を持つIAMロールを作成してRedshiftに関連づける
アカウント1でIAMロールを作成します。
信頼されたエンティティのタイプの選択で[AWSのサービス]を選択し、[Redshift]を選択します。
[ユースケースの選択]で[Redshift - Customizable]を選択します。
その後ポリシーやタグは追加せずロール名を入力して[ロールを作成]をクリックします。ロール名は「redshift_role1」とします。
次に作成したIAMロール「redshift_role1」をアカウント1のRedshiftクラスターにアタッチします。
アカウント1のデータ参照元となるRedshiftクラスターを選択し、[プロパティ]タブの[クラスターの許可]の[IAMロールを関連付ける]をクリックします。
先ほど作成した「redshift_role1」を選択し、[IAMロールを関連付ける]をクリックします。
「redshift_role1」の状態がin-syncになったことを確認します。
2.アカウント2にGlueおよびS3へのアクセス権を持つポリシーを作成する
アカウント2でIAMポリシーを作成します。
[ポリシーの作成]を選択し[JSON]タブをクリックして以下のようなIAMポリシーを入力します。
S3バケットにはデータを格納するバケット名、フォルダ名にはアカウント1からの参照を許可するデータが格納されているフォルダ名を指定します。
今回は「test1_db」のデータのみ参照を許可したいので、フォルダ名は「test1_db」と指定しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"glue:BatchCreatePartition",
"glue:UpdateDatabase",
"glue:CreateTable",
"glue:DeleteDatabase",
"glue:GetTables",
"glue:GetPartitions",
"glue:BatchDeletePartition",
"glue:UpdateTable",
"glue:BatchGetPartition",
"glue:DeleteTable",
"glue:GetDatabases",
"glue:GetTable",
"glue:GetDatabase",
"glue:GetPartition",
"glue:CreateDatabase",
"glue:BatchDeleteTable",
"glue:CreatePartition",
"glue:DeletePartition",
"glue:UpdatePartition"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"s3:ListBucketMultipartUploads",
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::S3バケット名"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"フォルダ名/*"
]
}
}
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListMultipartUploadParts"
],
"Resource": [
"arn:aws:s3:::S3バケット名/フォルダ名/*"
]
}
]
}
ポリシー名を入力して[ポリシーの作成]をクリックします。ポリシー名は「test-policy」としました。
3.アカウント2にロールを作成する
アカウント2でIAMロールを作成します。
信頼されたエンティティタイプで[AWSアカウント]を選択し、[別のAWSアカウント]を選択し、アカウント1のアカウントIDを入力し[次へ]をクリックします。
ポリシーの一覧で作成したポリシー[test-policy]の隣にあるチェックボックスをオンにして[次へ]をクリックします。
ロール名を入力して[ロールを作成]をクリックします。ロール名は[glue_s3_role2]としました。
次に作成したIAMロール[glue_s3_role2]を選択して、信頼関係を編集します。
信頼されたエンティティのプリンシパルがアカウント1のrootになっていますが、[信頼ポリシーを編集]をクリックしてこの部分を編集します。
アカウント1のrootのarnをアカウント1に作成したIAMロール「redshift_role1」のarnに置き換えて[ポリシーを更新]をクリックします。
4.アカウント1で作成したロールの許可を編集する
アカウント1に作成したIAMロール「redshift_role1」にインラインポリシーを追加します。
IAMロール「redshift_role1」を選択して、[許可を追加]から[インラインポリシーを作成]をクリックします。
[JSON]タブを選択して既存のポリシーを削除し、次のようなIAMポリシーを入力して[次へ]をクリックします。
リソースにはアカウント2に作成したIAMロール「glue_s3_role2」のarnを指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1487639602000",
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": "アカウント2に作成したIAMロールのarn"
}
]
}
ポリシー名を入力して[ポリシーの作成]をクリックします。今回は「redshift_policy」としました。
5.アカウント1のRedshiftで外部スキーマを作成する
アカウント1のRedshiftに接続して外部スキーマを作成します。今回はクエリエディターv2で接続しました。
以下のようなクエリを実行して外部スキーマを作成します。
create external schema 外部スキーマ名
from data catalog
database 'アカウント2のGlueデータカタログのDB名'
iam_role 'アカウント1に作成したIAMロールのarn,アカウント2に作成したIAMロールのarn'
今回は外部スキーマ名を「spectrum-test-schema」としてクエリを実行したところ、外部スキーマが作成されて、データカタログのDB「spectrum-test」に紐づくテーブル「test1_db」と「test2_db」が外部テーブルとして確認できるようになりました。
6.データを参照できるか確認する
外部テーブル「test1_db」と「test2_db」に対してクエリを実行し、データを参照できるか確認します。
まずは「test1_db」に対してselectを実行したところ、期待通りデータを取得することができました。
次に「test2_db」に対してselectを実行したところ、Acccess Deniedとなりデータを参照することはできませんでした。
期待通りの挙動になったため、検証成功です!