Ubuntu

DiscourseをSAML認証で使えるようにする

先日、前々から実装してみたかったSSOにトライして、それがSPNEGO認証だったと理解し、環境ができたからじゃあDiscourseでSSOしてみるか…と思ったら、認証用のプログラムを書いて、それを動かすRuby on Rails(?)の専用の環境を作る必要があるっぽい。



広告


興味はちょっとだけあるけど今じゃない感じなので、別の方向を探ってみたらSAML認証もあるらしい。
SAMLといえば…他にも使い道があるはず!と思って挑戦することを決意。

しかし、注意書きを見ながら長い旅になりそうだと思った。
Github / discourse / discourse-saml

結果的にできあがったのは、Discourseにアクセスするだけで自動的に(なければユーザーが作られて)ログインする仕組み。ドメインに参加しているPC限定だけど、かなり便利。
ドメインに参加していないPCからもIDとパスワードを入力すればログイン可能(ちょっとだけ難ありだけど)、Android端末からも同様にログイン可能、まぁまぁ問題なく運用はできそうだ。

やること。

環境

https://temp.hogeserver.hogeddns.jp としてDiscourseを設定済み(ApacheでProxy)。ここに、
https://temp.hogeserver.hogeddns.jp:8443 としてKeycloakを構築していく。

ホスト名用途備考
temp.hogeserver.hogeddns.jp今回の構築対象。keycloak 10.0.2(Docker版)
discourse 2.6.0.beta1
Apache2 2.4.29-1ubuntu4.1
addc.hogeserver.hogeddns.jpSamba ad dcを運用中。
Kerberos認証、LDAP(S)サービスを提供。
Realmを管理
HOGESERVER.HOGEDDNS.JP

認証サーバーをインストール

認証サーバーとしてKeycloakに挑戦してみようかと。後々色々活用できそうな予感満点。

Keycloakのインストール

いつもの通りがっつりインストール…とも考えたんだけれど、ソースからコンパイルする形になっていて目的達成に時間が掛かりそう。
KEYCLOAK / Downloads
Medium / Setup Keycloak Server on Ubuntu 18.04

DiscourseがDockerで動いているので、これもDockerで動かしてみようかと考えた。
KEYCLOAK / Keycloak on Docker

Dockerイメージのインストール

コマンド一発。初期ユーザーとしてuser:admin / password:admin を指定。
確かに楽だけど、どこに何があるのかサパーリ分からん。

$ sudo docker run -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:10.0.2
Unable to find image 'quay.io/keycloak/keycloak:10.0.2' locally
10.0.2: Pulling from keycloak/keycloak
…
00:52:40,699 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990
00:52:40,700 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Keycloak 10.0.2 (WildFly Core 11.1.1.Final) started in 34814ms - Started 689 of 994 services (708 services are lazy, passive or on-demand)

※この日のバージョンは10.0.2だった。マニュアルページは自動でバージョン表記が変わるんだろうか。

これで動作するんだけれど、コマンドが動いたまま…んー。
バックグラウンドで動作させるためには -d オプションが必要とのこと。
ThinkIT / Dockerコンテナの起動と廃棄

なので、しばらくこのままにしてブラウザでアクセスしてみる。

アクセステスト

ブラウザでアクセスしてみる。
http://temp.hogeserver.hogeddns.jp:8080

アクセスしたら、勝手にhttp→httpsにリダイレクトされてエラー。以下でどうにか解決。
かもメモ / Google Chrome 勝手にhttpsにリダイレクトされるにハマる

調べていると 「chrome://net-internals/#hsts」にアクセスして、Delete domain security policiesで該当ドメインを削除する

かもメモ

かっこいいなこれ。

Administration Consoleから入って、admin / adminでログインしてさらっと色々と回ってみた。洗練されたデザインでいい感じ。

ここで一旦コマンドプロンプトで [Ctrl]+[c] を押して止めてみた。
Dockerも止まった。

自動起動設定

Dockerイメージをインストールすると、それを再生するためのコンテナが作られているはずだ。
どんな名前で登録されているのか確認してみる。

$ sudo docker ps -a
CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS                      PORTS               NAMES
41bf393541e4        quay.io/keycloak/keycloak:10.0.2   "/opt/jboss/tools/do…"   58 minutes ago      Exited (0) 17 seconds ago                       hoge_hoge
d19edf550884        local_discourse/app                "/sbin/boot"             6 days ago          Up 4 hours                                      app

※この環境ではDiscourseが動いている。

名前が違っていて起動しにくいので、名前を変えてしまう。

$ sudo docker rename hoge_hoge keycloak

※この名前、インストールするたびにランダムに変わることが分かった。

自動起動するように設定。

$ sudo docker update --restart=always keycloak

これで再起動してみた。よし、自動で起動してくる、行けそうだ。

通信の保護(SSL)

Discourse用にオレオレなサーバー証明書を用意しているので、通信を保護しようと考えた。公式はJavaのkeystoreを作成する方法を説明している。
Keycloak Documentation / Version 10.0.2 / Server Installation and Configuration Guide

ApacheのProxy設定

Apacheで8443にProxyする。ファイルは新しいものを作ってもいいし、既存のものに追記してもいいと思う。今回は既存のものに追記。

/etc/apache2/sites-available/temp.hogeserver.hogeddns.jp.conf

Listen 8443
…
<VirtualHost *:8443>
    ServerName temp.hogeserver.hogeddns.jp
    ServerAdmin webmaster@hogeserver.hogeddns.jp

    ErrorLog  ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLProxyEngine on
    ProxyPreserveHost on
    RemoteIPHeader X-Forwarded-For
    RequestHeader set X-Forwarded-Proto "https"
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/

    SSLEngine on
    SSLCertificateFile    /etc/ssl/private/temp.crt
    SSLCertificateKeyFile /etc/ssl/private/temp.key
</VirtualHost>

Proxy設定はDiscourseで使ったものを流用。
証明書はオレオレ認証局で署名したもの。

設定を有効化する。

$ sudo systemctl reload apache2

この環境ではDiscourseをProxyする際に必要なモジュールを有効化済み。
reloadでエラーが出たら、必要モジュールをa2enmodで追加していく

Dockerの環境変数を変更

KeyCloakがProxサーバーを通じたアクセスを許容するためには、Javaアプレット(?)の設定変更が必要。

設定は環境変数が反映されるようになっているので、環境変数をどこかで設定しなければ…
これのやり方がなかなか分からなかった~。
hawksnowlog / 一度 run したコンテナを削除せずに環境変数を設定する方法

環境変数は
/var/lib/docker/containers/<41bf393541e4・・・・・>/config.v2.json
にある。

赤文字部分は、docker ps -a で先頭が一致するディレクトリで物凄く長ーいものだった。
また、rootでないとアクセスできなかった。

ファイルの中身は1行で書かれている。以下を修正。

…BACKGROUND=1","PROXY_ADDRESS_FORWARDING=true","JBOSS_HOME=…

変更したら、Dockerサービスを再起動する。

# systemctl restart docker

 

アクセステスト

Proxy動作し始めたので、以下でアクセス。
https://temp.hogeserver.hogeddns.jp:8443

問題なくアクセスができ、先に進むことができそうだ。

Keycloakの統合Windows認証設定

Keycloakには最初にMasterというRealmがあって、これがKeycloak管理用。
各種サービスに接続するユーザー達は別のRealmを追加して管理していく。

統合Windows認証は、過去記事で実施できるようになっている
(必要なものはそろっていて、サービスが正常に稼働している)

そこでまず、統合Windows認証で自動的にログインできる設定にしてみる。
Qiita / Keycloakで統合Windows認証を試してみる

Realmの追加

Keycloakにadminでログインし、Realmを追加する。
Masterと書かれているあたりをマウスでポイントすると、Add realmボタンが表示される。

※Realm wordpressを追加後に取ったキャプチャなのはご愛敬。

discourseという名前のRealmを追加する。

User Federationの追加

フェデレーションってのは、認証を連携する仕組みとのこと。
Kerberos連携の設定を追加する。

サイドメニューのUser Federationをクリックし、LDAPを選択して設定を入れていく。
途中でKerberos認証の設定も入れる感じ。
※必要な項目だけを以下で説明。

項目設定値備考
プロバイダーID14nnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn作成時に生成され、変更できない。
有効オン
コンソール表示名ldapわかりやすい名前で問題ない。
優先度0
ユーザーのインポートオフSamba ad dc等の認証サーバーの負荷を軽減するにはオンが良いかも。
編集モードREAD_ONLY
登録の同期オフ
ベンダーActive Directory作成時に指定。変更できない。
ユーザー名の LDAP 属性sAMAccountName
RDN LDAP 属性cn
UUID LDAP 属性objectGUID
ユーザーオブジェクトクラスperson, organizationalPerson, userカスタムユーザーLDAPフィルターと合わせて利用者を限定できそう。
接続 URLldap://addc.hogeserver.hogeddns.jpLDAPサーバーとしても動作するSamba AD DCサーバーを指定。LDAPSで接続するためには証明書を仕込んでおく必要があり、将来の課題とする。
接続テストもしておくと安心。
ユーザー DNCN=Users,DC=hogeserver,DC=hogeddns,DC=jpユーザーが含まれる場所。Windows Serverの場合にはきっと違う値。
バインドタイプsimpleLDAPサーバーの設定に合わせる。
StartTLS の有効オフLDAPサーバーの設定に合わせる。
Bind DNadministrator@hogeserver.hogeddns.jp問い合わせのためのアカウントを指定。administratorである必要はないはず、適切なアカウントで。
Bind のクレデンシャルBind DNに指定したユーザーのパスワード認証テストをしておくと安心。
カスタムユーザー LDAP フィルタユーザーオブジェクトクラスと併せて利用者を限定できそう。
検索スコープOne LevelSamba ad dcではouをサポートしていないので、Userのところから情報を取り出す。ここは1階層なので、One Level。
パスワードポリシーの検証オフ
Eメールを信頼オフ
トラストストア SPI を使用Only for ldaps
接続プーリングオン※機能の想像がつかない
接続タイムアウト未指定
読み取りタイムアウト未指定
ページネーションオン※機能の想像がつかない
Kerberos 認証を許可オン
Kerberos RealmHOGESERVER.HOGEDDNS.JPSamba AD DCが管理するRealm。
Server PrincipalHOST/temp.hogeserver.hogeddns.jp@HOGESERVER.HOGEDDNS.JP一般にはHTTP/~というのが多いと思う。過去記事で利用したライブラリの関係でHOSTになっている。
KeyTab/opt/jboss/keycloak/standalone/configuration/temp.keytab後でコンテナの中にファイルを持ち込む。
デバッグオフ
パスワード認証に Kerberos を使用オン
バッチサイズ1000※機能の想像がつかない
定期的なフル同期オフユーザーをインポートしないので無意味。
定期的な変更ユーザーの同期オフユーザーをインポートしないので無意味。
キャッシュポリシーDEFAULT

設定を保存する。

続いて、マッパーの確認。これらがユーザー情報としてLDAP+Kerberosから取り出されるんだと思う。
DiscourseのSAMLで要求されるのは、
username, email, firstName, lastName位かなと思われ、これらは自動生成されていると思われるが、念のためメモ。

項目設定値備考
名前usernameログインアカウントになる。
マッパータイプuser-attribute-ldap-mapper
User Model Attributeusername
LDAP AttributesAMAccountName
Read Onlyオン
Is Mandatory In LDAPオン
Is Binary Attributeオフ
項目設定値備考
名前emailアカウントに関連付けられた連絡先になる。
マッパータイプuser-attribute-ldap-mapper
User Model Attributeemail
LDAP Attributemail
Read Onlyオン
Is Mandatory In LDAPオフ
Is Binary Attributeオフ
項目設定値備考
名前first name
マッパータイプuser-attribute-ldap-mapper
User Model AttributefirstName
LDAP AttributegivenName
Read Onlyオン
Is Mandatory In LDAPオフ
Is Binary Attributeオフ
項目設定値備考
名前last name
マッパータイプuser-attribute-ldap-mapper
User Model AttributelastName
LDAP Attributesn
Read Onlyオン
Is Mandatory In LDAPオン
Is Binary Attributeオフ

keytabをコンテナの中に設置

Dockerのコンテナと特定のディレクトリやファイルを共有する方法はあると思うが、それに取り組む時間はないので後回し。

使用可能なkeytabをコンテナの中に放り込む。
keytabはここで作成したものを利用する。
このタイミングで使用したApcheのライブラリの都合(多分…)で、サービスプリンシパルの先頭がHTTPではなくHOSTになっている。名前は問題ではなく、利用までの理屈が整っていれば問題はないみたい。

場所は /opt/jboss/keycloak/standalone/configuration が良さそう。
(参照先サイトがここを使っていて、実際に中を見る限りここは適切だと思う)

# docker cp /etc/apache2/keytab/temp.keytab keycloak:/opt/jboss/keycloak/standalone/configuration

コピーしたkeytabのアクセス権を変更する。

# docker exec -u 0 -it keycloak /bin/bash --login
[root@41bf393541e4 /]# chown jboss:root /opt/jboss/keycloak/standalone/configuration/temp.keytab
[root@41bf393541e4 /]# chmod 660 /opt/jboss/keycloak/standalone/configuration/temp.keytab

アクセステスト

ドメインに参加したPCからアクセスし、SSOできることを確認する。

アクセス先となるURLはサイドメニューのクライアントをクリックし、クライアント ID が account の行にあるベース URL。
具体的には以下。
https://temp.hogeserver.hogeddns.jp:8443/auth/realms/discourse/account

SSOできなければログイン画面が、SSOできればログイン後のユーザー作成画面に遷移する。

これで、WindowsからkeycloakのRealm:KerberosにSSOできるようになった。

Discourseの設定

この設定で、Discourseは起動しなくなるが、後々設定を加えて動作させていく。

SAMLと自動ログインのプラグインを追加

この環境では、/opt/discourse にインストールしているので、標準の手順とは違った場所にファイルがある。

/opt/discourse/containers/app.yml

…
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-saml.git
          - git clone https://github.com/clkao/discourse-sso-auto.git

※赤文字部分を追加。プラグインのための環境変数と、プラグイン追加。

SAML認証には以下のプラグイン利用する(最初、ここに書かれている設定内容を見て途方に暮れた)。
一旦、設定は置いといて、プラグインを組み込む。再構築には時間が掛かるのだ。
Github / discourse / discourse-saml

また、SAML認証ができるようになっても自動ログインするわけではなく、with SAMLボタンを押す必要がある。
せっかく統合Windows認証の設定を済ませているのだから、勝手にログインしてもらいたい。
Github / clkao / discourse-sso-auto

プラグインを追加するので、再構築する。このコマンドは時間が掛かる。

$ sudo /opt/discourse/launcher rebuild app

自動ログイン的なプラグインはもう1つ見つかったけれど、管理メニューから設定を止められるようなので discourse-sso-auto を選択した。
見つけたもう1つのプラグインはこちら。
Github / procourse / discourse-saml-auto-login-plugin

KeycloakとDiscourseのSAML設定

DiscourseのSAMLはIdP開始のシナリオで動作するとのことで、Github?の設定をチラチラと見ながら設定を進めた。
IdP開始とはいっても、Keycloakに「クライアント」を追加して連携させるのね…(これが分からずかなり迷走した)。

Keycloakへのクライアント追加

Discourseとの通信について設定する。

なお、:8443(Keycloak自体)は設定値としては登場しない。
よく分からなくて色々と試行錯誤したが、基本的には「相手」と「通信内容」の定義をするから。

項目設定値備考
クライアント IDhttps://temp.hogeserver.hogeddns.jpDiscourseのSAMLプラグインからClient IDとして送られてくる。
クライアントプロトコルsaml
クライアント SAML エンドポイントhttps://temp.hogeserver.hogeddns.jp/auth/saml/callbackSAML を処理するマスター URLに反映される。

一旦これで作成し、その後に詳細項目を設定していく。現在動作している設定を記す。
もっとセキュリティを強化したり、もっと効率を高めたり、いらない設定を排除したり…とやれることはありそうな気がするが、とりあえず「署名が必要」を設定しているので、いくらかマシかなと思われる。

項目設定値備考
クライアント IDhttps://temp.hogeserver.hogeddns.jp最初に設定した値が反映されている。
名前Discourse使われている形跡が見当たらない。
説明未設定
有効オン
同意が必要オフ
ログインテーマ未設定
クライアントプロトコルsamp最初に設定した値が反映されている。
AuthnStatement を含めるオン
OneTimeUse 条件を含めるオフ
ドキュメントを署名するオン
REDIRECT 署名鍵検索の最適化オフ
アサーションを署名する オン
署名アルゴリズムRSA_SHA256
SAML署名鍵名KEY_ID
正規化方式EXCLUSIVE
アサーションを暗号化するオフ
クライアント署名が必須オン
POST Binding を強制オン
フロントチャンネルログアウトオン
Name ID フォーマットを強制オン
Name ID フォーマットemail
ルート URLhttps://temp.hogeserver.hogeddns.jp
有効なリダイレクト URI https://temp.hogeserver.hogeddns.jp/auth/saml/callback
ベース URL未指定
SAML を処理するマスター URLhttps://temp.hogeserver.hogeddns.jp/auth/saml/callback
IDP Initiated SSO の URL NameloginIdP開始SSOのURLはこうなる。
https://temp.hogeserver.hogeddns.jp:8443/auth/realms/discourse/protocol/saml/clients/login
これが[DISCOURSE_SAML_TARGET_URL]で設定するURL。
IDP Initiated SSO の RelayState未指定
アサーションコンシューマサービスの POST Binding URLhttps://temp.hogeserver.hogeddns.jp/auth/saml/callback
アサーションコンシューマサービスの Redirect Binding URLhttps://temp.hogeserver.hogeddns.jp/auth/saml/callback
ログアウトサービスの POST Binding URL 未指定
ログアウトサービスの POST Binding URL 未指定
Assertion Lifespan未指定
ブラウザーフロー未指定

クライアントにマッパーを追加

KeycloakがSSOの通信でDiscourseに伝えたいものは、マッパーで定義できた。

ユーザーフェデレーションのマッパーでLDAP+Kerberosから取り出した情報を、クライアントマッパーで渡してあげるイメージのようだ。

DiscourseのSAMLプラグインはemailとusername、firstName、lastNameを要求する。
name(表示名で、フルネームを想定しているらしい)は、firstName + ” ” + lastNameで生成される。

emailとusernameはデフォルトで渡されるので、firstNameとlastNameを追加する。
名前を日本語で管理している場合の設定は後述

firstNameを渡すマッパーの作成

項目設定値備考
プロトコルsaml自動設定、変更不可。
IDa90nnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn自動生成、変更不可。
名前first name最初に設定、変更不可。
わかりやすいものを設定。
マッパータイプUser Property最初に選択、変更不可。
プロパティfirstNameユーザーフェデレーションの情報を取ってくる。
Friendly Name未設定
SAML Attribute NamefirstNameこの名前でDiscourseに伝わる模様。これで入れ替える
SAML Attribute Name FormatBasic

lastNameを渡すマッパーの作成

項目設定値備考
プロトコルsaml自動設定、変更不可。
ID1aennnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn自動生成、変更不可。
名前last name最初に設定、変更不可。
わかりやすいものを設定。
マッパータイプUser Property最初に選択、変更不可。
プロパティlastNameユーザーフェデレーションの情報を取ってくる。
Friendly Name未設定
SAML Attribute NamelastNameこの名前でDiscourseに伝わる模様。これで入れ替える
SAML Attribute Name FormatBasic

Discourse向けにSAML通信用の証明書を抜き出す

エンドポイントの情報から証明書を取り出す

レルムの設定にあるエンドポイント情報、「SAML 2.0アイデンティティー・プロバイダー・メタデータ」の情報を表示させる。

この中で<dsig:X509Certificate>で表示される長い文字列をコピーしてきて、作業ディレクトリに保管する。

~/keycloak.pem(名前は何でもOK)

-----BEGIN CERTIFICATE-----
MIICoTCCAYkCBgFzeX7YeTANBgkqhkiG9w0BAQsFADAUMRIwEAYD…
-----END CERTIFICATE-----

※赤文字部分を加えて証明書ファイルにする。

この証明書ファイルは、まるごとDiscourseの[DISCOURSE_SAML_CERT]の設定値になる。

証明書から指紋を取り出す

また、Discourseの[DISCOURSE_SAML_CERT_FINGERPRINT]として設定するため、証明書ファイルからFingerPrintを抽出する。

$ openssl x509 -in ~/keycloak.pem -noout -fingerprint
SHA1 Fingerprint=13:01:33:C8:60:FB:02:AD…

 

Discourseの環境変数を設定

今までに取り出した情報+αでDiscourseのSAMLプラグインのための環境変数を設定を追加していく。
追加する場所は env セッションの中であればどこでも構わない。

/opt/discourse/containers/app.yml

…
env:
…
  ## Saml plugin setting
DISCOURSE_SAML_TARGET_URL: https://temp.hogeserver.hogeddns.jp:8443/auth/realms/discourse/protocol/saml/clients/login
DISCOURSE_SAML_CERT_FINGERPRINT: "13:01:33:C8:60:FB:02:AD:CF:57:69:50:89:BF:5B:27:1F:9A:1E:4E"
DISCOURSE_SAML_CERT: "-----BEGIN CERTIFICATE-----
  MIICoTCCAYkCBgFzeX7YeTANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlkaXNjb3Vyc2U<省略>72kM=
  -----END CERTIFICATE-----"
DISCOURSE_SAML_SP_CERTIFICATE: "-----BEGIN CERTIFICATE-----
  MIICoTCCAYkCBgFzebYZEzANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlkaXNjb3Vyc2U<省略>JExk=
  -----END CERTIFICATE-----"
DISCOURSE_SAML_SP_PRIVATE_KEY: "-----BEGIN RSA PRIVATE KEY-----
  MIIEpAIBAAKCAQEAuYBQkiitiZIxlJLI70WxLoHbr6pSLlQFVTqgrR9JyCR7vvZWZ0riB7M<省略>8RHQ==
  -----END RSA PRIVATE KEY-----"
  DISCOURSE_SAML_AUTHN_REQUESTS_SIGNED: true
  DISCOURSE_SAML_WANT_ASSERTIONS_SIGNED: true
  DISCOURSE_SAML_AUTO_CREATE_ACCOUNT: true
…

※証明書のところは改行が含まれても大丈夫?と気になるところだけれども、問題なし。

④と⑤はKecloakのクライアントID https://temp.hogeserver.hogeddns.jp にあるSAML鍵から取得。
証明書は BEGIN CERTIFICATE ~ END CERTIFICATE
秘密鍵は BEGIN RSA PRIVATE KEY ~ END RSA PRIVATE KEY
で囲んでいる。

その他に、
DISCOURSE_SAML_AUTHN_REQUESTS_SIGNED: true
DISCOURSE_SAML_WANT_ASSERTIONS_SIGNED: true
を設定。
これで、Keycloak側の情報が署名されていることを求める(つもり、実際Keycloak側で署名設定していないとエラーになる)。

最後に、
DISCOURSE_SAML_AUTO_CREATE_ACCOUNT: true
を設定。
これで、初めてアクセスしたユーザーのアカウントが即座に作られる。

既に再構築は済ませており、envを変更しただけなので、コンテナを作り直して環境変数の定義を反映させる。
再構築と比較してだいぶ時間短縮、無駄なイメージも作られない。
Discourse / How to change environment variable after docker has bootstrapped site?

$ sudo /opt/discourse/launcher destroy app
$ sudo /opt/discourse/launcher start app

これで、Discorseが起動するようになり、統合Windows認証が動作するPCからアクセスすると、ユーザーが作られてログインした状態になっているはず。

アクセステスト

コンテナの再作成が終わったら、ドメインに参加したPCからDiscourseにアクセスしてみる。
SAML認証が上手く動作する状態になっていれば、DiscourseにアクセスしただけでKeycloakに遷移し、自動的に認証されてDiscourseに画面が遷移する。

上手くいかないようならログを見ながら設定を修正していく。
Discourseのログはこちら
Keycloakのログはこちら

Discourseの最終設定

Discourseは広くコミュニケーションするためのシステムだけど、組織で運用する場合には以下のような限定のための設定をしても良いと思う。

設定は管理者画面から。

項目設定値備考
<ログイン>
login required
チェックログインしていないユーザーには中身を見せない。
<ログイン>
enable local logins
チェックを外すDiscourse標準のローカルログインを無効化。外部の認証しか受け付けなくなるので、SAML認証でミスるとサイトに入れなくなる。※
<ログイン>
allow new registrations
チェックを外すドメインのユーザーだけが使えるようにしたいので、ユーザーを登録する機能を外した。
<プラグイン>
sso auto enabled
チェックdiscourse-sso-autoを有効化。これはプラグインをインストールした段階で有効になっている。

※ローカルログインを無効化した後にミスしてログインできなくなっても、回復させることは可能

Keycloakの認証フロー条件見直し

デフォルト設定

Keycloakは認証フローを定義できる。デフォルトではKerberosがALTERNATIVEになっている。
この状態だと、ドメインに参加したPCでは自動的に認証が行われる。

ドメイン参加していないPCでは、Kerberos認証画面が表示されるが、何を入力しても認証は成功せず、Keycloakのログイン画面に遷移する。
ここで正しい情報を入力すれば、サービスにアクセスできる。
Windows 10 Homeでも同じ動作となった。

Android端末からアクセスしたところ、Keycloakのログイン画面が表示され、正しいIDとパスワードを入力すればサービスにアクセスができる。

Kerberos必須の設定

KerberosをREQUIREDにすると、ドメイン参加したPCからだけアクセスができる。

ドメイン参加していないPCでは、Kerberos認証画面が表示されるが、正しい情報を入力しても否認されてエラー画面に遷移する。
Android端末からアクセスすると、即座にエラー画面に遷移する。

おまけ Discourseのモデレーター同期

おまけ扱いするのはどうかと思うけれど、まずはSSOできることが最優先だった。
でも、ここまでできたので、モデレーターも自動で設定されるような形にしてみようと考えた。

ユーザーフェデレーションでロールを取り込む設定をして、ユーザーにロールを割り付ける。
そして、クライアントで特定のロールに含まれているユーザーにtrueフラグを立てた情報を送る。

Discourseの設定

SAMLプラグインに追加の設定をする。

/opt/discourse/containers/app.yml

…
env:
…
  DISCOURSE_SAML_AUTO_CREATE_ACCOUNT: true
  DISCOURSE_SAML_SYNC_MODERATOR: true

※赤文字部分を追加。

コンテナを再作成して環境変数を反映させる。

$ sudo /opt/discourse/launcher destroy app
$ sudo /opt/discourse/launcher start app

 

Keycloakの設定

User Federationでrole-ldap-mapperを追加

ldap(Kerberos認証している)を開き、マッパーを追加する。

項目設定値備考
IDeb1nnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn自動設定、変更不可。
名前role map最初に設定、変更不可。
わかりやすいものを設定。
マッパータイプrole-ldap-mapper最初に設定、変更不可。
LDAP Roles DNCN=Users,DC=hogeserver,DC=hogeddns,DC=jpSamba ad dcはOU対応していないため、グループを使う。OUを使っても良いのだろうと思う。
Role Name LDAP Attributecn
Role Object Classesgroup
Membership LDAP Attributemember
Membership Attribute TypeDN
Membership User LDAP AttributesAMAccountName
LDAP Filter(objectClass=group)ユーザーも同じところにあるので、フィルターを掛ける。
ModeREAD_ONLY
User Roles Retrieve StrategyLOAD_ROLES_BY_MEMBER_ATTRIBUTEもしかしたら、RECURSIVELYの設定が必要かもしれない。
※RECURSIVELYを指定すると、取ってきたgroupが持っている子供もたぐっていくようになる。groupをまとめたような親グループを指定する場合には設定しておく。2021/05/05追記
Member-Of LDAP AttributememberOf
Use Realm Roles Mappingオン
Client IDaccount

クライアントにJavascript Mapperを追加

DiscourseのSAMLプラグインはisModeratorでtrue(または1)が戻されたユーザーをモデレーターにする。
特定のグループに含まれたユーザー(=上の設定で同じ名前のロールに含まれる)ならばtrueを戻すJavascript Mapperを作る。

項目設定値備考
プロトコルsaml自動設定、変更不可。
ID966nnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn自動設定、変更不可。
名前isModerator最初に設定、変更不可。
Discourseが求める名前。
マッパータイプJavascript Mapper最初に選択、変更不可。

定義するスクリプトはこんな内容にした。

/**
 * Available variables: 
 * user - the current user
 * realm - the current realm
 * clientSession - the current clientSession
 * userSession - the current userSession
 * keycloakSession - the current keycloakSession
 */


//insert your code here...
exports=false;

for each ( var role in user.getRoleMappings()) {
    if ( role.getName() == 'GroupName' ) {
        exports=true;
        break;
    }
}

※GroupNameのところにモデレーターにしたいグループの名前を入れる。

もっと格好いい書き方(効率の良い書き方、メンテナンス性が高い書き方)があるかもしれないが、Javascriptのコーディング経験はないのでご容赦。

呼び出せる関数については、ここを参考しにした。他の情報は見つからなかった。
Github gist / Steps to provide Hasura Claims in Keycloak generated JWT

 

やったこと

Discourseのログ

ログについてはここに書かれていた。
Discourse / Where does Discourse store and show logs?

Web UI

運用上の多くは管理者メニューから見ることができた。
また、GUIログビュアーがあり、管理者メニュー → ログ → エラーログ で見ることができた。
https://temp.hogeserver.hogeddns.jp/logs/

コンテナに入って見られるログ

コンテナのディレクトリの一部が共有になっているようで、以下にログが見えている。
/var/discourse/shared/standalone/log/rails
/var/discourse/shared/standalone/log/var-log

コンテナには以下のコマンドで入ることができる。

$ sudo /opt/discourse/launcher enter app

ここにログがある。
/shared/log/rails
/var/log

Keycloakのログ

ログを見る

ものを知らないのは恐ろしい…設定が大体終わった今になってログの見方が分かった。

■Keycloak
$ sudo docker logs -f --tail 10 keycloak

 

ログレベルを変える

認証が上手くいかないので、ログを見てみることにした。
dockerhub / jboss / keycloak ※Specify log levelのところ

今見ているログについては、2行目のを実行したところでデバッグログが出力されるようになった。

$ sudo docker exec -u 0 -it keycloak /bin/bash --login
[root@41bf393541e4 /]# /opt/jboss/keycloak/bin/jboss-cli.sh --connect --command='/subsystem=logging/console-handler=CONSOLE:change-log-level(level=DEBUG)'
[root@41bf393541e4 /]# /opt/jboss/keycloak/bin/jboss-cli.sh --connect --command='/subsystem=logging/root-logger=ROOT:change-root-log-level(level=DEBUG)'

元に戻すには、DEBUGのところをINFOに変える。

Discourseのローカルログインを強制的に復活させる

ログイン関連の設定をしていると、ミスってログインできなくなり、ローカルログインしたいけどできない…。
こんなときは、中に入ってコマンドを叩けば復旧できる。
Discourse / Official Single-Sign-On for Discourse (sso)

$ sudo /opt/discourse/launcher enter app
root@temp-app:/var/www/discourse# rails c
[1] pry(main)> SiteSetting.enable_local_logins = true
=> true
[2] pry(main)> exit
root@temp-app:/var/www/discourse# logout

 

DiscourseのSAML認証で作られるアカウントのフルネームの調整

サイトにアクセスすると自動的にSAML認証が起動し、初めてのログインならアカウントが作られるようになったのだが、名前(フルネーム)が中途半端。

当初、SAML認証のプラグインはユーザーのフルネームを書き換える機能を提供していないようだった。
Discourse / Discourse-saml as sole login method

しかし、少なくとも最終ソースでは提供がされている。
Github / discourse / discourse-saml

実際、本編で記載したとおり、クライアントのマッパーでSAML認証プラグインに情報を渡せば、フルネームは作られる。
しかし…

  • ドメインコントローラーで日本語の姓名を管理している場合、残念表記になる。
    e.g.) Taro Yamada → 太郎 山田
  • fullNameを生成して渡しても、firstName + ” ” + lastNameで上書きされる。
    firstNameとlastNameを渡さないようにしても、何か別の情報で上書きされる。

という課題が残った。対策は3つ。

  1. KeycloakからfirstNameとlastNameの値を入れ替えて渡す
  2. プラグインのソースでfirstNameとlastNameを入れ替える
  3. KeycloakでfullNameを作って渡し、DiscourseではfullNameしか使わない

 

KeycloakからfirstNameとlastNameの値を入れ替えて渡す

運用上はメンテナンスでミスが発生しにくいやり方かなと思われる。
ただし、SAML認証の情報が他でも使われるようになると(何かでfirstNameが使われるとか…)、負の影響が出てくるので注意。

クライアント → https://temp.hogeserver.hogeddns.jp を開き、マッパータブを開く。
ユーザーフェデレーション(LDAP)で取り出した情報を、クライアントでDiscourseに渡すイメージ。

firstNameとしてlastNameを渡すマッパーの作成
項目設定値備考
プロトコルsaml自動設定、変更不可。
IDa90nnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn自動生成、変更不可。
名前first name reverse最初に設定、変更不可。
わかりやすいものを設定。
マッパータイプUser Property最初に選択、変更不可。
プロパティfirstNameこの情報を取ってくる。
Friendly Name未設定
SAML Attribute NamelastNameこの名前でDiscourseに伝わる模様。これで入れ替える
SAML Attribute Name FormatBasic
lastNameとしてfirstNameを渡すマッパーの作成
項目設定値備考
プロトコルsaml自動設定、変更不可。
ID1aennnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn自動生成、変更不可。
名前last name reverse最初に設定、変更不可。
わかりやすいものを設定。
マッパータイプUser Property最初に選択、変更不可。
プロパティlastNameこの情報を取ってくる。
Friendly Name未設定
SAML Attribute NamefirstNameこの名前でDiscourseに伝わる模様。これで入れ替える
SAML Attribute Name FormatBasic

プラグインのソースでfirstNameとlastNameを入れ替える

Discourseのプラグインに手を入れて姓名の順になるように変更。
プラグインのソースが変わったときに検知して、都度修正することができれば安全。

fullNameを生成する処理を修正

firstName + lastNameとしている処理を変更する。

$ sudo /opt/discourse/launcher enter app
root@temp-app:/var/www/discourse# vi plugins/discourse-saml/lib/saml_authenticator.rb

という具合で編集を開始。

/var/www/discourse/plugins/discourse-saml/lib/saml_authenticator.rb

…
    result.name = begin
      if attributes.present?
        fullname = attributes['fullName'].try(:first)
//      fullname = "#{attributes['firstName'].try(:first)} #{attributes['lastName'].try(:first)}"
        fullname = "#{attributes['lastName'].try(:first)} #{attributes['firstName'].try(:first)}"
      end
      fullname ||= result.name
      fullname
    end
…

※firstNameとlastNameを入れ替え。

編集が終わったらDiscourseを再起動する。

$ sudo /opt/discourse/launcher restart app

 

KeycloakでfullNameを作って渡し、DiscourseではfullNameしか使わない

こちらもDiscourseプラグインに手を入れるので、ソースが変わったときに検知して修正する必要がある。
fullNameの生成にはJavascript Mapperを利用することになったので、学習の意味でやってみた。

fullNameを生成する処理を修正

firstName + lastNameとしている処理を無効化し、fullNameを受け取るようにする。

$ sudo /opt/discourse/launcher enter app
root@temp-app:/var/www/discourse# vi plugins/discourse-saml/lib/saml_authenticator.rb

という具合で編集を開始。

/var/www/discourse/plugins/discourse-saml/lib/saml_authenticator.rb

…
    result.name = begin
      if attributes.present?
        fullname = attributes['fullName'].try(:first)
//      fullname = "#{attributes['firstName'].try(:first)} #{attributes['lastName'].try(:first)}"
      end
      fullname ||= result.name
      fullname
    end
…

※firstNameとlastNameからfullNameを作る処理を無効化。

編集が終わったらDiscourseを再起動する。

$ sudo /opt/discourse/launcher restart app

 

fullNameを生成するマッパーの作成

LDAPで取得した値を組み合わせてfullNameを作成する Javascript Mapper を作成する。

項目設定値備考
プロトコルsaml自動設定、変更不可。
ID1f0nnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn自動生成、変更不可。
名前fullName最初に設定、変更不可。
Discourseが求める名前。
マッパータイプJavascript Mapper最初に選択、変更不可。

定義するスクリプトはこんな内容にした。

/**
 * Available variables: 
 * user - the current user
 * realm - the current realm
 * clientSession - the current clientSession
 * userSession - the current userSession
 * keycloakSession - the current keycloakSession
 */


//insert your code here...
var fName = user.getFirstName();
var lName = user.getLastName();
exports = lName + " " + fName;

//var flName = user.getFirstAttribute("displayName");
//exports = flName;

firstNameやlastNameは取り出す関数が用意されている。
ユーザーページで表示される基本的な情報はこれで取り出すのだろう。

一方、ユーザーフェデレーションのマッパーで例えばdisplayNameを作った場合、displayNameで取得したLDAPの情報はgetFirstAttributeで取り出す。
Kerberosで取った情報と、LDAPで取った情報とで扱いが違うのかもしれない。今回の調査はここまで。

関数を利用するにあたって、この投稿で示されているソースがわかりやすかった。
stackoverflow / How to create a Script Mapper in Keycloak?

user: Source JavaDoc(リンク切れ https://www.keycloak.org/docs-api/6.0/javadocs/org/keycloak/models/UserModel.html)
realm: Source JavaDoc(リンク切れ https://www.keycloak.org/docs-api/6.0/javadocs/org/keycloak/models/RealmModel.html)
token: Source JavaDoc(リンク切れ https://www.keycloak.org/docs-api/6.0/javadocs/org/keycloak/representations/IDToken.html)
userSession: Source JavaDoc(リンク切れ https://www.keycloak.org/docs-api/6.0/javadocs/org/keycloak/models/UserSessionModel.html)
keycloakSession: Source JavaDoc(リンク切れ https://www.keycloak.org/docs-api/6.0/javadocs/org/keycloak/models/KeycloakSession.html)

André B.さんの回答

SAMLRequestの中身を確認する

Discourseから認証要求は飛んでいるけれど、userId=nullとなって前に進まない。どんなリクエストが飛んでいるのか見てみたいと思った。

URL形式をデコードし、Base64形式なのをデコードし、inflateすれば見られるらしい。
Github / onelogin / ruby-saml / Generated SamlRequest doesn’t Base64 decode properly #394

これをワンラインで実現できなかったので、シェルを作成。

samldecode

#!/bin/bash
MGCODE="\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

# URL形式からのデコード
TGCODE=`urlencode -d "$1"`

# Base64形式からのデコード
TGCODE=`echo $TGCODE | base64 -d`

# gzip用にマジックコードを追加してinflate
TGCODE=`printf "$MGCODE%s" "$TGCODE" | gzip -dc 2>/dev/null`

# 整形して表示
echo "----- Result -----"
echo $TGCODE | xmllint --format -

※inflateは実際にはzlibでdecompressしているらしく、gzipコマンドに入れてみたけれども展開できず。マジックコードを付ければ良いと教えてくれたのでやってみたら上手くいった。
it-swarm-ja.tech / UNIXでzlibデータを解凍する方法は?(リンク切れ)

シェルから呼び出すコマンドをインストールし、実行権を付ける。

$ sudo apt install gridsite-clients ← urlencodeコマンドを使うため
$ sudo apt install libxml2-utils ← xmllintコマンドを使うため
$ chmod +x samldecode

ブラウザでアクセスしてエラーとなった時に、URLに表示されている
?SAMLRequest=~~~
~~~部分をコピーしてこのスクリプトに渡したら、デコードしてくれた。

$ ./samldecode ~~~
----- Result -----
<?xml version="1.0"?>
<samlp:AuthnRequest xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://temp.hogeserver.hogeddns.jp/auth/saml/callback" Destination="https://temp.hogeserver.hogeddns.jp:8443/auth/realms/Kerberos/protocol/saml" ID="_3702917b-61f4-45a3-a9cd-afd803913810" IssueInstant="2020-07-11T22:57:36Z" Version="2.0">
  <saml:Issuer>https://temp.hogeserver.hogeddns.jp</saml:Issuer>
</samlp:AuthnRequest>

こうしてみると、確かに認証は要求しているけれど、中身がよく分からない。
Cybozu Inside Out / SAML認証ができるまで
Qiita / (ちょっと噛み砕いた)SAML入門

項目意味設定値
xmlns:samlurn:oasis:names:tc:SAML:2.0:assertion
xmlns:samlpurn:oasis:names:tc:SAML:2.0:protocol
AssertionConsumerServiceURLDiscourseが認証応答を受け取るURLhttps://temp.hogeserver.hogeddns.jp/auth/saml/callback
Destinationリクエストの宛先https://temp.hogeserver.hogeddns.jp:8443/auth/realms/Kerberos/protocol/saml
IDユニークなランダム文字列_3702917b-61f4-45a3-a9cd-afd803913810
IssueInstan認証要求をした日時2020-07-11T22:57:36Z
VersionSAMLバージョン2.0
<saml:Issuer>SPのIDhttps://temp.hogeserver.hogeddns.jp

後から考えると、IdP開始のシナリオでsaml:Issuerがhttps://temp.hogeserver.hogeddns.jpとなっているんだから、これがKeycloakでいうところのClientIDなのかもしれない…と気付いた。
結果的にはそれで上手くいったように思われる。

 

起きたこと

KeycloakをProxyしたらMixed Contentエラー

こんなエラーが出た。楽をしようとして、結果的に時間が掛かるパターン。

Mixed Content: The page at ‘https://temp.hogeserver.hogeddns.jp:8443/auth/admin/master/console/’ was loaded over HTTPS, but requested an insecure script ‘http://temp.hogeserver.hogeddns.jp:8443/auth/js/keycloak.js?version=up50l’. This request has been blocked; the content must be served over HTTPS.

コンテナの中に入ってみる。

■1人目のユーザーでログイン
$ sudo docker exec -it keycloak /bin/bash --login
[jboss@b8d8e12d9516 /]$ cd
[jboss@b8d8e12d9516 /]$ pwd
/opt/jboss

■ルートユーザーでログイン
$ sudo docker exec -u 0 -it keycloak /bin/bash --login
[root@b8d8e12d9516 /]#

このイメージにはfindやvi等が入っていなくて、この中でファイルを編集することはできない。
仕方がないので、中からファイルを取りだして、書き換えて送り込むことを考える。

今回はstandaloneで動いてる?となると、恐らくこのファイルが編集対象。
/opt/jboss/keycloak/standalone/configuration/standalone.xml

結果は外れ。これが対象だった(少なくともログイン画面では)。
/opt/jboss/keycloak/standalone/configuration/standalone-ha.xml

$ sudo docker cp keycloak:/opt/jboss/keycloak/standalone/configuration/standalone-ha.xml ./

ファイルを編集。

…
    <server name="default-server">
      <ajp-listener name="ajp" socket-binding="ajp"/>
      <http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="${env.PROXY_ADDRESS_FORWARDING:false}" enable-http2="true"/>
      
      <http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="true" enable-http2="true"/>
…

編集結果を書き戻し、コンテナを再起動する。

$ sudo docker cp standalone-ha.xml keycloak:/opt/jboss/keycloak/standalone/configuration/standalone.xml
$ sudo docker restart keycloak

確かにこれで動く(半日かかったぜ…)。

でも、環境変数で動いてくれるっぽいから、そっちをちゃんと調べよう。となって、本編の解決策となった。

Keycloakが再起動を繰り返す

Proxyを受け入れるための環境変数を変えようとして、runコマンドに環境変数を追加して起動してみたところ、Keycloakが再起動を繰り返すようになった。
コンテナが2つあるけれど、イメージは1つという状態を作り出した結果、競合的な問題が発生したのだろう。

設定をしっかりした状態だったら設定内容の保全をしながら起動できる方法を考えたと思うが、まだ設定などほとんどしていない状態だったので、コンテナもイメージも全てをきれいに削除して、runコマンドを叩いた。

Keycloakが自動起動しない

自動起動するはずのKeycloakとDiscourseが起動しなくなっている。何でかなぁと思ってsshでログインし、docker.serviceが起動していないことが判明。

$ sudo systemctl enable docker

これで、しっかりと自動起動するようになった。

Discourseのイメージがたくさんある

使用しているディスク容量がやけに増えているなぁ…と思ったらこんなことに。

# docker image ls
REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
local_discourse/app         latest              5fa587e920ea        2 hours ago         2.65GB
<none>                      <none>              432b2305cbc8        5 hours ago         2.65GB
<none>                      <none>              d35bbbea2ae8        5 hours ago         2.65GB
<none>                      <none>              f38f6b5c6fc0        6 hours ago         2.65GB
<none>                      <none>              6fbda624f25e        6 hours ago         2.65GB
<none>                      <none>              26f3332683f5        6 hours ago         2.65GB
<none>                      <none>              de00ef9de579        8 hours ago         2.65GB
<none>                      <none>              febf54a5c910        13 days ago         2.61GB
<none>                      <none>              95eca1c4afae        13 days ago         2.61GB
quay.io/keycloak/keycloak   10.0.2              dc8d0176a668        5 weeks ago         740MB
discourse/base              2.0.20200512-1735   991acdba0b1f        8 weeks ago         2.22GB

再構築するたびにイメージが新たに作られるんだなこれ。

ここで示唆されているオプションを指定してlauncherを実行してみた。
Github / A rebuild doesn’t remove the old docker image #21

# cd /opt/discourse
# ./launcher cleanup
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y
Deleted Images:
deleted: sha256:febf54a5c910db3b03b628bba4cc8693bcdea4bbd7cb46ce297178db357eb648
deleted: sha256:1c08a84f8c2a8240bb773779e5bac00d19192d39f14c03d5df7a9ab2ed35a172
deleted: sha256:95eca1c4afae367fffd6ec0fe65ea5da77ae6ebf242b6335fd8961b5b723209d
deleted: sha256:0b209505686fd47327d14e029534fb5921a2c2d90294ef0cd686dd5091bcfc67
deleted: sha256:de00ef9de5799ae2eaacf054b1f935c7969337eea11ce6ae0705b446a7ab8240
deleted: sha256:98b60bf88bef6a6bbe3c8049319a483d67defbb51491a22911844c5cae4d2e0d
deleted: sha256:26f3332683f51cfaf39d4745076fe367e43b4b10981afb2187ca594649751cfd
deleted: sha256:d021db6b2caebfe342497bd9c6beefad2dfc7035ff7e9eaac315e7aa631bb779
deleted: sha256:f38f6b5c6fc054236e4288217dc96f95c3d4cc5711b6353475728dfcd26a3563
deleted: sha256:e2ba479751e8a949545fc5955370c8eca28f5a48f9e606eb86c90991a0f45635
deleted: sha256:432b2305cbc85ec4bc67761775203167db366224c684f913295c685af4d21b25
deleted: sha256:2625555c5af1a5f3f76a6c99e41d3e11e284e04b400925da3c925cd2ebe9c672
deleted: sha256:6fbda624f25edf8c56ebd00887cb75528ee8b588004df850b1d10f16835a858f
deleted: sha256:67f6f72f94b1d2cf0f1a1a6a533bcaa259f58a81679da31cf847ec9b986395f9
deleted: sha256:d35bbbea2ae81b17e335269a9d1bfae3afc8f79f6b8284957fb4dc9e4293c55b
deleted: sha256:7e0c8a2085d794d49b7b5dd8fee55eb16fc1eeddcf567f461190808fb98ea4cf
untagged: discourse/base:2.0.20200512-1735
untagged: discourse/base@sha256:7f6c5be23a8e4237cecafaca9d041de5964f8237345b7b183cebdee1f73ed024

Total reclaimed space: 3.386GB

古くなったイメージが消されて、容量が戻ってきた。

KeycloakとWordpressのSAML認証連携を試す

DiscourseのSAML認証がどうしても構成できず、これは一度上手くいく連携というものを体験すべき、と考えた。
前々から読んでいたつもりだったんだけど、いざ設定をするとなって、色々と気付かせてくれたのがこちらの記事。
Qiita / KeycloakでSAMLを使ってみる(WordPress編)

これってどういう意味かな?これって?これって?と注意深く見ることが大切なんだけど、読むだけではなかなか頭に入らない性格なんだなと痛感。
最終的には、ちゃんと自動ログインできるようになった。

MariaDBが上手くインストールできない

WordPressをインストールする過程で間違えてMySQLをインストールしてしまった。
MySQLをpurgeした後、mariadbをインストールしようとしたら、異常に時間が掛かるし、上手くいかない。

これはこれで小さくないテーマなので記事にしてみた。

WordPressのOneLogin SAML SSOでエラー

上手く動く事例を作成するために、OneLogin SAML SSOを動作させたところ、エラーが発生。

[19-Jul-2020 10:16:39 UTC] PHP Fatal error:  Uncaught Error: Class 'DOMDocument' not found in /var/www/wordpress/wp-content/plugins/onelogin-saml-sso/php/lib/Saml2/Response.php:100

必要なライブラリがあるらしい。
ajike switch / 【解決方法】 Fatal error: Class ‘DOMDocument’ not found

$ sudo apt install php7.2-xml
$ sudo systemctl restart apache2

これで先に進んだ。

WordPressでデバッグログを出力したい

WordPressのエラーログをファイルにだけに出力したい。
Qiita / WordPressのデバッグモード(ログ出力)

/var/www/wordpress/wp-config.php

//define( 'WP_DEBUG', false );
define( 'WP_DEBUG', true );
if ( WP_DEBUG ) {
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', false );
    @ini_set( 'display_errors',0 );
}

※この設定、いいなぁ。WP_DEBUGをfalseにすれば、元の状態に戻るもん。

ログファイルは、/var/www/wordpress/wp-content/debug.log に出力される。

さいごに

SSOはあくまで認証を1つのサーバーで行おうとする仕組みであって、自動ログインとは違う。
自動ログインってのはブラウザ側も協調して行われる仕組みで、[with SAML]ボタンをクリックしたときに起きることを自動的に呼び出してくれると分かった。
ちょっとややこしいけれど、理解できて良かった部分。

ドメインに参加していないPCでChromeを使ってアクセスすると、絶対に成功しない認証の要求がある(その後にKeycloakが表示するログイン画面ではログインができる)。
これをどうにかして止めたいんだけど、どうにもその方法が見つけられなかった。何かそういうヘッダーでも送ればいいのか?残課題。

今まで避けてきたSSOだけど、どうにか第一歩を踏み出せたような気がする。

広告

コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他