Apache HTTP サーバ バージョン 2.4
「認証」とは、誰かが自分は誰であるかを主張した場合に、 それを確認するための全過程を指します。「承認」とは、 誰かが行きたい場所に行けるように、あるいは欲しい情報を 得ることができるようにするための全過程を指します。
認証と承認の処理に関連する 3 種類のモジュールがあります。 それぞれ少なくともひとつずつ必要です。
AuthType
ディレクティブ参照)
AuthBasicProvider
,
AuthDigestProvider
ディレクティブ参照)
Require
ディレクティブ参照)
これらのモジュールに加えて、mod_authn_core
と mod_authz_core
があります。
この 2 つのモジュールは認証モジュールに共通なコアディレクティブを
実装しています。
mod_authnz_ldap
は認証プロバイダと承認プロバイダの
両方の機能を持っています。
mod_authz_host
はホスト名、IP アドレスや
リクエストの特徴に基づいたアクセス制御を行いますが、
認証プロバイダのシステムの一部ではありません。
mod_access との後方互換性のため、
新しいモジュールの mod_access_compat
があります。
様々なアクセス制御の行ない方については、 アクセス制御の方法をご覧ください。
もし機密の情報や、ごくごく少数グループの人向けの情報を ウェブサイトに置くのであれば、この文書に書かれている テクニックを使うことで、そのページを見ている人たちが 望みの人たちであることを確実にできるでしょう。
この文書では、多くの人が採用するであろう、 ウェブサイトの一部分を保護する「一般的な」 方法についてカバーしています。
データが本当に機密なのであれば、認証に加えてさらに
mod_ssl
を使うと良いでしょう。
この文書で取り扱われるディレクティブは、
メインサーバ設定ファイル (普通は
<Directory>
セクション中) か、あるいはディレクトリ毎の設定ファイル
(.htaccess
ファイル) かで用います。
.htaccess
ファイルを用いるのであれば、
これらのファイルに認証用のディレクティブを置けるように
サーバの設定をしないといけないでしょう。これは
AllowOverride
ディレクティブで可能になります。
AllowOverride
ディレクティブでは、ディレクトリ毎の設定ファイル中に置くことのできる
ディレクティブを、もしあれば、指定します。
認証について話を進めているので、次のような
AllowOverride
ディレクティブが必要になるでしょう。
AllowOverride AuthConfig
そうでなく、メインサーバ設定ファイルの中に 直接置くのであれば、当然ながらそのファイルへの書き込み 権限を持っていなければならないでしょう。
また、どのファイルがどこに保存されているか知るために、 サーバのディレクトリ構造について少し知っておく 必要があるでしょう。 これはそんなに難しくないので、この文書中で ディレクトリ構造について知っておく必要がある場面では、 明らかになるようにします。
mod_authn_core
と mod_authz_core
の両方が httpd バイナリに静的に組み込み済みであるか、httpd.conf
設定ファイルで動的にロードされるかして、httpd に組み込まれていなければ
なりません。これらの二つのモジュールは、設定ファイルのなかで非常に
重要でウェブサーバの認証と承認で使用されるコアディレクティブと
その機能を提供しています。
では、サーバ上のあるディレクトリをパスワードで保護する 基本手順を示します。
まずはじめに、パスワードファイルを作ります。 どの認証プロバイダを使うかによって、パスワードファイル生成の手順は 大きく異なります。ここでの例では、手始めにテキストパスワードファイルを 使います。
このパスワードファイルは、ウェブからアクセスできる場所に
置くべきではありません。他の人がパスワードファイルを
ダウンロードできないようにするためです。例えば、
/usr/local/apache/htdocs
でドキュメントを
提供しているのであれば、パスワードファイルは
/usr/local/apache/passwd
などに置いた方が良いでしょう。
ファイルを作るためには、Apache 付属の htpasswd
を使います。このコマンドは Apache をどこにインストールしようとも、
インストールディレクトリの bin
ディレクトリ以下に置かれます。サードバーティ製のパッケージで
インストールした場合は、実行パスの中で見つかるでしょう。
ファイルを作るには、次のようにタイプしてください。
htpasswd -c /usr/local/apache/passwd/passwords rbowen
htpasswd
は、パスワードを要求し、その後
確認のためにもう一度入力するように要求してきます。
# htpasswd -c /usr/local/apache/passwd/passwords rbowen
New password: mypassword
Re-type new password: mypassword
Adding password for user rbowen
もし htpasswd
がパスの中に入っていない場合は、
もちろん、実行するためにプログラムまでのフルパスを
タイプする必要があります。デフォルトのインストール状態であれば、
/usr/local/apache/bin/htpasswd
にプログラムが置かれています。
次に、サーバがパスワードを要求するように設定して、
どのユーザがアクセスを許されているかをサーバに知らせなければ
なりません。 httpd.conf
を編集するか
.htaccess
ファイルを使用するかで
設定します。例えば、ディレクトリ
/usr/local/apache/htdocs/secret
を保護したい場合は、
/usr/local/apache/htdocs/secret/.htaccess
か httpd.conf 中の <Directory
/usr/local/apache/htdocs/secret> セクションに
配置して、次のディレクティブを使うことができます。
AuthType Basic
AuthName "Restricted Files"
# (Following line optional)
AuthBasicProvider file
AuthUserFile /usr/local/apache/passwd/passwords
Require user rbowen
個々のディレクティブについて見てみましょう。
AuthType
ディレクティブはどういう認証方法でユーザの認証を行うかを
選択します。最も一般的な方法は Basic
で、これは mod_auth_basic
で実装されています。しかしながら、
これは気を付けるべき重要なポイントなのですが、
Basic 認証はクライアントからサーバへ、
パスワードを暗号化せずに送ります。ですからこの方法は、
mod_ssl
と組み合わせない状態では、
特に機密性の高いデータに対しては用いるべきでは
ありません。 Apache ではもう一つ別の認証方法:
AuthType Digest
をサポートしています。
この方法は mod_auth_digest
で実装されていて、もっと安全です。
最近のクライアントは Digest
認証をサポートしているようです。
AuthName
ディレクティブでは、認証に使う Realm (訳注: 領域)
を設定します。Realm は大きく分けて二つの機能を提供します。
一つ目は、クライアントがパスワードダイアログボックスの
一部としてユーザにこの情報をよく提示する、というものです。
二つ目には、クライアントが与えられた認証領域に対してどのパスワードを
送信すれば良いのかを決定するために使われる、という機能です。
例えば、"Restricted Files"
領域中で
一度認証されれば、同一サーバ上で "Restricted Files"
Realm としてマークされたどんな領域でも、クライアントは
自動的に同じパスワードを使おうと試みます。
このおかげで、複数の制限領域に同じ realm を共有させて、
ユーザがパスワードを何度も要求される事態を
防ぐことができます。もちろん、セキュリティ上の理由から、
サーバのホスト名が変わればいつでも必ず、
クライアントは再びパスワードを尋ねる必要があります。
AuthBasicProvider
はデフォルト値が file
なので、今回の場合は無くても構いません。
mod_authn_dbm
や mod_authn_dbd
といった他のモジュールを使う場合には必要になります。
AuthUserFile
ディレクティブは htpasswd
で作った
パスワードファイルへのパスを設定します。
ユーザ数が多い場合は、リクエスト毎のユーザの認証のための
プレーンテキストの探索が非常に遅くなることがあります。
Apache ではユーザ情報を高速なデータベースファイルに
保管することもできます。
mod_authn_dbm
モジュールが
AuthDBMUserFile
ディレクティブを提供します。これらのファイルは dbmmanage
プログラムで作成したり操作したりできます。
Apache
モジュールデータベース中にあるサードパーティー製の
モジュールで、その他多くのタイプの認証オプションが
利用可能です。
最後に、Require
ディレクティブが、サーバのこの領域にアクセスできるユーザを
指定することによって、プロセスの承認部分を提供します。
次のセクションでは、Require
ディレクティブの様々な用法について述べます。
上記のディレクティブは、ただ一人 (具体的にはユーザ名
rbowen
の誰か) がディレクトリに
入れるようにします。多くの場合は、複数の人が
入れるようにしたいでしょう。ここで
AuthGroupFile
の登場です。
もし複数の人が入れるようにしたいのであれば、 グループに属するユーザの一覧の入っている、グループ名のついた グループファイルを作る必要があります。このファイルの 書式はきわめて単純で、お好みのエディタで生成できます。 ファイルの中身は次のようなものです。
GroupName: rbowen dpitts sungo rshersey
一行にスペース区切りで、グループに所属するメンバーの 一覧をならべるだけです。
既に存在するパスワードファイルにユーザを加える場合は、 次のようにタイプしてください。
htpasswd /usr/local/apache/passwd/passwords dpitts
以前と同じ応答が返されますが、新しいファイルを
作るのではなく、既にあるファイルに追加されています。
(新しいパスワードファイルを作るには -c
を使います。)
ここで次のようにして .htaccess
ファイルを
修正する必要があります。
AuthType Basic
AuthName "By Invitation Only"
# Optional line:
AuthBasicProvider file
AuthUserFile /usr/local/apache/passwd/passwords
AuthGroupFile /usr/local/apache/passwd/groups
Require group GroupName
これで、グループ GroupName
にリストされていて、
password
ファイルにエントリがある人は、
正しいパスワードをタイプすれば入ることができるでしょう。
もっと特定せずに複数のユーザが入れるようにする、 もう一つの方法があります。グループファイルを作るのではなく、 次のディレクティブを使えばできます。
Require valid-user
require user rbowen
行でなく、上記を使うと、
パスワードファイルにリストされている人であれば誰でも
許可されます。
単にパスワードファイルをグループ毎に分けておくことで、
グループのような振る舞いをさせることもできます。
このアプローチの利点は、Apache は二つではなく、
ただ一つのファイルだけを検査すればよいという点です。
欠点は、たくさんのパスワードファイルを管理して、その中から
AuthUserFile
ディレクティブに正しいファイルを参照させなければならない点です。
Basic 認証が指定されている場合は、 サーバにドキュメントをリクエストする度に ユーザ名とパスワードを検査しなければなりません。 これは同じページ、ページにある全ての画像を リロードする場合であっても該当します (もし画像も保護されたディレクトリから来るのであれば) 。 予想される通り、これは動作を多少遅くします。 遅くなる程度はパスワードファイルの大きさと比例しますが、 これは、ファイルを開いてあなたの名前を発見するまで ユーザ名のリストを読まなければならないからです。 そして、ページがロードされる度にこれを行わなければ なりません。
結論としては、一つのパスワードファイルに置くことのできる ユーザ数には実質的な限界があります。 この限界はサーバマシンの性能に依存して変わりますが、 数百のエントリを越えたあたりから速度低下が見られると予期されています。 その時は他の認証方法を考慮に入れた方が良いでしょう。
プレーンテキストでパスワードを保存する方法には上記の問題があり、 データベースのような別の場所にパスワードを保存したいと思う かもしれません。
mod_authn_dbm
と mod_authn_dbd
を使うと、それができるようになります。
AuthBasicSource
で file の代わりに、dbm
あるいは dbd
を格納形式として選べます。
テキストファイルの代わりに dbm ファイルを選択する場合は、たとえば次のようにします。
<Directory /www/docs/private>
AuthName "Private"
AuthType Basic
AuthBasicProvider dbm
AuthDBMUserFile /www/passwords/passwd.dbm
Require valid-user
</Directory>
この他のオプションも存在します。詳細に関しては
mod_authn_dbm
のドキュメントをご覧ください。
認証承認アーキテクチャに基づいている新しいプロバイダを使うと、 認証承認の方法をひとつに縛る必要がなくなります。 いくつものプロバイダを組み合わせて、自分の望みの挙動にできます。 次の例では file 認証プロバイダと ldap 認証プロバイダを 組み合わせています。
<Directory /www/docs/private>
AuthName "Private"
AuthType Basic
AuthBasicProvider file ldap
AuthUserFile /usr/local/apache/passwd/passwords
AuthLDAPURL ldap://ldaphost/o=yourorg
Require valid-user
この例では、まず file プロバイダがユーザ認証を試みます。 認証できなかった場合には、ldap プロバイダが呼び出されます。 組織で複数の認証格納方法を使っている際などに、 この方法を使って認証のスコープを拡大できます。 もうひとつのシナリオは、ひとつの認証タイプと異なる承認を 組み合わせる方法でしょう。たとえば、パスワードファイルで認証して、 ldap ディレクトリで承認を行うといった場合です。
認証プロバイダを複数実装できるように、承認方法も複数使用できます。 この例では file グループ承認と ldap グループ承認を使っています。
<Directory /www/docs/private>
AuthName "Private"
AuthType Basic
AuthBasicProvider file
AuthUserFile /usr/local/apache/passwd/passwords
AuthLDAPURL ldap://ldaphost/o=yourorg
AuthGroupFile /usr/local/apache/passwd/groups
Require group GroupName
Require ldap-group cn=mygroup,o=yourorg
承認をより細かく制御したい場合は、
<SatisfyAll>
と
<SatisfyOne>
ディレクティブを使って AND/OR ロジックで指定し、設定ファイルで
承認の処理順番の制御ができるようになっています。
これらのディレクティブをどのように使えるか、網羅した例をご覧ください。
承認の方法は、ひとつのデータソースを見て一回だけチェックするのと比べて、 ずっと多彩な適用方法ができます。 承認処理の適用順序や制御、選択ができるようになりました。
承認がどのような順序で適用されているか、また、それをどのように制御するかは、
これまで混乱を招いていました。
Apache 2.2 ではプロバイダベースの認証メカニズムが導入され、
承認処理から認証処理とサポート機能とが切り分けられました。
これによるひとつの効果として、
認証モジュールのロード順やモジュール自体の順序に依存することなく、
指定した順番で認証プロバイダが呼び出せるよう、
設定できるようになりました。
このプロバイダメカニズムは承認処理でも導入されています。
つまり、Require
ディレクティブは単にどの承認手法が使われるかを指定するだけではなく、
それらの呼び出し順序も指定できるようになりました。
複数の承認手法があるとき、その呼び出し順は、設定ファイルの
Require
ディレクティブ中で
現れた順序と同じになります。
追加で導入された
<SatisfyAll>
,
<SatisfyOne>
ディレクティブを使って、承認手法がいつ呼び出され、アクセスが許可された際に
どの手続きが適用されるか指定することができます。
たとえば、次の承認ブロックのロジックを見てみましょう:
# if ((user == "John") ||
# ((Group == "admin")
# && (ldap-group <ldap-object> contains auth'ed_user)
# && ((ldap-attribute dept == "sales")
# || (file-group contains auth'ed_user))))
# then
# auth_granted
# else
# auth_denied
#
<Directory /www/mydocs>
Authname ...
AuthBasicProvider ...
...
Require user John
<SatisfyAll>
Require Group admins
Require ldap-group cn=mygroup,o=foo
<SatisfyOne>
Require ldap-attribute dept="sales"
Require file-group
</SatisfyOne>
</SatisfyAll>
</Directory>
デフォルトでは Require
ディレクティブは OR 操作として扱われます。つまり、もし指定した承認手法の
ひとつでも合格すれば、承認されます。
Require
ディレクティブのセットを
ひとつの <SatisfyAll>
ブロックで囲むとAND 操作となり、全ての承認手法で合格しなければ許可されません。
ユーザ名とパスワードによる認証は全体の一部分でしかありません。 誰がアクセスしてきたかといった情報以外の条件を使いたい、 とよく思うことでしょう。 たとえば、どこからアクセスしてきているか、といった具合です。
承認プロバイダ all
,
env
,
host
,
ip
を使うと、リクエストを送信してきているマシンのホスト名や IP アドレス
といった、ホストベースでのアクセス制御ができます。
これらプロバイダの扱いは
Require
や
Reject
で
指定されます。これらのディレクティブは承認プロバイダを登録し、
リクエスト処理の承認段階で呼び出されます。たとえば:
Require ip address
ここで、address は IP アドレス (あるいは IP アドレスの 一部) か :
Require host domain_name
ここで domain_name は FQDN (あるいはドメイン名の一部) で、必要であれば複数のアドレスやドメイン名を書くことができます。
たとえば、スパムメッセージを送信してくる誰かを拒否したい場合、 次のようになります :
Reject ip 10.252.46.165
このディレクティブが有効な範囲のコンテンツに対しては、 そのアドレスからアクセスしてきても見ることができません。 もしマシン名がわかっていて IP アドレスよりもそちらで 指定したいのであれば、そのマシン名が使えます。
Reject host host.example.com
また、特定のドメインからのアクセス全てをブロックしたい場合は、 IP アドレスの一部や、ドメイン名が指定できます :
<SatisfyAll>
Reject ip 192.168.205
Reject host phishers.example.com moreidiots.example
Reject host ke
</SatisfyAll>
Reject
ディレクティブを
<SatisfyAll>
ブロックの中で使うと、
許可したいグループにのみアクセスができるように確認できます。
上記の例では <SatisfyAll>
を使って、アクセスに合格する前段階で、全ての
Reject
ディレクティブが
満たされていることを確認しています。
認証プロバイダベースの機構があるため、以前使用されていたディレクティブ
Order
,
Allow
,
Deny
,
Satisfy
は必要なくなりました。
とはいうものの、古い設定ファイルでの後方互換性を提供するため、
これらのディレクティブは mod_access_compat
モジュールに移されました。
これらのディレクティブの抱えていた問題のひとつに、承認の設定行とアクセス制御の設定行の
関係がとてもあいまいだったことが挙げられます。
Satisfy
ディレクティブは
リクエスト処理中でそれ自身を呼び出すことによって、これらの 2 つの処理段階を結びつけようとします。
現在は、これらのディレクティブは mod_access_compat
に移動し、
新しい認証ディレクティブと古いアクセス制御ディレクティブを混ぜて使うことは
難しくなっています。この問題のため、mod_authz_default
モジュールを
ロードすることがとても重要で、必須になっています。
mod_authz_default
モジュールの主な目的は、どの承認プロバイダで
処理されなかった承認リクエストを受けることにあります。
しかし、古いアクセス制御ディレクティブが用いられた場合には、
アクセス制御と承認を結びつけて、すべての処理段階の出力結果を見てアクセスに合格するかを決めています。
ですから、古いディレクティブがうまく動作しない場合は、
mod_authz_default
がロードされていないからかもしれない、
と疑ってみてください。
これら全てがどのように動作するかについて
もっと多くの情報が書かれている mod_auth_basic
と
mod_authz_host
の文書も読むとよいでしょう。
<AuthnProviderAlias>
ディレクティブを使うと、特定の認証設定が簡単に書けるようになります。
アクセス制御の方法も、 関連するトピックがたくさん記載されていますので、ご覧ください。