Policy Agentを組み込んだApacheをリバースプロキシにする

## 今日やること

今日はPolicy Agentを導入したWebサーバーをリバースプロキシにします。リバースプロキシの先には、また別のWebサーバーをセットアップします。

文字で書いてもわかりにくいので、簡単に図を書いてみます。

![001.jpg](https://qiita-image-store.s3.amazonaws.com/0/148404/55234f6e-a3b6-b892-5526-a67b8ec8c65c.jpeg)

（かえってわかりにくい...？）
位置関係が分かってもらえればいいかなとおもいます。
ユーザーはOpenAMで認証後、Policy Agentが導入されたProxyにアクセスします。
Proxyは`/org/`パス以下にアクセスがあると、Originにリバースプロキシするという構成です。

この構成の嬉しいところとしては、以下のような点が挙げられます。

* OriginにPolicy Agentを導入しなくていい
    - 本当はOriginのWebサーバーに導入するものだけど、Originにそのような変更が加えられない場合などに有用です
* たくさんのアプリをリバースプロキシにぶら下げられる
    - リバースプロキシをガチガチに固めて、バックエンドのアプリのかわりにセキュリティの実装をしてあげられる
    - `/org1`にアクセスされるとOrigin 1、`/org2`にアクセスされるとOrigin 2...みたいな

## 準備

### SSOのみモードをONに

今回は認可制御は不要なので、**SSOのみモードをON**にしときましょう。

[12月3日の記事](http://qiita.com/nanazero/items/10a593c6b0ac770ee92e#openam側にpolicy-agentの設定をつくる)を参考に設定しましょう。

### Originサーバーの準備

こちらはただのApacheサーバーです。本記事では以下のような構成です。

* OS
    - CentOS 6.8(Vagrant)
* Memory
    - 512MB
* FQDN
    - org.example.com

また、Apacheのコンテンツとして下記コンテンツを配置します。

```bash
$ tree /var/www/html/
/var/www/html/
├── img
│   └── openam-alone.jpg
└── index.html
```

直接、`https://org.example.com/index.html`にアクセスすると以下のような表示がされます。

<img width="370" alt="002.JPG"  border="1" src="https://qiita-image-store.s3.amazonaws.com/0/148404/70e76d5f-8275-b871-1305-bd82138d68eb.jpeg">

## リバースプロキシの設定

それではPolicy Agentを導入したWebサーバー（Apache）をリバースプロキシに仕立てましょう。**ここからの作業は全てWebサーバー上（web.example.com）で行います**。

事前にhostsを編集して、Originの名前解決ができるようにしておきましょう。
こんな感じです。

```bash
$ sudo diff /etc/hosts{,.org}
3,5d2
< 192.168.33.10 iam.example.com
< 192.168.33.20 web.example.com
< 192.168.33.30 org.example.com
```

### ssl.confの設定

`/etc/httpd/conf.d/ssl.conf`の設定を変更します。

```bash
$ sudo diff /etc/httpd/conf.d/ssl.conf{,.org}
222,224d221
< SSLProxyEngine on
< ProxyPass /org https://org.example.com
< ProxyPassReverse /org https://org.example.com
```

`ProxyPass`と`ProxyPassReverse`はApacheのリバースプロキシ設定です。適当に言うと、**/orgにアクセスされたら`https://org.example.com`にプロキシする**っていう設定です \\(´ー｀)ﾉ
設定の詳細な内容はApacheのサイトをご参照ください。

* [ProxyPassディレクティブ](https://httpd.apache.org/docs/2.2/ja/mod/mod_proxy.html#proxypass)
* [ProxyPassReverseディレクティブ](https://httpd.apache.org/docs/2.2/ja/mod/mod_proxy.html#proxypassreverse)

`SSLProxyEngine`はHTTPSのサイト（今回は`https://org.example.com`）にリバースプロキシする際に必要な設定です。
設定の詳細な内容なApacheのサイトをご参照ください。

* [SSLProxyEngine](https://httpd.apache.org/docs/2.2/ja/mod/mod_ssl.html#sslproxyengine)

設定が終わったら、Apacheを再起動します。

```bash
$ sudo service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
```

### 確認

それでは、実際にプロキシを行うパス（`https://web.example.com/org/`）にアクセスしてみましょう。OpenAMのサインインはどのユーザーでも構いません。

<img width="367" alt="003.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/d74e66f7-7fc0-318b-de88-9fe46e4a1619.jpeg">

先ほど、リバースプロキシを返さずに閲覧した時とは異なり、画像が閲覧できません。
理由はデベロッパーコンソールを見るとわかります。

<img width="456" alt="004.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/db604925-1365-09d6-e251-217d6ff4f2ac.jpeg">

問題の箇所は**リクエストを送ったパス**になります。リバースプロキシの設定は**`/org`以下のアクセスを`https://org.example.com`にプロキシする**となっているので、`/img/openam-alone.jpg`のリクエストはプロキシされずに**404 Not Found**となってしまうのです。

これは、`org.example.com`が`/img/openam-alone.jpg`で画像を配信しようとしているために起こる事象であり、今回のような特定のパス以下を別のWebサーバーにプロキシするという構成をとったときに、よくある事象だそうです。

### mod_substituteの設定

とはいえ、コンテンツがちゃんと見えないと困ります。そんな悩みを解決するmod_substituteというApacheのモジュールがあります。これを使って、プロキシ先から返却されるコンテンツの書き換えを行うことができます。

たとえば、今回ですと`https://org.example.com/index.html`から返却されるコンテンツは、

```html
<img src="../img/openam-alone.jpg" width="384" height="256">
```

ですが、これを

```html
<img src="/org/img/openam-alone.jpg" width="384" height="256">
```

という感じで、リバースプロキシ経由でもしっかり見れるように書き換えを行うことができます。

では、先ほどに引き続き、`/etc/httpd/conf.d/ssl.conf`に設定を追加します。

```bash
$ sudo diff /etc/httpd/conf.d/ssl.conf{,.org}
222,226d221
< SSLProxyEngine on
< ProxyPass /org https://org.example.com
< ProxyPassReverse /org https://org.example.com
< AddOutputFilterByType SUBSTITUTE t text/html
< Substitute "s|(src=\")(.*)(/img)|$1/org$3|i"
```

`AddOutputFilterByType`は、Content-Typeが`text/html`のコンテンツを書き換えるというルール（ルール名`Substitute`）の定義になります。
実際の書き換えルールは`Substitute`からになります。正規表現で書き換えをすることができます。上記の例は、`..`を`/org`に書き換えるという単純なものです。

設定が終わったら、Apacheを再起動します。

```bash
$ sudo service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
```

### 今度こそ確認

気を取り直して、再度、プロキシ行うリソース（`https://web.example.com/org/`）にアクセスしてみましょう。

<img width="488" alt="005.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/2616e9f5-715c-8db4-530b-b6d0a0d0ac05.jpeg">

ばっちりですね。

## 〆

なんだか、OpenAMと銘打っておきながら、Apacheのリバースプロキシ設定の話になっちゃいましたね。ま、いっか(´◉◞౪◟◉)

まとめとしては、

* Policy Agent導入済みのApacheのmod_proxyを使ってリバースプロキシにできる
* コンテンツがちゃんと表示されないときはmod_substituteをつかって書き換え書き換え～↑↑↑
* 認証済みユーザーの情報もHTTP HEADERとかでOriginに渡せるので、認証の実装の代替にもなりそう

明日は何しようかな～。SAMLにしようかと思ったど、連携先のサービスを用意するのが~~めんどくさい~~大変なので、別のことするかも。

ばい！