OpenIG v4 on CentOS7

# はじめに
#### 本記事は、[OpenAM/OpenIGを使用したシングルサインオン環境の構築](http://qiita.com/gzock/items/af6f820b5e872366e853)という記事から続く関連記事の一部です

本記事では、リバプロ方式でのSSOを実現するべく、既にJettyが構築してあることを前提に、OpenIGのインストールから初期セットアップをし、OpenIGが動作するまでを目指す。

最終的にはOpenAMと連携させるのだけど、やることがかなり多いので、まずはOpenIG単体での動作を目指す。
基本的に本記事は、ForgerockのOpenIGのところから落とせる「openig-4-gateway-guide.pdf」という公式ガイドに基いている。
具体的には、P14から始まるGetting Startedを日本語にして画像を交えて説明し直している。
なので英語得意な人は公式ガイド読んだほうが絶対に早い。

# 前提
* OpenIGをインストールするサーバはCentOS7.3を想定
* OpenIGは無料で手に入るv4.0を使用
* OpenIGはJavaアプリケーションサーバとしてjettyを使用する
    * そのためJettyをインストール済であること
* 検証目的の構成を行う

# 環境
* OpenAM側
  * サーバOS: CentOS7.3
  * ホスト名: sso.test.local
  * IPアドレス: 172.16.1.130
  * JDK Ver: 1.8.0_111
  * Tomcat Ver: 8.0.39
  * OpenAM Ver: 13.0.0

* OpenIG側
  * サーバOS: CentOS7.3
  * ホスト名: openig.test.local
  * IPアドレス: 172.16.1.131
  * JDK Ver: 1.8.0_111
  * Jetty Ver: 8.1.21
  * OpenIG ver: 4.0.0


# 構築作業

## OpenIGの入手
OpenIGはForgerockという会社が開発・公開しているので、以下のURLからIG => Open Identity Gateway => 4.0.0 => OpenIG 4 と辿って、.warを落としてくる。
[https://backstage.forgerock.com/downloads/OpenIG/Open%20Identity%20Gateway/4.0.0/OpenIG](https://backstage.forgerock.com/downloads/OpenIG/Open%20Identity%20Gateway/4.0.0/OpenIG
)

恐らく`subscription only`というラベルが付いていてDLできないようになっていると思うが、これはサインインしていないため。
面倒くさいけど、まずは右上の`Register`から、アカウントを作ってサインインする必要がある。
ちなみに、サインインしたとしても`subscription only`になっているものに関しては、それはお金払わないと落とせないやつら。
一部、そういうのがある。

## OpenIG配置
公式から頂戴した.warを対象サーバにアップロード。
※私は自PCに落としてsftpで持っていった
OpenAMと同じでDLした.warをJettyのwebappsフォルダ配下に配置すればそれで終わり。
ただし、/ で見れるように配置する。(root.warとすることで/になる)

```
[root@openig ~]# mv openig-war-4.0.0.war /opt/jetty/webapps/root.war
[root@openig ~]# cd /opt/jetty/webapps/
[root@openig ~]# chown jetty:jetty root.war
[root@openig ~]# systemctl restart jetty
```

### 動作確認
jettyを再起動後、WebブラウザでリバプロのURLにアクセスしてみる。
今回であれば、http://openig.test.local:8080/
そして、OpenIGと大きなAAで書かれたページが表示されたら、OpenIGとしては正しく動作している。
もちろん、この状態ではリバプロとしてまともに動かないので、コンフィグファイルを作成していく。

## OpenIG関連のコンフィグファイルを作成
OpenIGは実行ユーザのホームディレクトリ配下に存在する`.openig`フォルダの中の様々なコンフィグファイルを読み込み動作をする。
まずはフォルダを作成。

```
[root@oepnig ~]# su - jetty
[jetty@openig ~]# mkdir -p .openig/config/routes
```

Jetty実行ユーザのホームディレクトリ配下の.openig配下にさらに`config`フォルダ、そのさらに下に`routes`フォルダを用いする。これでお膳立てはOK
configフォルダ配下には、config.jsonというコンフィグファイルを配置する。
OpenIGは起動時にこのファイルを勝手に読み込み、OpenIGのグローバル設定として使用する。
さらに下のroutesフォルダ配下には、ルートファイルというファイル群がたくさん配置される。
ルートファイルというのは私が勝手に読んでいる名称なのだが、簡単に言うとOpenIGにおけるSSO連携対象のバックエンドサーバ(リバプロ先)を定義するファイルで、SSO連携対象1つにつきルートファイルを1つ作ることになる。
ルートファイルの中でどのURLに対してリバプロするのか、どんなFormをPOSTしてログイン代行処理を行うのか・・・といったことを定義する。
これらルートファイルも配置さえしておけばOpenIGが勝手に読み込んでくれる。
OpenIGにおけるこういった各種ファイルは全てjson形式での記述になる。

まずは基本的なconfig.jsonが、OpenIGのGetting Startedに載っているので、それを流用する。

```
[jetty@openig ~]# vim .openig/config/config.json
{
        "handler": {
        "type": "Router",
        "audit": "global",
        "baseURI": "http://sso.test.local:8080",
        "capture": "all"
        },
        "heap": [
                        {
                        "name": "LogSink",
                        "type": "ConsoleLogSink",
                        "config": {
                                "level": "DEBUG"
                                }
                        },
                        {
                                "name": "JwtSession",
                                "type": "JwtSession"
                        },
                        {
                                "name": "capture",
                                "type": "CaptureDecorator",
                                "config": {
                                        "captureEntity": true,
                                        "_captureContext": true
                                }
                        }
        ]
}
```

ひとまず、超基本的なルートファイルを配置して動作を見てみる。

```
[jetty@openig ~]# vim .openig/config/routes/99-default.json

{
  "handler": "ClientHandler"
}
```

* 再起動
```
[jetty@openig ~]# exit
[root@openig ~]# systemctl restart jetty
```

### 動作確認
http://openig.test.local:8080 にアクセスすると、sso.test.local:8080のtomcatの画面が見えるはず。見えたら正常動作している。
何故、こんな動作になるかと言うと、config.jsonのbaseURIの中で、tomcatのURLを指定しているからである。
baseURIはリバプロの対象URLにアクセスしたとき、どこにリバプロするか、つまりリバプロ先のURLを決める値である。
config.jsonはグローバル設定であるため、OpenIGのルートパスにアクセスした今回の場合、config.jsonのbaseURIの設定が採用される。
今後、たくさんのルートファイルを作っていくと、こういったconfig.jsonのbaseURIに出会うことはまずなくなるのだが・・・
とりあえず今回は動作確認のため。
それでは、個別のルートファイルを作り、OpenIGのログイン代行処理を実現してみる。

## ルートファイル作成
ここでは、サンプルアプリケーションに対して自動的にPostするルートファイルを作成する。
Getting Started上にも載っている素敵なサンプルアプリケーションがあるので、是非使わせてもらいましょう。

```
[jetty@openig ~]# wget http://maven.forgerock.org/repo/releases/org/forgerock/openig/openig-doc/4.0.0/openig-doc-4.0.0-jar-with-dependencies.jar
[jetty@openig ~]# java -jar openig-doc-4.0.0-jar-with-dependencies.jar
Preparing to listen for HTTP on port 8081.
Preparing to listen for HTTPS on port 8444.
The server will use a self-signed certificate not known to browsers.
When using HTTPS with curl for example, try --insecure.
Using OpenAM URL: http://openam.example.com:8088/openam/oauth2.
Starting server...
3 24, 2017 3:48:19 午後 org.glassfish.grizzly.http.server.NetworkListener start
情報: Started listener bound to [0.0.0.0:8444]
3 24, 2017 3:48:20 午後 org.glassfish.grizzly.http.server.NetworkListener start
情報: Started listener bound to [0.0.0.0:8081]
3 24, 2017 3:48:20 午後 org.glassfish.grizzly.http.server.HttpServer start
情報: [HttpServer] Started.
Press Ctrl+C to stop the server.
```

これで、ポート8081でサンプルアプリケーションが動作する。
試しにWebブラウザからアクセスしてみると、下図のような画面が表示されるはず。

![2017-03-24-15-50-05.png](https://qiita-image-store.s3.amazonaws.com/0/80163/2fd0325e-d612-b0c8-42a9-9f5be9427ccf.png)

右上のFormに`demo/changeit`というID/パスワードでログインしてみると、アクセス情報が表示される。これがログイン後画面。
ログインユーザ名とHttp Headerなどが表示される。

![2017-03-24-15-51-35.png](https://qiita-image-store.s3.amazonaws.com/0/80163/8d2432a6-3a0a-52db-5f86-a0f26bc73e7c.png)

このサンプルアプリケーションに自動的にログインするルートファイルを作成する。
といっても、これもGetting Startedに載っているルートファイル。
ルートファイルに関しては、保存すると自動的にOpenIGに読み込まれるので、サービスを再起動やリロードする必要はない。

```
[jetty@openig ~]# vim .openig/config/routes/99-default.json

{
    "handler": {
        "type": "Chain",
        "config": {
            "filters": [
                {
                    "type": "StaticRequestFilter",
                    "config": {
                        "method": "POST",
                        "uri": "http://openig.test.local:8081",
                        "form": {
                            "username": [
                                "demo"
                            ],
                            "password": [
                                "changeit"
                            ]
                        }
                    }
                }
            ],
            "handler": "ClientHandler"
        }
    },
    "condition": "${matches(request.uri.path, '^/static')}"
}
```

簡単に説明すると、StaticRequestFilterというのは、名前の如くHTTPリクエストを生成するフィルターであり、今回の場合はサンプルアプリケーションに対して、username: demo, password: changeit というFormをPOSTしている。
また、conditionというのは、このルートファイルが適用される条件を示す。
conditionがtrueになった際、このルートファイルが採用される。
上記のルートファイルの場合、ユーザからのリクエストURIのパスが前方一致で/staticであった場合、このルートファイルが採用される。
matchesというのは、第一引数に文字列、第二引数に正規表現をとり、存在すればtrueを返してくれる関数である。
こういった便利な関数がOpenIGにはたくさん用意されているので、これらを組み合わせることにより、複雑な条件指定が指定できる。
この辺のルートファイルの中身の詳しい説明は[別記事](http://qiita.com/gzock/items/0ffe8a73ac1ba12685a2)にまとめます。

### 動作確認
さて、話を戻して、この状態で、http://openig.test.local/static にアクセスする。
そうすると、サンプルアプリケーションのログイン後画面が表示されるはず。おぉ勝手にログインできた。SSOっぽい。
これで、OpenIG単体としてはリバプロ動作による自動的なログイン代行処理を行えたことになるが、まだこの状態では正直SSOとはいえない。それっぽくはあるが。

次のステップとしては、OpenAMと連携する。
OpenAMとの連携には公式に提供されているJ2EEエージェントを利用する。
OpenAMと連携しOpenAMにさえログインできていればOpenIG側でもその認証情報を使ってSSO連携対象のWebアプリにログインできるようにする。まさにSSOの実現といえる。
この話はとても話が長くなるので、[別記事](http://qiita.com/gzock/items/3daa08d6f8562d58534e)として分けます。