ということをやりました。実は下記の記事の通り(Mattermostの部分まで含めて)やりたいことをそのまんまやっている方がいらっしゃいました。

KeycloakのSAML SSOでGitLabやMattermostにログインする

基本的にこちらの記事通りにやってます。こちらの記事がなかったら、たぶんできてないと思います。ありがとうございます。併せて下記の公式ドキュメントも参考にしています。

SAML OmniAuth Provider

環境


  • GitLab Omnibus 10.6.0
  • Keycloak 3.4.3 Final

手順


基本的に前述の記事のとおりでうまくいくハズです…。が、詰まったところを書いていきます。また、以下サンプルのドメインやRealmで記述していますが実際はご自身のものに置き換えてください。

クライアントIDとIssuerについて


KeycloakのクライアントIDとGitLab側の設定のissuerが一致しないといけないようです。

この辺SAML認証に関する知識がないので、はっきりとは言えないのですがKeycloak側でここが一致するかどうかで判断しているようです。一致していないとKeycloak側でクライアントが見つからず下記のようなエラーが表示されます。

1
2
2018-04-03 15:18:50,261 WARN [org.keycloak.events] (default task-7) type=LOGIN_ERROR,realmId=realm-id,
clientId=https://gitlab.example.com,userId=null,ipAddress=***.***.***.***,error=client_not_found

今回は両方ともhttps://gitlab.example.comで設定しました。

証明書


前述の記事ではKeycloakで取得したX.509証明書をGitLabの設定ファイルgitlab.rbにPEM形式で設定しているのですが、これではダメでした。

GitLabでは下記のomniauth-samlというgemを利用してSAML認証を行っているようで、リポジトリのREADMEを見る限りではPEMでも問題ないようなのですが、なぜかうまくいきませんでした。

この時、GitLab側でCan't verify CSRF token authenticityというエラーが出ていました。

フィンガープリント確認

後述する調査の結果、証明書がうまく設定されていないことがわかりました。

gitlab.rbでPEMではなくフィンガープリントを設定する方法に変えたら上手くいきました。証明書(PEM形式)を適当なファイルに保存します。後は下記のコマンドでフィンガープリントを確認します。

1
openssl x509 -sha1 -fingerprint -noout -in 証明書.pem

後は表示されたフィンガープリントをgitlab.rbに設定します。

gitlab.rb


出来上がったgitlab.rbこんな感じです。フィンガープリントのところ以外は前述の記事と同じです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
gitlab_rails['omniauth_enabled'] = true 
gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
gitlab_rails['omniauth_block_auto_created_users'] = false
gitlab_rails['omniauth_auto_link_saml_user'] = true
gitlab_rails['omniauth_providers'] = [
{
"name":"saml",
"label":"Keycloak",
"args":{
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
idp_cert_fingerprint: 'フィンガープリント',
idp_sso_target_url: 'https://keycloak.example.com/auth/realms/realm-id/protocol/saml',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
attribute_statements: { username: ['username'] }
}
}
]

エラー時の調査方法


基本はKeycloakとGitLabのログを確認してどちらに問題があるか切り分けます。

GitLabのログ

問題はGitLabの方で、詳細がログ出力されません。例えば前述の証明書がちゃんと設定できていなかったケースですが、ログには下記しか表示されません。

1
2
3
4
5
6
7
Parameters: {"authenticity_token"=>"[FILTERED]"}
Completed 200 OK in 0ms (ActiveRecord: 0.0ms)
Started POST "/users/auth/saml/callback" for 172.18.0.1 at 2018-04-03 23:01:10 +0000
Processing by OmniauthCallbacksController#failure as HTML
Parameters: {"SAMLResponse"=>"**"}
Can't verify CSRF token authenticity
Redirected to http://gitlab.example.com/users/sign_in

詳細を表示する

GitLabのソースコードを変更すればもう少し詳細なエラーが確認できるのでコードを変更します。このやり方は公式に書かれてます。

/opt/gitlab/embedded/service/gitlab-rails/app/controllersomniauth_callbacks_controller.rbを変更します。変更点は2箇所です。

  • class直下にskip_before_action :verify_authenticity_tokenを追記
  • rotect_from_forgery exceptの行をコメントアウト

下記のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
# 下記の行を記述する
skip_before_action :verify_authenticity_token
include AuthenticatesWithTwoFactor
include Devise::Controllers::Rememberable

# コメントアウトする
#protect_from_forgery except: [:kerberos, :saml, :cas3]

Gitlab.config.omniauth.providers.each do |provider|
define_method provider['name'] do
handle_omniauth
end
end

これらの設定が終わればsudo gitlab-ctl restart unicornでunicornを再起動します。Dockerの場合でもコンテナ内に入って作業すればよいです。

後は動かしてみれば下記のような感じでログイン画面でエラーメッセージが表示されます。

今回は「No fingerprint or certificate on settings」ということで「証明書が設定されていないよ」というエラーでした。「なんでや!!設定してるやんけ!!」という気持ちになったのですが、原因がどこにあるのかハッキリわかったのと、フィンガープリントに変えるきっかけになったのでよかったです。

公式ドキュメントがしっかりしていると助かりますね。