QuickSightの利用IAMロールをデフォルトから変更してAthena にアクセスする

# はじめに
最近、AWSサービスの主となる部分よりも、その権限管理をどうやるかの方に興味を惹かれる私です。今回は、QuickSightのアクセス権限の管理を色々カスタマイズしたので、備忘として書いておきます。

# やりたいこと
以下のように、QuikciSightは既存の専用ロール `aws-quicksight-service-role-v0` に対して、コンソールの管理画面から権限を付与します。**直接ロールを編集することはしません**。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/a49c4382-595b-d77d-47d2-71b6ede50267.png)
[Amazon QuickSight アカウント/ユーザー管理におけるポイント](https://pages.awscloud.com/rs/112-TZM-766/images/%5B%E7%AC%AC%E4%B8%80%E9%83%A8%5DAmazonQuickSight%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%83%A6%E3%83%BC%E3%82%B5%E3%82%99%E3%83%BC%E7%AE%A1%E7%90%86%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%9B%E3%82%9A%E3%82%A4%E3%83%B3%E3%83%88_1014.pdf) p.20 より

ただ、別のロールを用意してそれをQuickSightに使わせることもできます。そのようにすることで、その権限付与をIaC（CloudFormationやCDK、Terraformなど）で管理できます。つまり、権限付与や剥奪の操作を履歴に残すことが出来ます。

今回は、QuickSightから**Athenaのデータセットを作成できるようなロール**を作成して、実際に付与してデータセットを作成してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/50cade39-66ef-acdb-f1e5-e8f368626da9.png)

# 前提条件
- リージョンはバージニア北部リージョン
- QuickSightのユーザーは管理者Admin（ロール）
    - IAMロールのセルフプロビジョニングで作成
- QuickSightはエンタープライズ版
- 事前に以下のリソース作成済み
    - Athenaのワークグループ `test-athena-wg`
    - Athenaのクエリ履歴を保存するS3バケット `s3://athena-query-result-20231227`
    - データを格納するS3のフォルダ `s3://sample-data-qs-kensyo/tables/sample-data1/`
        - フォルダ内にcsvファイル `sample-data.csv` を格納
    - Glueデータベース `sample-database`
    - Glueテーブル `sample-data1`
        - Glueクローラーでデータを格納するS3のフォルダをクロールすることで作成

# 付与する権限
いきなり結論ですが、以下を付与したロールを「QuickSight の AWS のサービスへのアクセス」で設定することで、Athenaのデータセットを作成することが出来ました。

:::note warn
AWSアカウントIDは`123456789012`に変更しています。
:::



```json
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"athena:ListEngineVersions",
				"athena:ListWorkGroups",
				"athena:ListDataCatalogs",
				"athena:ListDatabases",
				"athena:GetDatabase",
				"athena:ListTableMetadata",
				"athena:GetTableMetadata"
			],
			"Resource": "*"
		},
		{
			"Effect": "Allow",
			"Action": [
				"athena:GetWorkGroup",
				"athena:BatchGetQueryExecution",
				"athena:GetQueryExecution",
				"athena:ListQueryExecutions",
				"athena:StartQueryExecution",
				"athena:StopQueryExecution",
				"athena:GetQueryResults",
				"athena:GetQueryResultsStream",
				"athena:CreateNamedQuery",
				"athena:GetNamedQuery",
				"athena:BatchGetNamedQuery",
				"athena:ListNamedQueries",
				"athena:DeleteNamedQuery",
				"athena:CreatePreparedStatement",
				"athena:GetPreparedStatement",
				"athena:ListPreparedStatements",
				"athena:UpdatePreparedStatement",
				"athena:DeletePreparedStatement"
			],
			"Resource": [
				"arn:aws:athena:us-east-1:123456789012:workgroup/test-athena-wg"
			]
		},
		{
			"Effect": "Allow",
			"Action": [
				"s3:ListBucket"
			],
			"Resource": [
				"arn:aws:s3:::sample-data-qs-kensyo"
			]
		},
		{
			"Effect": "Allow",
			"Action": [
				"s3:GetObject"
			],
			"Resource": [
				"arn:aws:s3:::sample-data-qs-kensyo/tables/*"
			]
		},
		{
			"Effect": "Allow",
			"Action": [
				"s3:GetBucketLocation",
				"s3:GetObject",
				"s3:ListBucket",
				"s3:ListBucketMultipartUploads",
				"s3:AbortMultipartUpload",
				"s3:PutObject",
				"s3:ListMultipartUploadParts"
			],
			"Resource": [
				"arn:aws:s3:::athena-query-result-20231227",
				"arn:aws:s3:::athena-query-result-20231227/*"
			]
		},
		{
			"Action": [
				"glue:GetDatabase",
				"glue:GetDatabases",
				"glue:GetPartition",
				"glue:GetPartitions",
				"glue:GetTable",
				"glue:GetTables"
			],
			"Resource": [
				"arn:aws:glue:us-east-1:123456789012:catalog",
				"arn:aws:glue:us-east-1:123456789012:database/sample-database",
				"arn:aws:glue:us-east-1:123456789012:table/sample-database/*"
			],
			"Effect": "Allow"
		}
	]
}
```
# 解説
## Athena
Athenaは、Resource句でワークグループを絞ることで他のワークグループを使用させないようにしています。また、ワークグループの削除や更新などの管理系のactionは許可していません。

以下のドキュメントの「**指定したワークグループでクエリを実行するためのポリシーの例**」をそのまま使ってます。

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/example-policies-workgroup.html

## S3
S3は、データ自体が格納されている `s3://sample-data-qs-kensyo/tables/sample-data1/` と、Athenaのクエリ履歴を保存する `s3://athena-query-result-20231227` の2つで別の権限を付与しています。前者は参照しかしないのでListBucketとGetObjectのみ、後者はクエリ履歴を保存する必要があるのでPutObjectを含むいくつかのactionを許可しています。

以下のドキュメント内のポリシーをそのまま使ってます。

https://repost.aws/ja/knowledge-center/access-denied-athena

## Glue
Glueは、データベース、テーブル、パーティションについてのGet権限を付与しています。また、Resource句の `catalog` は、データカタログ自体を示すので入れないとDBもテーブルも選択できなくなってしまいます。参考ドキュメントは[こちら](https://docs.aws.amazon.com/ja_jp/glue/latest/dg/glue-specifying-resource-arns.html)。

以下のドキュメントの「**クロスアカウント実行アクセス権の付与**」をそのまま使っています。

https://aws.amazon.com/jp/blogs/news/cross-account-aws-glue-data-catalog-access-with-amazon-athena/

# QuickSightでデータセット作成
上記の権限を付与したロールをQuickSightに設定して、データセットを作成してみます。

以下の画面で「データソースを作成」をクリックし、新規Athenaデータソースを作成します。「接続を検証」も成功しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/a7669f62-9e9b-5813-9cf2-483c5a2df0b2.png)

以下のように、指定のテーブルを選択することが出来ます。この画面で「選択」をクリックしてデータセットを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/a2186802-b571-8051-30b9-4833f6a7a4b9.png)


データセットが作成できました。データを参照できるかの確認のため、「データの編集/プレビュー」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/6da0d4b9-2fa8-ee96-18d8-01f46db6a1d3.png)


データもちゃんと見えてますね！（権限が足りないと、ここでエラーが出てデータセットの中身が見えなかったりする）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/024628bd-ed39-f459-c144-2c53e56ecfe4.png)

:::note warn
今回、色々なドキュメントを参考に権限を付与しましたが、要件によっては足りない権限もあると思うので、ご自身の環境で実際に検証することをお勧めします。
:::

# おわりに
IAM ポリシーを色々と試行錯誤するのは、なかなか大変ですね。GUIでポチポチ出来るのなら、そちらの方が楽だなと痛感しました。GUIで変更したポリシーをどこかで履歴管理する仕組みを構築できるなら、そっちでやりたいですね。では、皆さん良い年末を！