RedmineでSSOしたい阿部です。
IISでリバースプロキシができて、REMOTE_USERを使ってRedmineで自動ログインができるとなれば、IISでWinodws認証をして、そのユーザ情報(REMOTE_USER
)でRedmineに自動ログインしたくなります。
しかし、課題がありIISでリバースプロキシをするとうまくいきません。
本記事ではIISでリバースプロキシをするとうまくいかない理由を簡単に説明し、どのようにしたらその課題を打開できるのかを説明します。 具体的にはPHPでリバースプロキシ相当の処理をさせて課題を打開する方法を説明します。
IISのリバースプロキシ設定ではバックエンドにREMOTE_USER
が送れない!?
本題の前に導入部分で触れた課題について説明します。
前提知識
IISではWinodws認証ができます。IISでWindows認証を設定すると認証に成功したユーザのみがWebページにアクセスできるようになります。 (Basic認証に馴染みがある方は、Basic認証のようなものだと思っておいてよいです。)
IISで認証をしているので、REMOTE_USER
環境変数も設定されます。
(IISでFastCGIを動かすと、スクリプトからREMOTE_USER
を参照することができます。)
IISでリバースプロキシ設定をしたときの課題
ということで、IISでWindows認証を有効にするとREMOTE_USER
が設定されるので、「IISでリバースプロキシ」)の通り「ARR」と「URL 書き換え」を使ってリバースプロキシを設定したら、バックエンドにもREMOTE_USER
を転送してほしいところですが、そうはなりません。
これは「URL 書き換え」がREMOTE_USER
の値が設定される前に動作するためです。「URL 書き換え」が動作するタイミングではREMOTE_USER
の値がないので、バックエンドに転送もできないというわけです。
課題の打開方法
いくつか方法はあると思いますが、今回はPHPでリバースプロキシを実現する方法を紹介します。
理由は以下の2つです。(小難しく書きましたが、要は一番簡単に実現できそうだったからです。)
- IISでFastCGIを動かすと、スクリプトから
REMOTE_USER
を参照するのは容易- FastCGIでPHPを動かすのも容易
- Microsoftの公式ドキュメントでも紹介されている
- PHPでリバースプロキシを実装しているスクリプトがすでにあった
「Windows認証でRedmineに自動ログイン」: 設定手順
本題の「Windows認証でRedmineに自動ログイン」の設定方法を説明します。
/redmine
というパスで運用する設定例です。
またRedmineの静的ファイルはIISが返すように設定をします。
やること
- 準備: IISでPHPを動かす設定
- 準備: アプリケーションの追加
- 準備: IISでWindows認証を有効にする
- 準備: PHPのハンドラーマッピングの設定
- Redmine関連の設定もろもろ
no.php
の配置と設定- = リバースプロキシの設定
- IISでURL書き換え設定
準備の1~4については一般的な設定なので、つまづきそうなポイントを中心に簡単な説明のみに留めます。
準備の1~4
すべて表示すると長すぎてメリハリがないので準備の1~4は非表示にしています。ご覧になりたい場合は「詳細」から確認をお願いします。
1. 準備: IISでPHPを動かす設定
IISでPHPを動かすためには「IISにFastCGIをインストール」と「PHPのインストール」を行う必要があります。
IISにFastCGIをインストール
Microsoftのドキュメントの通りに「サーバー マネージャー」で「CGI」をインストールします。 ドキュメントの通りにポチポチ押してインストールするだけなのでスムーズにインストールできると思います。
CGIの追加: https://learn.microsoft.com/ja-jp/iis/configuration/system.webserver/fastcgi/#setup
PHPのインストール
ダウンロードページ( https://www.php.net/downloads )からZIPファイルをダウンロードして展開するだけです。
ダウンロードして展開するだけではありますが、いくつかポイントがあるので紹介します。
- ダウンロードページに「Windows downloads」というWindows専用のページがあるのでそこからダウンロードする
- Non Thread SafeのZIPファイルをダウンロード
- 展開すると
php-cgi.exe
というファイルがあるはずなのでダブルクリックをしてみる- エラーがなかったら問題なし
- 「VCRUNTIME140.dllが見つからない」というエラーが出る場合は追加で「Microsoft Visual C++ 再頒布可能パッケージ」をダウンロードしてインストールする
2. 準備: アプリケーションの追加
「Default Web Site」へ設定する例です。 サイト > Default Web Site で右クリックをして表示されるメニューの「アプリケーションの追加」から追加します。
/redmine
というパスで運用するので、次の通り設定します。
- エイリアス
redmine
- 物理パス
C:\inetpub\wwwroot\redmine
- リバースプロキシを実現するPHPスクリプトを配置するので、IISのドキュメントルート以下に設定
(「IISでリバースプロキシ > A. パスごとにアプリケーションを追加する方法」にも説明があります。)
3. 準備: IISでWindows認証を有効にする
IISで「Windows認証」をするためには「Windows認証のインストール」と「Windows認証の有効化」を行う必要があります。
Windows認証のインストール
Microsoftのドキュメントの通りに「サーバー マネージャー」で「Winodws Authentication」をインストールします。 ドキュメントの通りにポチポチ押してインストールするだけなのでスムーズにインストールできると思います。
Winodws Authenticationの追加: https://learn.microsoft.com/ja-jp/iis/configuration/system.webserver/security/authentication/windowsauthentication/#setup
Windows認証の有効化
「Windows認証」を設定する範囲は選ぶことができます。今回はURLの /redmine
パス以下にのみ設定したいので、redmine
アプリケーションにて設定します。
redmine
アプリケーションを開くと「認証」というアイコンがあるのでダブルクリックしてメニューを開きます。
そして「Windows認証」のみ有効にします。「Windows認証」以外は無効にしてください。
4. 準備: PHPのハンドラーマッピングの設定
今回は redmine
アプリケーションでのみ有効になるように設定するので、redmine
アプリケーションの「ハンドラー マッピング」をダブルクリックします。
右のメニューにある「モジュール マップの追加」をクリックして「モジュールマップの編集」画面で設定します。
- 要求パス
*.php
- モジュール
FastCgiModule
- 実行可能ファイル
C:\PHP\php-cgi.exe
- この例では
C:\PHP\
へPHPをインストールしたのでこのパスですが適宜環境に合わせて設定してください
- この例では
php.exe
ではなく、php-cgi.exe
の方を選ぶ- 選択画面でファイルの種類が
*.dll
になっていると*.exe
は表示されないので変更して選ぶ - 適宜PHPをインストールしたパスに変更してください
- 名前
PHP
なり、PHP-FastCGI
なり、わかりやすい名前を設定
PHP 用のグローバル FastCGI ハンドラー マッピングを作成する方法: https://learn.microsoft.com/ja-jp/iis/configuration/system.webserver/fastcgi/#how-to-create-a-global-fastcgi-handler-mapping-for-php
5. Redmine関連の設定もろもろ
やること
- Redmine Plugin Auth Remote Userを導入
- Redmineを起動
- Redmineの静的ファイルを物理パスにコピー
Redmine Plugin Auth Remote Userを導入
「REMOTE_USERを使ってRedmineで自動ログイン」でも紹介している通りにインストールと設定をします。概要のみ記載します。
プラグインのインストール
Redmineのフォルダに移動し、プラグインをcloneします。
cd redmine
git clone https://gitlab.com/redmine-plugin-auth-remote-user/redmine-plugin-auth-remote-user.git plugins/auth_remote_user
REMOTE_USERの置換設定
「Windows認証」の場合、REMOTE_USER
には domain\username
のように domain\
付きで設定されるので、「domain\username
からdomain\
の部分のみ削除」を有効にして domain\
を削除します。
注意:
- Redmine Plugin Auth Remote Userの仕様上、
REMOTE_USER
にRedmineのログインIDが含まれていないと自動ログインはできません - 置換設定を誤ると予期せぬログインが発生するリスクがありますので、機能を理解した上、入念な検証をした後にご利用ください
Redmineを起動
/redmine
というパスで運用するための設定をして起動します。
set SCRIPT_NAME=/redmine
set RAILS_RELATIVE_URL_ROOT=/redmine
ruby bin/rails server
-
SCRIPT_NAME
- 生成されるリンクのパスに
SCRIPT_NAME
で指定したパスが付与されます
- 生成されるリンクのパスに
-
RAILS_RELATIVE_URL_ROOT
- 静的ファイルのパスに
RAILS_RELATIVE_URL_ROOT
で指定したパスが付与されます
- 静的ファイルのパスに
Redmineの静的ファイルを物理パスにコピー
Redmineフォルダにはpublic/
というフォルダがあります。そこにスタイルシートや画像など静的ファイルが配置されています。
そのフォルダの中身を物理パスにコピーします。
この記事ではアプリケーションの物理パスを C:\inetpub\wwwroot\redmine
に設定したので、そのフォルダにコピーします。
public/javascripts/
であれば、C:\inetpub\wwwroot\redmine\javascripts\*
のように配置します。
(物理パスは適宜置き換えてコピーしてください。)
6. no.php
の配置と設定
https://raw.githubusercontent.com/abetomo/no.php/refs/heads/patch-clear-code/no.php をダウンロードして、C:\inetpub\wwwroot\redmine\index.php
に配置します。(配置するフォルダはアプリケーションの設定に合わせて変更してください。ファイル名もお好みで変更してください。)
(no.php
について: 本家の方だと一部機能が不足しているので、機能追加のプルリクエストを出しました。2024/09/25現在取り込まれていないため、上記のフォークリポジトリからダウンロードしてください。)
no.php
はスクリプト内で設定をするため、配置した後に直接変更をして環境に合った設定をします。
設定例:
-$backend_url = "https://myapp.backend.com:3000/";
+$backend_url = "http://localhost:3000";
$backend_info = parse_url($backend_url);
$host = $_SERVER['HTTP_HOST'];
$request_uri = $_SERVER['REQUEST_URI'];
-$uri_rel = "subdir/no.php"; # URI to this file relative to public_html
-$is_followlocation = true;
+$uri_rel = "/redmine"; # URI to this file relative to public_html
+$is_followlocation = false;
-$request_includes_nophp_uri = true;
+$request_includes_nophp_uri = false;
if ( $request_includes_nophp_uri == false) {
$backend_url
- バックエンドののURLを指定します
- ローカルで動いているRedmineをしているする場合は
http://localhost:3000
を指定します
$uri_rel
- 運用するパスを指定します
/redmine
で運用するので/redmine
を指定します- 次のセクションで説明する「IISでURL書き換え設定 >
/redmine
へのアクセスをindex.php
へのアクセスに書き換え」と連動しているので合わせて設定してください
$is_followlocation
- バックエンドのリダイレクト処理をそのそのままブラウザに返すかどうか
false
にするとそのままブラウザに返します- Redmineではログインに成功するとマイページにリダイレクトされます。それを正しく扱うために
false
を設定します
$request_includes_nophp_uri = false
- バックエンドにリクエストするときに
$uri_rel
を含めるかどうか - 今回は含まないURLを受け付けるようにRedmineを起動するので
false
にします
- バックエンドにリクエストするときに
7. IISでURL書き換え設定
/redmine
パスについて設定したいので、redmine
アプリケーションの「URL 書き換え」で設定します。
具体的には /redmine
へのアクセスを index.php
へのアクセスに書き換える設定をします。
この設定がいないと/redmine/index.php/projects
や/redmine/index.php/issues
のようにパスにindex.php
が含まれてしまいカッコよくありません。
自然なパスで利用できるように設定します。
「URL 書き換え」画面の右のメニューから「規則の追加」をクリックします。
「規則の追加」メニューが開きますので、規則テンプレートの中から「空の規則」をダブルクリックします。
表示される「受信規則の編集」で以下の通り設定をします。
- 名前
- 例では
rewrite-to-index.php
を設定しましたが適宜わかりやすい名前を設定してください
- 例では
- パターン
(.*)
- 条件
- 条件の設定で静的ファイルはIISが返すを実現します
- 「追加」で条件追加のメニューを開き、「入力文字列が次の条件を満たしているかどうかチェック」の選択肢から「ファイルではない」を選んで「OK」を押します。そうするとキャプチャの通り設定されます
- この設定でドキュメントルートに静的ファイルがある場合はそれをIISが返し、ないときは
index.php
へのアクセスへ書き換える、が実現できます
- URLの書き換え
index.php/{R:1}
{R:1}
でパターンの(.*)
にマッチした部分を参照します
- 後続の規則の処理を処理を停止する
- チェックする
この設定で /redmine/projects
というリクエストは /redmine/index.php/projects
というリクエストに内部で書き換えられます。
(「条件」の効果で /redmine/javascripts/tribute-5.1.3.min.js
といったドキュメントルートにある静的ファイルはIISが直接返します。)
おまけ: no.php
でバランサ
ApacheでリバースプロキシをしてRedmineを運用する場合、Apacheモジュールのmod_proxy_balancerを利用する場合があります。
参考: https://httpd.apache.org/docs/2.4/ja/mod/mod_proxy_balancer.html
WindowsではRedmineがマルチプロセスで動きません。
そこでRedmineのサーバを複数起動し、Apacheでロードバランスをする構成をとることがあります。
それと同等の設定を no.php
で実現するための設定例を紹介します。
Redmineの起動:
ポート番号3001、3002、3003、3004の4つのサーバを起動します。(コマンド例はイメージです)
set SCRIPT_NAME=/redmine
set RAILS_RELATIVE_URL_ROOT=/redmine
ruby bin/rails server --port 3001 --pid tmp/pids/3001.pid
ruby bin/rails server --port 3002 --pid tmp/pids/3002.pid
ruby bin/rails server --port 3003 --pid tmp/pids/3003.pid
ruby bin/rails server --port 3004 --pid tmp/pids/3004.pid
no.php
の設定:
$backend_url
の設定がポイントなので、そこの差分だけ記載します。
-$backend_url = "https://myapp.backend.com:3000/";
+$backend_urls = [
+ "http://localhost:3001",
+ "http://localhost:3002",
+ "http://localhost:3003",
+ "http://localhost:3004",
+];
+$backend_url = $backend_urls[array_rand($backend_urls, 1)];
バックエンドのURLを配列で定義して、その中からランダムで1つ選ぶ、という設定です。
まとめ
「Windows認証でRedmineに自動ログイン」の設定方法を紹介しました。
IISでリバースプロキシを実現するよくある方法(「ARR」と「URL 書き換え」を使ってリバースプロキシ)で実現できれは単純な話だったのですが、実現できなかったため、PHPでリバースプロキシを実現しました。