こんにちは、アプリケーション基盤チームの池添(@zoetro)です。 2016年9月に中途入社し、Necoプロジェクト(アーキテクチャ刷新プロジェクト)において新しいログ基盤の構築を進めています。 その一環でRedashの導入もおこなっています。
新しいツールやサービスを導入するときに気になるのが認証の仕組みです。 社内ではいろいろなツールやサービスを活用していますが、それぞれにアカウントをつくるのは大変なので、やはりシングルサインオン(SSO)したいですよね。
Redash v0.11のドキュメントを見るとSAML認証について記載されていました。 さっそくSAML認証の設定をし始めたわけですが、どうにもうまくいきません。
そこで、SAML認証ができるまで - Cybozu Inside Out | サイボウズエンジニアのブログを読み、RedashやOpenAMのソースを調査し、SAMLの仕様書とにらめっこしながら、なんとか認証できるようになったので、その過程を紹介したいと思います。
なお、IdP(Identity Provider)としてはOpenAMとAD FSで動作確認しています。
ちなみにRe:dashはv1.0からRedashという名前に変わるみたいですね。
TL;DR
- RedashでSAML認証をやってみた
- v0.11では問題があってうまく認証できなかった
- 問題を修正してPRを投げたらv0.12で取り込まれた
Redash v0.11でSAML認証が使えるようになるまで
SAML認証の有効化
まず、Redash v0.11においてSAML認証を有効にするためには.env
ファイル(Redashの設定ファイル)にREDASH_SAML_METADATA_URL
の設定を追加します。
REDASH_SAML_METADATA_URL
にはIdPのメタデータを返すURLを指定します。
たとえば、OpenAMならhttp://Your_Domain_Name/openam/saml2/jsp/exportmetadata.jsp
、AD FSならhttps://Your_Domain_Name/FederationMetadata/2007-06/FederationMetadata.xml
のようになります。
この設定をしてRedashを起動すると、下図のように通常のログインフォームの上に SAML Login
というリンクが表示されるようになります。
認証要求が通らない
さっそくSAML Login
のリンクをクリックしてみましょう。
しかし、認証に失敗します。
OpenAMのログを確認してみると"The name identifier is missing or an empty string"
というエラーメッセージが出力されていました。
OpenAMでは、認証要求メッセージ(AuthnRequest)のIssuer
が空になっていてはいけないのですが、Redashではここに何も指定していませんでした。
この件に関してはPRを投げて、Redash v0.12で取り込まれました。
.env
ファイルにREDASH_SAML_ENTITY_ID
という項目を追加し、SP(Service Provider: ここではRedashのこと)を一意に表す文字列を指定すればOKです。一般的にはSPの実際のURLを指定することが推奨されているようです。
アカウントの表示名がつくれない
再度SAML Login
のリンクをクリックしてみますが、今度はRedash内でエラーが発生しました。
Redashでは、認証応答メッセージ(Response)のSAMLアサーションの属性ステートメント(AttributeStatement)に、"FirstName"
と"LastName"
が含まれていることを期待しているようです。
Redashのドキュメントにも書いてありますね。
RedashのアカウントにはNameとEmailという項目がありますが、"FirstName"
と"LastName"
を結合した名前がNameとして使われます。
また、認証応答メッセージのNameId
がEmailとして使われます。
この属性ステートメントはIdPで設定することができるので追加してあげましょう。設定方法はそれぞれのIdPのドキュメントなどを確認してください。
なおこの件に関して、属性ステートメントに"FirstName"
と"LastName"
が含まれなかった場合は、認証応答メッセージのNameId
を使うというPRを投げてみたのですが、残念ながら採用されませんでした。
おとなしくIdPでの設定をおこなうこととしましょう。
アカウント無限増殖
さて、ここまでの設定でめでたく認証は通るようになりましたが、認証が成功するたびにRedash上のアカウントが増えるという問題が発生していました。
Redashではpysaml2というライブラリを使っているのですが、このライブラリはデフォルトのNameIDFormatとしてurn:oasis:names:tc:SAML:2.0:nameid-format:transient
を使うようになっています。
このフォーマットを指定した場合、認証応答メッセージのNameId
として毎回異なるIDが発行されます。
Redashではこの発行されたIDをアカウントを一意に識別するために使っており、アカウントが存在しなければ新規にアカウントを作成するという動きになっています。
この状態は困るので、PRを投げてNameIDFormatに任意の値を指定できるようにしました。これもv0.12で取り込まれています。
.env
ファイルのREDASH_SAML_NAMEID_FORMAT
にurn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
などを指定しておきましょう。
イントラ内のIdPが使えない
最初にSAML認証を有効にするためにREDASH_SAML_METADATA_URL
を設定するという説明をしました。
RedashはこのREDASH_SAML_METADATA_URL
にHTTPリクエストを投げてIdPメタデータを取得するようになっています。
つまりRedash(SP)からIdPに直接アクセスできなければならないということになります。 しかし、IdPがイントラ内に設置されているためSPから直接アクセスできないというケースもよくあるのではないでしょうか。
そこで、メタデータをIdPから直接取得するのではなく、ファイルから読み込む機能を実装しPRを投げました。これもv0.12から使えるようになっています。
IdPからメタデータファイルをエクスポートしてRedashをデプロイしているホストに配置し、そのファイルのパスを.env
ファイルのREDASH_SAML_LOCAL_METADATA_PATH
で指定します。
なお、この項目はREDASH_SAML_METADATA_URL
と併用することはできないので、どちらか一方だけを設定するようにしてください。
Redash v0.12のSAML関連設定まとめ
Redash v0.12におけるSAML関連の設定項目を以下の表にまとめました。
REDASH_SAML_METADATA_URL
またはREDASH_SAML_LOCAL_METADATA_PATH
のどちらかを設定することでSAML認証が有効になります。それ以外の項目はオプショナルになっています。
環境変数名 | 説明 |
---|---|
REDASH_SAML_METADATA_URL | IdPメタデータを取得できるURLを指定します。REDASH_SAML_LOCAL_METADATA_PATH と同時に指定することはできません。 |
REDASH_SAML_LOCAL_METADATA_PATH | IdPメタデータファイルのパスを指定します。REDASH_SAML_METADATA_URL と同時に指定することはできません。 |
REDASH_SAML_ENTITY_ID | [オプショナル] SPを一意に表す文字列を指定します。OpenAMを利用する場合は必須です。 |
REDASH_SAML_NAMEID_FORMAT | [オプショナル] NameIDFormatを指定します。デフォルトでは urn:oasis:names:tc:SAML:2.0:nameid-format:transient になります。 |
REDASH_SAML_CALLBACK_SERVER_NAME | [オプショナル] IdPからコールバックされるRedashのホスト名を指定します。 |
また、認証応答メッセージのSAMLアサーションの属性ステートメントに設定する項目を以下の表にまとめました。
属性名 | 説明 |
---|---|
FirstName | [必須項目] Redash上のアカウントの表示名として利用されます。 |
LastName | [必須項目] Redash上のアカウントの表示名として利用されます。 |
RedashGroups | [オプショナル] Redash上のアカウントが所属するグループ名を指定することができます。 |
まとめ
RedashでSAML認証を使えるようになるまでの顛末を紹介しました。
Redash v0.12ではOpenAMやAD FSでSAML認証ができるようになっているかと思います。 しかし、限定的な条件でしか動作確認していないので、もし問題などが見つかったらご指摘いただけるとうれしいです。
サイボウズではログ基盤構築に興味のあるエンジニアを募集しています!