QuickSightでIAMロールを使ってRedshiftにクエリを実行する

# はじめに
QuickSightでRedshiftに接続する方法は、以下のようにデータソースにDBユーザーとパスワードを指定する方法があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/f9eafd11-64ed-a22f-f9c6-8a8acb358bd1.png)

しかし、2023年10月に**IAMロールを使って**Redshiftへの接続が出来るようになりました！

https://aws.amazon.com/jp/about-aws/whats-new/2023/10/amazon-quicksight-queries-iam-role-redshift-data-sources/

この機能を用いると、IAMロールの認証情報を使ってDBユーザーにアクセスするため、**DBユーザーのパスワードを入力する必要がありません。**
つまり、利用者はパスワードを覚える必要がなく、管理者はパスワード流失セキュリティインシデントの懸念が減ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/917be8e3-5dd7-53ff-37ac-af9a6fdc066d.png)

今回は、この接続方法を試してみます。

# 前提条件
- RedshiftのRA3クラスターをバージニア北部リージョン（us-east-1）に作成済み
    - パブリックアクセスを有効にしています
- QuickSightを同じくバージニア北部リージョン（us-east-1）に作成済み

:::note warn
2024年2月9日時点では、RedshiftとQuickSightが同じアカウントに存在する必要があります。試してみましたが、確かに同じアカウントでないとエラーとなりました。
:::

# やってみる
以下のドキュメントを見ながらやっていきます。

https://docs.aws.amazon.com/ja_jp/quicksight/latest/user/datasource-run-as-role.html#datasource-run-as-role-redshift

## IAMロールを作成する
`TestRedshiftRoleForQuickSight`という名前のIAMロールを作成します。
ドキュメントではCLIで作成していますが、私はGUIで作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/26be3017-743c-0fd4-b010-2ab56209c6f9.png)

## IAMポリシーを作成する
`RedshiftGetClusterCredentialsPolicy1`という名前のIAMポリシーを作成します。
ポリシーの内容は以下です。
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RedshiftGetClusterCredentialsPolicy",
            "Effect": "Allow",
            "Action": [
                "redshift:GetClusterCredentials"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```

こちらも、ドキュメントではCLIで作成していますが、私はGUIで作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/e6dae29d-1866-ae9f-1f23-dca4fbd3a2bf.png)

:::note info
`redshift:GetClusterCredentials` は、指定のRedshiftのDBユーザーの認証情報を取得するアクションです。現在はResource句が`*`となっていますが、ここでDBユーザーを指定することで特定のDBユーザーのみアクセスさせることが可能です。[このAWSドキュメント](https://docs.aws.amazon.com/ja_jp/redshift/latest/mgmt/generating-iam-credentials-role-permissions.html)が参考になります。
:::

## ロールにポリシーをアタッチする
先ほど作成したIAMロール`TestRedshiftRoleForQuickSight`に、2つのIAMポリシーをアタッチします。
1つは先ほど作成したIAMポリシー`RedshiftGetClusterCredentialsPolicy1`、もう1つはQuickSightが自動生成する`AWSQuickSightRedshiftPolicy`です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/06f33ada-441d-aa44-f23b-34323615647b.png)

ちなみに、QuickSightが自動生成する`AWSQuickSightRedshiftPolicy`は以下のような内容になっています。
QuickSightはRedshiftの接続情報としてcluster-nameのみ（cluster-idとAWSリージョンなし）を指定できますが、この時`redshift:DescribeClusters`を呼び出してcluster-nameから必要な情報（cluster-idとAWSリージョン）を取得しています。それができるように、ここで`redshift:Describe*`を許可しているものと思われます。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "redshift:Describe*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
```

参考：

https://docs.aws.amazon.com/ja_jp/redshift/latest/mgmt/generating-iam-credentials-configure-jdbc-odbc.html

## データソースを作成する
こちらでようやくQuickSightのデータソースを作成します。
ここで注意ですが、IAMロールを利用したデータソースについては、2024年2月9日現在ではCLIでしか作成できません。そのため、Cloud Shellを利用して実行していきます。

まずは、ローカルで以下のjsonを`redshift-data-source-iam.json`という名前で作成します。
値はそれぞれご自身の環境に併せて変更してください。

```json:redshift-data-source-iam.json
{
    "AwsAccountId": "123456789012",
    "DataSourceId": "test-redshift-iam-role",
    "Name": "test-redshift-iam-role",
    "Type": "REDSHIFT",
    "DataSourceParameters": {
        "RedshiftParameters": {
            "Database": "db_name",
            "Host": "cluster-name.jhageijtksjd.us-east-1.redshift.amazonaws.com",
            "Port": 5439,
            "ClusterId": "cluster-name",
            "IAMParameters": {
                "RoleArn": "arn:aws:iam::123456789012:role/TestRedshiftRoleForQuickSight",
                "DatabaseUser": "db_user"
            }
        }
    },
    "Permissions": [
      {
        "Principal": "arn:aws:quicksight:us-east-1:123456789012:user/default/qs_user",
        "Actions": [
          "quicksight:DescribeDataSource",
          "quicksight:DescribeDataSourcePermissions",
          "quicksight:PassDataSource",
          "quicksight:UpdateDataSource",
          "quicksight:DeleteDataSource",
          "quicksight:UpdateDataSourcePermissions"
        ]
      }
    ]
}
```

次に、作成した`redshift-data-source-iam.json`をCloud Shellでアップロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/46e20476-1209-60f1-64b4-9f36b7205240.png)

その後、以下のコマンドを実行します。

```bash
aws quicksight create-data-source \
--region us-east-1 \
--endpoint https://quicksight.us-east-1.amazonaws.com/ \
--cli-input-json file://redshift-data-source-iam.json
```

成功すると、以下のように`Status 202`が返ってくるはずです。

```json
{
    "Status": 202,
    "Arn": "arn:aws:quicksight:us-east-1:123456789012:datasource/test-redshift-iam-role",
    "DataSourceId": "test-redshift-iam-role",
    "CreationStatus": "CREATION_IN_PROGRESS",
    "RequestId": "e7d1edba-5155-4bc0-a050-a2e71f1f9ffc"
}
```

QuickSightの画面を見てみると、データソースがちゃんとできていますね。ただし、このままの状態だと接続できません。Redshift側のセキュリティグループを設定する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/5f3506c6-defd-7fec-2fe4-035c97998eb4.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/783f58b1-7f29-3124-fa77-e847d0fb27ef.png)

## Redshiftのセキュリティグループを作成して付与する
バージニア北部のQucikSightのIPアドレスからの通信を、セキュリティグループで許可してあげる必要があります。
以下のサイトから確認すると、バージニア北部リージョン（us-east-1）のデータソース接続のIPアドレス範囲は`52.23.63.224/27`とのことでした。

https://docs.aws.amazon.com/ja_jp/quicksight/latest/user/regions.html

Redshiftのコンソールから、接続先のクラスターの詳細を開き、「プロパティタブ」をクリックします。
その中の「ネットワークとセキュリティの設定」に、「VPC セキュリティグループ」があるのでそこをクリックすると付与されているセキュリティグループの設定画面に飛べます。
そこで、以下のように先ほど調べたIPアドレスからの接続を許可しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/c5e2d903-6f07-6e5b-0805-5ea8aa29f332.png)

## QuickSightから接続確認
QuickSightの画面に戻り、データセットを作成してみます。
データソースを選択して「データセットを作成」を押すと、以下のようにスキーマとテーブルを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/59b4534e-57ff-feae-3f9b-508d42fb2a57.png)

選択してデータセットを作成し、データのプレビューを見てみます。
以下のように、データが参照できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949357/d08156e9-62f7-7d36-f60b-ddd592eb01fe.png)

# 注意事項
- QuickSightとRedshiftのリージョンが異なる環境で実施すると、エラーでうまく接続できませんでした。
- 以下のドキュメントを参考にすると、Cloud Shellにアップロードするjsonの中のRedshiftParameters句の中は、"Host"と"Port"が記載されていれば"ClusterId"は省略可能なはずです。ただ、省略するとエラーで接続できませんでした。

https://docs.aws.amazon.com/quicksight/latest/APIReference/API_RedshiftParameters.html

# おわりに
リージョンの指定を誤って何回かエラーとなりましたが、無事にロールでRedshiftに接続できました。Redshiftと色々なサービスを接続して使うことは多いと思いますが、それぞれ全てロールで接続が統一できると楽になりそうです。ただし、現在はクロスアカウントで使えないようなので、是非使えるようになってほしいですね。