LDAPでADのグループに所属するメンバを取得する
LDAPでActiveDirectoryを操作することはよくありますが、
数千名からなるグループにユーザを登録/削除するのは初めてでした。
システム開発に携わったことがある人であれば
お分かりでしょうが、データの規模がある程度の
レベルを超えると必ずといっていいほど予想外の
ことが起きてきます。
今回はそんなお話。ちなみに使用する言語はPHPですが、
他言語でも同じことが言えます。
たとえば、exampleグループのメンバを取得しようと思えば
$result = ldap_search($ld, "cn=Users, dc=test, dc=local", "(cn=example)");
$entry = ldap_first_entry($ld, $result);
$attrs = ldap_get_attributes($ld, $entry);
で、$attrs['member']にユーザの一覧が取れます。ちなみに、
$attrs['member']['count']には自動的に件数が入ります。
(可読性向上のために「あえて」エラー処理は省いてますから、そのまま真似しないように)
これが、ある日突然全く取得できなくなってしまいました。
当然、$attrs['member']['count']に入っている値は0です。
よーく取得できた値を見てみると、いつもの['member']ではなく、
['member;Range=0-1499']というキーの中にちょうど1500件だけ
ユーザの一覧が入っています。その脇にはしっかり['member']もいます。
ちょうどこんな感じです。
$attrs = array(
'member' => array(
'count' => 0
),
'member;Range=0-1499' => array(
'count' => 1500,
....
(ユーザの情報が1500件分)
)
);
最初はサーバの設定を疑いましたが、どうもそうではなさそうです。
じゃあPHPかっ!とも思いましたが、PHPのソースをひっくり返しても
0-1499みたいな操作をしているところは見当たりません。
もしや……、と思ってLDAPのパケットを拾ってみると、
サーバから返ってくるデータ自体が「member;Range=0-1499」
のようになっていることが判明しました。
早速そのへんをググって見ると……、ありました。
Searching Using Range Retrieval(英語):
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/searching_using_range_retrieval.asp
えーと、要は1回の問い合わせでは1500件を超えるデータは返せないと。
それ以上取得するときは、Rangeを変えながら繰り返し取得せいと。
……ざけんな、コラ。
つまりは、きちんと全件取るにはこんな処理になるということですね。
$range = 0;
$max = 1500;
$member = array('count' => $max);
while ($member['count'] == $max) {
$result = ldap_search($ld, "cn=Users, dc=test, dc=local", "(cn=example)",
array('member;Range=' . $range . '-*'));
if (!$result) {
$member['count'] = 0;
break;
}
$entry = ldap_first_entry($ld, $result);
$attrs = ldap_get_attributes($ld, $entry);
$member = array_merge($member, $attrs[$attrs[0]];
$range += $max;
}
これで、$member に $attrs['member']相当のものが取得できます。
まー、パフォーマンスを考慮してなんでしょうけど、
そういうのは開発する側がきちんと考えればいいことで、
時間がかかっても全部返すようにしとけよ、って感じですかね。
| 固定リンク


コメント