第11回 ユーザー認証によるアクセス制限(データベース認証編) ベーシック認証に続き、今回はデータベースを利用した認証方法について解説する。データベースを利用することにより、メンテナンス性やセキュリティの向上が期待できる。 一志 達也<ichishi@pochi.tis.co.jp>
データベース認証のメリット データベース認証とベーシック認証の違いは、コンテンツの閲覧を許可するユーザーの管理をパスワードファイルで行うかデータベースで行うか、という点にある。ユーザーの管理をデータベースで行う利点としては、次の2つが挙げられる。 ■メンテナンス性の高さ データベースに格納されたデータは、SQLを使って簡単にメンテナンスできる。htpasswdコマンドでユーザーを管理するのは、追加するのも更新するのも面倒だ。数人ならともかく、何百人ものユーザーをコマンドとファイル操作で管理し、さらにグループまで作成するとなると、正確にメンテナンスするのは不可能に近い。 また、データベースであればPHPやJava、Perlなどを使ったアプリケーションも作りやすい。ユーザーのデータを管理するテーブルを操作するアプリケーションを作ってしまえば、Webブラウザなどで簡単にメンテナンスできるようになるだろう。セキュリティにさえ注意すれば、ユーザー側でパスワードを変更するアプリケーションも容易に作成できるから、管理者はパスワード変更の手間からも解放される。 さらに、社員データベースや顧客データベースなど、ほかのデータベースからデータを移行しやすいこともメリットとなる。たいていの場合、企業はすでにそうしたデータを持っている。社内イントラネットなら社員データベースのデータが使えるし、特定顧客向けのWebサイトなら顧客データベースのデータが使えるだろう。 こうしたデータはSQLを使って移し替えてもいいし、CSV形式のファイルなどを通して取り込んでもいい。定期的に同期も取れるようになれば、メンテナンスの手間は大幅に軽減されるはずだ。もちろん、やりようによってはそのまま使ってしまうことだってできてしまう。 ■より強固なセキュリティの確保 htpasswdによって作成されるパスワードファイルは、前回も説明したとおり単なるテキストファイルである。パスワードの部分こそ暗号化されているが、ユーザー名やグループについてはそのままの形で記録されている。これが何かの間違いで外部に漏れれば、ユーザーの数やユーザー名、所属グループは簡単に把握されてしまう。もし相手が高度な技術者であれば、暗号化されたパスワードを復号化してしまう可能性もある。 データベースのファイルは、それだけを入手しても簡単に中身を見ることはできない。暗号化されたパスワードを破る技術があれば、データベースの中身を見ることもできてしまうかもしれないが……。 危険性を完全に排除することはできないが、単純なテキストファイルを置いておくよりは安全であろう。適切に権限を設定していれば、データベースのファイルを読み取られること自体、そう簡単なことではない。インストールや設定はパスワードファイルを使う場合より多少ややこしいものの、メリットの大きさを考えればデータベース認証を積極的に採用するべきだろう。 データベース認証に利用できるデータベース それでは、データベース認証に利用できるデータベースを紹介しよう。データベースなら何でもよいのか、というとそういうわけにはいかないからである。データベース認証を行うには、そのデータベースに対応したApacheのモジュールが必要になるのだ。 モジュールは「mod_auth_xxxx」といった名前が付けられていて、xxxxの部分がデータベースによって異なる。例えば、Apacheのパッケージには「mod_auth_db」というモジュールが含まれている。これは、「Berkeley DB」と連携してデータベース認証を行うモジュールである。 Berkeley DBは日本ではなじみが薄いが、Apacheにはこれしか付いてこない。とはいえ、
といったモジュールも存在している。ただ、Apacheのパッケージには含まれていないというだけである。後は、そのモジュールが信頼に足るものなのかどうか、本当に採用して大丈夫なのか、というところだろう。この点について、筆者が簡単に太鼓判を押すわけにもいかないのだが、次のような理由から心配は無用と考える。
本稿では、PostgreSQL用のモジュールを例に解説する。とはいえ、ほかのモジュールも同じくデータベース認証を行うのだから、基本に違いはない。ユーザーデータを登録し、グループデータと関連付け、それをApacheの認証設定に伝える。もちろん若干の違いは存在するが、作業の流れや仕組みが分かってしまえば、それほど重大な問題にはならないだろう。 |
PostgreSQLを使ったデータベース認証の設定 先に紹介したとおり、PostgreSQLを使ってデータベース認証を行うにはmod_auth_pgsqlを入手する必要がある。 入手先:http://www.giuseppetanzilli.it/mod_auth_pgsql/ ■apxsを使ったインストール ここでは、「apxs」と呼ばれるプログラムを使ったインストール方法を解説する。apxsを使うことで、mod_auth_pgsqlは「DSO」と呼ばれる形式のモジュールとしてコンパイルされる。この方法であれば、Apacheが導入済みの環境でもApacheを再コンパイルすることなくインストールできる。 Apacheをまだ導入していない環境であったり、再コンパイルしても構わないというのであれば、別の道を選ぶことも可能だ。その場合、mod_auth_pgsqlはApacheのスタティック・モジュールとして導入される。しかし、それは面倒であまり一般的とはいい難い方法である。ApacheとPostgreSQLを導入し、稼働確認も済ませたうえで必要なモジュールをDSOで組み込む方が簡単だからだ。DSOで組み込めるモジュールは、無理せずDSOを利用することをお勧めする。
■ソースコードの展開とコンパイル 1.ソースコードの展開
2.生成されたディレクトリへの移動
3.INSTALLの参照
4.configureの実行
5.モジュールのコンパイル
6.モジュールのインストール
7.確認
8.Apacheの再起動 ■httpd.conf(.htaccess)の設定 インストールできたら、httpd.conf(または .htaccess)の設定を行おう。本来ならデータベースを先に用意するべきだが、説明の都合上こちらを先にする。 これらのファイルの設定は、前回説明したようにディレクトリ別のセキュリティ設定に用いられる。ここでは、httpd.confに/usr/local/apache/htdocsで公開されているコンテンツへのアクセス制限を設定する方法を紹介する。
これは、ごく単純なデータベース認証を設定した例である。簡単に説明すると、
はデータベースがローカルホスト(127.0.0.1)にインストールされていること、
でポートが5432であることを指定している。次に、
はデータベース名が「test」で、
データベースへのアクセスには、ユーザー「postgres」とパスワード「pg_password」を用いる。
この3行では、テーブル名が「user_data」であり、その「user_name」フィールドをユーザー名、passwdフィールドをパスワードとして扱うことを指定している。この場合、user_dataテーブルに含まれるデータに一致すれば、アクセス権を持つユーザーとして認証する。このように、mod_auth_pgsqlではユーザー名とパスワードを含むテーブル名やフィールド名は自由に決定できる。 悩ましいのは、PostgreSQLへアクセスするユーザー名とパスワードをここに記述している点である。ユーザー名とパスワードを書いてしまうのでは、データベースのセキュリティを低くしてしまう。解決策の1つは、user_dataテーブル(認証に使うテーブル)にnobodyユーザーでアクセスできるように権限設定することだ。そうすれば、設定ファイルにユーザー名とパスワードを書かなくても(省略しても)、ちゃんとデータを読み取ることができるようになる。しかし、今度はだれでもデータを読み取れることになる。何とも悩ましいところだが、筆者はnobodyユーザーに権限を与える方法を勧める。なぜなら、そこに格納するパスワードは、次に紹介するように暗号化することも可能だからだ。 ■PostgreSQLへのユーザー登録 設定が済んだら、データベースにユーザーを準備しよう。先に説明したとおり、ユーザーを登録するテーブルやフィールドの名称は自由に決めて構わない。とにかく、1つのテーブルにユーザー名とパスワードに当たるフィールドがあればいいのだ。 ここでは、先の例になぞらえてuser_dataテーブルを作成しよう。そして、nobodyユーザーに権限を与え、データを登録してみる。 1.nobodyユーザーの作成
ただし、データベースを作る権限は与えない方がいい。
新規ユーザーを作る権限も与えない方がいい。
2.testデータベースに接続し、user_dataテーブルを作成する
3.user_dataテーブルに、nobodyユーザーのみに参照権限を与える
4.ユーザーを登録する
後は手順4を繰り返し、必要なだけユーザーを登録すればいい。ポイントは、パスワードのフィールドに格納している意味不明な文字列だろう。この文字列は、CRYPT方式で暗号化されたパスワードである。 mod_auth_pgsqlは、デフォルトでCRYPT方式で暗号化されたパスワードを採用している。このほかに MD5形式で暗号化されたパスワードを用いることも可能だが、その場合は
という行をhttpd.conf(または.htpasswd)に設定する必要がある。逆に、パスワードを暗号化しないのであれば、
という行をhttpd.conf(または .htpasswd)に設定する。 CRYPT方式で暗号化されたパスワードは、意外に簡単に作成できる。Perlがインストールされているなら、以下のようにするのが簡単だ。
上記の「xx」は、自由に決めた2文字の英数字を入れること。同じ文字列を暗号化する場合でも、この2文字の英数字によって結果が変化するようになっている。また、暗号化したパスワードの先頭の2文字は、ここで指定した2文字と一致するようになっている。 ここまで説明すれば、後は想像に難くないだろう。ユーザーが入力したパスワードを検査する際、先頭の2文字を読み取って入力したパスワードを暗号化するのである。一度暗号化した文字列は、決して元に戻すことはできない。少なくとも、そんなアルゴリズムは紹介されていない。パスワードを暴くには、適当な文字列を暗号化して、一致するものを探すしかないのである。しかし、これが弱点となる。 つまり、辞書に載っているような単語であれば、それを暗号化した辞書を作るのは簡単だ。従って、簡単な文字列の場合、暗号化した後の文字列さえ分かれば比較的容易に破られてしまう。この弱点を補うには、辞書に載っているような単語をパスワードにしないようにするしかない。
■グループを使ったセキュリティ設定 次は、グループでの認証を行う方法である。これには、ユーザーを管理するテーブルのほかに、グループを管理するテーブルが必要となる。 mod_auth_pgsqlの仕様的には、同じテーブルでユーザーとグループを管理することもできる。しかし、この場合は1人のユーザーが複数のグループに所属するような管理が難しい。RDBの設計上も、こうした設計は冗長なものと見なされる。従って、グループを柔軟に管理しやすいよう、複数のテーブルを作成する方法をお勧めする。
上のようなテーブルを作成した場合、グループ名はgroup_nameフィールドに格納される。その中のAdminグループにのみアクセス権限を与えるのであれば、次のように設定すればよい。
■より高度なセキュリティ設定 mod_auth_pgsqlにはほかにもディレクティブが存在する。その中で重要と思われるのが「Auth_PG_pwd_whereclause」と「Auth_PG_grp_whereclause」である。これは、Auth_PG_pwd_tableもしくはAuth_PG_grp_tableで指定したテーブルに、さらに条件を付け加えるために用いられる。 例えば、user_dataテーブルに登録されたユーザーで、なおかつlocationフィールドが TOKYOのユーザーだけを認証するとしよう。その場合、
となる。このように、「""」で条件を囲み、その条件の先頭には「and」を付け加える。同様に、グループを登録したテーブルに含まれる列に対して特定の条件を付け加えたいのであれば、Auth_PG_grp_whereclauseを使えばよい。 ■監査(ログを取る) mod_auth_pgsqlは、PostgreSQLを使って独自にアクセスログを収集できる。ログは、認証に成功した際にログ用テーブルに記録される。記録できるのは、ユーザー名、時刻、リクエストしたURI、クライアントのIPアドレス、パスワード(平文)となっている。 通常、パスワードを記録することはないと思われるが、場合によっては制限されたコンテンツに対してだれがどこからいつアクセスしたかを記録したいこともあるだろう。その際は、以下のように設定すればよい。
この設定例では、log_dataテーブルの各フィールドにユーザー、時刻、URI、IPアドレスが記録される。注意点は、やみくもに記録したのではディスクを無駄に消費するだけになるということである。ログを記録するのであれば、その運用についてもルールを定め、定期的にデータをクリーニングするなどの手段を用意しなければならない。 ◆ ほかのデータベースでも、基本的な流れやできることに大差はない。これを参考に、ほかのデータベースを使ってみるのもよいだろう。 |