IAM Identity CenterのユーザーをLake Formationで許可してAthenaでクエリする

# やりたいこと
タイトルの通りです。
「ユーザー認証はOktaなどの外部IdP認証にして、Data Catalogへの認可はLake Formationで一元管理したい！」というユースケースなどで使われます。

2023年の12月の以下のアップデートで上記の構成が可能となりました。

https://aws.amazon.com/jp/about-aws/whats-new/2023/12/amazon-athena-identities-data-access-audit/

ただし、これで利用できるのはAthenaコンソールではなく、**Amazon EMR Studioから**のAthena SQLインターフェースであることに注意してください。

>信頼できる ID 伝達を使用する Athena ワークグループからのクエリは、IAM アイデンティティセンターが有効な EMR Studio の Athena SQL インターフェイスから実行する必要があります。

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/workgroups-identity-center.html

# 実施の流れ
基本的には、以下のAWS Big Data Blogを実施していけばできます。
BlogではOktaを使っていますが、私は東京リージョンのIAM Identity Centerのユーザーとグループを作成して実施して、Athenaでクエリできるところまで行けました。

https://aws.amazon.com/jp/blogs/big-data/bring-your-workforce-identity-to-amazon-emr-studio-and-athena/

Blogの手順を日本語に直したものを記載します。なお、先ほども言った通り、1のOktaのところはIAM Identity Centerでユーザーとグループを作成することで代替しています。

1. OktaとIAM Identity Centerを統合し、ユーザーとグループを同期する。

2. IAM Identity CenterとEMR Studioを統合する。

3. IAM Identity CenterからユーザーまたはグループをEMR Studioに割り当てる。

4. IAM Identity CenterでLake Formationをセットアップする。

5. 伝搬されたコーポレートIDに対して、Lake Formationを使用して細かいロールベースのアクセス権を設定する。

6. Athenaでワークグループを設定し、アクセスを制御する。

7. Amazon S3リソース(バケット、プレフィックス、オブジェクトなど)への細かいアクセスを許可するために、Amazon S3 Access Grantsを設定する。

8. AWS アクセスポータルを介してIAM Identity CenterでEMR Studioにアクセスする。

9. EMR StudioのAthena SQLエディターでクエリを実行する。

10. ワークフォースIDの終了から終了までの監査証跡を確認する。

最終的には、以下のようにAWS Identity Centerからログインして、EMR Studioに入り、Athenaでクエリを実行することが出来ました。ただし、**Blogに書いてあることだけだとうまくいかない**ので、独自に実施した点を次の「注意点」に記載します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/1fef4caf-4cf2-e37c-c0ef-f73832fc5f70.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/8a789a7f-1849-3add-e4dd-32082b88ee7b.png)

# 注意点

## Amazon S3 Access GrantsでAthenaクエリ結果バケットへの許可を付与する
手順の7で実施しているのがこれです。
**Amazon S3 Access Grants**とは、AWS Identity Centerのユーザーやグループに対して、S3バケットへの権限を付与できるサービスです。今回、Athenaクエリ結果バケットへAWS Identity Centerのグループへの許可を与えたいため、これを使います。
これをやらないと、Athenaでクエリしても「そんなクエリ結果バケットはない」というエラーが出てしまいます。

## Amazon S3 Access GrantsでのLocationで指定するIAMロールは新規作成したら信頼ポリシーを変える
同じくAmazon S3 Access Grantsです。Blogではここの設定を動画で説明していて、Locationで指定するロールは前もって作成しているためどんなロールを作成すれば良いかよくわかりません。
ただ、現在は以下のように`Create new role`があるのでこれを選択してみましたが、**この新規に作成されたロールのままだとうまくいきません。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/4a03367c-9efc-65c7-5a30-27c1b30ecd67.png)

原因は信頼ポリシーです。自動で作成されたIAMロールの信頼ポリシーをEditしてみると、以下のようにエラーが出てしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/cbef3d21-7efb-dbee-8701-54f9465b4b35.png)

そこで、信頼ポリシーを以下の記事の通りに修正しました。

https://qiita.com/hayao_k/items/e96471bd1874585985b1

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "access-grants.s3.amazonaws.com"
            },
            "Action": [
                "sts:AssumeRole",
                "sts:SetSourceIdentity",
                "sts:SetContext"
            ]
        }
    ]
}

```

## Amazon S3 Access GrantsでのGrant scopeはサブプレフィックス「*」を指定する
さらに同じくAmazon S3 Access Grantsです。ここは、動画と全く同じ操作をしてもうまく動きません。
Grant scopeの指定の仕方に問題があります。
動画では、以下のようにサブプレフィックスには何も入力せず、`The grant scope is an object`にチェックを入れていました。この設定だと、Athenaでクエリ実行してエラーが出ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/7894992b-f7e3-0894-d848-3c7339f4aa26.png)

以下のように、サブプレフィックスに「*」を指定し、`The grant scope is an object`にはチェックなしが正解です。こうすると動きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/fe7e3df0-1b7a-b182-cdcf-98667feed28e.png)

## Lake FormationのData lake locationに付与するIAMロールは自分で作成する
次はLake Formationです。Data Catalogの元データが格納されているS3の場所をData lake locationとして登録する必要がありますが、その時にIAMロールも指定します。
普通ならLake Formationが用意してくれるサービスリンクロールを使うのですが、これを使うとエラーが起きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/531377a9-6347-f142-04c4-c3b5cbb1ffaa.png)

Service-linked rolesはSetContext auditingをサポートしていないとのこと。であれば、自分で作るしかありません。
作成したロールに付与する権限は、おそらくサービスリンクロールと同じで大丈夫なはずです（私はテスト用にAdministratorAccessを付与しました）。重要なのは、またもや**信頼ポリシー**です。以下のように信頼ポリシーを設定します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lakeformation.amazonaws.com"
            },
            "Action": [
                "sts:AssumeRole",
                "sts:SetContext"
            ]
        }
    ]
}
```

サービスロールの信頼ポリシーは`"sts:AssumeRole"`しか許可していなかったので、最初はそれをそのまま使ったのですが、`"sts:SetContext"も許可してください`というエラーが出てしまいました。そのため、`"sts:SetContext"`を追加しています。

以下の画像の、上が自作のロール、下がサービスリンクロールです。これでクエリ実行が成功しました（Hybrid access modeは、デフォでテーブル作成ができるようになるモードなのであまり関係ないです）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/02f7fd77-6e54-464e-8b5a-ca1aedf9160f.png)


## AWS Identity Centerのポータル画面はシークレットウィンドウで開きなおす
これは全体を通してなのですが、Adminとして色々操作するロールと同じブラウザ上（別タブ）でAWS Identity Centerポータルを開いてユーザー操作していたら、何やら変なエラーが多発しました。セッションか何かが残ってしまっているのかわかりませんが、それを回避するために**Chromeのシークレットウィンドウ**や**Firefoxのプライベートウインドウ**でIdentity Centerユーザーはログインするようにしたら直りました。

# おわりに
かなり道なき道を行った感じがありますが、何とかAthenaでクエリ実行ができました。
ただ、IAMポリシー書きたくないからLake Formation使ったのに、この検証でいくつのIAMロールを作成したのかと思うと、ちょっと複雑な気分です。特にLake Formationのサービスリンクロールはどこにもドキュメントに記載がなかったのでこれで合っているのかは少し不安です。
色々試行錯誤しましたが、最終的にクエリは実行できてよかったです。

# 参考
https://docs.aws.amazon.com/ja_jp/singlesignon/latest/userguide/trustedidentitypropagation-integrations.html

https://dev.classmethod.jp/articles/athena-identities-data-access-audit/

https://qiita.com/itsuki3/items/de2462ede9c9966c9bc6