Lake Formationでアクセス制御を体験しよう

このハンズオンでは、AWS Lake FormationのLF-Tagを使ったタグベースのアクセス制御を実際にハンズオン形式で手を動かしながら体験します。

  • S3上のCSVデータをGlueクローラーでデータカタログに登録する
  • LF-Tagを作成し、カラムごとにタグを割り当てる
  • 「マーケティング担当」「カスタマーサポート担当」「データ管理者」の3つのロールに対して、LF-Tagで異なるアクセス権限を設定する
  • Athenaでクエリを実行し、ロールごとに参照できるカラムが異なることを確認する
  • データロケーション登録により、S3への直接アクセスもLake Formationの管理下に置く

1. 事前準備

この講座のハンズオンでは、以下のツールやアカウントが必要です。まだ準備できていない場合は、リンク先の手順に沿って準備をお願いします。

2. ハンズオンの概要

このハンズオンでは、S3上に顧客データのCSVファイルを配置し、Glueクローラーでデータカタログに登録した上で、Lake FormationのLF-Tagを使ったアクセス制御を設定します。

Lake Formationの講座で学んだ通り、LF-Tagを使うことで「タグの割り当て」と「タグへの権限付与」の2ステップで効率的にアクセス制御を行えます。このハンズオンでは、業務上の役割が異なる3つのロールを作成し、それぞれに異なるカラムへのアクセス権限を設定します。

今回使用するデータは、機密度の異なる情報を含む顧客管理データです。実務のデータ分析基盤では、同じ顧客データであっても、業務上の必要性に応じて参照できる範囲を制限することが求められます。各ロールに対して、以下のようにアクセスを制御します。

ロール アクセスできるカラム 用途
マーケティング担当 顧客ID、地域、購入総額など集計情報のみ 地域別売上分析やレポート作成
カスタマーサポート担当 集計情報に加え、氏名・メールアドレス・電話番号 顧客への問い合わせ対応
データ管理者 すべてのカラム(生年月日・住所・クレジットカード情報を含む) データ品質管理やコンプライアンス監査

このハンズオンの全体構成を示します。

graph LR
    A["Amazon S3<br>(CSVデータ)"] -->|"クロール"| B["AWS Glue<br>(データカタログ)"]
    B -->|"アクセス制御"| C["AWS Lake Formation<br>(LF-Tag)"]
    C -->|"権限に基づくクエリ"| D["Amazon Athena<br>(データ参照)"]

    style A fill:#e8f5e9,stroke:#2e7d32
    style B fill:#fff3e0,stroke:#e65100
    style C fill:#e3f2fd,stroke:#1565c0
    style D fill:#f3e5f5,stroke:#6a1b9a

3. テストデータの準備

Lake Formationのアクセス制御を体験するには、まず制御対象となるデータが必要です。このセクションでは、機密度の異なるカラムを含むCSVファイルを作成し、S3にアップロードします。このデータが、後のセクションでロールごとにアクセスを制限する対象になります。

3.1 CSVファイルの作成

まず、ハンズオンで使用するCSVファイルを作成します。以下の内容をテキストエディタに貼り付け、customers.csv という名前で保存してください。

customer_id,name,email,phone,region,total_purchases,birth_date,address,credit_card_last4
C001,田中太郎,tanaka@example.com,090-1234-5678,東京,150000,1985-03-15,東京都渋谷区神宮前1-1-1,1234
C002,佐藤花子,sato@example.com,080-2345-6789,大阪,230000,1990-07-22,大阪府大阪市北区梅田2-2-2,5678
C003,鈴木一郎,suzuki@example.com,070-3456-7890,福岡,80000,1978-11-08,福岡県福岡市博多区博多駅前3-3-3,9012
C004,山田美咲,yamada@example.com,090-4567-8901,東京,310000,1995-01-30,東京都新宿区西新宿4-4-4,3456
C005,高橋健太,takahashi@example.com,080-5678-9012,名古屋,120000,1988-09-12,愛知県名古屋市中区栄5-5-5,7890

このCSVには、以下の3種類のカラムが含まれています。

分類 カラム 説明
集計情報 customer_id, region, total_purchases 業務で広く利用される一般的な情報
個人情報 name, email, phone 個人を特定できる情報(PII)
機密個人情報 birth_date, address, credit_card_last4 特に保護が必要な機密性の高い個人情報

3.2 S3バケットの作成とアップロード

CSVファイルをLake Formationで管理するには、データをS3上に配置する必要があります。GlueクローラーがS3バケット内のファイルを読み取り、データカタログに登録するため、まずデータの保管場所となるS3バケットを作成します。

S3のダッシュボードを開き、「バケットを作成」をクリックします。

下記表に従い、設定を行ってください。記載のない項目はデフォルトのままで構いません。

設定項目 設定の基準
バケット名 lf-handson-data-{自分の名前} グローバルで一意になるよう、自分の名前を付与
AWSリージョン アジアパシフィック(東京)ap-northeast-1 他のリソースと同じリージョンに配置

⚠️ バケット名が重複する場合
S3のバケット名はグローバルで一意である必要があります。「BucketAlreadyExists」エラーが出る場合は、バケット名の末尾に日付や数字を追加してください。

設定後、「バケットを作成」をクリックします。

バケットが作成されたら、バケットを開き、「フォルダの作成」をクリックして customers という名前のフォルダを作成します。作成した customers/ フォルダを開き、「アップロード」をクリックして先ほど作成した customers.csv をアップロードします。

customers/ フォルダの中に customers.csv が表示されていれば、テストデータの準備は完了です。Glueクローラーがこのフォルダを読み取ると、フォルダ名がテーブル名(customers)になります。

4. Lake Formationの初期設定

S3にデータを配置できたので、次にLake Formationの初期設定を行います。Glueでデータベースやテーブルを作成する前にLake Formationの権限モデルを有効にしておくことで、最初からLake Formationの管理下でリソースが作成されるようになります。後から設定を切り替える場合はデータベースの再作成が必要になるため、先に設定しておく方がスムーズです。

📝 この設定による影響について
この初期設定を行うと、以降に作成するGlueデータベースやテーブルはLake Formationの権限モデルに従うようになります。GlueクローラーやAthenaからのアクセスにもLake Formation側の権限設定が必要になるため、既存の環境に影響がないか確認した上で実施してください。

4.1 データレイク管理者の登録

Lake Formationでアクセス制御を管理するには、まず「誰がデータレイクの管理者か」を登録する必要があります。管理者として登録されたユーザのみが、LF-Tagの作成や権限の付与といった管理操作を行えます。

Lake Formationのダッシュボードを開きます。初回アクセス時には「Welcome to Lake Formation」画面が表示されます。「Add myself」にチェックを入れ、「Get started」をクリックします。

⚠️ 「Welcome to Lake Formation」画面が表示されない場合
すでにLake Formationを使用したことがある場合、この画面は表示されません。左メニューの「Administration」>「Administrative roles and tasks」から、現在のIAMユーザがデータレイク管理者として登録されていることを確認してください。登録されていない場合は「Choose administrators」から追加してください。

4.2 データカタログ設定の変更

AWSではデフォルトでIAMポリシーによるアクセス制御が有効になっています。このままではLake Formationの権限設定が無視されてしまうため、Lake Formationによるアクセス制御を優先するよう設定を変更します。

左メニューの「Administration」>「Data Catalog settings」を開きます。

💡 ポイント
画面上部に「Permissions alert」という青い警告メッセージが表示されることがあります。これは「現在はIAMポリシーのみでアクセス制御している状態です」という案内であり、このハンズオンでこれからLake Formationの権限モデルに切り替える手順を行うため、問題ありません。

以下の2つのチェックボックスが表示されます。

  • 「Use only IAM access control for new databases」
  • 「Use only IAM access control for new tables in new databases」

これらのチェックをすべて外して、「Save」をクリックします。

💡 ポイント
これらのチェックボックスがオンになっていると、Lake Formationの権限ではなくIAMポリシーのみでアクセス制御が行われます。Lake Formationのアクセス制御を使用するには、これらのチェックを外す必要があります。

これでLake Formationの初期設定は完了です。この後に作成するデータベースやテーブルは、最初からLake Formationの権限モデルの管理下に置かれます。

5. Glueクローラーによるデータカタログの作成

Lake Formationの初期設定が完了したので、Glueでデータカタログを作成します。S3にデータを配置しただけでは、Lake FormationやAthenaはそのデータの構造(カラム名やデータ型など)を認識できません。データの構造を自動的に解析してカタログ化するために、Glueクローラーを使用します。ここで作成されるデータカタログが、後のセクションでLF-Tagによるアクセス制御を設定する対象になります。

5.1 データベースの作成

Glueクローラーがテーブル情報を登録する先として、まずGlueデータカタログ上にデータベースを作成します。

Glueのダッシュボードを開き、左メニューから「Data Catalog」>「Database」を選択し、「Add database」をクリックします。

下記表に従い、設定を行ってください。

設定項目 設定の基準
Name lf_handson_db ハンズオン用のデータベースであることがわかる名前

設定後、「Create database」をクリックします。

無事に lf_handson_db が作成されていれば、ここまでの操作は完了です。

5.2 クローラー用ロールへのLake Formation権限付与

前のセクションでLake Formationの権限モデルを有効にしたため、Glueクローラーがデータベースにテーブルを作成するには、Lake Formation側でクローラーのIAMロールに権限を付与する必要があります。

まず、クローラーで使用するIAMロールを先に作成します。IAMのダッシュボードを開き、左メニューから「ロール」を選択し、「ロールを作成」をクリックします。

設定項目 設定の基準
信頼されたエンティティタイプ AWSのサービス Glueサービスが使用するロール
サービス Glue クローラーがGlueサービスとして実行されるため
許可ポリシー AWSGlueServiceRole Glueの基本的なアクセス権限
ロール名 AWSGlueServiceRole-lf-handson Glueサービスロールの命名規則に従う

また、このロールにS3バケットへの読み取り権限を追加します。ロールを開き、「許可を追加」>「インラインポリシーを作成」から、以下のポリシーを追加してください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::lf-handson-data-{自分の名前}",
                "arn:aws:s3:::lf-handson-data-{自分の名前}/*"
            ]
        }
    ]
}

{自分の名前} の部分は、実際のバケット名に合わせて変更してください。

次に、Lake Formationでこのロールにデータベースへの権限を付与します。Lake Formationのダッシュボードを開き、「Permissions」>「Data permissions」から「Grant」をクリックします。

下記表に従い、設定を行ってください。

設定項目 設定の基準
Principals IAM users and roles IAMロールに権限を付与するため
IAM users and roles AWSGlueServiceRole-lf-handson クローラー用ロールを選択
Named Data Catalog resources Databases: lf_handson_db 対象のデータベースを指定
Database permissions Create table, Describe テーブル作成とメタデータ参照を許可

設定後、「Grant」をクリックします。

「Data permissions」画面に AWSGlueServiceRole-lf-handson への権限エントリが表示されていれば、クローラー用の権限付与は完了です。

5.3 クローラーの作成と実行

データベースとクローラー用の権限が準備できたので、S3上のCSVファイルを自動的に解析してテーブルとして登録するクローラーを作成します。クローラーは、CSVのヘッダ行からカラム名を、データの内容からデータ型を自動的に判別してくれます。

左メニューから「Data Catalog」>「Crawlers」を選択し、「Create crawler」をクリックします。

ステップ1: クローラーのプロパティの設定

下記表に従い、設定を行ってください。

設定項目 設定の基準
Name lf-handson-crawler ハンズオン用のクローラーであることがわかる名前

設定後、「Next」をクリックします。

ステップ2: データソースの設定

「Add a data source」をクリックし、下記表に従い設定を行ってください。

設定項目 設定の基準
Data source S3 CSVファイルがS3に保存されているため
S3 path s3://lf-handson-data-{自分の名前}/customers/ 先ほど作成したフォルダを指定

設定後、「Add an S3 data source」をクリックし、「Next」をクリックします。

ステップ3: セキュリティ設定

クローラーがS3やGlueデータカタログにアクセスするためのIAMロールを設定します。

「Choose an existing IAM role」を選択し、先ほど作成した AWSGlueServiceRole-lf-handson を指定します。

設定後、「Next」をクリックします。

ステップ4: 出力の設定

下記表に従い、設定を行ってください。

設定項目 設定の基準
Target database lf_handson_db 先ほど作成したデータベースを指定

設定後、「Next」をクリックします。

ステップ5: 確認と作成

設定内容を確認し、「Create crawler」をクリックします。

クローラーが作成されたら、「Run crawler」をクリックして実行します。

実行が完了するまで数分かかります。

ステータスが「Completed」になったら完了です。

5.4 テーブルの確認

クローラーの実行が完了したら、CSVファイルの構造が正しくデータカタログに登録されたかを確認します。

左メニューから「Data Catalog」>「Tables」を選択し、lf_handson_db データベースに customers というテーブルが作成されていることを確認します。テーブルを開くと、CSVファイルのカラム(customer_id, name, email, phone, region, total_purchases, birth_date, address, credit_card_last4)が認識されていることを確認できます。

テーブルが作成され、9つのカラムがすべて表示されていれば、データカタログの作成は完了です。

5.5 Athenaでデータを確認する

Lake Formationのアクセス制御(LF-Tag)を設定する前に、現時点でAthenaからすべてのカラムが参照できることを確認しておきましょう。この状態がLF-Tag設定後にどう変わるかを比較するためです。

Athenaのダッシュボードを開き、クエリエディタで以下のクエリを実行します。

💡 ポイント
Athenaを初めて使用する場合、クエリ結果の保存先が未設定のためエラーになります。「Settings」タブから「Manage」をクリックし、「Location of query result」に任意のS3バケットを指定してください。
SELECT * FROM lf_handson_db.customers;

customer_idnameemailphoneregiontotal_purchasesbirth_dateaddresscredit_card_last49つのカラムすべてが表示されることを確認してください。現時点ではLF-Tagによるアクセス制御が設定されていないため、全カラムを参照できる状態です。

この後のセクションでLF-Tagによるアクセス制御を設定すると、ロールに応じて参照できるカラムが制限されるようになります。

💡 ポイント
「Permissions」>「Data permissions」を開いた際に、lf_handson_db に対する IAMAllowedPrincipals というエントリが表示されている場合は、選択して「Revoke」で取り消してください。IAMAllowedPrincipals はLake Formationを介さずにIAMポリシーのみでアクセスを許可する特別なグループで、この権限が残っているとLF-Tagのアクセス制御が機能しません。今回の手順ではData Catalog settingsを先に変更しているため、通常は付与されません。

6. LF-Tagの作成

初期設定が完了し、Lake Formationでアクセス制御を行う準備が整いました。ここからが本題です。カラムごとに異なるアクセス権限を設定するために、まず各カラムの機密度を表すLF-Tagを作成し、カラムに割り当てます。LF-Tagを使うことで、「カラムにタグを付ける」→「タグに対して権限を設定する」という2ステップで効率的にアクセス制御を実現できます。

6.1 タグの設計

このハンズオンでは、sensitivity というキーのLF-Tagを作成し、各カラムの機密度に応じてタグを割り当てます。

LF-Tagの値 意味 対象カラム
general 集計情報 customer_id, region, total_purchases
personal 個人情報 name, email, phone
sensitive 機密個人情報 birth_date, address, credit_card_last4

6.2 LF-Tagの作成

左メニューの「Permissions」>「LF-Tags and permissions」を開き、「Add LF-Tag」をクリックします。

下記表に従い、設定を行ってください。

設定項目 設定の基準
Key sensitivity カラムの機密度を表すタグ
Values general, personal, sensitive 3段階の機密レベル

値は1行に1つずつ入力します。設定後、「Add LF-Tag」をクリックします。

6.3 カラムへのLF-Tag割り当て

左メニューから「Data Catalog」>「Tables」を選択し、lf_handson_db データベースの customers テーブルを開きます。

「Edit LF-Tags」をクリックし、各カラムにLF-Tagを割り当てます。「Edit LF-Tags for columns」タブを選択し、以下のようにタグを設定してください。

集計情報のカラムに sensitivity=general を割り当てます。

  • customer_id → sensitivity=general
  • region → sensitivity=general
  • total_purchases → sensitivity=general

個人情報のカラムに sensitivity=personal を割り当てます。

  • name → sensitivity=personal
  • email → sensitivity=personal
  • phone → sensitivity=personal

機密個人情報のカラムに sensitivity=sensitive を割り当てます。

  • birth_date → sensitivity=sensitive
  • address → sensitivity=sensitive
  • credit_card_last4 → sensitivity=sensitive

設定後、「Save」をクリックします。

テーブルの「LF-Tags」タブで、各カラムにタグが正しく割り当てられていることを確認できれば、LF-Tagの設定は完了です。

7. IAMロールの作成

LF-Tagをカラムに割り当てたことで、「データ側」の準備は整いました。次に、「誰がどのタグにアクセスできるか」を設定するために、アクセスする側のIAMロールを作成します。このハンズオンでは、業務上の役割が異なる3つのロールを作成し、それぞれに異なるLF-Tag権限を付与することで、同じデータに対してロールごとに見えるカラムが変わることを体験します。

7.1 ロールの作成

IAMのダッシュボードを開き、左メニューから「ロール」を選択し、「ロールを作成」をクリックします。以下の3つのロールを作成してください。

各ロールは「AWSのサービス」>「Athena」を信頼されたエンティティとして選択し、許可ポリシーには AmazonAthenaFullAccess を付与します。

ロール名 説明
lf-handson-marketing マーケティング担当用ロール
lf-handson-support カスタマーサポート担当用ロール
lf-handson-data-admin データ管理者用ロール
💡 ポイント
ここでは各ロールにAthenaの実行権限のみを付与しています。データへのアクセス制御はIAMポリシーではなく、Lake Formationで行います。これにより、IAMの権限管理とデータのアクセス制御を分離できます。

7.2 Athenaクエリ結果用S3バケットの作成

Athenaでクエリを実行すると、結果がS3に保存されます。各ロールからAthenaを実行できるようにするために、クエリ結果の保存先となるS3バケットを作成し、各ロールに書き込み権限を付与します。

S3のダッシュボードから「バケットを作成」をクリックし、下記表に従い設定を行ってください。

設定項目 設定の基準
バケット名 lf-handson-athena-results-{自分の名前} Athenaのクエリ結果保存用
AWSリージョン アジアパシフィック(東京)ap-northeast-1 他のリソースと同じリージョンに配置

設定後、「バケットを作成」をクリックします。

各IAMロールに、このバケットへの書き込み権限を追加します。各ロールを開き、「許可を追加」>「インラインポリシーを作成」から、以下のポリシーを追加してください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::lf-handson-athena-results-{自分の名前}",
                "arn:aws:s3:::lf-handson-athena-results-{自分の名前}/*"
            ]
        }
    ]
}

{自分の名前} の部分は、実際のバケット名に合わせて変更してください。

3つのロールすべてにインラインポリシーを追加できたら、IAMロールの作成は完了です。

8. Lake Formationでの権限付与

IAMロールとLF-Tagの両方が揃ったので、いよいよ「どのロールがどのタグのデータにアクセスできるか」を設定します。ここがこのハンズオンの核心部分です。各ロールに対してアクセスを許可するLF-Tagの値を指定することで、カラムレベルのアクセス制御が実現されます。

8.1 マーケティング担当用ロールへの権限付与

Lake Formationのダッシュボードで、左メニューの「Permissions」>「Data permissions」を開き、「Grant」をクリックします。

マーケティング担当は、地域別の売上分析やレポート作成が主な業務です。個人を特定できる情報は業務上不要なため、集計情報のみにアクセスを許可します。

下記表に従い、設定を行ってください。

設定項目 設定の基準
Principals IAM users and roles IAMロールに権限を付与するため
IAM users and roles lf-handson-marketing マーケティング担当用ロールを選択
LF-Tags key sensitivity 作成したLF-Tagを指定
LF-Tags values general 集計情報のみアクセス可能
Database permissions Describe データベースのメタデータ参照を許可
Table and column permissions Select, Describe テーブルのデータ参照とメタデータ参照を許可

設定後、「Grant」をクリックします。

8.2 カスタマーサポート担当用ロールへの権限付与

同様に「Grant」をクリックし、下記表に従い設定を行ってください。

カスタマーサポート担当は、顧客からの問い合わせに対応するために氏名や連絡先を参照する必要があります。ただし、生年月日や住所、クレジットカード情報といった機密性の高い情報は、問い合わせ対応には不要です。

設定項目 設定の基準
Principals IAM users and roles IAMロールに権限を付与するため
IAM users and roles lf-handson-support カスタマーサポート担当用ロールを選択
LF-Tags key sensitivity 作成したLF-Tagを指定
LF-Tags values general, personal 集計情報と個人情報にアクセス可能
Database permissions Describe データベースのメタデータ参照を許可
Table and column permissions Select, Describe テーブルのデータ参照とメタデータ参照を許可

設定後、「Grant」をクリックします。

8.3 データ管理者用ロールへの権限付与

同様に「Grant」をクリックし、下記表に従い設定を行ってください。

データ管理者は、データ品質の管理やコンプライアンス監査を担当するため、すべてのカラムへのアクセスが必要です。

設定項目 設定の基準
Principals IAM users and roles IAMロールに権限を付与するため
IAM users and roles lf-handson-data-admin データ管理者用ロールを選択
LF-Tags key sensitivity 作成したLF-Tagを指定
LF-Tags values general, personal, sensitive すべての機密レベルにアクセス可能
Database permissions Describe データベースのメタデータ参照を許可
Table and column permissions Select, Describe テーブルのデータ参照とメタデータ参照を許可

設定後、「Grant」をクリックします。

8.4 権限設定の確認

3つのロールへの権限付与が完了したら、設定内容に誤りがないか確認します。左メニューの「Permissions」>「Data permissions」を開き、3つのロールに対する権限が正しく設定されていることを確認してください。

ロール sensitivityの値 アクセスできるカラム
lf-handson-marketing general customer_id, region, total_purchases
lf-handson-support general, personal customer_id, region, total_purchases, name, email, phone
lf-handson-data-admin general, personal, sensitive すべてのカラム

上記の表の通りに3つのロールが表示されていれば、Lake Formationでの権限付与は完了です。

💡 ポイント
Lake Formationでは、カラムの参照制御だけでなく、テーブルの作成・変更・削除といった操作権限もロールごとに設定できます。例えば「データ管理者だけがテーブルを作成・削除でき、マーケティング担当やカスタマーサポート担当は参照のみ」といった制御も可能です。今回のハンズオンではGlueクローラーがテーブルの作成・更新を担当しているため、テーブル操作の権限設定は扱いません。

9. Athenaで動作確認

すべての設定が完了しました。ここでは実際に各ロールでAthenaクエリを実行し、LF-Tagによるアクセス制御が正しく機能しているかを確認します。同じ SELECT * クエリを実行しても、ロールに応じて表示されるカラムが異なることを体験してください。

9.1 Athenaの初期設定

Athenaのダッシュボードを開き、「設定」タブから「管理」をクリックします。クエリ結果の保存先に s3://lf-handson-athena-results-{自分の名前}/ を設定し、「保存」をクリックします。

9.2 マーケティング担当用ロールでの確認

AWSマネジメントコンソールで「ロールの切り替え」を使い、lf-handson-marketing ロールに切り替えます。画面右上のアカウント名をクリックし、「ロールの切り替え」を選択してください。

設定項目
アカウント 自分のAWSアカウントID
ロール lf-handson-marketing

Athenaのクエリエディタで、以下のクエリを実行します。

SELECT * FROM lf_handson_db.customers;

実行結果を確認します。マーケティング担当用ロールでは、customer_idregiontotal_purchases の3カラムのみが表示されていればOKです。個人情報(name, email, phone)や機密個人情報(birth_date, address, credit_card_last4)が表示されていないことを確認してください。

9.3 カスタマーサポート担当用ロールでの確認

同様にロールを lf-handson-support に切り替え、同じクエリを実行します。

カスタマーサポート担当用ロールでは、集計情報に加えて nameemailphone の個人情報カラムが表示されていればOKです。一方、birth_dateaddresscredit_card_last4 の機密個人情報は表示されないことを確認してください。

9.4 データ管理者用ロールでの確認

ロールを lf-handson-data-admin に切り替え、同じクエリを実行します。

データ管理者用ロールでは、birth_dateaddresscredit_card_last4 を含むすべてのカラムが表示されていればOKです。

9.5 結果の比較

3つのロールでのクエリ結果を比較すると、以下のようにLF-Tagによるアクセス制御が機能していることが確認できます。

カラム マーケティング担当 カスタマーサポート担当 データ管理者
customer_id 参照可 参照可 参照可
name - 参照可 参照可
email - 参照可 参照可
phone - 参照可 参照可
region 参照可 参照可 参照可
total_purchases 参照可 参照可 参照可
birth_date - - 参照可
address - - 参照可
credit_card_last4 - - 参照可

同じ SELECT * クエリを実行しているにもかかわらず、ロールに割り当てられたLF-Tagの値に応じて、参照できるカラムが自動的に制御されていることがわかります。IAMポリシーを個別に設定することなく、LF-Tagの割り当てだけでこのような細やかなアクセス制御が実現できる点が、Lake Formationの大きな強みです。

10. データロケーションの登録

Athenaでのアクセス制御は正しく機能していることを確認できました。しかし、ここで一つ問題があります。現在の状態では、S3上のCSVファイルに直接アクセスされた場合、Lake Formationのカラム制御を迂回してすべてのデータが閲覧できてしまいます。このセクションでは、その問題を実際に確認した上で、データロケーション登録による解決方法を体験します。

10.1 S3への直接アクセスを試す

まず、Lake Formationの制御が及ばないケースを実際に確認します。マーケティング担当用ロール(lf-handson-marketing)に、データバケットへの読み取り権限を追加します。

ロールの切り替えを元のIAMユーザに戻し、IAMのダッシュボードで lf-handson-marketing ロールを開きます。「許可を追加」>「インラインポリシーを作成」から、以下のポリシーを追加してください。これはLake Formationの制御を迂回してS3に直接アクセスできることを検証するためのポリシーです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::lf-handson-data-{自分の名前}",
                "arn:aws:s3:::lf-handson-data-{自分の名前}/*"
            ]
        }
    ]
}

{自分の名前} の部分は、実際のバケット名に合わせて変更してください。

ポリシーを追加したら、lf-handson-marketing ロールに切り替え、S3のダッシュボードから lf-handson-data-{自分の名前} バケットを開きます。customers/ フォルダ内の customers.csv を選択し、「ダウンロード」または「開く」をクリックしてください。

CSVファイルの中身がすべて表示され、Athenaでは参照できなかったはずの nameemailphonebirth_dateaddresscredit_card_last4 を含む全カラムのデータが閲覧できてしまうことを確認してください。

これは、Lake FormationのLF-Tagによるアクセス制御がAthenaなどの分析エンジン経由のアクセスに対して機能するものであり、S3への直接アクセスには効力がないためです。

10.2 データロケーションの登録

この問題を解決するのが、データロケーション登録です。S3のパスをLake Formationに登録すると、Lake FormationがそのS3パスへのアクセスを一元管理するようになります。具体的には、credential vending(一時的な認証情報の発行)という仕組みにより、Lake Formationが許可したアクセスだけがS3のデータに到達できるようになります。

Lake Formationのダッシュボードを開き、左メニューの「Administration」>「Data lake locations」を選択し、「Register location」をクリックします。

下記表に従い、設定を行ってください。

設定項目 設定の基準
Amazon S3 path s3://lf-handson-data-{自分の名前}/ アクセス制御の対象となるデータバケット
IAM role AWSServiceRoleForLakeFormationDataAccess Lake FormationがS3にアクセスするためのサービスリンクロール
⚠️ サービスリンクロールが表示されない場合
「AWSServiceRoleForLakeFormationDataAccess」はLake Formationが自動的に作成するサービスリンクロールです。表示されない場合は、Lake Formationの初期設定が完了しているか確認してください。

設定後、「Register location」をクリックします。

10.3 登録後の確認

データロケーションを登録したら、再び lf-handson-marketing ロールに切り替えて、S3のダッシュボードから同じCSVファイルにアクセスしてみてください。

先ほどはダウンロードできたCSVファイルが、今度は**アクセス拒否(Access Denied)**となることを確認してください。データロケーション登録により、S3上のデータへのアクセスがLake Formationによって制御されるようになったためです。

一方、元のIAMユーザに切り替えてAthenaのクエリエディタで先ほどと同じ SELECT * クエリを実行すると、引き続きLF-Tagの設定通りにカラムが制御された状態で正しく表示されます。

💡 ポイント
データロケーション登録後は、Athenaからのアクセスもcredential vending(一時的な認証情報の発行)を通じてS3にアクセスするようになります。Lake Formationで適切な権限が付与されているロールであれば、引き続きAthenaからクエリを実行できます。

このように、データロケーション登録を行うことで、Athenaなどの分析エンジン経由のアクセスだけでなく、S3への直接アクセスもLake Formationの管理下に置くことができます。

11. 不要リソースの削除

ハンズオンが完了したら、課金を防ぐために作成したリソースを削除します。以下の順序で削除してください。

11.1 データロケーションの登録解除

Lake Formationのダッシュボードで、左メニューの「Administration」>「Data lake locations」を開き、登録した s3://lf-handson-data-{自分の名前}/ を選択して「Deregister」をクリックします。

11.2 Lake Formationの権限を削除

「Permissions」>「Data permissions」を開き、このハンズオンで作成した3つのロールへの権限をすべて「Revoke」します。

11.3 LF-Tagの削除

左メニューの「Permissions」>「LF-Tags and permissions」から、sensitivity タグを削除します。

11.4 Glueリソースの削除

Glueのダッシュボードから、以下のリソースを削除します。

  1. 「Crawlers」から lf-handson-crawler を削除
  2. 「Tables」から customers テーブルを削除
  3. 「Databases」から lf_handson_db データベースを削除

11.5 IAMロールの削除

IAMのダッシュボードから、以下のロールを削除します。

  • lf-handson-marketing
  • lf-handson-support
  • lf-handson-data-admin
  • AWSGlueServiceRole-lf-handson

11.6 S3バケットの削除

S3のダッシュボードから、以下のバケットを空にしてから削除します。

  • lf-handson-data-{自分の名前}
  • lf-handson-athena-results-{自分の名前}
💡 ポイント
S3バケットはオブジェクトが存在する状態では削除できません。まず「空にする」操作でバケット内のオブジェクトをすべて削除してから、バケットを削除してください。

11.7 (任意)Lake Formationの権限モデルを無効にする

このハンズオンではLake Formationの権限モデルを有効にしました。この設定が有効なままだと、今後Glueで新しいデータベースやテーブルを作成した際にもLake Formationの権限設定が必要になります。Lake Formationを引き続き使用しない場合は、以下の手順でIAMポリシーのみによるアクセス制御に戻すことができます。

Lake Formationのダッシュボードで、左メニューの「Administration」>「Data Catalog settings」を開き、以下の2つのチェックボックスをオンに戻して「Save」をクリックします。

  • 「Use only IAM access control for new databases」
  • 「Use only IAM access control for new tables in new databases」

これにより、以降に作成するデータベースやテーブルはIAMポリシーのみで制御される従来の動作に戻ります。

12. (参考)Terraformで構築する場合

このハンズオンで作成したリソース(S3バケット、Glueデータベース・クローラー、IAMロール、Lake Formationの設定)をTerraformで構築する方法を紹介します。

ただし、Lake Formationの一部の設定(LF-Tagのカラムへの割り当て、LF-Tagベースの権限付与、データロケーション登録)はTerraformで管理できますが、Data Catalog settingsの変更(チェックボックスの切り替え)はTerraformでは対応していないため、手動で実施する必要があります。

12.1 事前に手動で実施する設定

Terraformを実行する前に、以下の2点をAWSマネジメントコンソールで設定してください。

  1. Lake Formationのダッシュボードで「Add myself」にチェックを入れて、データレイク管理者を登録する
  2. 「Administration」>「Data Catalog settings」で2つのチェックボックスを外し、Data Catalog settingsを変更する

詳細な手順は、ハンズオン本編の「Lake Formationの初期設定」セクションに記載があります。

12.2 Terraformコード

以下のコードを main.tf として保存してください。

# ==============================================================
# Provider(プロバイダ設定)
# ==============================================================
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1" # 東京リージョン
}

# ==============================================================
# Variables(入力変数)
# ==============================================================
variable "bucket_suffix" {
  description = "S3バケット名のサフィックス(グローバルで一意にするため)"
  type        = string
}

# ==============================================================
# S3(データ格納用バケット)
# ==============================================================

# データ格納用S3バケット
resource "aws_s3_bucket" "data" {
  bucket        = "lf-handson-data-${var.bucket_suffix}"
  force_destroy = true # terraform destroy時にオブジェクトごと削除
}

# customers/フォルダ(プレフィックス)を作成
resource "aws_s3_object" "customers_folder" {
  bucket = aws_s3_bucket.data.id
  key    = "customers/"
}

# サンプルCSVデータをS3にアップロード
resource "aws_s3_object" "customers_csv" {
  bucket  = aws_s3_bucket.data.id
  key     = "customers/customers.csv"
  content = <<-CSV
customer_id,name,email,phone,region,total_purchases,birth_date,address,credit_card_last4
C001,田中太郎,tanaka@example.com,090-1234-5678,東京,150000,1985-03-15,東京都渋谷区神宮前1-1-1,1234
C002,佐藤花子,sato@example.com,080-2345-6789,大阪,230000,1990-07-22,大阪府大阪市北区梅田2-2-2,5678
C003,鈴木一郎,suzuki@example.com,070-3456-7890,福岡,80000,1978-11-08,福岡県福岡市博多区博多駅前3-3-3,9012
C004,山田美咲,yamada@example.com,090-4567-8901,東京,310000,1995-01-30,東京都新宿区西新宿4-4-4,3456
C005,高橋健太,takahashi@example.com,080-5678-9012,名古屋,120000,1988-09-12,愛知県名古屋市中区栄5-5-5,7890
  CSV
}

# Athenaクエリ結果保存用S3バケット
resource "aws_s3_bucket" "athena_results" {
  bucket        = "lf-handson-athena-results-${var.bucket_suffix}"
  force_destroy = true
}

# ==============================================================
# IAM(権限管理)
# ==============================================================

# --- Glueクローラー用IAMロール ---
resource "aws_iam_role" "glue_crawler" {
  name = "AWSGlueServiceRole-lf-handson"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { Service = "glue.amazonaws.com" }
    }]
  })
}

# Glueの基本権限をアタッチ
resource "aws_iam_role_policy_attachment" "glue_service" {
  role       = aws_iam_role.glue_crawler.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole"
}

# S3データバケットへの読み取り権限
resource "aws_iam_role_policy" "glue_s3_access" {
  name = "glue-s3-data-access"
  role = aws_iam_role.glue_crawler.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = ["s3:GetObject", "s3:ListBucket"]
      Resource = [
        aws_s3_bucket.data.arn,
        "${aws_s3_bucket.data.arn}/*"
      ]
    }]
  })
}

# --- 3つの業務ロール(マーケティング・サポート・データ管理者) ---
locals {
  roles = {
    marketing  = "lf-handson-marketing"
    support    = "lf-handson-support"
    data_admin = "lf-handson-data-admin"
  }
}

# 各ロールの作成(Athenaからの利用を想定)
resource "aws_iam_role" "business" {
  for_each = local.roles
  name     = each.value

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { Service = "athena.amazonaws.com" }
    }, {
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { AWS = data.aws_caller_identity.current.arn }
    }]
  })
}

data "aws_caller_identity" "current" {}

# 各ロールにAthenaFullAccessをアタッチ
resource "aws_iam_role_policy_attachment" "athena_access" {
  for_each   = local.roles
  role       = aws_iam_role.business[each.key].name
  policy_arn = "arn:aws:iam::aws:policy/AmazonAthenaFullAccess"
}

# 各ロールにAthenaクエリ結果バケットへの書き込み権限を付与
resource "aws_iam_role_policy" "athena_results_access" {
  for_each = local.roles
  name     = "athena-results-access"
  role     = aws_iam_role.business[each.key].id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = ["s3:PutObject", "s3:GetObject", "s3:GetBucketLocation"]
      Resource = [
        aws_s3_bucket.athena_results.arn,
        "${aws_s3_bucket.athena_results.arn}/*"
      ]
    }]
  })
}

# ==============================================================
# Glue Data Catalog(データカタログ)
# ==============================================================

# データベースの作成
resource "aws_glue_catalog_database" "main" {
  name = "lf_handson_db"
}

# クローラーの作成
resource "aws_glue_crawler" "main" {
  name          = "lf-handson-crawler"
  role          = aws_iam_role.glue_crawler.arn
  database_name = aws_glue_catalog_database.main.name

  s3_target {
    path = "s3://${aws_s3_bucket.data.id}/customers/"
  }

  depends_on = [
    aws_lakeformation_permissions.glue_crawler_db
  ]
}

# ==============================================================
# Lake Formation(アクセス制御)
# ==============================================================

# --- クローラー用ロールへのデータベース権限 ---
resource "aws_lakeformation_permissions" "glue_crawler_db" {
  principal   = aws_iam_role.glue_crawler.arn
  permissions = ["CREATE_TABLE", "DESCRIBE"]

  database {
    name = aws_glue_catalog_database.main.name
  }
}

# --- LF-Tagの作成 ---
resource "aws_lakeformation_lf_tag" "sensitivity" {
  key    = "sensitivity"
  values = ["general", "personal", "sensitive"]
}

# --- LF-Tagベースの権限付与 ---

# マーケティング担当: generalのみ
resource "aws_lakeformation_permissions" "marketing" {
  principal   = aws_iam_role.business["marketing"].arn
  permissions = ["DESCRIBE"]

  lf_tag_policy {
    resource_type = "DATABASE"
    expression {
      key    = "sensitivity"
      values = ["general"]
    }
  }
}

resource "aws_lakeformation_permissions" "marketing_table" {
  principal   = aws_iam_role.business["marketing"].arn
  permissions = ["SELECT", "DESCRIBE"]

  lf_tag_policy {
    resource_type = "TABLE"
    expression {
      key    = "sensitivity"
      values = ["general"]
    }
  }
}

# カスタマーサポート担当: general + personal
resource "aws_lakeformation_permissions" "support" {
  principal   = aws_iam_role.business["support"].arn
  permissions = ["DESCRIBE"]

  lf_tag_policy {
    resource_type = "DATABASE"
    expression {
      key    = "sensitivity"
      values = ["general", "personal"]
    }
  }
}

resource "aws_lakeformation_permissions" "support_table" {
  principal   = aws_iam_role.business["support"].arn
  permissions = ["SELECT", "DESCRIBE"]

  lf_tag_policy {
    resource_type = "TABLE"
    expression {
      key    = "sensitivity"
      values = ["general", "personal"]
    }
  }
}

# データ管理者: すべて
resource "aws_lakeformation_permissions" "data_admin" {
  principal   = aws_iam_role.business["data_admin"].arn
  permissions = ["DESCRIBE"]

  lf_tag_policy {
    resource_type = "DATABASE"
    expression {
      key    = "sensitivity"
      values = ["general", "personal", "sensitive"]
    }
  }
}

resource "aws_lakeformation_permissions" "data_admin_table" {
  principal   = aws_iam_role.business["data_admin"].arn
  permissions = ["SELECT", "DESCRIBE"]

  lf_tag_policy {
    resource_type = "TABLE"
    expression {
      key    = "sensitivity"
      values = ["general", "personal", "sensitive"]
    }
  }
}

# --- データロケーション登録 ---
resource "aws_lakeformation_resource" "data_location" {
  arn = aws_s3_bucket.data.arn
}

# ==============================================================
# Outputs(出力値)
# terraform apply後にコンソールに表示される情報
# ==============================================================
output "data_bucket_name" {
  description = "データ格納先のS3バケット名"
  value       = aws_s3_bucket.data.id
}

output "athena_results_bucket_name" {
  description = "Athenaクエリ結果の保存先S3バケット名"
  value       = aws_s3_bucket.athena_results.id
}

output "crawler_name" {
  description = "Glueクローラー名"
  value       = aws_glue_crawler.main.name
}

12.3 Terraformで管理するリソースの解説

リソース Terraformリソース名 説明
S3バケット(データ用) aws_s3_bucket / aws_s3_object CSVデータの格納先。customers/フォルダとCSVファイルをインラインで作成
S3バケット(Athena用) aws_s3_bucket Athenaのクエリ結果保存用バケット
Glueクローラー用ロール aws_iam_role / aws_iam_role_policy Glueクローラーの実行ロール。AWSGlueServiceRoleポリシーとS3読み取り権限をアタッチ
3つの業務ロール aws_iam_role(for_each) マーケティング・サポート・データ管理者用ロール。AmazonAthenaFullAccessとAthena結果バケットへの書き込み権限を付与
Glueデータベース aws_glue_catalog_database データカタログのデータベース(lf_handson_db
Glueクローラー aws_glue_crawler S3上のCSVを解析してテーブルを自動作成
LF-Tag aws_lakeformation_lf_tag sensitivityタグ(general / personal / sensitive)
LF-Tagベース権限 aws_lakeformation_permissions 各ロールに対するLF-Tagベースのアクセス権限(DATABASE / TABLE)
データロケーション aws_lakeformation_resource S3バケットをLake Formationの管理下に登録
💡 ポイント
LF-Tagのカラムへの割り当てはTerraformでは対応していないため、Terraform実行後にAWSマネジメントコンソールから手動で設定する必要があります。手順はハンズオン本編の「カラムへのLF-Tag割り当て」セクションに記載があります。

12.4 実行方法

Terraform実行

terraform.tfvarsを作成し、変数を設定します。

bucket_suffix = "yamada"  # ご自身の名前に置き換えてください

まず、Terraformの初期化を行います。プロバイダのダウンロードなどが実行されます。

terraform init

次に、作成されるリソースの実行計画を確認します。どのようなリソースが作成されるかを事前に確認できます。

terraform plan

問題がなければ、実際にリソースを作成します。確認プロンプトが表示されるので、yesと入力してください。

terraform apply

Glueクローラーの実行

Terraformでリソースを作成しただけではクローラーは自動実行されません。AWSマネジメントコンソールから手動で実行します。

AWSマネジメントコンソールで「AWS Glue」を開き、左メニューから「Crawlers」を選択します。クローラー一覧から lf-handson-crawler を選択し、「Run」ボタンをクリックして実行します。ステータスが「Completed」になったら、「Data Catalog」>「Tables」に customers テーブルが自動作成されます。

LF-Tagのカラム割り当て(手動)

クローラーの実行が完了したら、ハンズオン本編の「カラムへのLF-Tag割り当て」セクションの手順に従って、各カラムにLF-Tagを割り当ててください。

Athenaで動作確認

LF-Tagのカラム割り当てが完了したら、ハンズオン本編の「Athenaで動作確認」セクションの手順に従って、各ロールでクエリを実行し、アクセス制御が機能していることを確認してください。

リソースの削除

環境を削除する場合は、以下のコマンドを実行します。

terraform destroy

force_destroy = trueを設定しているため、S3バケット内にオブジェクトがあっても削除されます。

💡 ポイント
terraform destroyではLake FormationのData Catalog settings(チェックボックス)は元に戻りません。Lake Formationを引き続き使用しない場合は、ハンズオン本編の「(任意)Lake Formationの権限モデルを無効にする」セクションの手順で手動で戻してください。

13. まとめ

このハンズオンでは、AWS Lake FormationのLF-Tagを使ったタグベースのアクセス制御を体験しました。

  • S3上のCSVデータをGlueクローラーでデータカタログに登録した
  • sensitivity というLF-Tagを作成し、カラムの機密度に応じて generalpersonalsensitive の値を割り当てた
  • 「マーケティング担当」「カスタマーサポート担当」「データ管理者」の3つのIAMロールに対して、LF-Tagで異なるアクセス権限を付与した
  • Athenaでクエリを実行し、同じ SELECT * でもロールごとに参照できるカラムが異なることを確認した
  • LF-Tagを使うことで、IAMポリシーを個別に設定することなく、効率的にカラムレベルのアクセス制御を実現できることを学んだ
  • データロケーション登録により、S3への直接アクセスもLake Formationの管理下に置き、分析エンジンを迂回したデータ閲覧を防止できることを確認した