QuickSight で API 呼び出しを活用した Dashboard の埋め込みをフェデレーション環境でやってみた

# はじめに

QuickSight では、可視化したダッシュボードやコンソール画面を 簡単にWebサービスに埋め込めます。SaaS サービス社内イントラページなどに、ダッシュボードを埋め込むことで、データを活用した経営やサービスに活かすことができます。自分たちで一から可視化のためのアプリケーションを作る場合と比べて、実装工数が削減でき、継続的な AWS 側の機能拡張をそのまま利用できるメリットがあります。

また、別の機能の話になりますが、QuickSight で大規模なユーザーを管理する場合に、IAM を使ったフェデレーション(Federation)が便利に使えます。例えば、Azure AD や、ADFS、Okta など、SAML や OpenID Connect が使える IdP と連携して、SSO が実現出来ます。

このフェデレーション環境のときに、どのようにユーザー認証を意識した埋め込みが出来るのか不明だったので、検証してみました。



# 前提条件

- Azure AD と QuickSight が連携済みの環境で検証を行う
  - Azure AD と QuickSight の連携から試したい場合は、このあたりの手順を参考にしてみてください。
  - https://qiita.com/sugimount-a/items/9dd4650306222d6c3c57
  - https://qiita.com/sugimount-a/items/9fb1c7a204f372c2c95d



# 検証を通じてわかったこと

この検証を通じてわかったことを冒頭に記載します。ここの部分は読み飛ばしても大丈夫です。

- Dashboard の埋め込み用 URL を生成するときに、利用者のユーザーアカウントを `user-arn` 引数で指定可能。
- 匿名ユーザー(ANONYMOUS) で Dashboard を生成することができる。ただ、QuickSight の支払いプランが Session capacity pricing のときだけ利用可能。Per reader pricing (初期状態) の場合はエラーになる
- `get-dashboard-embed-url` は古い API になっている。新しい API `generate-embed-url-for-registered-user` や `generate-embed-url-for-anonymous-userr` では新機能が使えるため、基本的には新しい API の方が良いはず。
- 古い API についてわかったこと
  - IAM のフェデレーション環境で QuickSight の自己プロビジョニングをしているユーザーは、identity-type が `IAM` になる。このユーザーを使って埋め込み用URLを  `get-dashboard-embed-url` で取得するとき、identity-type `QUICKSIHGT` を使って取得可能
  - 詳細は後述



# QuickSight のユーザー認証状態

Azure AD と AWS IAM 間でフェデレーションを実施済みです。フェデレーション環境であっても、QuickSight 上でユーザー管理画面を開くと、Azure AD 上のユーザーが登録されています。Azure AD 上にユーザーが存在しているだけでは、QuickSight は利用できません。Azure AD のユーザー名と一致するような名前で、QuickSight 上にプロビジョニングが必要です。

プロビジョニングの方法はいくつかありますが、今回の記事では詳細は取り上げません。気になる場合は Google や Document で検索してみると良いでしょう。

- IAM ユーザーを使った自己プロビジョニング
- AWS API, CLI, SDK などを利用した手動プロビジョニング

![image-20220102131701428.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/1423c7c4-9aa2-aee0-5e8c-3416bbb60fc2.png)



# QuickSight の User ARN を調べる

Dashboard の埋め込みURLを生成するために、QuickSight User の ARN が必要です。list-users コマンドで、ユーザー一覧を表示します。

```
aws quicksight list-users \
--aws-account-id xxxxxxxxxx \
--namespace default
```



実行例です。`Arn` の部分が必要なので、必要に応じてメモっておきます。

```
{
    "Status": 200,
    "UserList": [
        {
            "Arn": "arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightAdminforAzureAD/quicksight-admin01@test.com",
            "UserName": "QuickSightAdminforAzureAD/quicksight-admin01@test.com",
            "Email": "admin01@test.com",
            "Role": "ADMIN",
            "IdentityType": "IAM",
            "Active": true,
            "PrincipalId": "federated/iam/AROAVNVNXMHCFY7644GS4:quicksight-admin01@test.com"
        },
        {
            "Arn": "arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightReaderforAzureAD/quicksight-reader01@test.com",
            "UserName": "QuickSightReaderforAzureAD/quicksight-reader01@test.com",
            "Email": "reader01@test.com",
            "Role": "READER",
            "IdentityType": "IAM",
            "Active": true,
            "PrincipalId": "federated/iam/AROAVNVNXMHCFCZUZ6HV7:quicksight-reader01@test.com"
        },
        {
            "Arn": "arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightAuthorforAzureAD/quicksight-author01@test.com",
            "UserName": "QuickSightAuthorforAzureAD/quicksight-author01@test.com",
            "Email": "author01@test.com",
            "Role": "AUTHOR",
            "IdentityType": "IAM",
            "Active": true,
            "PrincipalId": "federated/iam/AROAVNVNXMHCD6IM6PBIJ:quicksight-author01@test.com"
        }
    ],
    "RequestId": "e13851d2-71bd-4d10-b37a-9a61b10bc018"
}
```



# 既に QuickSight に登録しているユーザーの場合

既に QuickSight 上に登録されているユーザーを使って、Dashboard の埋込URLを生成します。次の AWS の Document を参考にしています。

https://docs.aws.amazon.com/ja_jp/quicksight/latest/user/embedded-analytics-dashboards-for-authenticated-users.html



`generate-embed-url-for-registered-user` コマンドを使って埋め込み用 URL を生成できます。古いコマンド `get-dashboard-embed-url` は引き続き使えますが、新しい機能が使えないので、基本的には新しい コマンドである `generate-embed-url-for-registered-user` が良いと思います。



それでは、実際に既存のユーザーを指定した埋め込み用 URL を生成してみます。

- user-arn: 利用するユーザーの QuickSight 上の ARNを指定。IAM ARN ではない。
- experience-configuration : Dashboard の ID を指定。その他いくつかのカスタマイズも可能

```
aws quicksight generate-embed-url-for-registered-user \
--aws-account-id xxxxxxxxxx \
--session-lifetime-in-minutes 600 \
--user-arn arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightAdminforAzureAD/quicksight-admin01@test.com \
--experience-configuration Dashboard={InitialDashboardId=97acc558-1bfc-4e39-93cd-5aca9153fab0}
```



実行例です。`EmbedUrl` が生成された埋め込み用 URL です。埋め込みたいページに iframe として埋め込めば、すぐにダッシュボードを表示できます。

```
> aws quicksight generate-embed-url-for-registered-user \
      --aws-account-id xxxxxxxxxx \
      --session-lifetime-in-minutes 600 \
      --user-arn arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightAdminforAzureAD/quicksight-admin01@test.com \
      --experience-configuration Dashboard={InitialDashboardId=97acc558-1bfc-4e39-93cd-5aca9153fab0}
{
    "Status": 200,
    "EmbedUrl": "https://ap-northeast-1.quicksight.aws.amazon.com/embed/61979ca4bd2f43ad9bf72a332330c306/dashboards/97acc558-1bfc-4e39-93cd-5aca9153fab0?code=AYABeDKtFNkAj8h7JAqf8gzHWV8AAAABAAdhd3Mta21zAFBhcm46YXdzOmttczphcC1ub3J0aGVhc3QtMTozNjcwOTQ1NjE4OTQ6a2V5LzkyZDU3MjEzLTc0MjItNGNhOC1iYWZiLTg2MDFjNGZkODgyNwC4AQIBAHh19lpIdHJLvWmpW7433A8711o_o_2vfnBuxyXbJJdfkwFwbBYSqTLUnExHrDzXqTC0AAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQME7zGHn9nXmudtCIGAgEQgDv2CxbNQF2cqAwQxeF9V2ZeBGGLs2gXcQ_G_3h88Pkq_QmidM2PZ4h9dSHP3Gl-SyMtQnx_BkJpqRUSFwIAAAAADAAAEAAAAAAAAAAAAAAAAABDOvK8IxKJRRa8q3PwjZsW_____wAAAAEAAAAAAAAAAAAAAAEAAADqKOV71O2jbuYqk5f08IXwo51RM_WJj1i1zlcmRV-1Qzl51cgGzCT2Jbs8n9kWNQ4JmBKDw-L1QhCaCByVZW95oFRHjhDQLJ2LUM-ZvTkzfEBNLBGPU8mcL1h6zA05hIMyADvzBGjri3R-uo7snl1S9uxIqg0Ah1KJtDpowBeWO8g8o6hs3hMzcMd3KiBGdNDBJdpW1_-qXCI0yzT_imf5NXt2saLcd5brRu8AiOziZUDE5yn8R9d0D10iGFLAJ-w0yStls4KvB1DwToVt0pD93Ah2OGS_RepbUgIpBPHsD3VvR0jBevpkgPmHJ7c-ThCz0Yc7gS76bNeBXw%3D%3D&identityprovider=quicksight&isauthcode=true",
    "RequestId": "19bd2508-b9c6-44d3-abd4-5a9681027ff4"
}
```



今回は埋め込み用 Web ページはないので、単純にこのページを表示してみます。サンプル用の Dashboard が表示されました。

![image-20220102205609275.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/d314da31-b9d8-ed19-e8e5-dc8d828ba733.png)



# 新しいユーザーの場合

次に新しいユーザーの場合を見ていきましょう。「新しいユーザー」というのは、IdP である Azure AD 上にユーザーが作成されているが、QuickSight 上には登録されていないユーザーのことを指しています。

このあたりの手順を参考に、新しいユーザーを Azure AD 上に作成します。
https://qiita.com/sugimount-a/items/3eb74c064597d60aa287

下の画像は Azure AD 上のユーザー画面ですが、`quicksight-admin02` が新しいユーザーです。

![image-20220102194857052.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e310ef93-fc5f-8f9d-3bfc-b4b0977bfdba.png)



念のため、QuickSight のユーザー画面を見てみます。QuickSight 上には `quicksight-admin02`  ユーザーがプロビジョニングされていません。

![image-20220102131701428.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/9128986f-0272-ed39-9cee-3bda5cfe4dff.png)



エラーになることを想定して、実際の埋込用URLを生成コマンドを実行してみます。

```
aws quicksight generate-embed-url-for-registered-user \
--aws-account-id xxxxxxxxxx \
--session-lifetime-in-minutes 600 \
--user-arn arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightAdminforAzureAD/quicksight-admin02@test.com \
--experience-configuration Dashboard={InitialDashboardId=97acc558-1bfc-4e39-93cd-5aca9153fab0}
```



想定通りエラーです。

```
An error occurred (ResourceNotFoundException) when calling the GenerateEmbedUrlForRegisteredUser operation: User arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightAdminforAzureAD/quicksight-admin02@test.com does not exist.
```



今回は、AWS CLI を使ってユーザーを登録します。実際の Web アプリケーションでは、Lambda と API Gateway や EC2 などを利用し、ユーザーが登録されていない場合は登録するようなプログラムを作成していくと思います。

- iam-arn : IAM Role の ARN を指定。
- session-name : ユーザー名を指定。IdP 側の設定と合わせて、同じ Session Role Name を指定するようにする。異なる名前にしてしまうと、QucikSight 側で異なるユーザーとして認識されてしまうため。

```
aws quicksight register-user \
--aws-account-id xxxxxxxxxx \
--namespace default \
--identity-type IAM \
--iam-arn "arn:aws:iam::xxxxxxxxxx:role/QuickSightAdminforAzureAD" \
--user-role ADMIN \
--session-name "quicksight-admin02@test.com" \
--email admin02@test.com \
--region ap-northeast-1
```



プロビジョニングされています。

![image-20220102200100572.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/9d70b319-1d0a-28d3-a28f-957a7dd7c96b.png)



今回の手順では、新たに登録したユーザーを既存グループに追加します。

- グループ `admin-group01` は事前に作成しており、Dashboard を参照可能な権限設定済み
- グループ単位で権限管理することで、ユーザーはそのグループに参加すれば済むので管理負担が軽減可能

```
aws quicksight create-group-membership \
--aws-account-id xxxxxxxxxx \
--namespace default \
--group-name admin-group01 \
--member-name "QuickSightAdminforAzureAD/quicksight-admin02@test.com"
```



これで準備が出来たので、ダッシュボードの埋め込み URL を生成します。

```
aws quicksight generate-embed-url-for-registered-user \
--aws-account-id xxxxxxxxxx \
--session-lifetime-in-minutes 600 \
--user-arn arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightAdminforAzureAD/quicksight-admin02@test.com \
--experience-configuration Dashboard={InitialDashboardId=97acc558-1bfc-4e39-93cd-5aca9153fab0}
```



実行できました！

```
> aws quicksight generate-embed-url-for-registered-user \
      --aws-account-id xxxxxxxxxx \
      --session-lifetime-in-minutes 600 \
      --user-arn arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightAdminforAzureAD/quicksight-admin02@test.com \
      --experience-configuration Dashboard={InitialDashboardId=97acc558-1bfc-4e39-93cd-5aca9153fab0}
{
    "Status": 200,
    "EmbedUrl": "https://ap-northeast-1.quicksight.aws.amazon.com/embed/b3d6694926dd4ad192deda99517d6bc5/dashboards/97acc558-1bfc-4e39-93cd-5aca9153fab0?code=AYABeO6cqoTatGMvowe3r89M_LAAAAABAAdhd3Mta21zAFBhcm46YXdzOmttczphcC1ub3J0aGVhc3QtMTozNjcwOTQ1NjE4OTQ6a2V5LzkyZDU3MjEzLTc0MjItNGNhOC1iYWZiLTg2MDFjNGZkODgyNwC4AQIBAHh19lpIdHJLvWmpW7433A8711o_o_2vfnBuxyXbJJdfkwGU8ccG1iWcqMHxPdoQWanpAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMqCqaep7O5drqhi8FAgEQgDtTDy6bUnkaVF-okLxOfedpETamJpLePVHmBgdabLR6GzYBibdclcvgH6JjItmlz8wNbi7BTUF3u1cRLgIAAAAADAAAEAAAAAAAAAAAAAAAAACxTvax12WQkU-i1_cJP9bx_____wAAAAEAAAAAAAAAAAAAAAEAAADqe3RCSmWdR-hM8qm9V3dg0EoC_HcGhSRkN9yS5shFNjG5NviqAa6TLRAFNJE1BUe7f8A0hChXRvFYxi_x3a7QwQoNVl1BFv9ZgJtp2odGF3hiAu9167FlGViSoYhfC3vU5zrj_FTzK6KfCPgs_6Mi6LkMDhtKM_g8HCkXsrkiJxA8N5NPYNOV6sAHx6gZ3UI_gT8LIxxPOG78vvRSy75m0QNuoFt7FDr6zDExq5fw-t-6BZvHqyTbcIzjfMiqIbV6K1CkvrNdbZD2w6bLl9VtchB798byeJ6fkQ7W7Q1GKG6FWddxyvuF-grpukl6B_Ccc8k631Rk50K8Jg%3D%3D&identityprovider=quicksight&isauthcode=true",
    "RequestId": "881e4d80-89f1-43b1-b7d4-38c604c67881"
}
```



実際にアクセスしてみると、表示できました。

![image-20220102205530678.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/77229cd0-12de-bb55-d923-e78235e8eb49.png)



# 余談 : 古い APIの場合

ダッシュボードの埋込 URL を生成する古い API を調査してわかったことがあるので、備忘録として載せておきます。



Identity-type `IAM` で Dashboard URL を取得可能。AWS CLI そのものの権限が利用される。

```
aws quicksight get-dashboard-embed-url \
--aws-account-id xxxxxxxxxx \
--dashboard-id 0849cdf6-0b4b-46c1-9a0d-59a084bd0bb8 \
--identity-type IAM \
--session-lifetime-in-minutes 15
```



Identity-type `IAM` だと、user-arn を指定できない。

```
aws quicksight get-dashboard-embed-url \
--aws-account-id xxxxxxxxxx \
--dashboard-id 0849cdf6-0b4b-46c1-9a0d-59a084bd0bb8 \
--identity-type IAM \
--session-lifetime-in-minutes 15 \
--user-arn "arn:aws:quicksight:ap-northeast-1:xxxxxxxxxx:user/default/QuickSightAdminforAzureAD/quicksight-admin01@test.com"
```

エラーメッセージ

```
An error occurred (InvalidParameterValueException) when calling the GetDashboardEmbedUrl operation: Parameter UserArn is invalid for dashboard embedding for IdentityType: IAM.
```



Identity-type `QUICKSIGHT` だと、`user-arn` で QuickSight 上のユーザーを指定可能。IAM フェデレーション環境で登録したユーザーは、Identity-type `IAM`になるが、それを無視してIdentity-type `QUICKSIGHT` で発行できた。

ただ、ここまでやるくらいなら新しい API を使うのが楽だと思う。また、どうしてもふるい API を利用する場合は、STS の AssumeRole で生成したいユーザーにスイッチしたうえで、`get-dashboard-embed-url` を実行するのが良いとおもう。



# 参考URL

https://docs.aws.amazon.com/ja_jp/quicksight/latest/user/embedded-analytics.html

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

https://d1.awsstatic.com/webinars/jp/pdf/services/20201117_Blackbelt_Amazon_QuickSight_for_ISV_A.pdf

https://dev.classmethod.jp/articles/quicksight-embed-example/

https://github.com/awsdocs/amazon-quicksight-user-guide/blob/main/doc_source/embedded-dashboards-setup.md