Kerberos認証を行うためには、 "HTTP/[email protected]" のようなHTTP用のservice principalを作成する必要があります。 Kerberos標準のkadminを使って addprinc、 ktadd の順で作成することもできますが、 Active Directory相手ならSamba付属の net command もしくは adcli を利用するとLinux host側だけで作業を完結できるので簡単です。
Samba の net command を使うと、Windows client を domain参加させる権限のあるuserでservice principalを作成できます。
/etc/samba/smb.conf
... security = ads workgroup = WORK.HANABUSA.NET realm = WORK.HANABUSA.NET password server = dc1.work.hanabusa.net kerberos method = secrets and keytab
設定fileを用意したら、以下のcommandでActive Directoryに参加 & service principalの作成を行います。
# net ads dns register -U some_domain_user # net ads join -U some_domain_user # net ads keytab create -U some_domain_user # net ads keytab add HTTP -U some_domain_user
RHEL>=7 では、Samba以外にadcliをつかってActive Directoryに Linux hostを参加させることができます。 設定fileは不要で、command lineでdomain, domain controller, host名などを指定してadcliを走らせます。 実行すると、/etc/krb5.keytabにservice principalが書き込まれます。 また、computer accountのpasswordが表示されるので保管しておきます。
# adcli join -v --show-password --os-name=Linux --os-version=RHEL7 \ -K /etc/krb5.keytab --service-name=host --service-name=HTTP \ -D work.hanabusa.net -R WORK.HANABUSA.NET -S dc1.work.hanabusa.net \ -H webapp.work.hanabusa.net -N webapp -U some_domain_user
DNSへの登録は別途bind-utilsに含まれるnsupdateを使って実施します。
# nsupdate > server dc1.work.hanabusa.net > update add webapp.work.hanabusa.net. 86400 A 192.168.100.200 > update add 200.100.168.192.in-addr.arpa. 86400 PTR webapp.work.hanabusa.net. > send > ^D
上記の手順で正しくprincipalを作成できているか確認します。 "klist -k"で/etc/krb5.keytabにservice principal表示し、 HTTP/webappなどが入っていれば正しく設定できています。 同じ行が複数出てきますが、暗号の種類につき1行でてくるためです。 "klist -k -e " すると暗号種類まで表示できます。
# klist -k Keytab name: FILE:/etc/krb5.keytab KVNO Principal ---- -------------------------------------------------------------------------- 2 [email protected] 2 [email protected] 2 [email protected] 2 host/[email protected] 2 host/[email protected] 2 host/[email protected] 2 host/[email protected] 2 host/[email protected] 2 host/[email protected] 2 HTTP/[email protected] 2 HTTP/[email protected] 2 HTTP/[email protected] 2 HTTP/[email protected] 2 HTTP/[email protected] 2 HTTP/[email protected]
このあとApacheからkeytabを使うように設定しますが、 HTTP/webappだけを別のfileに分けて、 そのfileだけをApacheから使わせる方が安全面から好ましいです。
ktutilを使って/etc/httpd/httpd.keytabを作成します。 手順としては、rktで既存のkrb5.keytabを読み込み、 delentで不要なものを削除し、 wktで残ったHTTP/webapp... をhttpd.keytabに書き込むという手順になります。 やってみるとわかりますが、delentすると1行削除されて、slot番号が詰められます。 ですので、例のようなkeytabの場合、9回 "delent 1"を行なえば良いことになります。
最後にchownでApacheに読み取り権限をつけてください。 忘れるとApacheから読取できずにうまく動きません。
# rm /etc/httpd/httpd.keytab # ktutil ktutil: rkt /etc/krb5.keytab ktutil: list slot KVNO Principal ---- ---- --------------------------------------- 1 2 [email protected] ... 10 2 HTTP/[email protected] .. 15 2 HTTP/[email protected] ktutil: delent 1 ktutil: delent 1 ktutil: delent 1 ktutil: delent 1 ktutil: delent 1 ktutil: delent 1 ktutil: delent 1 ktutil: delent 1 ktutil: delent 1 ktutil: list slot KVNO Principal ---- ---- --------------------------------------- 1 2 HTTP/[email protected] 2 2 HTTP/[email protected] 3 2 HTTP/[email protected] 4 2 HTTP/[email protected] 5 2 HTTP/[email protected] 6 2 HTTP/[email protected] ktutil: wkt /etc/httpd/httpd.keytab ktutil: q # chown apache /etc/httpd/httpd.keytab
ApacheでKerberos認証を行うためには、mod_auth_kerbが必要です。 RHEL/CentOS系なら、yum install mod_auth_kerb だけでinstallできます。 mod_auth_kerbの設定として Apacheのhttpd.confに以下の例のように書きます。
<Location "/myapp/"> require valid-user AuthName "My Application Login" AuthType Kerberos KrbMethodNegotiate on KrbMethodK5Passwd on KrbMethodK4Passwd off KrbAuthRealms WORK.HANABUSA.NET Krb5Keytab /etc/httpd/httpd.keytab </Location>
Apache&mod_auth_kerbで認証を行って、 mod_proxy経由でbackendのapplication server (例えばUnicorn & Ruby on Rails) に認証情報を渡す方法です。
基本的には、httpd.confの中で REMOTE_USER環境変数の内容を RequestHeaderを使ってHTTP headerとして appliation serverに送ってやればokです。 Basic認証の場合は、 "RequestHeader set X-Forwarded-User %{REMOTE_USER}e" のように書けば良いのですが(最後のeに注意)、 mod_auth_kerbではなぜかうまく動きません。 その代わりに、mod_sslを有効にした上で、 "RequestHeader set X-Forwarded-User %{REMOTE_USER}s" とすると(最後のsに注意)、正しくREMOTE_USERを送れるようになります。
httpd.confの例
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule ssl_module modules/mod_ssl.so ... <Location "/myapp/"> require valid-user AuthName "My Application Login" AuthType Kerberos KrbMethodNegotiate on KrbMethodK5Passwd on KrbMethodK4Passwd off KrbAuthRealms WORK.HANABUSA.NET Krb5Keytab /etc/httpd/httpd.keytab ProxyRequests Off ProxyPreserveHost On ProxyPass http://localhost:3000/myapp ProxyPassReverse http://localhost:3000/myapp RequestHeader set X-Forwarded-User %{REMOTE_USER}s RequestHeader set X-Forwarded-SSL on </Location>
FirefoxからKerberos認証するには、 about:config で設定を変更する必要があります。 変更する必要のある設定名は "network.negotiate-auth.trusted-uris" と "network.negotiate-auth.delegation-uris" で、Kerberos認証するdomainをcomma区切りで書きます。 例として、 ".work.hanabusa.net,.bobby.hanabusa.net" という設定値を上記の両方に設定します。 そうすると、 http://webapp.work.hanabusa.net や http://robot.hobby.hanabusa.net のようなURLに対してKerberos認証するようになります。
上記の設定を順番に行なえばKerberos認証できるようになるはずですが、 うまく動かない場合はまずはApache側の問題なのか それ以外なのか問題を切り分けてみましょう。 まず、 http://webapp.work.hanabusa.net/myapp にaccessしてみます。 その後に、client側でklistを走らせて、 ticketを取得しているか確認します。 klistはWindows clientの場合でもcommand promptから実行できます。
$ kinit Password for [email protected]: mypassword $ curl --negotiate --user : http://webapp.work.hanabusa.net/myapp ... $ klist Ticket cache: FILE:/tmp/krb5cc_1000 Default principal: [email protected] Valid starting Expires Service principal 12/23/14 11:22:33 12/23/14 21:22:33 krbtgt/[email protected] 12/23/14 11:22:44 12/23/14 21:22:44 HTTP/[email protected]
Ticketを取得できているなら HTTP/webapp....の行があるはずです。 もしこの行が無い場合はticket取得に失敗しています。 その場合には以下のような原因が考えられます。
一方、HTTP/webapp....の行があってclientがHTTP用のticketを取得できているなら 基本的にはmod_auth_kerb周りの不具合です。 Apacheのerror logを読めば原因は特定できるはずです。
Ticket取得に失敗している場合にはclient側でlogを出させるのが有効です。 KRB5_TRACEという環境変数にfile名を書くと そこにKerberosのlogを出力するのでlogを確認してみてください。
$ export KRB5_TRACE=/tmp/krbclient.log $ curl --negotiate --user : http://webapp.work.hanabusa.net/myapp ... $ cat /tmp/krbclient.log