OpenAM/OpenIGを使用したシングルサインオン環境の構築

# はじめに
[　]() 2016年から2017年にかけて、自社内の業務システムのシングルサインオンを実現するべく、長い期間検証を行った。
検証を経て、自社の業務システム15個ほどをまとめあげたシングルサインオン環境を構築し、現在運用フェーズにある。
知っている人は知っていると思うが、日本国内だとシングルサインオン環境の構築スキルというのはあまり一般に広まっておらず、いくつかの企業による独占状態にある。
※独占というと何だか人聞きが悪いかもしれないが、SSO構築は非常に幅広い技術・知識が求められるため、ビジネスとしてやっていくにはハードルが高く、軽い気持ちで手を出せるものではないのだと思う。そのため、それほどのことを出来るような会社が日本にはさほど多くない・・・のではないだろうか。

[　]() そのため、そういった環境を作ろうと、ググってもなかなか情報は出てこないし、出てきても古い情報で役に立たない場合が多い。
日本語の情報は絶望的なほど少ないし、英語だとしても、求める情報を得られることなんて滅多にない。
誰かに教わろうにも、社内初挑戦の分野なので誰も頼れる人がいない。
そんな中で何度も泣きそうに、挫けそうになりながら、検証した結果を自身にためにも、SSOをやろうとして悩むどこかの誰かのためにも、頑張ってまとめます。
内容として、まだまだまとめきれていないし、こんな長文のまとめ記事を書くことも初めてなので大分拙い文章だとは思いますが、どうかご容赦下さい。


# SSOとは
[　]() まぁググって適当に出てきたサイト読んでくれたほうがわかりやすいと思うので、簡単に・・・

[　]() シングルサインオン(SSO)とは、とても雑に言うと、一度の認証処理で連携するアプリケーション全てで認証状態になる状態のことを指す。
例えば、自社内システムとして10個のシステムがあったとして、それぞれの社内システムを使用する度にログイン画面からログインを行っていたとする。
さらにユーザID/パスワードだけでなく、一部のシステムでは、部署名まで入力しなければならなかったとする。
さぁ、これは面倒くさい。とっても。
これがシングルサインオン環境になると、一度どこかのシステムでログインすると、その他9個のシステムでも自動的にログインが行われ、いちいちログインをする必要がなくなる。
いちいち部署名まで入れていたのに、その辺もSSOシステムが自動的にごにょごにょしてくれるので、気にする必要がなくなる。

よく目にする例としては、一度Gmailにログインすると、その後Google Driveを開いたり、Google Scheduleを開いたり、YouTubeを開いても、全て同じGoogleのアカウントでログインした状態になっていると思う。
これがシングルサインオンである。

あとは、Windowsでいうと、MicrosoftアカウントでWindows 10にログインすると、自動的にOne Driveが使用可能状態になって、DropBoxのようにローカルドライブとして使えるようになっているし、もしOffice365を契約していて適切に設定されているなら、そちらも自動的にログイン状態になってシームレスに扱える。
これもシングルサインオン。

[　]() 一度の認証処理で連携する全ての認証を済ませてしまう、という特性自体をシングルサインオンと指すため、本来対象は問わないと思うが、世間的にはWebアプリケーションに対して言われることのほうが多い気がする。なんとなく。

なので、意外と意識することは少ないのだろうけれど、実は既に様々なシステムの中で既にシングルサインオンは使われている。
本記事の中では、SSOの対象は専らWebアプリケーションのみとし、具体的な例として、社内の様々な業務システムをSSOとしてまとめあげることを想定する。

<div style="page-break-before:always"></div>

# OpenAM/OpenIGとは
[　]() そのとっても便利なSSOを実現するためのOSSとして有名なのが、OpenAMである。
そして、OpenAMと連携するアプリケーションとして、OpenIGというものも有名である。
正直、この2つの組合せで、やりたいことはほぼ出来てしまう、と思って良い。

GoogleやMicrosoft、あるいはそこまでいかずとも、それなりの技術力をもった会社なら、上記のものに頼らず自社実装でSSOを実現するのだろうけれど、その辺の企業の社内システムをSSO化したい、といったときに、フルスクラッチでSSOを作り上げる・・・なんてことは現実的ではない。

[　]() そんなとき、OpenAM/OpenIGを使えば、非常に手軽かつ迅速にSSOを実現できる。
また、GoogleやSalesforceなどの連携も標準でサポートしているので、既に自社でGApps(今はGSuiteか・・・)を使っている、といった場合でも、その辺を巻き取った上でSSOを実現できる。

[　]() OpenAMは様々なモジュールを持っていて、認証モジュールも非常に充実している。
例えばActive DirectoryやOpenLDAP、様々なRDBと連携が出来る。
つまり、SSOする際に最初に必要なログインを行うとき、OpenAM内部のデータベースで認証させる事もできるし、ADやOpenLDAPなどの別の認証ストアに任せることも出来る。
ある程度の規模の企業なら、ADやOpenLDAPなどで社員ID管理を行っているのが一般的だと思う。そういった場合にも、とても簡単に連携できる。

[　]() 以上のようにOpenAM/OpenIGは非常に強力なSSOアプリケーションであるため、探せばその他、SSOを実現するアプリケーションであったり、方式であったりいくつかあると思うが、本記事内ではOpenAMおよびOpenIGを対象にして、様々な説明や構築手法についての解説を行う。


# 代表的なSSOの方式
OpenAMを使う場合のSSOの方式として、代表的なものが3つある。
それぞれの方式について、特徴と長所、短所を紹介します。

## SSOの基本用語
まず方式の説明をする前に基本的な用語を2つ紹介します。
本記事においては、よく出てくる単語なのでまず最初に説明を・・・

### Identity Provider (IdP)
SSOにおける`認証情報を提供する側`をIdPと呼ぶ。
本記事内でいえば、OpenAMがIdPにあたる。
※OpenAMに一度ログインすれば、OpenAMと連携するSSO対象のWebアプリケーションに認証情報を提供し、自動的なログインが行われる

### Service Provider (SP)
SSOにおける`認証情報を利用する側`をSPと呼ぶ。
本記事内でいえば、各Webアプリケーション、社内の業務システムを指す。

<div style="page-break-before:always"></div>

## エージェント方式

![スライド1.PNG](https://qiita-image-store.s3.amazonaws.com/0/80163/4369f339-805f-5a83-9eb7-77ef2e3bf35d.png)

### 特徴
[　]() エージェント方式は、エージェントと呼ばれるOpenAMと連携するアプリケーションを別途サーバにインストールすることで、SSOを実現する方式である。
OpenAMでログインした場合、OpenAMから認証後Cookieが付与される。
エージェントはSPとなるWebアプリケーションのフロントに立ち、経由するHTTP通信を見て、認証後Cookieを持っているかどうかを確認する。
Cookieがなければ、OpenAMのログイン画面にリダイレクトしてログインを促し、Cookieがあればそのまま通過させる。
これらの処理をエージェントが行う。というか、これしかしない。
つまり、Cookieを持っていたとして、その結果どうするか、ログインさせるのか、ログインさせたとしてどんな認可を行うのか、といった振る舞いはWebアプリケーション側に任せられる。

### 長所
* エージェントのインストールだけなので、実装がとても楽で、幅広いWebサーバに対応している(Apache/IIS/Tomcat/Jetty/WebSphere etc...)
* 非常にシンプルな構成

### 短所
* 繰り返しになってしまうが、Cookieの有無で管理下のWebアプリケーションへアクセスさせるかどうかを決めているだけなので、エージェントを通過した後、そのままWebアプリケーションのトップページ(つまりはログインページ)に辿り着く
  * SSOの意味がない
  * これを回避するにはWebアプリケーション側でOpenAMから付与された認証後Cookieを持っている場合、ログイン済と見なす、といったロジックを追加する必要がある => `既存Webアプリケーションの改修が事実上必須`

<div style="page-break-before:always"></div>

## リバースプロキシ方式

![スライド2.PNG](https://qiita-image-store.s3.amazonaws.com/0/80163/ff71d428-1b60-da48-7fa5-cb82d6be5313.png)


### 特徴
[　]() リバースプロキシ方式、長いので以下リバプロ方式と呼ぶが、これはユーザがWebアプリケーションにアクセスする際に、必ずSSOシステムとして用意したリバプロを経由する。
このリバプロはOpenAMと連携し、ユーザID/パスワードを取得し、Webアプリケーションのログインページ内のFormにPostする処理を代行する。
これにより、SSOを実現する。つまりは、本来人間が手動で行っていたログイン作業をリバプロが自動的にやってくれる方式である。
そのため、他の方式と違い、基本的には`既存Webアプリケーションの改修は必要ない`

[　]() リバプロ方式と言うが、実はOpenAMとの連携にはエージェントを使用しているので、現実的には1つ目のエージェント方式とのハイブリット方式である。
ユーザーがリバプロURLにアクセスすると、エージェントはOpenAM認証後Cookieを持っているかどうかを判断し、なければOpenAMにリダイレクトしてログインを促す。Cookieがある場合、そのCookieを使ってOpenAMに問合せユーザID/パスワードを取得し、それをリバプロが使用してWebアプリケーションにpostしてログインを行う。これを完全に自動で行うため、ユーザーからしたらSSOしているように見える。

### 長所
* やってることが非常に単純、システムとしても単純
* 既存Webアプリケーションの改修が不必要
* SSOなしログインとSSOありログインを簡単に実現できる
  * SSOシステムが死んだら、ユーザーには通常のログインページのURLからログインしてもらえば良いだけ

### 短所
* OpenAMとは別にリバプロである`OpenIG`を構築・運用する必要があるので大変だし面倒くさい
* それぞれのWebアプリケーションに合わせた作り込みをしないといけないので、調査がかなり大変
  * WebアプリAには、このformを投げてcookieはこれを使って・・・WebアプリBはこれをこうして・・・というのを調べながら、検証しながら頑張る必要がある
  * 開発ベンダーがその辺の情報を簡単に出してくれたら良いんだけど、世の中そんなに優しくない・・・
* 必ずリバプロを経由する関係で、アクセスが集中するためリバプロのパフォーマンスが非常に大事になってくる。
* もしリバプロが死んだらSSOが一切不可能になる

<div style="page-break-before:always"></div>

## SAML方式

![スライド3.PNG](https://qiita-image-store.s3.amazonaws.com/0/80163/0e91cd42-3eb2-c31a-411e-23e3d83098f6.png)


### 特徴
[　]() SAMLとは、Security Assertion Markup Languageの略称であり、とても簡単にいうとSSOを実現するための仕様・規格である。
SAMLを実装していれば、どのWebアプリケーションでも非常に簡単にSSOを実現できるようになっている。
業界標準な方式なので、信頼性が高く、GoogleやSalesForceなど、サイボウズなど既にSAMLを実装している様々なWebアプリケーション、クラウドサービスとのSSO連携が非常に簡単に可能。

[　]() 本来は、この方式はフェデレーション方式と呼ぶのだと思う。(他のメディアだとそう書いている)
というのも、こういったことはSAMLだけでなく、最近ではOpenIDと呼ばれる規格も普及してきており、基本的な概念は同じである。
そのため、それらをまとめてフェデレーション方式と呼ぶ。が、SAMLがまだまだ主流だと思うので、こう書かせてもらいました。
あと自分自身、OpenIDでの検証をやっていないのでよくわからないってのもある。

### 長所
* 信頼性が高く、設定・構築が簡単
* セキュアな通信・やり取りが可能
* 認証情報/認可情報もSAMLでやりとりされるので、Webアプリケーション側で情報を持たなくて良い
 * 例えば、リバプロ方式の場合、認証処理はWebアプリケーション内部で行われる関係で、ユーザID/パスワードなどの情報は自身の中で保有しておかなければならない

### 短所
* インターネット上のWebアプリケーション、クラウドサービスならSAMLは当たり前のように対応しているが、社内の業務システムでSAMLに対応している、というパターンはほぼない
  * パッケージ製品を使っているならSAML対応の可能性がある
  * フルスクラッチの独自システムならSAMLに対応しているのは絶望的
   * そのため、対応していないなら、`既存Webアプリケーションの改修が必須`
* SSLを使用する関係で、証明書の用意が必要
* どう動作しているか、流れや仕様の理解が非常に難しく、うまくいかないことがあるとトラブルシュートが難しい (私のスキルが足りないだけなんだけど・・・)

<div style="page-break-before:always"></div>

# 実際のSSO環境の構築について
[　]() SSOを実現するにあたって、手っ取り早いのがOpenAMを使用することなので、本記事においても、OpenAMを使用したSSO環境の構築について説明を行う。
また、既存Webアプリケーションの改修を行わない、あるいは、行えない、ということも多々あるかと思うので、OpenIGを組合せたリバプロ方式についての説明を主とする。
※エージェント方式に軽く触れます。SAMLはいつか記事として書くかも・・・検証はやってはいるがまだまだ内容が甘く理解しきれていない点が多々あるので、まだ記事にできるレベルではないです。
OpenAMとOpenIGは有償版ではなく、無償版を使用する。バージョンは2017年3月時点で最新のOpenAM v13.0とOpenIG v4.0 を使用する。

[　]() どの構築記事についても言えることだが、OpenAMとOpenIGはリファレンスガイドが非常に充実しているので、基本的にはそういった公式から提供されているガイドを読めば、だいたいの構築は行える。
ただ、OpenAMもOpenIGもやれることが多すぎる関係で、実際に社内の業務システムをSSOとしてまとめようとしたときに、どうやって実現すればいいのかわからない、どこから手を付ければ良いかわからない、となってしまう。(私がそうでした)

というのも、OpenAMにしろ、OpenIGにしろ、とりあえずのGetting Startedは用意されているので、試すだけならさほど難しくはないんだけど、こういったときにはこうする、といったSample/Exampleがほとんど載っていないので、実環境への適用に本当に苦労する。全然わからない。さっぱり。
要はこの機能を使いたいならこう設定してね、ということは載っていても、こういうパターンのときにこれとこれをこうして、ああすれば良いんだよってのが全くわからない。
現実のWebアプリケーションは単純ではないので、リファレンスガイドの内容を読み込んだとしても、ほぼ太刀打ちできないと思う。

そのため基本的な構築はもちろんのこと、こういったパターンのときにはこうしてみたら良いかも、とちょっと実践的な手法も載せていきたいと思っている。
ただ、あくまで私が独自に検証を重ねた結果、こういうやり方をした、ということを示しているだけで、ベストプラクティスだとは思えないし多分違う。絶対違う。

[　]() この辺はSSOを得意としてるベンダーさんは色々と素晴らしいノウハウを持っているんだろうけど、何分初挑戦のゼロノウハウの状態から始めたので、全く洗練はされていないです。
読んでくれている方には本当に申し訳ないんだけれど、その辺はご容赦下さい。あくまで参考程度に・・・
そして、読んでくれた優しい人達の中に、詳しい方がいて、いやいやそれは間違ってるよ、こんな方法のほうが良いよ、とか、その知識は間違っている、といったことがあったら、是非是非教えて欲しいです。
土下座するので本当に教えて欲しいです。本当にお願いします。

## 共通情報
以下に構築についての具体的な目次と記事を記すが、どの記事においても共通する情報を事前にまとめておく。

* サーバOS
  * OpenAM/OpenIG: CentOS7.3
* ホスト名
  * OpenAM: sso.test.local
  * OpenIG: openig.test.local
* IPアドレス
  * OpenAM: 172.16.1.130
  * OpenIG: 172.16.1.131

<div style="page-break-before:always"></div>

## 目次
以下に羅列した記事は公開済あるいは近日公開予定です。
予定なので、増えたり、減ったりするかもです。

* [Tomcat インストール](http://qiita.com/gzock/items/4c5cb135f3bb240b1213)
* [Jetty インストール](http://qiita.com/gzock/items/a988eb5742de09949eee)
* Tomcat / Jetty パフォーマンスチューニング
* OpenAM
  * [インストールと初期セットアップ](http://qiita.com/gzock/items/d7d68e5fd3bdefed3db7)
  * [Web Policy Agent for Apache セットアップ](http://qiita.com/gzock/items/a64940833dbaae9802db)
  * [Web Policy Agent for Nginx セットアップ](http://qiita.com/gzock/items/3e2d61b39d92646e687c)
  * [J2EE Policy Agent セットアップ](http://qiita.com/gzock/items/ac28015aaf1f9940c832)
  * [ユーザ一括追加](http://qiita.com/gzock/items/3399c8d4f5c526c29af0)
  * [データストア追加 (AD連携)](http://qiita.com/gzock/items/2702342f9838a010d79d)
  * [ログイン画面日本語化](http://qiita.com/gzock/items/a2df9d47eb5813ea090e)
  * チューニング

* OpenIG
    * [インストールと初期セットアップ](http://qiita.com/gzock/items/1c3ba22e06f284132729)
    * [OpenAM連携](http://qiita.com/gzock/items/3daa08d6f8562d58534e)
    * [ルートファイル作成](http://qiita.com/gzock/items/0ffe8a73ac1ba12685a2)
    * [多段プロキシ構成](http://qiita.com/gzock/items/68f195a5bcc2f2a947b1)
    * OpenIGの困った話
        * shift_jisが扱えない
        * syslogのバグ
        * Cookie処理のバグ
        * 不思議な二連POSTの話
    * [対httpsサイト](https://qiita.com/gzock/items/bb51a8bdfccc86cb0df0)
    * チューニング


### そのうち書くかも・・・？
優先度としては低め(まずは上のやつが先)なんだけど、そのうち記事として書きたいなーという内容

* SAMLの話
* デスクトップSSOの話
* OpenAM/OpenIG SSL化
* OpenDJの話
* OpenAM 冗長構成
  * ステートフル構成
  * ステートレス構成
* 二要素認証