[CentOS6][OpenAM10] OpenAMを試す - OpenIGの代理認証を試す


Create: 2014/02/10
LastUpdate: 2014/02/22
≪ メニューに戻る

ここでは、OpenAMのテスト環境を構築したときの手順の一部を紹介します。
テスト環境の概要は、メニューを参照してください。
「テスト用WEBサイト」にOpenAMでSSOするには、ユーザの代わりに機械的にユーザIDとパスワードを入力してログインする代理認証の仕組みが必要になります。
ここでは、SSOを試す前に、通常は、SSOと連携して使用する代理認証の機能だけを先に試します。
代理認証機能は OpenIGで提供してくれます。OpenIGでリバースプロキシを構築し、リバースプロキシ経由でWEBサイトにアクセスした場合は、自動的にログイン済みの状態になるようにし、ユーザのログイン操作が不要になるようにします。
システム構成のイメージは以下のとおり。
ユーザ端末とWEBサーバの間にリバースプロキシが入ります。リバースプロキシは CentIS6.4 + Tomcat6 + OpenIG とします。


 ユーザ端末:192.168.1.91
 リバースプロキシサーバ:192.168.1.93
 WEBサーバ:192.168.1.94

環境構築と動作確認の手順は、以下のとおり。
  1. リバースプロキシ・サーバの構築(CentOS6 + Tomcat6 + OpenIG)
  2. 動作確認

1.リバースプロキシサーバの構築

CentOS6 + Tomcat6 + OpenIGの組み合わせで代理認証機能をもったリバースプロキシを構築します。

1.1.CentOS6のインストール


CentOS6のインストール手順は、「 [XenServer 6.1.0] CentOS6.4(32bit)のネットワーク・インストール」を参照してください。
今回は、以下のような設定にします。
  • OS:CentOS6.4 (32bit)
  • SELinux:無効
  • ファイヤーウォール:無効
  • タイムゾーン:Asia/Tokyo
  • 言語:ja_JP.UTF-8
  • パッケージ:最小構成
  • ホスト名: exig01
  • IPアドレス: 192.168.1.93

1.2.JAVA SE JDKのインストール


OpenIGは、JAVA SE JDK6 Update21 以降が必要です。
Oeracleのサイトから JDK をダウンロードしてインストールします。
今回は、JDK6をダウンロードしました。
ダウンロードしたファイルをサーバにおいて、以下のように実行してインストールします。
# sh ./jdk-6u45-linux-i586-rpm.bin

1.3.Tomcat6 のインストール


OpenIGを動かせるアプリケーションサーバは、Tomcat6/7、Jetty6/7、JBoss5 などがありますが、今回は、Tomcat6 をインストールします。
以下のように yum を実行して Tomcat6 をインストールします。
# yum install tomcat6
Tomcat6 が、上記1.2でインストールした JDK6 を使用するように設定します。
/etc/sysconfig/tomcat6 を以下のように修正します。
JAVA_HOME="/usr/java/default"
Tomcat6はデフォルトで 8080 ポートを使用しますが、今回は、バックエンドになる「テスト用WEBサイト」と同じ80 ポートでアクセスできるようにしたいので、Tomcat6にも80ポートでアクセスできるように設定します。
80ポートを使用するには、root 権限が必要ですが、Tomcat6 のサービスは、tomcatユーザで実行されるため、単純に設定変更してポート番号を変更してもうまくいきません。
なので、今回は、80ポートへのアクセスを8080ポートにNATするように設定することにします。
iptabes コマンドを以下のように実行して NAT します。
iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
このままだと、サーバを再起動すると設定が消えてしまうので、現在の iptables の設定を/etc/sysconfig/iptablesに保存して、サーバ起動時に保存した設定を自動的に適用するようにします。
# service iptables save
# chkconfig iptables on
iptables の設定を表示して見たい場合は以下のようにservice コマンドを実行します。
赤字部分が、今回設定したTomcat用の設定です。
# service iptables status
テーブル: nat
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 redir ports 8080

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
次に、「Tomcat6自身は8080番ポートで待機するが、リクエストは80番ポートで受け付ける」ということを設定します。具体的には、設定ファイルのConnector要素にproxyPort属性を追加します。
/usr/share/tomcat6/conf/server.xml を以下のように修正します。(赤字部分)
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               proxyPort="80" />
Tomcat6 のサービスを自動起動/停止するように設定して、サービスを起動します。
# chkconfig tomcat6 on
# service tomcat6 start

■ 参考にしたページ

1.4.OpenIGのインストール


OpenIGのコミュニティ版は、ForgeRockのダウンロードサイトで、WARファイルで提供されています。
  • http://forgerock.org/openig-archive.html
今回は、wget コマンドを使って gateway-2.1.0.war ファイルをダウンロードしました。
# wget http://download.forgerock.org/downloads/openig/2.1.0/gateway-2.1.0.war
ダウンロードした gateway-2.1.0.war ファイルを、Tomcat6 に配置します。しばらくすると、自動的にROOT.warが展開されてROOTディレクトリができるので、webapps 以下のファイル/ディレクトリの所有者を tomcat にしておきます。
# cp ./gateway-2.1.0.war /usr/share/tomcat6/webapps/ROOT.war
# chown -R tomcat.tomcat /usr/share/tomcat6/webapps
これで、OpenIGのアプリケーションを設置できたので、こんどはOpenIGの設定を行います。
設定ファイルの格納場所は、Tomcat6実行ユーザのホームディレクトリの “.ForgeRock/OpenIG" ディレクトリです。
設定ファイル名は、"config.json" です。
今回だと、”/usr/share/tomcat6/.ForgeRock/OpenIG/config.json" がOpenIGの設定ファイルになります。
初期状態では、設定ファイルを格納するディレクトリが存在しないので新規作成します。
# mkdir -p /usr/share/tomcat6/.ForgeRock/OpenIG
# chown -R tomcat.tomcat /usr/share/tomcat6/.ForgeRock
ディレクトリができたら、config.json ファイルにOpenIGの設定を記述します。
JSON形式でパラメータを記述するので、少しわかりにくいですが、今回は、以下のように設定しました。
{
    "heap": {
        "objects": [
            {
                "name": "HandlerServlet",
                "type": "HandlerServlet",
                "config": {
                    "handler": "DispatchHandler",
                    "baseURI": "http://192.168.1.94:80"
                }
            },
            {
                "name": "DispatchHandler",
                "type": "DispatchHandler",
                "config": {
                    "bindings": [
                        {
                            "condition": "${matches(exchange.request.uri.path,'^/demo1/.*') != null}",
                            "handler": "LoginChain1",
                        },
                        {
                            "condition": "${exchange.request.uri.path == '/demo2/logon.php'}",
                            "handler": "LoginChain2",

                        },
                        {
                            "handler": "OutgoingChain",
                        }
                    ]
                }
            },
            {
                "name": "LoginChain1",
                "type": "Chain",
                "config": {
                    "filters": ["ApacheAuthenticator"],
                    "handler": "OutgoingChain"
                }
            },
            {
                "name": "ApacheAuthenticator",
                "type": "HttpBasicAuthFilter",
                "config": {
                    "username": "user01",
                    "password": "p@ssw0rd",
                    "failureHandler": "OutgoingChain"
                }
            },
            {
                "name": "LoginChain2",
                "type": "Chain",
                "config": {
                    "filters": ["LoginRequestFilter2"],
                    "handler": "OutgoingChain"
                }
            },
            {
                "name": "LoginRequestFilter2",
                "type": "StaticRequestFilter",
                "config": {
                    "method": "POST",
                    "uri": "http://192.168.1.94:80/demo2/logon.php",
                    "form": {
                        "id": ["user01"],
                        "pwd": ["password"],
                        "login": ["login"],
                    }
                }
            },
            {
                "name": "OutgoingChain",
                "type": "Chain",
                "config": {
                    "filters": ["CaptureFilter"],
                    "handler": "ClientHandler"
                }
            },
            {
                "name": "CaptureFilter",
                "type": "CaptureFilter",
                "config": {
                    "captureEntity": true,
                    "file": "/tmp/gateway.log"
                }
            },
            {
                "name": "ClientHandler",
                "type": "ClientHandler",
                "config": {
                }
            }
        ]
    },
    "servletObject": "HandlerServlet"
}
設定内容は、以下のとおり。
  • 赤:リバースプロキシの設定
    tomcatへのリクエストをWEBサーバ(192.168.1.94)に中継します。
  • 緑:URLによる制御
    どの代理認証設定(青、茶)を適用するかURLで制御します。
    a) /demo1/以下のURLが指定された場合は、BASIC認証用の代理認証を実施します。
    b) /demo2/logon.php のURLが指定された場合は、フォーム認証用の代理認証を実施します。
    c) 上記a)、b)以外のURLが指定された場合は、代理認証を実施しません。
  • 青:BASIC認証用の代理認証
    固定のユーザ(user01)、パスワード(p@ssw0rd)を使用して自動的にログインします。
  • 茶:フォーム認証用の代理認証
    固定のユーザ(user01)、パスワード(password)を使用して自動的にログインします。
  • 紫:OpenIGのログファイル出力
    OpenIGのログをファイルに出力します。

■参考URL

2.動作確認


ユーザ端末から上記1のリバースプロキシにアクセスして動作を確認します。
リバースプロキシには、以下のURLでアクセスします。リバースプロキシ経由でWEBサーバにアクセスする場合と、直接WEBサーバにアクセスする場合の違いを見れるように、異なるURLにしておきます。
  • http://exig01.example.com
今回はDNSサーバを用意していないので、管理者モードでエディタ(メモ帳など)を起動して、C:\windows\system32\drivers\etc\hosts に以下の内容を追記します。
192.168.1.93    exig01.example.com
ブラウザでリバースプロキシのURLにアクセスすると、下図のようにWEBサーバのページが表示されます。



[BASIC認証]ページをクリックすると、BASIC認証用のダイアログが表示されずに下図のページが表示されます。
OpenIGの代理認証機能で、自動的にログイン済みの状態になっているので、ヒトが、ユーザIDとパスワードを入力する必要がありません。



トップページに戻って、[フォーム認証ページ]をクリックします。



 下図のようにログイン後のページが表示されます。
OpenIGの代理認証機能で、自動的にログインが実行されているので、ヒトがユーザIDとパスワードを入力する必要がありません。



OpenIGのログを見てみると、WEBサーバへのリクエストと、WEBサーバからのレスポンスを確認できます。
[BASIC認証ページ]へアクセスしたときのログは以下のとおり。
OpenIGが、赤字で示したHTTPヘッダでBASIC認証を認証済みにしていることがわかります。
--- REQUEST 16 --->

GET http://192.168.1.94:80/demo1/ HTTP/1.1
cookie: JSESSIONID=1A70CFA6081E3D5CF79F51E834748C7F; PHPSESSID=3so3cii9vis4cce56ai2sp2hi1
connection: Keep-Alive
Authorization: Basic dXNlcjAxOnBAc3N3MHJk
host: exig01.example.com
accept-language: ja-JP
accept: text/html, application/xhtml+xml, */*
user-agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)
dnt: 1
accept-encoding: gzip, deflate
referer: http://exig01.example.com/

<--- RESPONSE 16 ---

HTTP/1.1 200 OK
ETag: "4236a-d6-4ee8f9f3b102b"
Date: Sun, 29 Dec 2013 00:41:14 GMT
Content-Length: 214
Last-Modified: Sat, 28 Dec 2013 03:15:26 GMT
Content-Type: text/html; charset=UTF-8
Accept-Ranges: bytes
Server: Apache/2.2.15 (CentOS)

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>DEMO1 PAGE</title>
</head>
<body>
<h1>DEMO1 PAGE</h1>
<p>BASIC認証で保護されたページです。</p>
</body>
</html>

[フォーム認証ページ]へアクセスしたときのログは、以下のとおり。
[REQUEST 19]の赤字部分で、OpenIGがユーザIDとパスワードを渡していることがわかります。
--- REQUEST 19 --->

POST http://192.168.1.94:80/demo2/logon.php HTTP/1.1
Content-Length: 34
Content-Type: application/x-www-form-urlencoded

id=user01&pwd=password&login=login

<--- RESPONSE 19 ---

HTTP/1.1 302 Found
Date: Sun, 29 Dec 2013 00:44:56 GMT
Content-Length: 0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Location: main.php
Set-Cookie: PHPSESSID=dg5see7ovd2lq21dciquc67em0; path=/
Set-Cookie: PHPSESSID=12aa1l4r25gu04q0rt2onko9c7; path=/
Content-Type: text/html; charset=UTF-8
X-Powered-By: PHP/5.3.3
Server: Apache/2.2.15 (CentOS)
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0



--- REQUEST 20 --->

GET http://192.168.1.94:80/demo2/main.php HTTP/1.1
cookie: JSESSIONID=1A70CFA6081E3D5CF79F51E834748C7F; PHPSESSID=12aa1l4r25gu04q0rt2onko9c7
connection: Keep-Alive
host: exig01.example.com
accept-language: ja-JP
accept: text/html, application/xhtml+xml, */*
user-agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)
dnt: 1
accept-encoding: gzip, deflate

<--- RESPONSE 20 ---

HTTP/1.1 200 OK
Date: Sun, 29 Dec 2013 00:44:56 GMT
Content-Length: 309
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Content-Type: text/html; charset=UTF-8
X-Powered-By: PHP/5.3.3
Server: Apache/2.2.15 (CentOS)
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0


<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>DEMO2 PAGE - main</title>
  </head>
  <body>
  <h1>DEMO2 PAGE - main</h1>
  <p>ようこそuser01さん</p>
  <ul>
  <li><a href="logout.php">ログアウト</a></li>
  </ul>
  </body>
</html>