最低限のセキュリティ設定

デフォルトではアクセス制限がかなり甘いので、最低限の引き締めを行う。

管理サーバのクライアントIP制限

389 Management Console で Administration Server を開き、Configuration タブ -> Network タブを開く。

ウィンドウ中ほどの Connection Restrictions のドロップダウンで Host Names to allow を選ぶ。デフォルトでは、
*.hoge.com
のような 1エントリがあるだけだが、設定クライアントホストが絞り込めるのなら、ワイルドカードはやめる。管理サーバ自体の FQDN と、localhost.localdomain 及び localhost を書いておくのは、管理サーバのアクセスエラーログ出力を減らすため。サーバとは異なるセグメントにあるマシンからも設定を行うなら、それも書き加えないとアクセスできない。
次に、ドロップダウンを IP Address to allow に変える。デフォルトでは、全てのクライアントを許可する
*
だけが登録されている。こちらも管理サーバ自体の IPアドレスとループバックアドレスを加え、絞り込めるのならワイルドカードはやめる。別セグメントからも設定を行うなら適宜追加。

なお、ヘルプによると、コネクション制限ではまずホスト名のほうで評価され、一致しなければ IPアドレスのほうが試されるようだ。

ディレクトリのアノニマスBIND抑止

389 DS ではアノニマスバインドが有効になっており、ディレクトリサーバで管理されるツリーの最上位オブジェクト (当ページの例だと `dc=hoge,dc=com') 自体に、アノニマスアクセスを許可する ACI (アクセスコントロールインストラクション、その集合体が ACL) が設定されている。389 DS でも他の大多数の LDAPサーバと同様に、上位オブジェクトに設定された ACL はその樹下全てへ継承される。ただし、危ないからといってこの ACI を単に削除してしまうと、DSGW からのアクセスがまったくできなくなるなど使用に支障を来す。そのため、ちょっと複雑な設定をしなくてはならない。加えて、DSGW の設定にも少し手を加える。

当解説では、LDAPデータの照会や更新を、専用の代表エントリでバインドして行うことを想定している。主眼としているのはバーチャルユーザで運用するメールサーバからの利用だ。LDAPに登録してあるユーザエントリ各自でバインドしてパスワードなどの変更も許可するログインユーザデータベース的な使い方をする場合には、違ったアプローチが必要だろう。

389 DS の ACI はなかなか複雑。詳しくは 389 DS の "How to use access control" や、Red Hat DS の Administration Guide 内の "Managing Access Control" の章 を参照するといい。

当例では、ディレクトリサーバの管轄ツリーが dc=hoge,dc=com だと仮定。その下にデフォルトで存在する ou=People 下で uid=taro,ou=People,dc=hoge,dc=com といった実際のユーザエントリを管理するものとする。dc=hoge,dc=com の直下に実ユーザエントリを置く運用にしてしまうと規制が掛けにくい。また、389 DS では、管理 GUI の都合から、できるだけデフォルトの ou を使った方が無難で、DSGWカスタマイズも最小限で済む。

最上位オブジェクトのACL調整

[達成したいこと]: ディレクトリツリー最上位オブジェクトの ACL を、OpenLDAP で言うところの 'by anonymous auth' 相当に設定する。また、DSGW の動作に支障を来さないために、DSGW CGI をデフォルトで BIND させるための特別なユーザエントリを作り、read, compare, search を許可する。

まず、DSGW 初期BIND用のユーザを dc=hoge,dc=com の直下に作成する。ディレクトリの最上位オブジェクトである hoge を左クリックしてハイライトしてから右クリックして、New -> User を選択する。
このユーザは、DSGW CGI をデフォルトで BIND させるために作成するユーザだ。通常の LDAP クライアント (ldapsearch などのツールや例えば Postfix MTA や Dovecot IMAP/POPサーバ) は、こんなものはなくてもディレクトリデータが使えるのだが、これからやるようにアノニマス参照を制限すると、DSGW はデータが見られなくなってしまうのだ。
dsgwuser という名前は任意であり、何でも構わない。パスワードは必ず登録しないとこのユーザの意味がない。左図のように上から6項目を入れたら OK ボタンで登録する。 uid=dsgwuser,dc=hoge,dc=com というエントリが作成される。
好みの問題だが、dsgwuserDNcn=dsgwuser,... にしたかったので、上記で作ったユーザをダブルクリックしてプロパティ画面を表示し、Naming AttributeChange ボタンをクリック。そうすると左図の小窓が出るので、uid のチェックを外して cn にチェックを付ける。これで、DNcn=dsgwuser,dc=hoge,dc=com に変わる。
次に、この非常に特殊なユーザを入れるグループを作る。hoge の下位の Groups を左クリックでハイライトさせてから右クリックして、New -> Group を選択する。
General 画面で、グループ名を、これも任意だが RestrictedAdmins と入れてから、
Members 画面で Add ボタンを押し、ユーザ dsgwuser をメンバに入れる。それ以外にいじる箇所はないので OK で登録する。
次に、ディレクトリ最上位オブジェクトの ACI を編集する。hoge をハイライトさせてから右クリックし、Set Access Permissions を選択。
ACL 編集ウィンドウで、作りつけの Enable anonymous access をハイライトして Edit ボタンを押す。
Rights タブを開き、read のチェックを外す。389 DS には OpenLDAPACL の "auth" にあたるパーミッションがないのだが、compare + search が同等の役目を果たす。OK でこの窓を閉じる。これによって、OpenLDAP の `by anonymous auth' に相当するACI が設定できたわけだ。
なお、Enable anonymous access アクセスリストの Targets は、元々「userPassword アトリビュート以外全部」の設定になっているので編集の必要がない。
今度は ACI を新規に追加するため New ボタンを押す。
名称を例えば RestrictedAdminAccess とし、Users タブで、デフォルトで入っている "All Users" を削除し、先ほど作ったグループ RestrictedAdmins を加える。
Rightsread, compare, search の 3つを有効にする。
Targets タブのアトリビュート部で、念のため Check All ボタンを押してから、userPassword 属性だけチェックを外す。ターゲットエントリとフィルタは空のまま。OK で窓を閉じる。
これが、最上位 dc=hoge,dc=comACL を編集し終わった状態。

運用ouのACL調整

[達成したいこと]: 実際のユーザエントリ登録ツリーとする ou=People 下を代表で読み書きする管理ユーザ (参照専用と書込用の 2人) を作り、権限を与える。また、最上位から継承されるアノニマス参照許可を打ち消す ACI を追加する。

管理ユーザはまた dc=hoge,dc=com 直下に作る。hoge を右クリックして New -> User で登録に入る。
もうこのへんで操作方法はだいたい飲み込めたと思うので、以降細かい手順は省かせていただく。
エントリ登録/編集/削除用の管理ユーザ uid=usermanager,dc=hoge,dc=com を作る。作成後、例によって、好みによりまた DNcn=usermanager,... に変更。

絵は省くが、同様にして、エントリ参照専用の管理ユーザ cn=userretriever,dc=hoge,dc=com も作る。
メイン画面に戻ったら、Groups の下に UserManagers グループを新規に作成し、上記の管理ユーザ 2つをメンバにする。
メイン画面から、PeopleACL 編集ウィンドウを開き、アノニマス参照を打ち消すための新しい ACI を追加する。名称は例えば DenyAnonymousUsers タブで、デフォルトで入っている "All Users" を削除し、先ほど作った UserManagers グループを加える。
Rights タブで、ウィンドウ右側の Check None ボタンを押す。これにより、LDIF 定義上のアクションが `deny(all)' になる。
Targets タブでは、ターゲットとフィルタは空欄のまま、アトリビュートリスト右の Check All ボタンを念のため押す。
次に、GUI ではサポートされていないACI文言を使うために、画面左下の Edit Manually ボタンを押す。
`groupdn = "ldap:///.."' を `groupdn != "ldap:///.."' に書き換える。右隣の Check Syntax ボタンをクリックすると、文法が変になっていないかどうか確認できる。
ou=People サブツリーに、「管理ユーザしか参照も何もできない」という DenyAnonymous ACI が追加された状態。LDAPスーパーユーザである cn=Directory ManagerACL を無視するのでこの規制を受けない。
続いて、ユーザエントリ管理ユーザに権限を与える作業に入る。まず、参照用管理ユーザ。上記画面で New ボタンを押し、名称を UserDataAdminRetrieveUsersuserretriever のみを登録。
Rightsread, compare, search だけにして、
Targets では、ターゲットディレクトリ欄に
uid=*,ou=People,dc=hoge,dc=com
を入力 (This Entry ボタンを利用すると入力が楽)。この指定は、「ou=People,dc=hoge,dc=com 配下で uid 属性を持つあらゆるエントリ」を意味する。仮に ou=People 下にさらに ou=RandD を作ったとすると、uid=hanako,ou=RandD,ou=People,dc=hoge,dc=com も対象となる。
アトリビュートは、理想を言えば運用に必要な属性だけ選択するべきだが、属性が絞り込めない場合は Check All ボタンを押して全アトリビュートにチェックを付ける。
UserDataAdminRetrieve ACI はこれで OK だ。
次にもうひとつ、データ登録/編集/削除用管理ユーザのための ACI を作る。名称は UserDataAdminWrite とでもしよう。Usersusermanager だけを登録。
権限は Proxy 以外全部。右の Check All ボタンを押すとその状態になる。

Targets タブは、説明を省くが、参照用の UserDataAdminRetrieve と同一の設定をする。
管理ユーザ用 ACI 2つの追加が完了した状態。
DSGWou=People サブツリー配下をきちんと表示できるようにするには、ユーザエントリ管理用ユーザにも hoge 最上位オブジェクトの read, compare, search 権限を与えてやらなければならない。そうしないと、"there is no display template for this type of entry available" という変なエラーメッセージが出て属性値の表示や編集ができない。

新たな ACI を作ってもいいのだが、既に述べた RestrictedAdminAccess という ACI に制御を集約できる。つまり、やるべきことは、グループ RestrictedAdminsUserManagers グループを追加することだけだ。
ACLをコマンドで確認するには

例えば ou=People,dc=hoge,dc=com に設定されている ACL を出力するには;

user$ ldapsearch -T -D "cn=Directory Manager" -w - \
    -b "ou=People,dc=hoge,dc=com" -s base 'aci=*' aci

ACI ひとつひとつはたいてい非常に長いので、出力の折り返しを抑止する -T オプションを付けたほうが正確な出力が得られる。

アノニマス抑止に伴うDSGWの設定変更

上記のセキュリティ強化を行うと、既定ではアノニマスBIND ありきで設定されている Directory Server Gateway からは、データの検索も認証もできない状態に陥る。普通の LDAPクライアントなら、BIND しようとしてこちらが提示している DN とパスワードが 正しいかどうか を LDAPサーバに訊くだけなので BIND は成功するのだが、DSGWAuthentication 画面の CGI は、まずユーザ名を search + read して uid なり cn なりとして得られた値を画面に一旦表示し、それからパスワードを入力させて合否をチェックする、という 2ステップになっている。おかげで、ディレクトリツリー全体にアノニマスでの read 権限のない状態では、第1ステップで失敗するため認証が成り立たないのだ。

幸いなことに DSGW には、アノニマスBIND をやめ、あらかじめ特定の DN で初期バインドさせる方法が用意されている。その用に供するために作成したのが、前述の dsgwuser という非常に限られた権限だけを持つ LDAPユーザだ。

設定手順

初期BIND に使う DN とパスワードを納めたテキストファイルを作成する。置き場所は任意だが、管理サーバ HTTPD実行ユーザ (= ディレクトリインスタンス及び管理サーバのデプロイの際にSystem Userとして指定したUNIXアカウント = 当ページの例では dsadmin) のアクセスできる場所でなければならない。ただし、管理サーバの HTTPD を通してクライアントからアクセスされる可能性のある場所 (/etc/dirsrv/dsgw//usr/share/dirsrv/ 配下) は避けなければならない。ここでは例として、/etc/dirsrv/dsgwdn というファイルを作る。書式 (※) はこんな具合;

binddn "cn=dsgwuser,dc=hoge,dc=com"
bindpw mysecret

もちろん DN とパスワードは前述の手順で LDAP に登録した DSGW用ユーザのものだ。ファイルパーミッションは dsadmin:root 600 または 640 に設定する。

※ 初期パスワードファイルの正しい書式を見つけるのには苦労した。389 DS オフィシャルサイトのドキュメントの記述は間違っており、さんざんネットを放浪した末、行き当たったのは Netscape Directory Server 4.0 の Netscape Directory Server Gateway Customization Guide という古い文書。ホストはルーマニアにあるようだ。

次に、/etc/dirsrv/dsgw/dsgw.conf をエディタで開き、

binddnfile	/etc/dirsrv/dsgwdn

というディレクティブを書き加えることによって先ほどの初期BIND用パスワードファイルのフルパスを教えてやる。

以上が終わったら、変更を反映させるため `service dirsrv-admin restart' で管理サーバを再起動。

サーバ自体の上からブラウザで Directory Server Gateway にアクセスし、People をワイルドカード `*' で検索。この章で作った管理ユーザが表示されれば (左図)、binddnfile 設定は成功している。

ou=People 下のエントリは、Authentication タブで usermanageruserretriever としてログインしてからでなければ参照も編集もできなくなったはずだ。

ただし、どうしても、画面での認証以前にも管理ユーザだけは丸見えになってしまう。そこで、せめてもの対策として、DSGW にアクセスできるクライアント IP を Apache のレベルで制限する。クライアントIP制限を掛けるには、/etc/dirsrv/dsgw/dsgw-httpd.conf の下記の部分を修正して管理サーバデーモンを再起動すればいい。下記は、サーバ自体からと 192.168.0.0/255.255.255.0 のネットワークセグメントからのみ許可する例。

# Allow access to the cgi programs
<Location "/dsgwcmd">
    Options +ExecCGI
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1 192.168.0.0/24
</Location>