🏷️

LF-tagを使ってクロスアカウント連携を行うまで(AWS Lake Formation)

2024/12/25に公開

はじめに

こんにちは!D2Cでデータエンジニアをしております、飯森と申します。
今回はAWSのLake Formationの機能、LF-tagを使って、2アカウント間でDB・テーブルのクロスアカウント連携を行う方法を共有したいと思います。
ここで紹介する方法はあくまで一例ですので、ご了承ください。

流れ

簡単に作業の流れをざっと並べますと、

  • GlueのData catalog settingsに設定を追加
  • クロスアカウント連携用LF-tagを作成
  • 作成したLF-tagをDB・テーブルに付与
  • 同じLF-tagへの権限を連携先アカウントに付与
  • Data lake locationsにテーブルのロケーションバケットを設定
  • Data locationsにテーブルのロケーションバケットを設定(ここまで連携元で作業)
  • リソースリンクDBを作成(ここから連携先で作業)
  • リソースリンクDBにユーザによる閲覧を許可するLF-tagを付与
  • 連携元アカウントのLF-tagへの権限をユーザに付与

と少々作業が必要です。ただ、やり方を覚えてしまえば流れで覚えられると思うので、他の方法よりもクロスアカウント連携がかなり簡単に感じてくると思います。

前提

この連携設定ですが、作業を行う前にいくつか前提として満たしている条件みたいなものがあります。

  • 両アカウントで連携したい環境が同じリージョンである
  • 両アカウントともLF-tag管理によるテーブルの権限設定が完了している
  • 両アカウントともクロスアカウントのバージョンが同じである(片方がversion1のとき、もう片方もversion1である)
  • 両アカウントともデータベースおよびテーブルにIAMAllowedPrincipalsへの権限がついていない
  • 両アカウントとも利用するIAMユーザー(もしくはロール)がLake FormationのData lake administratorsの権限を持っている

これら全てが網羅的にクリアできていれば絶対大丈夫とは言い切れないのですが、何か関連するサービスの権限の追加・変更を大々的に行なっていなければ大丈夫かと思います。

本文内で使われる表現の定義

次の章から詳しい作業を説明していきますが、そこで使われる各表現について説明します。

  • アカウントA:連携元アカウント、ここに連携したいテーブルがある。アカウントID:111122223333
  • アカウントB:連携先アカウント、ここへテーブルを連携する。アカウントID:999988887777
  • db_a:連携元アカウントにあるデータベース
  • table_a:連携元アカウントにあるテーブル
  • bucket_a:連携元アカウントにあるS3バケット、table_aのデータが入っている

連携元で必要な作業

GlueのData catalog settingsに設定を追加する

まず最初にGlueのData catalog settingsにて、連携先のアカウントのアクセス権限を付与する必要があるため、その設定を行います。

  1. Data catalog settingsのpermissionsに設定するポリシーのjsonファイルを作る
    CLIコマンドを実行できる環境下に下記内容を元にしたjsonファイルを作ります。
    Principalに連携先のiam root arnを、Resourceに連携元のアカウントIDのcatalog, database, tableの各リソースを指定します。
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowConsumerFullCatalogAccess",
          "Effect": "Allow",
          "Principal": {
            "AWS": [
              "arn:aws:iam::999988887777:root"
            ]
          },
          "Action": "glue:*",
          "Resource": [
            "arn:aws:glue:ap-northeast-1:111122223333:catalog",
            "arn:aws:glue:ap-northeast-1:111122223333:database/*",
            "arn:aws:glue:ap-northeast-1:111122223333:table/*/*"
          ]
        }
      ]
    }
    
  2. CLIコマンドを実行してポリシー内容を反映させる
    連携元アカウントのIAM(ユーザかロール)で下記コマンドを実行します。
    aws glue put-resource-policy --policy-in-json file://catalog_policy.json --enable-hybrid TRUE
    

クロスアカウント連携用LF-tagを作成する

下記のコマンドを連携元アカウントに実行してLF-tagを作成します。今回作成するタグ名はbridgeとします。タグにはvalueを設定できるのですが、ここの付け方はいろんなやり方があります。今回の説明ではtrue/falseをvalueに与えていくやり方で進めます。

aws lakeformation create-lf-tag --tag-key bridge --tag-values true false

作成したLF-tagをDB・テーブルに付与する

下記コマンドを連携元アカウントに実行して作成したLF-tagを連携したいリソースに付与します。
データベースしか付与していないように見えますが、この設定だけで配下のテーブルにも自動でLF-tagが付与されます。

aws lakeformation add-lf-tags-to-resource \
    --resource '{ "Database": { "Name": "db_a" }}' \
    --lf-tags TagKey=bridge,TagValues=true

同じLF-tagへの権限を連携先アカウントに付与する

下記コマンドを連携元アカウントに実行し、各種権限を連携先アカウントに対して付与します。
1行目は連携元で作ったLF-tagの閲覧と操作権限を連携先アカウントに付与しています。
2行目と3行目はbridgeタグがついたデータベース、テーブルの閲覧権限(DESCRIBE, SELECT)を連携先アカウントに付与しています。ここのDESCRIBESELECTと入っている権限には他にもALTERDROPなど他のクエリ権限を与えることもできるので、連携先に付与したい権限に合わせて調整します。

aws lakeformation grant-permissions \
    --principal '{ "DataLakePrincipalIdentifier": "999988887777" }' \
    --resource '{ "LFTag": { "TagKey": "bridge", "TagValues": ["true"] }}'\
    --permissions "DESCRIBE" "ASSOCIATE" "GRANT_WITH_LF_TAG_EXPRESSION" \
    --permissions-with-grant-option "DESCRIBE" "ASSOCIATE" "GRANT_WITH_LF_TAG_EXPRESSION"
aws lakeformation grant-permissions \
    --principal '{ "DataLakePrincipalIdentifier": "999988887777" }' \
    --resource '{ "LFTagPolicy": {"ResourceType": "DATABASE", "Expression": [{ "TagKey": "bridge", "TagValues": ["true"] }]}}' \
    --permissions "DESCRIBE" \
    --permissions-with-grant-option "DESCRIBE"
aws lakeformation grant-permissions \
    --principal '{ "DataLakePrincipalIdentifier": "999988887777" }' \
    --resource '{ "LFTagPolicy": {"ResourceType": "TABLE", "Expression": [{ "TagKey": "bridge", "TagValues": ["true"] }]}}' \
    --permissions "SELECT" "DESCRIBE" \
    --permissions-with-grant-option "SELECT" "DESCRIBE"

Data lake locationsにテーブルのロケーションバケットを設定する

連携先で連携するDBのテーブルの中身が見られるよう、下記コマンドでその中身が置かれているS3をData lake locationsに登録します。この登録を行うと、連携先でテーブルの中身が見られるようになりますが、代わりに連携元でよっぽどの強い権限を持たない限りテーブルの中身をathena等で見ることができなくなります。その対応として、次の手順にあるData locationsの設定を行う必要があります。

aws lakeformation register-resource --resource-arn arn:aws:s3:::bucket_a --use-service-linked-role

Data locationsにテーブルのロケーションバケットを設定する

連携元で連携したDBのテーブルの中身が再度見られるように、下記コマンドでその中身が置かれているS3をData locationsに登録します。この登録を行うことで連携元アカウント・連携先アカウント両方で連携したテーブルの中身を見ることができるようになります。

aws lakeformation grant-permissions \
    --principal DataLakePrincipalIdentifier=111122223333:IAMPrincipals \
    --permissions "DATA_LOCATION_ACCESS" \
    --resource '{ "DataLocation": {"ResourceArn":"arn:aws:s3:::bucket_a", "CatalogId": "111122223333"}}'

連携先で必要な作業

リソースリンクDBを作成する

下記コマンドを実行して連携先アカウントに連携されたデータベースのリソースリンクデータベースを作成します。
連携先では連携されたデータベースをathena等で直接参照することができないため、このリソースリンクデータベースを作成するのが必須となります。

aws glue create-database --database-input '{"Name":"db_a","TargetDatabase":{"CatalogId":"111122223333","DatabaseName":"db_a"}}'

リソースリンクDBにユーザによる閲覧を許可するLF-tagを付与する

事前に連携先アカウントにて使われている、ユーザ(ロール)に付与される閲覧許可のLF-tagをリソースリンクDBに付与します。今回はそのLF-tagが「user」という名前だったという場合の実行コマンドを表示しています。

aws lakeformation add-lf-tags-to-resource \
    --resource '{ "Database": {"CatalogId": "999988887777", "Name": "'db_a'" }}' \
    --lf-tags TagKey=user,TagValues=true;

連携元アカウントのLF-tagへの権限をユーザに付与する

下記コマンドを連携先アカウントで実行し、連携元のLF-tagが付与されたリソースのDESCRIBE, SELECT権限を連携先アカウントのユーザ(下記コマンドだとhogehoge)に対し付与します。このコマンドは閲覧させたいユーザ及びロール全てに対し実行する必要があります。

aws lakeformation grant-permissions \
    --principal '{ "DataLakePrincipalIdentifier": "arn:aws:iam::999988887777:user/hogehoge" }' \
    --resource '{ "LFTagPolicy": {"CatalogId": "111122223333", "ResourceType": "DATABASE", "Expression": [{ "TagKey": "bridge", "TagValues": ["true"] }]}}' \
    --permissions "DESCRIBE" \
    --permissions-with-grant-option "DESCRIBE"
aws lakeformation grant-permissions \
    --principal '{ "DataLakePrincipalIdentifier": "arn:aws:iam::999988887777:user/hogehoge" }' \
    --resource '{ "LFTagPolicy": {"CatalogId": "111122223333", "ResourceType": "TABLE", "Expression": [{ "TagKey": "bridge", "TagValues": ["true"] }]}}' \
    --permissions "SELECT" "DESCRIBE" \
    --permissions-with-grant-option "SELECT" "DESCRIBE"

作業後はAthena等で実際にクエリを実行し、出力が返ってくるかご確認ください。

SELECT * FROM db_a.table_a LIMIT 10

おわりに

今回はLF-tagを使ったクロスアカウント連携の方法についてご紹介させていただきました。
いろんな用途によってどの連携手段が最適か変わってくるので、今回の方法は一例として参考にしていただけると幸いです。

D2C m-tech

Discussion