Tableau Cloudの埋め込みビューに対するJWTを用いたSSOの手法

はじめに

どうも!ecbeing20年目のYです。

今回はTableau Cloudの埋め込みビューに対してSSOするために、2022年1月に実装された連携アプリの機能を利用して実装してみました。 その手法をご紹介します。

◆(参考) Tableau Cloud ヘルプ - 直接信頼を使用して接続済みアプリを構成する https://help.tableau.com/current/online/ja-jp/connected_apps_direct.htm

概要

・Tableau Cloudの埋め込みビューに対してSSOしたい!

・SAML認証のIdP立てるのは工数がかかってしまう。しかし借りるとランニングが…。そうだ!連携アプリで解決しよう!

・JWT発行するにはPythonかJavaのサンプルコードが公式ヘルプに載っていた。今回はPythonで実装!

・環境依存したくないのでGAE上にデプロイ!AjaxでJWT取得してSSOを実現!

・JWTとはなんぞやという方は下記の記事を参考にしてください!

◆JWTの基本のキ https://blog.ecbeing.tech/entry/2024/12/25/080000

Tableau Onlineにて連携アプリの設定

・設定→連携アプリ→新しい連携アプリへアクセス

・連携アプリの設定。ドメインを指定する場合は後述のGAEのホストを指定。

・シークレットID、シークレット値(Key)の払い出し

・クライアントID、シークレットID、シークレット値(Key)の保存。  後ほどapp.yaml、seacret.yamlの設定に使用。

・作成した連携アプリの有効化

JWTを払い出すためのコードを作成

・下記5ファイルを"jwt"ディレクトリ上に作成

main.py

from flask import Flask
from flask_cors import CORS
import jwt
import datetime
import uuid
import os

token = jwt.encode(
{
'iss': os.getenv('connectedAppClientId'),
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=5),
'jti': str(uuid.uuid4()),
'aud': 'tableau',
'sub': os.getenv('connectedAuthMailAddress'),
'scp': ['tableau:views:embed']
},
os.getenv('connectedAppSecretKey'),
algorithm = 'HS256',
headers = {
'kid': os.getenv('connectedAppSecretId'),
'iss': os.getenv('connectedAppClientId')
}
)

app = Flask(__name__)
CORS(app)

@app.route('/')
def jwt():
   return token

requirements.txt

pyjwt==2.6.0
flask==2.1.0
Flask-Cors==3.0.10

app.yaml

runtime: python311
service: jwt

env_variables:
  connectedAppClientId: "【★クライアントID★】"
  connectedAppSecretId: "【★シークレットID★】"
  connectedAuthMailAddress: "【★該当PRJに権限を持ったTableau Cloud上に登録済みのメールアドレス★】"

includes:
- secret.yaml

secret.yaml

env_variables:
  connectedAppSecretKey: "【★シークレット値(Key)★】"

.gcloudignore(追記)

secret.yaml

GCPの作成

①Googleアカウントを取得する

 https://accounts.google.com/signup/v2/webcreateaccount?flowEntry=SignUp

②GCPのコンソールへアクセス

 https://console.cloud.google.com/

③新しいプロジェクトを作成

GAEへのデプロイ

①Cloud SDKのインストール

 https://cloud.google.com/sdk/

②コマンドプロンプトを起動

③gcloud initコマンドの実行

 Googleへのログイン確認メッセージが出力されるため「Y」を入力。(WEBブラウザが開く)

 あらかじめGCPにて権限付与が済んでいるアカウントでGoogleログインを行う。

 Cloud SDK のリクエストを許可する。

④プロジェクトIDの選択

 使用するGoogle Cloud PlatformのプロジェクトIDを選択する。

⑤Google App Engineへのデプロイ

・CD [Path]コマンド用いてWEBアプリケーションのルートディレクトリ(ソースファイル一式の「jwt\app.yaml」が配置されているディレクトリ)へ移動する。

・以下のコマンドを実行してデプロイ作業を開始する。

  gcloud app deploy

・デプロイの最終確認メッセージが出力されるため「Y」を入力する。

⑥App Engineのサービス画面へ遷移する。

 https://console.cloud.google.com/appengine/services

⑦サービスの「jwt」部分のリンクからURLを取得する。

 https://jwt-dot-[プロジェクトID].[リージョンコード].r.appspot.com/

 アクセスするとJWT(Json Web Token)が表示される。

埋め込みビューの準備

・SSO対象のダッシュボードまで移動し、共有を選択。

・埋め込みコードのコピーを選択。

埋め込みコードのコピー例

<script type='module' src='https://us-east-1.online.tableau.com/javascripts/api/tableau.embedding.3.latest.min.js'></script>
<tableau-viz id='tableau-viz' src='【ダッシュボードURL】' width='1757' height='1111' toolbar='bottom' ></tableau-viz>

上記のtableau-vizの引数としてtoken=でJWTを渡せばSSOできる。

SSO呼び出し元ファイルの作成

・今回はHTMLファイルにて実装。

・JavaScript経由でAjax通信を行い、main.pyを呼び出してJWTを取得。

・応答が返ってきたら埋め込みビュー用のScriptを呼び出してtokenを渡しSSOを実現。

sample.html

<html>
<head></head>
<body>
<script type="module" src="https://us-east-1.online.tableau.com/javascripts/api/tableau.embedding.3.latest.min.js"></script>
<div id="tableau"></div>
  <script>
    var tableaudiv = document.getElementById("tableau");
    var jwt = new XMLHttpRequest();
    jwt.onreadystatechange=function(){
      if(jwt.readyState==4){
        tableaudiv.innerHTML = '\
          <tableau-viz id="tableau-viz"\
          src="【埋め込みビューのURL】"\
          token="' + jwt.responseText + '"\
          width="1760" height="1111" toolbar="bottom" >\
          </tableau-viz>\
        ';
      }
    }
    jwt.open('GET','https://jwt-dot-[プロジェクトID].[リージョンコード].r.appspot.com/');
    jwt.send();
</script>
</body>
</html>

まとめ

・SAML使うよりも簡単にSSOを実現することができる。

・IdPのランニングコストも生じないのでリーズナブルな運用が可能。

・secretkeyが抜かれないように、git上にuploadしないよう注意。 (.gcloudignoreで制御)

お知らせ

ecbeingでは新進気鋭なエンジニアを募集しております!
careers.ecbeing.tech