Apache(Linux)に、Windowsドメイン認証を利用して、シングルサインオンを実現する詳細手順

by ViaMoi


Linuxで稼動させているApacheにて認証が必要なWebサービスに、Windowsドメイン(Active Directory)の認証情報を使って、シングルサインオンを実現させるまでの手順を備忘録として残しておきます。


今回、ブラウザは、IEFirefoxにて動作確認を行いました。

Windowsドメインログオンをしているクライアントから、上記2種類のブラウザを使うと、NTLM認証を利用しているWebサービスには、認証済みのドメインログオンの情報を利用することができ、ユーザ名やパスワードを入力する必要の無いシングルサインオン環境が実現できます。

NTLM認証(NT LAN Manager authentication)とは - IT用語辞典 e-Words

前提

今回利用した構成は以下のような感じ。

  • Webサーバ
    • CentOS 5
    • Apache 2.2 + mod_auth_ntlm_winbind
    • Winbind(Samba)
    • (以下、今回の例では、web.hoge.co.jp)
  • 統合Windowsドメインサーバ(ドメインコントローラ)
    • Windows Server 2003
    • (以下、今回の例では、domain.hoge.co.jp)
  • クライアント
    • Windows XP + IE8/IE6/Firefox3


Webサーバは、今回CentOS 5を使った前提で書いていますが、他のディストリビューションでも、読み替えてもらえれば問題ないはずです。

https://farm4.static.flickr.com/3651/3365988292_2891b40749_o.png

尚、認証の流れとしては、上図の通りですが、
ブラウザ --> Apache(mod_auth_ntlm_winbind) --> winbindd --> ドメインコントローラ
となります。

Winbind(Samba)の設定

まず、Sambaを動かして、Webサーバをドメインに参加させるところまで。

# yum install samba

まず、Sambaをインストールします。

/etc/samba/smb.conf

Sambaの設定ファイルを編集。

# vi /etc/samba/smb.conf
[global]
security = ads
workgroup = DOMAIN
realm = DOMAIN.HOGE.CO.JP
password server = domain.hoge.co.jp
encrypt passwords = true
idmap uid = 10000-20000
idmap gid = 10000-20000
winbind use default domain = yes

今回、設定ファイル(smb.conf)には、上記掲載分のみを記述しました。
ちなみに、ドメイン名は仮に"DOMAIN"としています。
realmはFQDNを指定、password serverは、IPアドレスでもOKみたいです。

/etc/nsswitch.conf

次に、nsswitch.confを編集。

# vi /etc/nsswitch.conf
passwd: files winbind
shadow: files winbind
group: files winbind

passwd、shadow、groupの項目を上記のように書き換えます。

/etc/krb5.conf

次に、krb5.confを編集。

# vi /etc/krb5.conf
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = DOMAIN.HOGE.CO.JP
 dns_lookup_realm = false
 dns_lookup_kdc = false
 ticket_lifetime = 24h
 forwardable = yes

[realms]
 DOMAIN.HOGE.CO.JP = {
  kdc = domain.hoge.co.jp
  admin_server = domain.hoge.co.jp
  default_domain = domain.hoge.co.jp
 }

[domain_realm]
 .domain.hoge.co.jp = DOMAIN.HOGE.CO.JP
 domain.hoge.co.jp = DOMAIN.HOGE.CO.JP

[appdefaults]
 pam = {
   debug = false
   ticket_lifetime = 36000
   renew_lifetime = 36000
   forwardable = true
   krb4_convert = false
 }

今回は、krb5.confは上記の記述のみとしました。
主に、ドメインやドメインコントローラのサーバに関する記述を書き換えます。

/etc/hosts

次に、/etc/hostsを編集。

xxx.xxx.xxx.xxx    web.hoge.co.jp web

hostsに、上記のような感じで、Webサーバ(Sambaが稼動しているサーバ)のIPアドレスとホスト名(FQDNもあわせて)を記述します。
※これを記載しておかないと、後述の、ドメインへの参加がうまくいかなかった。

/etc/resolv.conf

最後に、/etc/resolv.confを編集。

search domain.hoge.co.jp
nameserver xxx.xxx.xxx.xxx

DNSとして、ドメインコントローラを参照するように設定します。
もし、ドメインコントローラからDHCPで取得している場合は、おそらくこの部分は書き換える必要が無いかと思います。

ドメインに参加する

ここまで準備できたら、Webサーバ(Samba稼動)をWindowsドメインに参加させます。

# /etc/init.d/winbind start

まずwinbinddを起動します。

# net ads join -U username
username's password:
Using short domain name -- DOMAIN
Joined 'WEB' to realm 'DOMAIN.HOGE.CO.JP'

上記コマンドを実行し、"Joined"と表示されると、Webサーバ(Samba稼動)のドメインへの参加が完了です。
尚、usernameの部分にドメインに参加しているユーザ名(ID)を入れるようにしてください。

[注意点] ドメイン参加に失敗(エラー)する場合・・・

ちなみに、ここで先ほど書き記した、/etc/hostsの設定が上手くいっていないと、

# net ads join -U username
username's password:
Using short domain name -- DOMAIN
Failed to set servicePrincipalNames. Please ensure that
the DNS domain of this server matches the AD domain,
Or rejoin with using Domain Admin credentials.
Deleted account for 'WEB' in realm 'DOMAIN.HOGE.CO.JP'

こんな感じで"Failed"と表示され、ドメインへの参加に失敗します。
/etc/hostsに自分自身となるWebサーバ(Samba稼動)のホスト名が記載されているかを確認してください。


もう1つ注意点。

# net ads join -U username
Host is not configured as a member server.
Invalid configuration.  Exiting....
Failed to join domain: Invalid domain role

こんな感じで"Failed"となる場合は、
smb.confのsecurityの項目が"ads"となっているか確認してください。

"security = ads"

ドメインに参加できたら・・・

以下のようなコマンドたち(一例)を実行することで、参加状況が確認できます。

# net ads info
LDAP server: xxx.xxx.xxx.xxx
LDAP server name: domain.hoge.co.jp
Realm: DOMAIN.HOGE.CO.JP
Bind Path: dc=DOMAIN,dc=HOGE,dc=CO,dc=JP
LDAP port: 389
Server time: 火, 17  3月 2009 21:57:27 JST
KDC server: xxx.xxx.xxx.xxx
Server time offset: 0
# net ads testjoin
Join is OK
# ntlm_auth --username=DOMAIN\\username
password:
NT_STATUS_OK: Success (0x0)

Apacheの設定

まず、Apacheのインストールを行います。

Apacheのインストール

私は最新版が使いたかったので、ソースからコンパイルを行いインストールを行いました。
以下、その前提で書いていきます。

# yum install gcc

まず、コンパイルを行うためにgccをインストール。(これは入っている場合が多いと思う。)

# wget http://ftp.riken.jp/net/apache/httpd/httpd-2.2.11.tar.gz
# tar zxvf httpd-2.2.11.tar.gz
# cd httpd-2.2.11
# ./configure
# make
# make install
# cd ..

お約束ですが、↑のような流れでインストールは完了。
デフォルトでは、/usr/local/apache2へインストールされます。

ちなみにApacheをyumでインストールすると・・・

yumコマンド一発で済みます。

# yum install httpd httpd-devel

バージョンにこだわりが無い場合は、こちらでも良いでしょう。

※この場合、インストール場所がソースからインストールする場合と異なりますので、以降、ディレクトリパスなどを読み替えるようにしてください。

mod_auth_ntlm_winbindのインストール

mod_auth_ntlm_winbindは、Subversionリポジトリとgitリポジトリで管理されています。
gitリポジトリには、configure.inが含まれていませんでしたので、今回はSubversionリポジトリから取得するようにします。

yum install subversion autoconf

ということで、まず、Subversionと、configureの生成を行うためのautoconfをyumでインストールします。

# svn co svn://svnanon.samba.org/lorikeet/trunk/mod_auth_ntlm_winbind mod_auth_ntlm_winbind

で、mod_auth_ntlm_winbindのソース一式をsvnコマンドで取得します。

# cd mod_auth_ntlm_winbind
# autoconf
# ./configure --with-apxs=/usr/local/apache2/bin/apxs --with-apache=/usr/local/apache2/bin/httpd
# make
# make install
# cd ..

あとは、↑のようにお決まりのパターンです。
こんな感じで。

Apacheで認証関連の設定

試しに、ドキュメントルート以下の"/ntlm_auth/"というURLに認証をかけることにします。
その場合のhttpd.confの設定例は、以下となります。

# vi /usr/local/apache2/conf/httpd.conf
KeepAlive On
LoadModule auth_ntlm_winbind_module modules/mod_auth_ntlm_winbind.so

Alias /ntlm_auth/ "/usr/local/apache2/htdocs/ntlm_auth/"
<Directory "/usr/local/apache2/htdocs/ntlm_auth/">
  NTLMAuth on
  AuthType NTLM
  AuthName "NTLM Authentication"
  NTLMAuthHelper "/usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp"
  NTLMBasicAuthoritative on
  require valid-user
</Directory>

上記を追記する感じで、設定に記載してください。
まず、LoadModuleは当然のことながら、"KeepAlive On"はNTLM認証に必須です。
/usr/local/apache2/htdocs/ntlm_auth/ 以下に試しにindex.htmlを配置し、認証が成功したらindex.htmlが表示されるようにします。


最後に、以下のchgrpコマンドを実行し、winbindd_privilegedディレクトリにApache(mod_auth_ntlm_winbind)のプロセスのユーザがアクセスできるようにアクセス権を設定します。

# chgrp daemon /var/cache/samba/winbindd_privileged

上記の"daemon"の部分は、Apacheプロセスのユーザ名に書き換えてください。
ちなみに、ソースからコンパイルしたときは、"daemon"や"nobody"、yumでインストールしたときは"apache"だった気がします。
いずれにせよ、httpd.confに記載されていますので、確認してください。

Apacheを起動

設定が完了したら、最後にApacheを起動します。

/usr/local/apache2/bin/apachectl start

これで、設定は完了です。


尚、yumでインストールした場合は、

# /etc/init.d/httpd start

で、Apacheを起動することが可能です。

ブラウザからアクセス!

早速、ブラウザから、アクセスしてみましょう。

http://web/ntlm_auth/

設定が問題なく行われた場合は、ドメインログオンしたクライアントからアクセスした際は、ユーザー認証のダイアログが表示されることなく認証に成功し、Webサービスの画面が表示されます。

ちなみに、ドメインログオンしていないクライアントからアクセスした際は、ユーザー認証のダイアログが表示されますので、ユーザー名とパスワードを入力し、認証が成功するとWebサービスの画面が表示されます。


尚、FQDN形式の、

http://web.hoge.co.jp/ntlm_auth/

で、上手くログインできない場合、ブラウザのセキュリティ設定を見直す必要があります。
FQDN形式ですと、ブラウザがイントラネットではなくインターネットへのアクセスと認識しますので、通常のセキュリティ設定だと、自動でログインはできない可能性が高いです。

その場合は、IEだとインターネットオプションのセキュリティタブにある、"信頼済みサイト"に個別に登録するようにしましょう。


https://farm4.static.flickr.com/3434/3365980232_94b402dc16_o.png

上図の、"インターネット"のレベルのカスタマイズにある"ユーザ認証"の設定を変えても対応は出来ますが、セキュリティ上推奨しません。

FirefoxからNTLM認証

ブラウザがFirefoxの場合は、少し設定が必要です。

まず、ブラウザのURLを入力する欄に"about:config"と入力します。

で、設定名"network.automatic-ntlm-auth.trusted-uris"の値の部分に、NTLM認証を許可するドメイン名を入力します。複数あるときはカンマ区切りとします。

追記:NTLM認証に失敗する場合

いくつか遭遇し、対処してきたので、上手くいかない場合は参考になるかもしれません。

NTLM認証がうまく動かないとき

上記で書いたとおりに構築したが、うまく認証されないというか、
NTLMで認証している形跡が無い場合、ひょっとしたら、ドメインにジョイン(Join)し忘れている可能性があります。

で、それに伴いWinbinddの起動に失敗している可能性があります。その時は↓のようなログが出る。

[2009/06/25 20:21:53, 0] nsswitch/winbindd_cache.c:initialize_winbindd_cache(2229)
  initialize_winbindd_cache: clearing cache and re-creating with version number 1
[2009/06/25 20:21:53, 0] nsswitch/winbindd_util.c:init_domain_list(506)
  Could not fetch our SID - did we join?
[2009/06/25 20:21:53, 0] nsswitch/winbindd.c:main(1114)
  unable to initalize domain list
[2009/06/25 20:21:54, 1] nsswitch/winbindd.c:main(1013)
  winbindd version 3.0.33-3.7.el5 started.
  Copyright Andrew Tridgell and the Samba Team 1992-2008
[2009/06/25 20:21:54, 0] nsswitch/winbindd_cache.c:initialize_winbindd_cache(2229)
  initialize_winbindd_cache: clearing cache and re-creating with version number 1
[2009/06/25 20:21:54, 0] nsswitch/winbindd_util.c:init_domain_list(506)
  Could not fetch our SID - did we join?
[2009/06/25 20:21:54, 0] nsswitch/winbindd.c:main(1114)
  unable to initalize domain list

その後再度、ドメインに参加し、再度winbinddを起動することで、認証は上手くようになる動くはず。

NTLM認証実現に向けてのwinbindとの格闘その1

Apache + mod_auth_ntlm_winbindな環境で、NTLM認証を実現するときの話。

NTLM認証にならず、Apacheのエラーログには、以下のように出力されている場合。

[Wed Jul 01 17:41:16 2009] [notice] child pid 18372 exit signal Segmentation fault (11)
[2009/07/01 17:41:16, 0] utils/ntlm_auth.c:winbind_pw_check(515)
  Login for user [hoge]\[foo]@[bar] failed due to [winbind client not authorized to use winbindd_pam_auth_crap. Ensure permissions on /var/cache/samba/winbindd_privileged are set correctly.]
[2009/07/01 17:41:16, 0] utils/ntlm_auth.c:manage_squid_ntlmssp_request(776)
  NTLMSSP BH: NT_STATUS_ACCESS_DENIED
[Wed Jul 01 17:41:16 2009] [error] [client xxx.xxx.xxx.xxx] (20014)Internal error: ntlm_auth reports Broken Helper: BH NT_STATUS_ACCESS_DENIED, referer: http://your.domain.com/id/login

"/var/cache/samba/winbindd_privileged"以下へのアクセスが、
Apacheのプロセスくんから出来なくなっているのが原因。
パーミッションを適切に設定しよう。↓のような感じで設定。

# chgrp apache /var/cache/samba/winbindd_privileged

# Apacheを、"apache"ユーザで稼動させている場合

NTLM認証実現に向けてのwinbindとの格闘その2

Apache + mod_auth_ntlm_winbindな環境で、NTLM認証を実現するときの話。

相変わらず、NTLM認証にはならず、Winbindのエラーログには、以下のように出力されている場合。
ごっつ、はまった。(ググッても日本語のページ出てこないし^^;)

[2009/07/01 18:07:26, 0] utils/ntlm_auth.c:get_winbind_domain(146)
  could not obtain winbind domain name!
[2009/07/01 18:07:26, 0] utils/ntlm_auth.c:get_winbind_netbios_name(172)
  could not obtain winbind netbios name!


あと症状としては以下のようなエラーログも同様だった。

[2009/07/01 18:02:31, 0] lib/util_sock.c:create_pipe_sock(1280)
  invalid permissions on socket directory /var/cache/samba/winbindd_privileged
open_winbind_socket: そのようなファイルやディレクトリはありません


この場合、以下のコマンドを実行すると、RPCでのcallに失敗しているらしい、ということがわかる。

# wbinfo -t
checking the trust secret via RPC calls failed
error code was  (0x0)
Could not check secret


しかし、AD(ActiveDiretory)へのJoinはできている。

# net ads testjoin
Join is OK


で、この時、"/var/cache/samba/winbindd_privileged"のパーミッションを見ると以下のような感じだった。

drwxr-x---  2 apache apache  4096  7月  2 11:03 winbindd_privileged


これを以下のように、オーナの所有権のみを"root"に戻してやると上手く動き始めた。

drwxr-x---  2 root apache  4096  7月  2 11:03 winbindd_privileged


この結果は、かなり解せないところがあるのだが、
winbindのチェック機構で何かをやっているのかもしれないな。

# wbinfo -t
checking the trust secret via RPC calls succeeded

上手く、動き始めると、↑のような結果となった。

最後に

ちょっと設定は面倒ですが、シングルサインオンは非常に便利な仕組みです。
ドメインコントローラが稼動するイントラネット内でのWebサービスに対しては、利便性の高い仕組みだと思いますので、試してみるのも面白いかもしれません。

参考


Apacheハンドブック

Apacheハンドブック

Apacheクックブック 第2版 ―Webサーバ管理者のためのレシピ集

Apacheクックブック 第2版 ―Webサーバ管理者のためのレシピ集