Redshift SpectrumからクロスアカウントでS3アクセスしてみた

この記事を書いたメンバー:

平野 真弓

Redshift SpectrumからクロスアカウントでS3アクセスしてみた

目次

ある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となりデータを参照することはできませんでした。

期待通りの挙動になったため、検証成功です!

カテゴリー
タグ

SAPシステムや基幹システムのクラウド移行・構築・保守、
DXに関して
お気軽にご相談ください

03-6260-6240 (受付時間 平日9:30〜18:00)