プロジェクト

全般

プロフィール

Redmineのシングルサインオン対応

redmineにシングルサインオン環境を構築する。
Redmineは構築済み、IdPサーバは仮にOpenAM、SPはredmine_omniauth_samlプラグインとする。

プラグインの準備

  • プラグインのアドレスを調べる
    https://github.com/chrodriguez/redmine_omniauth_saml
    上記にアクセスし、プルダウンのツリーから対応するredmineのメジャーバージョンを選択する。
    デフォルトの「master」は執筆時点ではredmine 4.x系の対応。5.x系は今のところまだないよう。
  • Redmineのプラグインディレクトリに移動する
    # cd /usr/local/redmine/plugins/
    
  • ソースコードを取得する(ここでは3.xなのでmaster→3.0とする)
    # wget https://github.com/chrodriguez/redmine_omniauth_saml/archive/redmine-3.0.zip
    
  • アーカイブを展開、リネームする
    # unzip redmine-3.0.zip
    # mv redmine_omniauth_saml-redmine-3.0 redmine_omniauth_saml
    
  • 必要なモジュールを取得する
    # cd ../
    # bundle install
    (中略)
    Bundle complete! 34 Gemfile dependencies, 62 gems now installed.
    Gems in the groups development and test were not installed.
    Bundled gems are installed into `./vendor/bundle`
    
  • プラグインを適用する
    # RAILS_ENV=production bundle exec rake redmine:plugins
    Migrating redmine_omniauth_saml (Redmine Omniauth SAML plugin)...
    
    • 対応していないredmineバージョン(特にmasterで取得した場合)はここで失敗する可能性が高い
  • redmineを再起動する(passengerの場合はhttpd再起動など)
    # systemctl restart httpd
    
  • redmineの画面上からプラグインの導入状況を確認する
    管理→プラグイン→Redmine Omniauth SAML plugin

以上でプラグイン自体は導入できました。

プラグインの設定

プラグインで設定可能な個所は以下です。
管理→プラグイン→Redmine Omniauth SAML plugin→設定
  • Enable SAML authentication
    SAML認証を有効にするか
  • Login page text
    ログインページのSAML認証ボタンに表示するテキスト
    デフォルトでは「Login with SAML」となる
    下記のオプションでログイン画面を置き換えた場合は表示されない。
  • Replace Redmine login page
    RedmineのログインページをSAML認証側に置き換えるか
    通常はRedmineのログインページにSAML認証ボタンが追加されているが、これを
    有効にすると通常のログイン画面が表示されなくなる。つまり、デフォルトでは
    SAML以外にRedmineのローカルユーザがいればそちらでログインできてしまう。
  • Create users automatically?
    認証したユーザが作成されていない場合にユーザを自動作成するか。
    これを無効にしている場合は、あらかじめSAMLに対応したユーザを作成しておく
    必要がある。逆に、認証が出来ても利用させたくないユーザ区分がある場合は
    このオプションを有効にするといい

SPの準備

SSOの親サーバとの連携を行うSPの設定を行います。

  • 設定ファイルのコピーと編集
    # cp -p /usr/local/redmine/plugins/redmine_omniauth_saml/sample-saml-initializers.rb /usr/local/redmine/config/initializers/saml.rb
    # cd /usr/local/redmine/config/initializers/
    # vi saml.rb
    
  • コピーしたファイルをもとに、下記内容を設定します。
    Redmine::OmniAuthSAML::Base.configure do |config|
      config.saml = {
        :assertion_consumer_service_url => "http://redmine.example.com", # The redmine application hostname
        :issuer                         => "sso_issuer",                 # The issuer name
        :idp_sso_target_url             => "http://sso.desarrollo.unlp.edu.ar/saml2/idp/SSOService.php", # SSO login endpoint
        :idp_cert_fingerprint           => "certificate fingerprint", # SSO ssl certificate fingerprint
        :name_identifier_format         => "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
        :signout_url                    => "http://sso.example.com/saml2/idp/SingleLogoutService.php?ReturnTo=",
        :idp_slo_target_url             => "http://sso.example.com/saml2/idp/SingleLogoutService.php",
        :name_identifier_value          => "mail", # Which redmine field is used as name_identifier_value for SAML logout
        :attribute_mapping              => {
        # How will we map attributes from SSO to redmine attributes
          :login      => 'extra.raw_info.username',
          :firstname  => 'extra.raw_info.first_name',
          :lastname   => 'extra.raw_info.last_name',
          :mail       => 'extra.raw_info.email'
        }
      }
    
      config.on_login do |omniauth_hash, user|
        # Implement any hook you want here
      end
    end
    
    • assertion_consumer_service_url
      このredmineがsammlサービスにコールバックするためのURL
      基本URL+/auth/saml/callback
    • issuer
      発行者名
      Redmineの基本URL
    • idp_sso_target_url
      IdPのSSOサービスのターゲットURL
      SSOサービス側が提供しているURL
    • idp_cert_fingerprint
      IdPの証明書フィンガープリント
      ※下記に補足
    • name_identifier_format
      名前空間のフォーマット形式urn名
    • signout_url
      サインアウト用のURL
    • single_logout_service_url
      シングルサインアウトURL(あれば
      基本URL+/auth/saml/sls
      ただし実際に機能するかはIdPによる
    • idp_slo_target_url
      シングルログアウトURL(あれば
      基本URL+/auth/saml/sls
      ただし実際に機能するかはIdPによる
    • name_identifier_value
      SAMLログアウト時に使用するユーザ名の項目定義
    • attribute_mapping
      アカウントに渡す属性マッピング
      • login
        ログインID
      • firstname
        名前(名)
      • lastname
        名前(姓)
      • mail
        メールアドレス
    • Implement any hook you want here
      ログイン時にフック処理が必要な場合はここに書く
  • 変更が完了したらサービスを再起動する
    # systemctl restart httpd
    

証明書についての補足

  • IdP証明書のフィンガープリントは単体提供されていない場合はIdPのメタデータから作成する。
  • メタデータXMLに含まれる「<ds:X509Certificate>」ディレクティブ内の文字列をもとに以下のようなデータを作成する。
    vi metadata.pem
    --------------------
    -----BEGIN CERTIFICATE-----
    (<ds:X509Certificate>内の文字列)
    -----END CERTIFICATE-----
    
  • 作成したファイルをもとに、OpenSSLコマンドでフィンガープリントを取得する。
    # openssl x509 -sha1 -fingerprint -noout -in metadata.pem
    SHA1 Fingerprint=<2バイトずつ:区切りの文字列>
    
  • 上記の<2バイトずつ:区切りの文字列>を設定ファイルの「name_identifier_format」に記載する。

上記を踏まえた設定と適用

  • SLOはIdPの機能にもよるので、いったん設定を見送る(ヘタに動かない値を指定していると全体が動作しないため)
    これをふまえてsaml.rbを下記のように設定する
    Redmine::OmniAuthSAML::Base.configure do |config|
      config.saml = {
        :assertion_consumer_service_url => "http://<ホスト名>/redmine/auth/saml/callback",
        :issuer                         => "http://<ホスト名>/redmine/",
        :idp_sso_target_url             => "https://<ホスト名>/openam/SSORedirect/metaAlias/idp",
        :idp_cert_fingerprint           => "**:**:**……(略)",
        :name_identifier_format         => "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
        :attribute_mapping              => {
          :login      => 'extra.raw_info.username',
          :firstname  => 'extra.raw_info.first_name',
          :lastname   => 'extra.raw_info.last_name',
          :mail       => 'extra.raw_info.email'
        }
      }
    end
    
    • 設定が有効でない場合、Passengerがブラウザにエラーを出力するためsaml.rbの拡張子を
      リネームしてhttpdまたはpassengerを再起動することで一時的に元に戻せる。

IdP側のSP登録

IdPによるので、今回はOpenAMの場合のみ。基本的にはリモートSPアプリケーションを作成するかんじ。

  • 「Top Realms」から「Create SAML v2 Providers」を実行
    (GoogleとかAzureだとそれに相応したApp作成メニューを使うと良いかも)
  • 「Register Remote Service Provider」を実行
  • 識別子にsaml.rbでの「issuer」で設定したURLを指定する
  • 応答URLにsaml.rbでの「assertion_consumer_service_url 」で設定したURLを指定する *

まだ執筆途中