ハロー世界。りくとんです。みんな元気にSSOしてますか?(挨拶)
この記事はTableau Onlineの埋め込みビューに対してSSOするために、2022年1月に実装された連携アプリの機能を利用して実装した記事です。
一応(あんま役に立たない)公式ヘルプ載せときますね。
◆Tableau Cloud ヘルプ - 直接信頼を使用して接続済みアプリを構成する
https://help.tableau.com/current/online/ja-jp/connected_apps_direct.htm
概要
・Tableau Onlineの埋め込みビューに対してSSO。
・SAML認証のIdP立てるのだるいし借りるとランニングが…。→連携アプリで解決。
・JWT発行するにはPythonかJavaのサンプルコードが載ってた。今回はPythonで実装。
・環境依存したくないからGAE上にデプロイしよう。AjaxでJWT取得してSSO。
・JWTとはなんぞやという知識は先人のQiitaを参考にしてください。
◆Qiita - 認証におけるJWTの利用について
https://qiita.com/shnmorimoto/items/a38690929d7d84bbdea6
Tableau OnlineにおけるJWTを利用したSSO相関図
Tableau Onlineにて連携アプリの設定
・設定→連携アプリ→新しい連携アプリへアクセス
・連携アプリの設定。ドメインを指定する場合は後述のGAEのホストを指定。
・シークレットID、シークレット値(Key)の払い出し
・クライアントID、シークレットID、シークレット値(Key)の保存。
後ほどapp.yaml、seacret.yamlの設定に使用。
・作成した連携アプリの有効化
JWTを払い出すためのコードを作成
・下記5ファイルを"jwt"ディレクトリ上に作成
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
pyjwt==2.6.0
flask==2.1.0
Flask-Cors==3.0.10
runtime: python311
service: jwt
env_variables:
connectedAppClientId: "【★クライアントID★】"
connectedAppSecretId: "【★シークレットID★】"
connectedAuthMailAddress: "【★該当PRJに権限を持ったTableau Online上に登録済みのメールアドレス★】"
includes:
- secret.yaml
env_variables:
connectedAppSecretKey: "【★シークレット値(Key)★】"
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を実現。
<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のランニングコストも生じないのでリーズナブル。
・seacretkey抜かれると終わるのでgit上にuploadしないよう注意。
(.gcloudignoreで制御)
・比較的新しい機能なので文献無さすぎてキレてた。ので記事書いた。