LDAPディレクトリを投入しフィルタで照会する
目標
slapdを自分で起動して組織のLDIFをロードし、LDAPの検索フィルターを組み合わせて、必要なユーザー・グループを正確に取り出せるようになります。
なぜ重要なのか
SIプロジェクトで「私たちのシステムに社内アカウントを付けてください」は、結局LDAP照会で終わります。ところが、フィルターをいい加減に書くと、無効なアカウントやサービスアカウントまでユーザー一覧に入ってきて、返す属性を指定しないと、10万人のディレクトリで全属性を取得してサーバーを苦しめます。また、このラボのディレクトリは、グループが人を指す(member)構造で、ログインのたびに「この人のグループ」を求めるために全グループをスキャンするコードが、実際に作られます。ユーザーが100人のときは気づかず、1万人になるとログインが3秒になります。
ステップ
- slapdを1389ポートで起動してください。
slapd -h ldap://127.0.0.1:1389 -F /opt/lab/ldap/slapd.dそして、Root DSEを照会して/root/ldap/root-dse.txtに保存してください。 ファイルにdc=labhub,dc=co,dc=krが含まれている必要があります。 /opt/lab/fixtures/auth/ldif/00-base.ldifをロードしてください。 Base DNdc=labhub,dc=co,dc=krの照会が成功する必要があります。/opt/lab/fixtures/auth/ldif/10-people.ldifをロードしてください。objectClass=inetOrgPersonのエントリが30個ある必要があります。/opt/lab/fixtures/auth/ldif/20-groups.ldifをロードしてください。objectClass=groupOfNamesのエントリが6個ある必要があります。- 開発チーム所属で、役職が課長(グァジャン)の人の
uidだけを選んで、1行に1つずつ昇順で/root/ldap/q1.txtに保存してください。 (部署の属性はou、役職の属性はtitleです。) - 役職が部長(プジャン)または次長(チャジャン)で、総務チームではない人の
uidを、同じ形式で/root/ldap/q2.txtに保存してください。 uid=hongが所属するグループのcnを、1行に1つずつ昇順で/root/ldap/groups-of-hong.txtに保存してください。/root/ldap/whois.shを作成してください。引数を1つ(uid)受け取り、次の4行を、正確にこの順序で出力してください。存在しないuidの場合は、0以外の終了コードで終了します。
(山括弧の中の韓国語はプレースホルダーで、順に名前、部署、役職、所属グループ数です。)cn=<이름> ou=<부서> title=<직급> groups=<소속 그룹 수>
参考
- 基本の照会:
ldapsearch -x -H ldap://127.0.0.1:1389 -b "dc=labhub,dc=co,dc=kr" -LLL "(필터)" 속성명(プレースホルダーはフィルターと属性名です) - ロード:
ldapadd -x -H ldap://127.0.0.1:1389 -D "cn=admin,dc=labhub,dc=co,dc=kr" -w labhub123 -f 파일.ldif(プレースホルダーはファイル名です) - 件数の数え方: 結果から
dn:で始まる行を数えれば済みます。 - よくあるミス1: フィルターの括弧の対応が合っていないことです。
(&(a=1)(b=2))のように、全体をもう一度括る必要があります。 - よくあるミス2: 返す属性を指定せず、全属性が流れ出してしまうことです。
- よくあるミス3:
-bを抜かすことです。Baseがないと、どこから探せばよいのかサーバーがわかりません。
slapdの起動とRoot DSEの確認
slapdを1389ポートで起動してください。
slapd -h ldap://127.0.0.1:1389 -F /opt/lab/ldap/slapd.d
そして、Root DSEを照会して/root/ldap/root-dse.txtに保存してください。
ファイルにdc=labhub,dc=co,dc=krが含まれている必要があります。
この環境では、1024未満のポートにバインドできません。Root DSEは、baseを空文字列に、scopeをbaseに指定すると照会できます。サーバーがどんなネーミングコンテキストを持っているかを教えてくれます。
ベースエントリのロード
/opt/lab/fixtures/auth/ldif/00-base.ldifをロードしてください。
Base DNdc=labhub,dc=co,dc=krの照会が成功する必要があります。
LDIFは上から下へ適用されるので、親のエントリが先にないと、子を入れられません。ldapaddに-fでファイルを渡します。
ユーザーエントリのロード
/opt/lab/fixtures/auth/ldif/10-people.ldifをロードしてください。
objectClass=inetOrgPersonのエントリが30個ある必要があります。
ロード後に件数を数える習慣をつけてください。LDIFを投入したからといって、すべて入っているわけではありません。重複するDNがあると、その項目だけが失敗します。
グループエントリのロード
/opt/lab/fixtures/auth/ldif/20-groups.ldifをロードしてください。
objectClass=groupOfNamesのエントリが6個ある必要があります。
groupOfNamesには、memberの属性が最低1つ必要です。空のグループを作ろうとしてスキーマ違反に遭うのが、最初の関門です。
複合条件のフィルター
開発チーム所属で、役職が課長(グァジャン)の人のuidだけを選んで、1行に1つずつ昇順で/root/ldap/q1.txtに保存してください。
(部署の属性はou、役職の属性はtitleです。)
LDAPのフィルターは、演算子が先に来る前置記法です。ANDは(&(...)(...))の形で、括弧の対応が合っている必要があります。
ORとNOTの組み合わせ
役職が部長(プジャン)または次長(チャジャン)で、総務チームではない人のuidを、同じ形式で/root/ldap/q2.txtに保存してください。
ORの中に複数の条件を入れ、全体をANDで束ねたうえで、NOTで1つを除外します。括弧を紙に書いてみると、ミスが減ります。
グループメンバーシップの逆引き
uid=hongが所属するグループのcnを、1行に1つずつ昇順で/root/ldap/groups-of-hong.txtに保存してください。
このディレクトリは、人がグループを指すのではなく、グループが人を指します。そのため、「この人が所属するグループ」は、グループ側で探す必要があります。
ユーザー照会スクリプト
/root/ldap/whois.shを作成してください。引数を1つ(uid)受け取り、次の4行を正確にこの順序で出力してください。存在しないuidの場合は、0以外の終了コードで終了します。
cn=<이름>
ou=<부서>
title=<직급>
groups=<소속 그룹 수>
(山括弧の中の韓国語はプレースホルダーで、順に名前、部署、役職、所属グループ数です。)
引数で受け取ったuid1つについて、必要な情報を集めて出力します。ldapsearchの出力から値だけを取り出すときは、-LLLオプションが役に立ちます。