はじめに
前回redhat6のapache2.2にmod_auth_mellonをインストールして大変苦労しましたが、今回はdockerで簡単に構築出来たので手順を共有します。
環境
項目 | 内容 |
---|---|
SP | Apache mod_auth_mellon |
IdP | Microsoft Azure Active Directory |
- シングルサインオンさせたいサーバーはリバースプロキシのバックエンドにいてサブドメインでアクセスするものとします。
dockerの設定
- hogeディレクトリ以下に構築するものとします。
hoge
├── certs
├── dhparam
├── docker-compose.yml
├── html
├── proxy
│ └── log
├── saml
│ ├── proxy.conf.template
│ ├── saml_idp.xml
│ ├── saml_sp.cert
│ ├── saml_sp.key
│ └── saml_sp.xml
└── vhost
version: '3'
services:
saml-proxy:
image: "mpar/saml-proxy"
environment:
- BACKEND="http://www.yahoo.co.jp" #テスト用の定義
- VIRTUAL_HOST=hoge.example.com
- VIRTUAL_PORT=8080
- LETSENCRYPT_HOST=hoge.example.com
- LETSENCRYPT_EMAIL=hoge@example.com
ports:
- "8080:80"
volumes:
- ./saml/saml_idp.xml:/etc/httpd/conf.d/saml_idp.xml
- ./saml/saml_sp.key:/etc/httpd/conf.d/saml_sp.key
- ./saml/saml_sp.cert:/etc/httpd/conf.d/saml_sp.cert
- ./saml/saml_sp.xml:/etc/httpd/conf.d/saml_sp.xml
- ./saml/proxy.conf.template:/etc/httpd/conf.d/proxy.conf.template
nginx-proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
restart: unless-stopped
volumes:
- ./proxy/log:/var/log/nginx
- ./html:/usr/share/nginx/html
- ./dhparam:/etc/nginx/dhparam
- ./vhost:/etc/nginx/vhost.d
- ./certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
TZ: Asia/Tokyo
labels:
- "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: nginx-proxy-lets-encrypt
depends_on:
- "nginx-proxy"
volumes:
- ./certs:/etc/nginx/certs:rw
- ./vhost:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- /var/run/docker.sock:/var/run/docker.sock:ro
(2022/01/29 追記)
リバースプロキシ先のコンテナにVIRTUAL_PORTの設定をすると、jwilder/nginx-proxyから接続出来ないケースがありました。
docker exec -it (コンテナ名) bash
でコンテナ内に入り、プロキシ先のコンテナからcurl等でコンテンツが取得出来るようなら、VIRTUAL_PORTの設定をコメントアウトしてみて下さい。
mod_auth_mellonの設定
mellon_create_metadata.shの取得
- hoge/saml ディレクトリを作成します。
-
https://gist.github.com/michaelrice/3c052dce7b1e2e1bf46e224c4e9bb692
から mellon_create_metadata.sh を取得して hoge/saml に保存します。
mellon_create_metadata.shの実行
hoge/saml ディレクトリで以下を実行します。
$ chmod 755 mellon_create_metadata.sh
$ sudo ./mellon_create_metadata.sh \
-k saml_sp.key \
-c saml_sp.cert \
-m saml_sp.xml \
-e https://hoge.example.com/mellon/metadata \
-b https://hoge.example.com/mellon
このコマンド実行後に出来た、
saml_sp.xml
をAzure ADの「メタデータファイルをアップロードする」でアップロードします。
アップロードして保存したら[フェデレーション メタデータ XML]をダウンロードして hoge/saml ディレクトリに
saml_idp.xml
というファイル名で保存します。
proxy.conf.templateの編集
- hoge/saml ディレクトリに proxy.conf.template を追加し自分の環境に合わせて編集します。
- このサンプルは https://hoge.example.com/fuga へのアクセスをローカルのバックエンドサーバー(192.168.1.11)に送る例です。
- サブドメインごとバックエンドに送る場合はこのファイルは不要ですので docker-compose.yml で proxy.conf.template のボリュームをマウントしている行を削除して下さい。
ServerName $SCHEMA://$HOST
<Location />
# Add mod_auth_mellon info to all contexts
MellonEnable "info"
# Auth redirects will be located under /$MELLON_PATH
MellonEndpointPath /$MELLON_PATH
# service provider metadata, cert, and key
MellonSPPrivateKeyFile /etc/httpd/conf.d/saml_sp.key
MellonSPCertFile /etc/httpd/conf.d/saml_sp.cert
MellonSPMetadataFile /etc/httpd/conf.d/saml_sp.xml
# idp metadata
MellonIdPMetadataFile /etc/httpd/conf.d/saml_idp.xml
</Location>
<LocationMatch "/fuga/.*">
# Protect with auth
MellonEnable "auth"
# Proxy to backend once authenticated
#ProxyPass $BACKEND
ProxyPass http://192.168.1.11
ProxyPassReverse http://192.168.1.11
<If "-z env('REMOTE_USER_SAML_ATTRIBUTE')">
# Set the Remote-User header to the value of the authenticated username
RequestHeader set Remote-User %{MELLON_NAME_ID}e env=MELLON_NAME_ID
</If>
<Else>
# Use a custom attribute as the remote username by setting $REMOTE_USER_SAML_ATTRIBUTE to a custom attribute name
# Require a value in the attribute we're going to use:
MellonCond ${REMOTE_USER_SAML_ATTRIBUTE} .+ [REG]
# Map the long attribute name to a nice short one
MellonSetEnv user ${REMOTE_USER_SAML_ATTRIBUTE}
# Set the Remote-User header to the value of the mapped envvar:
RequestHeader set Remote-User %{MELLON_user}e env=MELLON_user
</Else>
<If "-n env('REMOTE_USER_NAME_SAML_ATTRIBUTE')">
MellonSetEnv name ${REMOTE_USER_NAME_SAML_ATTRIBUTE}
RequestHeader set Remote-User-Name %{MELLON_name}e env=MELLON_name
</If>
<If "-n env('REMOTE_USER_EMAIL_SAML_ATTRIBUTE')">
MellonSetEnv email ${REMOTE_USER_EMAIL_SAML_ATTRIBUTE}
RequestHeader set Remote-User-Email %{MELLON_email}e env=MELLON_email
</If>
<If "-n env('REMOTE_USER_PREFERRED_USERNAME_SAML_ATTRIBUTE')">
MellonSetEnv preferred_username ${REMOTE_USER_PREFERRED_USERNAME_SAML_ATTRIBUTE}
RequestHeader set Remote-User-Preferred-Username %{MELLON_preferred_username}e env=MELLON_preferred_username
</If>
${REQUEST_HEADERS}
</LocationMatch>
テスト
Azure ADのユーザーをエンタープライズ アプリケーションに追加して
https://hoge.example.com/fuga
にアクセスし、Azure ADのログイン画面を経てバックエンドサーバーのfugaディレクトリの中身が見られれば完了です。
まとめ
前回の大ハマりと違って今回は特に問題なくサーバー構築が出来ました。
なお、ディレクトリ毎にリバースプロキシ先を変えたりアクセス制限をかけたい場合などは、1コンテナに詰め込むのではなく単機能のコンテナを多段に組み合わせて構築した方が良さそうです。