コンテンツにスキップ

PAM経由LDAP認証の設定

nginx の auth_pam で HTTP Basic 認証を要求し、PAM から libpam-ldapd / nslcd を通して LDAP 認証する。


項目 例
OS Debian 13.x(Ubuntu系でも概ね同様)
公開URL https://app.example.com/admin/
ドキュメントルート /var/www/app.example.com
nginxユーザー www-data
LDAPサーバー ldap://ldap.example.com/
Base DN dc=example,dc=com
LDAPユーザー uid=ldapuser,ou=people,dc=example,dc=com
PAMサービス /etc/pam.d/nginx

LDAP サーバー側には、認証に使うユーザーが存在している前提とする。LDAP ユーザー作成や nslcd の基本は Linuxユーザー認証の設定 を参照する。

証明書は HTTP/HTTPSとリダイレクトの設定 と同じく、fullchain.pem とroot所有・600の privkey.pem を使用する。証明書のSANには実際の server_name を含める。


Terminal window
sudo apt update
sudo apt install nginx libnginx-mod-http-auth-pam nslcd libpam-ldapd ldap-utils

役割は次のとおり。

パッケージ 役割
libnginx-mod-http-auth-pam nginx から PAM 認証を呼び出す
libpam-ldapd PAM から LDAP 認証を使う
nslcd LDAP への問い合わせを行うデーモン
ldap-utils ldapsearch などの確認コマンド

Debian / Ubuntu 系では、パッケージの導入により nginx の動的モジュールが読み込まれる構成になる。モジュール読み込み設定を確認するには、nginx -T で load_module 行を見る。

Terminal window
sudo nginx -T | grep -E 'load_module.*auth_pam|auth_pam_module'

load_module modules/ngx_http_auth_pam_module.so; のような行が表示されれば、nginx が PAM 認証モジュールを読み込む設定になっている。


/etc/nslcd.conf に LDAP サーバーと検索ベースを設定する。LDAP 接続を TLS で保護するかに応じて、次のどちらか一方を使う。

同一ホストまたは閉じた隔離ネットワークで使用する TLS なしの最小構成。

/etc/nslcd.conf
uid nslcd
gid nslcd
uri ldap://ldap.example.com/
base dc=example,dc=com
ssl off
filter passwd (objectClass=posixAccount)
filter group (objectClass=posixGroup)

この構成ではLDAP Simple Bindの認証情報が暗号化されない。閉じた隔離ネットワークでのみ使用する。

LDAP サーバー側で StartTLS を構成し、発行元 Root CA を nginx サーバーへ配布してから使用する。LDAP URI のホスト名はサーバー証明書の SAN と一致させる。

Root CA証明書を ca.crt としてコピー済みの場合の例。

Terminal window
sudo install -o root -g root -m 644 ca.crt \
/usr/local/share/ca-certificates/skills-root-ca.crt
sudo update-ca-certificates
/etc/nslcd.conf
uid nslcd
gid nslcd
uri ldap://ldap.example.com/
base dc=example,dc=com
ssl start_tls
tls_reqcert demand
tls_cacertfile /etc/ssl/certs/ca-certificates.crt
filter passwd (objectClass=posixAccount)
filter group (objectClass=posixGroup)

匿名検索を許可しない場合は、検索用の読み取り専用 DN を用意し、binddn と bindpw を設定する。

/etc/nslcd.conf
binddn cn=readonly,dc=example,dc=com
bindpw read-only-password

bindpw を書く場合は、ファイル権限に注意する。

Terminal window
sudo chown root:nslcd /etc/nslcd.conf
sudo chmod 640 /etc/nslcd.conf

設定を反映する。

Terminal window
sudo systemctl restart nslcd

LDAP サーバーに到達できるか確認する。TLSを使わない構成では次のように確認する。

Terminal window
ldapsearch -x -H ldap://ldap.example.com/ \
-b "dc=example,dc=com" \
"(uid=ldapuser)"

StartTLSを使う構成では -ZZ を付け、TLS開始に失敗した場合も処理を継続させない。

Terminal window
ldapsearch -x -ZZ -H ldap://ldap.example.com/ \
-b "dc=example,dc=com" \
"(uid=ldapuser)"

NSS も LDAP を見る構成にしている場合は、Linux ユーザーとして解決できるか確認する。

Terminal window
getent passwd ldapuser
id ldapuser

この確認は切り分けに使う。nginx の Basic 認証そのものは PAM サービス経由で判定されるが、LDAP ユーザーやグループが想定どおり引けるかを見るには getent が分かりやすい。


/etc/pam.d/nginx を作成する。

/etc/pam.d/nginx
auth required pam_ldap.so
account required pam_ldap.so

この PAM サービスは、nginx から渡されたユーザー名とパスワードを LDAP 認証へ渡す。

特定ユーザーだけに絞る場合は、pam_listfile.so を先に置く。

/etc/pam.d/nginx_restricted
auth required pam_listfile.so onerr=fail item=user sense=allow file=/etc/nginx/allowed_ldap_users
auth required pam_ldap.so
account required pam_ldap.so

許可ユーザーリストを作る。

Terminal window
printf '%s\n' ldapuser | sudo tee /etc/nginx/allowed_ldap_users
sudo chown root:www-data /etc/nginx/allowed_ldap_users
sudo chmod 640 /etc/nginx/allowed_ldap_users

5. nginxで保護するlocationを設定する

Section titled “5. nginxで保護するlocationを設定する”

静的サイトの /admin/ 配下に PAM 認証をかける例。

確認用ファイルを作成する。

Terminal window
sudo mkdir -p /var/www/app.example.com/admin
printf '%s\n' 'for LDAP users' | \
sudo tee /var/www/app.example.com/admin/index.html
/etc/nginx/sites-available/app.example.com.conf
server {
listen 80;
listen [::]:80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name app.example.com;
ssl_certificate /etc/nginx/tls/app.example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/tls/app.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/app.example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location /admin/ {
auth_pam "LDAP Login";
auth_pam_service_name nginx;
try_files $uri $uri/ =404;
}
}

この例では、/admin/ は /var/www/app.example.com/admin/ 配下のファイルに対応する。

auth_pam_service_name nginx; は /etc/pam.d/nginx を使うという意味である。nginx_restricted を使う場合は、auth_pam_service_name nginx_restricted; に変更する。


Debian / Ubuntu 系では、sites-available に設定ファイルを作っただけでは nginx に読み込まれない。sites-enabled へシンボリックリンクを作り、サイトを有効化する。

Terminal window
sudo ln -s /etc/nginx/sites-available/app.example.com.conf \
/etc/nginx/sites-enabled/app.example.com.conf
Terminal window
sudo nginx -t
sudo systemctl reload nginx

nginx が auth_pam を知らないというエラーを出す場合は、libnginx-mod-http-auth-pam が入っているか、モジュール読み込み設定が有効かを確認する。あわせて、作成した site 設定が nginx に読み込まれているかも確認する。

Terminal window
dpkg -l libnginx-mod-http-auth-pam
sudo nginx -T | grep -E 'load_module.*auth_pam|auth_pam_module|auth_pam'

load_module の行は PAM 認証モジュールの読み込み確認である。auth_pam と auth_pam_service_name の行は、sites-enabled 経由で自分の location 設定が読み込まれていることの確認である。


認証なしでアクセスし、401 Unauthorized が返ることを確認する。

Terminal window
curl -I https://app.example.com/admin/

LDAP ユーザーでアクセスする。

Terminal window
curl -u ldapuser https://app.example.com/admin/

成功の目安は、LDAP ユーザーのパスワードで認証が通り、保護された静的コンテンツが返ることである。

失敗時は nginx、PAM、nslcd の順に見る。

Terminal window
sudo tail -f /var/log/nginx/error.log
journalctl -u nginx
journalctl -u nslcd

症状 主な確認箇所
unknown directive "auth_pam" libnginx-mod-http-auth-pam が入っているか、モジュールが読み込まれているか
常に 401 になる /etc/pam.d/nginx、LDAP パスワード、nslcd の接続設定
LDAP検索はできるが認証できない Bind DN、ユーザー DN の検索、TLS、LDAP 側 ACL
HTTPでは動くが危険 Basic 認証を HTTP のまま使っている。HTTPS 化する
pam_unix.so で失敗する nginxの実行ユーザー、PAMサービス定義、PAM実装や特権ヘルパーの利用条件を確認する。LDAP認証が目的なら pam_ldap.so へ寄せる