7.6. HAProxyで認証する場合の設定例¶
7.6.1. レスポンス用ファイルの例¶
認証エラー時のレスポンスデータファイルの例は、以下の通りです。
HTTP/1.1 401 Unauthorized
Connection: close
Content-Type: application/json
{"error":"Invalid Client Certificate"}
7.6.2. HAProxyのコンフィギュレーションの例¶
HAProxyのコンフィギュレーションの例は、以下の通りです。
frontendの設定
例では事前に用意した証明書、エラーファイルを /etc/haproxy/ 配下に格納しています。
frontend main
# *:8080 ... 全IPアドレスのTCP 8080ポートでリクエストの待ち受けを行う
# ssl ... 通信にssl(https)を使用します
# crt ... サーバ証明書ファイル(pemフォーマット)
# サーバ証明書、サーバ証明書の秘密鍵、中間CA証明書(存在する場合)をcatコマンドで結合したファイル
# ca-file ... クライアント証明書の発行元CAの証明書(pemフォーマット)
# verify optional ... クライアント証明書が存在する場合は検証を行う
# クライアント証明書認証を必須とする場合は、verify requiredを指定する
# crt-ignore-err all ... クライアント証明書の検証が失敗した場合も処理を継続する
# no-sslv3 ... SSLv3を無効にする
# crl-file ... 証明書失効リスト
# クライアント証明書発行元のCAが提供するCRLを、定期的に取得・更新すること
bind *:8080 ssl crt /etc/haproxy/certs/server_cert.pem ca-file /etc/haproxy/certs/cacert.pem verify optional crt-ignore-err all no-sslv3 crl-file /etc/haproxy/certs/crl.pem
# L7 modeを使用する
mode http
# クライアントが付与した"X-SSL"で始まるヘッダを削除する
# 予期しないヘッダ転送を避けるため必ず設定すること
reqdel ^X-SSL
# クライアント証明書認証に失敗したケース(証明書なしの場合は除く)
use_backend invalid-cert-detected unless { ssl_c_verify 0 }
# クライアント証明書認証に成功したケース
use_backend with-client-cert if { ssl_c_used }
# クライアント証明書が付与されないケース(通常認証)
default_backend no-certificate
警告
HAProxyで使用するサーバ証明書ファイルは、秘密鍵を含みます。 適切なアクセス権限を設定し、外部への漏えいが発生しないよう管理してください。
backendの設定
# クライアント証明書認証に失敗
backend invalid-cert-detected
mode http
option httpclose
# 転送先のバックエンドサーバの指定を行っていないため、haproxyに503エラーが発生
# その結果、指定した/etc/haproxy/errors/401.httpファイルの内容がクライアントに返却される
errorfile 503 /etc/haproxy/errors/401.http
# クライアント証明書認証に成功
backend with-client-cert
mode http
balance roundrobin
# 転送先のバックエンドサーバを指定
# 複数のBaaS APIサーバが存在する場合は列挙すること
server certapi01 10.0.1.1:80
# server certapi02 10.0.1.2:80
option forwardfor
# バックエンドに送信する証明書情報ヘッダ
http-request set-header X-SSL-Client-CertAuth-Validated 1
http-request set-header X-SSL-Client-Serial %[ssl_c_serial,hex]
http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)]
http-request set-header X-SSL-Client-UID %{+Q}[ssl_c_s_dn(uid)]
http-request set-header X-SSL-Issuer-DN %{+Q}[ssl_c_i_dn]
# X-SSL-Validate-Tokenにはシステム毎に異なる値を設定すること
http-request set-header X-SSL-Validate-Token a3bbc802-4619-49de-8c74-b42ab4b9c2b5
# 通常認証
backend no-certificate
mode http
balance roundrobin
# 転送先のバックエンドサーバを指定
# 複数のBaaS APIサーバが存在する場合は列挙すること
server certapi01 10.0.1.1:80
#server certapi02 10.0.1.2:80
option forwardfor
http-request set-header X-SSL-Client-CertAuth-Validated 0
7.6.3. CRL更新用スクリプトの例¶
CRL更新用スクリプトの例は、以下の通りです。
#!/bin/sh
CONFIG_PATH=/etc/haproxy
HOST=10.0.255.75
CRL_FILE=crl.pem
CRL_TMP_FILE=crl.pem.tmp
CRL_FILE_PATH=${CONFIG_PATH}/${CRL_FILE}
CRL_TMP_FILE_PATH=${CONFIG_PATH}/${CRL_TMP_FILE}
# 作業ファイルが残っていれば削除
if [ -e ${CRL_TMP_FILE_PATH} ]; then
echo "remove old tmp crl"
rm –f ${CRL_TMP_FILE_PATH}
fi
# サーバからCRLを取得
wget http://${HOST}/${CRL_FILE} -O ${CRL_TMP_FILE_PATH}
# 取得成功した場合
if [ $? -eq 0 ] && [ -e ${CRL_TMP_FILE_PATH} ]; then
# 既にCRLファイルが存在する場合
if [ -e ${CRL_FILE_PATH} ]; then
if diff -q ${CRL_FILE_PATH} ${CRL_TMP_FILE_PATH} > /dev/null ; then
# CRLファイルが更新されていなかった
echo "no update"
else
echo "crl update. reload service"
# CRLファイルが更新されていた場合はファイルを置き換えて再読み込み
mv ${CRL_TMP_FILE_PATH} ${CRL_FILE_PATH}
sudo service haproxy reload
fi
else
# CRLファイルが存在しない場合はサービス起動に失敗している 再起動する
echo "get crl first time. restart service."
mv ${CRL_TMP_FILE_PATH} ${CRL_FILE_PATH}
sudo service haproxy restart
fi
else
echo "failed to get new crl" 1>&2
fi