Skip to content

LDAP Survival Guide

この記事は https://docs.evolveum.com/iam/ldap/ldap-survival-guide/ の翻訳です。

Radovan Semančík

Lightweight ディレクトリアクセスプロトコル (LDAP) は、1990年代に生まれたディレクトリプロトコルです。 さらに古い、1980年代にさかのぼる X.500 の作業に基づいています。 現在、LDAP は通常、中央ディレクトリサーバーでユーザーアカウントを維持管理するために使われます。

LDAP は広く使われているプロトコルです。 一部の、たいていは年長の エンジニアは LDAP を好みます。好まれる理由はたくさんあります。 単純さの中に elegance があり、非常に効率的で、1990年代に私たちが価値を置いていたものをほぼ備えています。 しかし多くの、たいていは若い エンジニアは LDAP を恐れ、嫌います。LDAP には嫌われる理由もたくさんあるからです。 LDAP の厄介な部分の多くは、過去の誤りs を修正し、変化した世界に適応できないことに由来します。

この文書は、一般的な LDAP 問題と、それらを回避する方法の説明です。 単純な bindsearch のような簡単なことだけを LDAP で行うなら、このガイド はまったく不要でしょう。 しかし LDAP グループ、paged 検索、同期を扱う場合、または LDAP を アイデンティティ管理 に使う場合、このガイド はおそらく役に立ちます。 LDAP の世界には、多くの慣習、落とし穴、暗黙のルール、文書化されていない慣行があります。 この文書は、そうした危険な waters を進む手助けをしようとするものです。

このガイド は、1990年代後半から LDAP を扱っている エンジニア によって書かれています。 あなたが古くからの LDAP エンジニア なら、私の view点 はほぼ確実に気に入らないでしょう。 私はあなたの opinion を変えようとしているわけではありません。 それはこのガイド の目的ではありません。 私がしようとしているのは、LDAP labyrinth を生き延びるための tip を提供することです。 この文書は、物事を片付ける必要がある 現実的 エンジニア を助けるためのものです。

認証

LDAP の最も一般的な用途は、アプリケーションに password-based 認証を可能にすることです。 アプリケーションはディレクトリサーバーに認証するために bind LDAP 操作を使います。 その操作が成功すると、アプリケーションはパスワードが正しかったと仮定します。 この認証を実装する間違った方法 (dn パターン を使う方法) と、それよりはましな方法 (search してから bind する方法) があります。 しかし適切な方法はありません。LDAP は認証サーバーとして設計されたわけではないからです。 それでも、これは圧倒的に最も広く使われている LDAP プロトコルの用途であり続けています。

もちろん、これは多くの問題を引き起こします。 これは実質的にパスワード認証に限られます。 他の認証機構をサポートできる SASL layer はありますが、サーバーはそもそも認証サーバーになるようには作られていません。 LDAP にはセッションの概念がないため、ディレクトリサーバーはセッション管理や監査には使えません。 このように使われることは想定されていませんでした。 しかし、そう使われています。

これは LDAP プロトコルそのものの問題ではありませんが、LDAP の世界 について多くを物語っています。 LDAP は、意図されておらず、元の設計者 が予期もしなかった方法で使われています。 1980年代の telecommunication world に根を持ち、1990年代に作られたプロトコルが、21世紀の利用ケースを扱うために使われています。 それに十分備わっていないのは不思議ではありません。

What To Do About It?

何もありません。 そういうものです。 LDAP は認証プロトコルとして設計されていません。 それでも、ほとんどの場合認証に使われています。 LDAP パスワード認証 (LDAP bind) は、単純アプリケーションやレガシーアプリケーション向けにパスワード認証を centralize する最も簡単な方法です。

しかし、あなたのアプリケーションがまともなものであれば、OpenID Connect (OIDC) や SAML のような本物の認証またはアクセス管理プロトコルをサポートしているでしょう。 可能であれば LDAP ではなくそれらの方法を使ってください。 それらは単純なパスワード認証よりはるかに多くを提供できます。 それが future への道です。

アカウント管理

確かに LDAP は認証プロトコルとして設計されたわけではありません。 しかし LDAP はディレクトリアクセスプロトコルとしては設計されました。 ほとんどの LDAP サーバーは実際にはディレクトリサーバーです。 ディレクトリ世界における目立つ生命体は ユーザーアカウント です。 LDAP がアカウント管理に優れたツールであると期待するのは妥当に思えます。 残念ながら、そうではありません。

Multiplicity Of Names

LDAP スキーマは、古い X.500 データモデルに影響を受けています。 それがおそらく、LDAP データ構造に慢性的な「multiplicity」がある由来です。 ユーザーの名前は cn 属性に保存されることになっています。 cn は、sngivenNameuid、その他ほとんどの LDAP 属性と同様に multi-valued です。 通常ユーザーの login 名前を保存する uid については、これはある程度意味があります。 ユーザー名 alias をサポートするために使えるかもしれません。 しかしそれでさえ完璧にはほど遠いものです。 そしてこの multiplicity は、cnsngivenName についてはほとんど意味がありません。 導入の圧倒的多数は、これらを single-valued 形式で使っています。 私は、ほとんどのアプリケーションがこれらの属性に複数価値があるのを見つけたら、ひどい誤りを出す方に昼食を賭けてもよいです。 なぜ LDAP はこれらの価値が multi-valued でなければならないと mandate しているのでしょうか。 厳密に言えば、standard-compliant LDAP クライアントは multi-valued 名前を扱える必要があります。 しかしクライアントはそれをどう扱うべきなのでしょうか。 LDAP は ordering を保証しないため、first 価値を取ることには意味がありません。

What To Do About It?

これは単純です。 cnsngivenName、および類似属性を multi-valued 属性として使ってはいけません。 常に single-valued 属性として使ってください。

uid の multi-valued nature が意味を持つケースはあります。 しかし、自分が何をしているかを本当に理解し、すべての consequence を完全に認識しているのでない限り、それも避ける方がよいです。

これは、ほぼすべての LDAP クライアントが実際に行っていることです。 したがって、LDAP クライアントの大多数は完全には LDAP 準拠 ではありません。 それでも、この non-compliance は現実世界で大きな問題を起こしません。 これが LDAP の世界です。LDAP 標準に加えて暗黙の LDAP 慣習に従えば問題ありません。

Blast from the past

TIP: スキーマには、1980年代を感じられる場所が他にもあります。 明らかに facsimileTelephoneNumbertelexNumber があり、懐かしい笑みを誘います。 これは面白いかもしれませんが、本当の問題ではありません。 問題は、スキーマが communication の将来の発展に備えていないことです。 Contact channel の概念がありません。 「作業 電話番号」の概念すらありません。 チャットアプリケーションやソーシャルネットワークは言うまでもありません。 スキーマは1990年代で凍結されています。

アカウント有効化

おそらく最も痛い問題は、account 無効化 機構がないことです。 はい、そういうことです。 LDAP ディレクトリでアカウントを無効化 する標準方法はありません。 ほとんどの エンジニアは、アカウント 有効化 の制御を非常に基本的なアカウント管理機能の1つと考えるでしょう。 それは telexNumber より確実にはるかに重要です。 それでも LDAP にはありません。 これはある程度理解できます。 1980年代の telecommunication world は、今日の世界とは大きく異なっていました。 当時は テレックス番号の方が account 無効化 よりずっと重要でした。 問題は、X.500 が LDAP に transposed された1990年代にこれが修正されなかったことです。 そして今日に至るまで修正されていません。

LDAP の課題の多くは理解でき、許容さえできますが、これだけは理解できません。

What To Do About It?

アカウントを無効化 する機構は、実務ではほぼ常に必要です。 そのため、ほとんどの LDAP サーバーはそのための 独自 機構を持っています。 LDAP クライアントは、ほぼすべての導入で必要な機能を実装するために non-standard な方法を使わなければなりません。

個々の LDAP サーバーでは次のようになります。

iPlanet family: (RedHat/Fedora) 389 ディレクトリサーバー, Sun/Oracle DSEE nsAccountLock 運用属性を使います。
OpenDS family: OpenDS, OpenDJ, wren:DS, UnboundId ds-pwp-account-disabled 運用属性を使います。
OpenLDAP 残念です。できません。パスワードポリシーを使ってパスワード認証を 無効化できます。単純ケースでは機能するかもしれませんが、すべてのアカウント機能を 無効化するわけではありません。たとえば代替策認証機構 (UNIX ssh鍵など) は引き続き機能します。このために専用属性を作成できますが、その場合はすべてのアプリケーションを修正してそれをサポートさせる必要があります。ACL を使って bind を 無効化 し無効化アカウントを隠す trick もあります。しかしそれも問題があります。実際、OpenLDAP でアカウント 無効化を行う良い方法はありません。
Active Directory userAccountControl 属性を使います。これは非常に醜い属性で、扱いにくいものです。しかし、ある意味では機能します。

グループ

LDAP グループは、信じられないほど間違っているものの1つです。 うまい言い方はありません。 LDAP グループ化機構が設計されたとき、うまくいかない可能性があったものはほぼすべてうまくいきませんでした。

グループはメンバーを持つ

典型的な LDAP グループは メンバーアカウント (または他グループ) のリスト を含みます。 これはグループスキーマを設計する明らかな方法に見えるかもしれません。 特にアクセス制御の単純化において、いくつかの advantage があります。 しかし 運用観点 から見ると悪夢です。

一般的な LDAP サーバーには、ほぼすべてのアカウントが メンバーである大きなグループがいくつかあります。 つまり、1つの属性に膨大な数の価値を持つ LDAP オブジェクトが存在することになります。 そのようなグループに member を追加するのは非常に苦痛です。 操作はしばしば非常に遅くなります。 それでも、これはアカウントが追加または削除されるほぼ毎回発生する操作です。 複数グループのメンバーシップを1つの操作で更新する方法はないため、関係するすべてのグループで遅い down に耐えなければなりません。 LDAP サーバーは lightning-fast であることを誇ります。 しかしアカウントを1ミリ秒未満で作成できても、そのアカウントの完全なプロビジョニングにグループ割り当てが含まれ、それに文字どおり数秒かかるなら、それに意味はあるのでしょうか。

What To Do About It?

これについてできることは多くありません。 古い LDAP サーバー (特に iPlanet family) は big グループで非常に問題があります。 一部の LDAP サーバー (特に OpenLDAP) は big グループでも高速に更新できます。 LDAP サーバーをより高速なものに置き換えることはできます。 しかしサーバー間には subtle incompatibility があるため、LDAP サーバーの置き換えは遅くリスクの高いプロセスです。

ただし、サーバーが big グループを扱える場合でも、アプリケーションでそれらを扱うときは注意が必要です。 大量の member を持つグループエントリを頻繁に読むと、性能を破壊する可能性が非常に高いです。 グループを読むときは、必要な属性だけを明示的に申請してください。 つまり member 属性を読むのは避けてください。 最良の方法は、グループエントリをまったく読まないことです。 グループメンバーシップを判定するには non-standard な member of 機構を使ってください。 グループを 変更するときは 標準外の permissive modify を使ってください。 これら2つは、グループを扱うときの基本 survival ツールです。

後で見るように、LDAP グループを扱うのは minefield を横断しようとするようなものです。 多くの trial と 誤りに備えてください。 一部の問題は full 本番環境に入って初めて遭遇します。 しかし少しの luck があれば、最後には機能するソリューションを得られます。

Member Of

グループが member list を持つという事実は、ユーザーのグループメンバーシップを判定するのを少し難しくします。 標準 LDAP では、クライアントは particular member DN を探すためにすべてのグループを検索しなければなりません。 LDAP 導入は認可目的のためにグループに依存することがよくあります。 つまりクライアントはグループメンバーシップを判定するために毎回 additional 申請を行わなければなりません。 Big グループの存在を考えると、この申請は必ずしも速くありません。

もちろん、この問題は過去に認識されていました。 そのため、ほぼすべての LDAP サーバーには、グループメンバーシップをユーザーエントリ上の 仮想属性として反映する "member of" 機構があります。 しかし、この機構は標準化されていません。 Virtual 属性はあるサーバーでは memberOf、別のサーバーでは isMemberOf です。 これは、ほぼすべての LDAP クライアントにとって crucial な、また別の non-standard 機構です。

What To Do About It?

利用可能な場合は、常に member of 機構を使ってください。 これはグループを扱う際の基本 survival ツールです。 ほぼすべてのサーバーがそのような機構を持ち、多くのサーバーではデフォルトで enabled です。 OpenLDAP は、デフォルトでは enabled ではない広く使われているサーバーの1つですが、この機能を提供する特殊な memberOf overlay があります。

空グループは禁止

状況を完全に bizarre にしているのは、LDAP 標準がグループ member を mandatory 属性として指定していることです。 はい、standard-compliant LDAP サーバーのすべてのグループは、少なくとも1つの member を持たなければなりません。 この判断の公式な理由は 空グループを避けることです。 これは noble 目的です。 問題は、それがまったく意味をなさないことです。

これはグループを pre-provision できないことを意味します。 これはグループの最後の member が削除された場合、そのグループも削除されなければならないことを意味します。 これはグループが一時的に empty になる場合、それを削除して再作成しなければならないことを意味します。 再作成されたグループは新しい entryUUID を持つため、smart LDAP クライアントには新しいオブジェクトと見なされます。 これは同期機構にとって大きな混乱を引き起こします。 標準 LDAP サーバーでは 空グループが legal に存在できないため、空グループに関する情報は何らかの外部データベースで維持管理しなければなりません。 最悪なのは、空グループがシステム管理者から見えないことを意味する点です。 全体として、これは実務では機能しません。

ほとんどの LDAP 導入は、現実世界の導入に適するよう、何らかの方法でこれを回避しています。 Full LDAP コンプライアンスにこだわる導入は、通常各グループに 偽メンバー を追加します。 それは機能しますが、セキュリティ担当者は完全には満足しないでしょう。 これを回避する 準厳格な方法は、空グループのみに 偽メンバー を追加することです。 残念ながら、それも実際には機能しません。 その場合、新しい member を追加するすべての操作は、偽メンバー も削除しなければなりません。 しかし、別の LDAP 特性 (下の "permissive modify" 参照) により、偽メンバー が存在しない場合、サーバーはその操作を失敗 しなければなりません。 したがってクライアントはまず 偽メンバー がグループの member かどうかを 確認しなければなりません。 しかし標準 LDAP にはこのケースをサポートする整合性保証 がないため、その check は信頼できるではありません。 確認と修正 の間に 偽メンバー が削除されている可能性があり、その場合 修正 操作はなお fail し得ます。 Empty グループに 偽メンバー を追加しようとするとさらに悪くなりますが、その particular アルゴリズムは読者が考えるものとして残しておきます。 全体として、LDAP 標準は単純なことを信じられないほど複雑にしています。

What To Do About It?

実際、唯一 reasonable な方法は、LDAP 標準を堂々と violate し、member 属性を optional にすることです。 多くの LDAP サーバーは、いずれにせよそうしています。

iPlanet family: (RedHat/Fedora) 389 ディレクトリサーバー, Sun/Oracle DSEE 大丈夫です。ベンダーがすでにあなたのために LDAP 仕様に違反 しています。
OpenDS family: OpenDS, OpenDJ, wren:DS, UnboundId 大丈夫です。ベンダーがすでにあなたのために LDAP 仕様に違反 しています。
OpenLDAP サーバースキーマを探してください。探しているのは cn={0}core.ldif ファイルです。groupOfNamesgroupOfUniqueNames のエントリを変更し、member 属性を MUST から MAY に移動します。
Active Directory 典型的な Microsoft のやり方で大丈夫です。Active Directory は LDAP グループ化機構を使っていません。

これは LDAP 仕様化の恥知らずな違反です。仕様化は標準スキーマに対するこのような変更をかなり明示的に禁止しています。 それでも、これが唯一 sensible なことです。 悪く思う必要はありません。 あなたの fault ではありません。 ほとんどの LDAP サーバー、Active Directory、eDirectory、類似の LDAP-like サーバー、ほぼ全員がこの問題に対する ready-made ソリューションを持っています。 この insane な LDAP 仕様化の部分に今も従っている広く使われている LDAP サーバーは、おそらく OpenLDAP だけです。

どうしても LDAP 仕様化に厳密に従わなければならない場合、いくつかの代替策があります。 残念ながら、どれも非常に痛ましいです。

  • すべてのグループに dummy アカウントを追加できます。 そうすればグループは常に少なくとも1つの member を持ちます。 Referential integrity を enforce しない場合、それは存在しないエントリの DN でも構いません。 そのようなエントリが誤って作成されないようにだけしてください。 そうすれば比較的安全です。 Referential integrity がある場合、おそらく real アカウントが必要になります。 セキュリティ担当者 と 監査人 との交渉に幸運を祈ります。
  • グループが empty のときに dummy アカウントを動的に add/削除 できます。 理論上は。 しかしアルゴリズムは insane で 信頼できないです。 さらに、dummy エントリを常にグループに入れておく場合とほぼ同じ disadvantage があります。 精神衛生のために、これはやめてください。
  • Empty グループを削除しようとすることもできます。 しかしアルゴリズムは trivial ではなく、多くの disadvantage があります。 さらに悪いことに、システム管理者はあなたを嫌うでしょう。 サポート エンジニア もあなたを嫌うでしょう。 コンプライアンス人々もあなたを嫌うでしょう。 良い人でいて、これはやめてください。
  • groupOfNamesgroupOfUniqueNames を忘れ、独自のグループ化機構を使うこともできます。 独自の myCustomGroup オブジェクト種類を作り、member を optional にします。 少なくとも理論上は正しいソリューションです。 しかし、その途中で予期しない問題の山に備えるべきです。 LDAP サーバーは myCustomGroup について何も知らないため、ACL や類似機構で使えません。 アプリケーションもそのグループを知りません。 一部のアプリケーションは configurable で、動作させることができます。 しかしあまりに多くのアプリケーションが、いまだに groupOfNames または groupOfUniqueNames を頑固に期待します。 これらのグループは LDAP 標準ですから、そうではありませんか。 この route を選ぶと多くの問題があります。 本当に 切迫した でない限り、これはやめてください。

わかりましたか。 問題を修正する最良の場所は、その origin です。 したがって先に進み、LDAP 仕様に違反 し、そのことは二度と話さないでください。

グループ, グループ と グループ

さて、LDAP グループ saga はまだ終わりません。 LDAP にはグループのオブジェクト種類が2つあります。 それらはほとんど同じですが、異なっています。 groupOfNamesgroupOfUniqueNames があります。 前者は member 属性を持ち、後者は 一意Member 属性を持ちます。 実務導入で意味のある唯一の重要な違いはそれです。 member 属性の 構文にも微妙な違い がありますが、その違いはほぼすべての LDAP 導入にとって 無視できる です。

一部の LDAP サーバーは groupOfNames を好み、他は groupOfUniqueNames を好みます。 一部のアプリケーションは groupOfNames に hardwired され、他は groupOfUniqueNames を 必要とします。つまり 相互運用できません。 多くのアプリケーションは標準に見切りをつけ、これを configurable にしました。 そして posixGroup など、他のグループ化機構もあります。 さらに多くのグループ化機構が、さまざまな LDAP サーバーで 独自 形式として提案または実装されました。 LDAP グループ化機構は、中規模の ZOO と大きな lunatic asylum を満たすほどあります。

What To Do About It?

ここに良いソリューションはありません。 あなたのアプリケーションが groupOfNames を欲しがるのか、groupOfUniqueNames を欲しがるのかを見極めてください。 幸い、多くのアプリケーションは configurable ですが、もちろんすべてではありません。 LDAP サーバーも確認してください。 一部の LDAP サーバーは ACL 内でそのうち1つだけをサポートします。

全体として、これは acrobatic な balancing act です。 最悪の場合、groupOfNamesgroupOfUniqueNames の両方が必要になり、両方のメンバーシップを管理する必要があります。 posixGroup や 独自/専用グループ化機構が必要な場合も同様です。 ここでは decent なアイデンティティ管理 (IDM) システムが必須です。

検索、ページング、ソート

LDAP は lightweight です。 ある面では、軽すぎるのかもしれません。 データ取得の汎用ツールである、非常に elegant で単純な search 操作があります。 クライアントは通常、特定の1つのエントリを探します。 LDAP はそれには優れています。 しかし long 検索申請は大きな問題です。 クライアントが大量のエントリを取得する良い方法がありません。 なぜクライアントが大量のエントリを取得する必要があるのでしょうか。 データが一貫していることを確認する同期や照合プロセスがあるかもしれません。 ポリシーコンプライアンスを確認する inspection プロセスがあるかもしれません。 またはデータのレポートを作成する必要があるかもしれません。 Long 検索操作は、LDAP author が予想したより頻繁に必要になります。

Long 検索操作の最も単純な選択肢は、plain LDAP 検索操作を使うことです。 しかしほとんどのディレクトリサーバーは、返されたエントリの数に "size limit" を enforce して、これを拒否します。 管理者が limit を 無効化 したとしても、欠点は残ります。 エントリは単一 TCP 接続 越しに sequential に返されます。 その接続 が壊れた場合、検索は最初からやり直す必要があります。

次に "単純 paged results" (SPR) LDAP 制御 (RFC2696) があります。 この制御を使うと、複数申請で結果を取得できます。 これはサーバー size limit を回避する一般的方法です。 しかしエントリは依然として sequential に deli非常に されます。 運がよければ、接続が壊れた場合に検索を 再開するために使えるかもしれません。 ただし 実際の アルゴリズムは容易ではなく、すべてのサーバーで機能するとは限りません。 また、これは依然として非常に simple な paging です。たとえば starting offset を指定する方法はありません。

SPR の代替策は Virtual List View (VLV) です。 これは non-standard ですが、非常に広く使われている LDAP 制御です。 結果の particular "page" を申請するために使えます。 しかし、まだ多くの gray zone があります。 これは信頼できるに動作するためにサーバーサイドソート (SSS, RFC2891) を必要とするため、サーバーへの 影響 が明確ではありません。 したがってサーバーは通常、複数申請にまたがる temporary データ構造を作成する必要があり、それを効率的に行う方法は明確ではありません。 職務を完了しつつサーバーに優しい LDAP クライアントを作るのはかなり困難です。

Long 検索には少なくとも3つの方法があります。 SPR と VLV はサーバーにサポートされることが多いですが、各サーバーには独自の 特性 があります。 これらの方法のどれも、すべてのサーバーで汎用に機能するわけではありません。 したがって 相互運用可能 な LDAP クライアントを書くのはかなり困難です。 これは、そもそも標準がある価値をいくらか損ないます。

What To Do About It?

幸い、ほとんどのサーバーは SPR と VLV の両方をサポートしており、そのサポートもデフォルトで enabled です。 ただし、またしても OpenLDAP は notable exception で、sssvlv overlay が必要です。 しかし、すべてのサーバーが同じように behave するという意味ではありません。 特に VLV については、サーバーの振る舞い に subtle difference があります。 たとえば OpenLDAP は、VLV 検索でさえ特殊な prtotal limit を設定する必要があります。 おそらくできる唯一のことは、特定のサーバーと設定で 実験 することです。

Permissive Modify

LDAP は更新を不必要に難しくしています。 LDAP 標準は、クライアントがすでに存在する価値を add しようとしたり、存在しない価値を 削除 しようとした場合、サーバーは fail しなければならないと mandate しています。 これは drawing board の上では良く見えたかもしれませんが、実務では失敗です。 LDAP は weak 整合性を前提に作られているため、既存価値の再追加や、すでに削除された価値の削除はよく起こります。 LDAP データは 設計上順序を持たない であるため、"permissive" 修正を禁止する 順序の課題はありません。 それでも LDAP 標準は明示的にそれを禁止しています。 つまり standard-compliant LDAP クライアントは、修正の前に価値がエントリに存在するかどうかを常に 確認しなければなりません。 しかし、その check はそもそも信頼できるではありません。check と更新の間にエントリが変更されていない保証がないからです。 したがって、それを行う良い方法はありません。 問題を信頼できるに示す特殊な誤り response があれば、問題は多少 less 痛ましいになったかもしれません。 しかし LDAP にはそれがありません。

他の LDAP 問題と同様、この問題は長い間知られています。 サーバーの振る舞い を変える Permissive Modify 制御があります。 これは多くの LDAP クライアント author にとって基本 survival kit の一部です。 はい、予想どおりです。 この制御は標準化されていません。 また、すべての LDAP サーバーでサポートされているわけでもありません。 特に (Fedora/RedHat) 389 ディレクトリサーバーはこの制御をサポートしていません。 そのため、そのサーバーを扱うのは非常に痛ましいです。

What To Do About It?

どの LDAP サーバーを持っているかによります。

(RedHat/Fedora) 389 ディレクトリサーバー 残念です。permissive modify のサポートはありません。申し訳ありませんが、できることはありません。
Sun/Oracle DSEE 不明です。ここで permissive modify がサポートされているか知っていますか。教えてください。
OpenDS family: OpenDS, OpenDJ, wren:DS, UnboundId 大丈夫です。permissive modify がサポートされています。
OpenLDAP permissive modify はサポートされていますが、root DSE で 通知されません。したがってアプリケーションは自動的に発見できません。アプリケーションにそれを使うよう明示的に強制する必要があります。
Active Directory 大丈夫です。permissive modify がサポートされています。

Distinguished Names

識別名 (DN) は LDAP における主なオブジェクト識別子です。 次のような形をしています。

uid=semancik,ou=People,dc=Example,dc=com

確かに、これは世の中で最も美しい識別子でも短い識別子でもありません。 しかし、他の問題と比べればこれは cosmetics にすぎません。

第一に、識別子はディレクトリ内のオブジェクトの location に依存します。 つまり、オブジェクトが move されると識別子が変更します。

第二に、識別子はユーザー名や一般的名前などオブジェクトの名前を含むことがよくあります。 つまり、オブジェクトが 名前変更d されると識別子が変更します。

DN は LDAP における 主な 識別子であり、ほぼすべての LDAP 操作が動作するために必要です。 それにもかかわらず、正確には stable ではありません。 これは、LDAP ディレクトリの多くの 運用手順 が、オブジェクトの moving と renaming を最小化するよう設計されていることを意味します。 これは LDAP ディレクトリにとって深刻な制約です。

しかし、これはさらに悪くなります。 本当の悪夢は DN を比較するときに始まります。 たとえば、次の DN はすべて同じでしょうか、それとも異なるでしょうか。

uid=semancik,ou=People,dc=Example,dc=com
uid=semancik,ou=people,dc=example,dc=com
UID=Semancik,OU=People,DC=example,DC=com
UID=semancik,OU=People,DC=ExAmPLE,DC=COM

ここまで来れば、答えに驚くべきではありません。 答えはもちろん「depends」です。 正確には、schema に依存します。 特定の価値を 大文字小文字を区別して比較するか 大文字小文字を無視して比較するかは、属性種類の定義に依存します。 特定の属性が 大文字小文字を区別するものとして定義されている場合、その DN の部分は 大文字小文字を区別して比較しなければなりません。 属性が大文字小文字を無視するものとして定義されている場合、その特定の部分は大文字小文字を区別せずに比較すべきです。 完全なスキーマ情報がなければ、DN が同じか異なるかを判断できません。 かわいいですね。

幸い、一般的に使われる LDAP 属性の多くは 大文字小文字を無視する文字列 として定義されています。 そのため多くの LDAP 実装 (特にクライアント) は、DN は完全に大文字小文字を区別しないと仮定し、大文字小文字を無視する方式で比較します。 これは厳密には正しくありません。 しかし sanity を保つ唯一の実用的な方法です。 信じてください。 私は、少なくとも2つの一般的 LDAP サーバーで動く正しい comparison アルゴリズムを実装しようとして、数日を無駄にしました。 機能しませんでした。 アルゴリズムは非常に fragile で、標準スキーマからの小さな deviation で完全に壊れる可能性があります。 試す価値はありません。

What To Do About It?

LDAP で serious なことを行うときは、DN に依存しないでください。 entryUUID や、その 独自 equivalent (Active Directory の GUID など) のような他の識別子を使ってください。 そうです、これは痛ましいになります。多くの LDAP 操作のために entryUUID を DN に変換 する必要があるからです。 LDAP land へようこそ。

しかし、多くのアプリケーションは DN に依存しています。 オブジェクトを move または 名前変更 すると、そのようなクライアントはそれを見つけられなくなります。 したがって、オブジェクトの moving と renaming を避けるようディレクトリ構造を design してください。 階層を避けてください。 すべてのユーザーを単一 OU に入れてください。 DN にフルネームを使わないでください。 変更しそうな属性は使わないでください。

DN の比較 については、損切りしてすべての DN に 大文字小文字を無視する比較 を使ってください。 多くの実装がいずれにせよそうしており、これが de facto 標準になりました。 つまり、DN では 大文字小文字を区別する属性を決して使うべきではありません。 クライアントはいずれにせよそれを 大文字小文字を無視する値として扱います。

OIDs

X.500 は world-wide 分散した phone book という vision のもとに作られました。 X.500 の設計判断の一部は、その環境では意味がありました。 しかし X.500 が LDAP に "lightweighted" されたとき、LDAP にはあまり合わない X.500 概念もいくつか持ち込まれました。 Object identifier (OID) の概念はその1つです。

元の考え方は OID を グローバルに一意 にすることでした。 誰でも自分の OID subtree を register し、オブジェクト種類、属性名、制御、その他 LDAP creature のために 一意 OID を作成できます。 LDAP クライアントが uid の代わりに 0.9.2342.19200300.100.1.1 を使っていたなら、それは完全に理にかなっていたでしょう。 驚くことに、エンジニアは 0.9.2342.19200300.100.1.1 より uid を少し好む傾向があります。 したがって、OID はもはや本当には機能していません。 それらは LDAP の世界 全体をかなり怖く見せるだけです。特に若い エンジニア にとってはそうです。 実際、多くの LDAP サーバーは numeric OID をまったく 必要と しません。 OID がまだ使われているおそらく唯一の2つのものは、LDAP 制御と拡張です。

What To Do About It?

OID の geeky な見た目を楽しんでみてください。 同僚と OID について話すと、エンジニアing wizard の aura を得られます。 それ以外では、OID はほぼ無視できます。 スキーマを拡張する場合でさえ、多くのサーバー (例: iPlanet と OpenDS family) は OID の代わりに plain string を使うことを許可します。 この選択肢を使って構いません。

レプリケーションと同期

ディレクトリサーバーは lightweight であるように作られています。 LDAP データ構造の単純さ には効果があります。 サーバーは低いリソース consumption で great 性能を提供できます。 しかし最も重要な効果は X.500 レガシーから来ています。 ディレクトリサーバーは水平にスケーラブルであること、分散したシステムとして機能することを意図しています。

ディレクトリサーバーは実際にはデータベースにすぎないため、replication 機能は horizontal 拡張性にとって絶対に crucial です。 本質的に、LDAP は複製データベースの良い基盤になるための前提条件をすべて持っています。 ACID プロパティの要件はなく、整合性保証 は十分低く、データモデルは単純です。 しかし LDAP 標準は、どういうわけかそれを活かせていません。

レプリケーション機構はありますが、ほぼすべて 独自 です。 1つの「標準」replication プロトコル (RFC4533) がありますが、それでさえ 実験al と指定されており、広く採用されていません。 標準化された replication は、たとえばディレクトリシステムの内容をアイデンティティ管理システムと同期するような同期機構を実装する理想的な方法だったでしょう。 しかしディレクトリサーバーは同期のために 独自 で、しばしば inferior な機構を提供します。 つまり LDAP サーバー同期機構の統合は毎回 adventure になります。

What To Do About It?

レプリケーションについては、ベンダーに問い合わせてください。

Cross-vendor replication は忘れてください。ほとんど信頼できるに機能しません。 一部のサーバーにはあります。たとえば OpenLDAP は AD に replicate できます。 しかし AD は標準スキーマに従っていません。そして見てきたように、LDAP 仕様化に厳密に従うことは実際にはあまり意味がありません。 したがって、サーバー間でデータが移動するときに、ほぼ確実にデータを変換する必要があります。 アイデンティティ管理 (IDM) システムはそれを支援できます。

それにより同期機能の話になります。 これはサーバーごとに異なります。

iPlanet family: (RedHat/Fedora) 389 ディレクトリサーバー, Sun/Oracle DSEE cn=changelog LDAP subtree に変更を公開する "Retro changelog" 機能があります。この機構はある程度機能します。しかし 389 ディレクトリサーバーのような古いコードに基づくサーバーは、changelog の実装が劣っています。削除済みオブジェクトと 名前変更 の detect は問題があります。
OpenDS family: OpenDS, OpenDJ, wren:DS, UnboundId これらのサーバーにも "Retro changelog" 機能があります。この version の changelog はかなりよく機能します。
OpenLDAP いくつかの機構があります。同期に理論上使える syncrepl (RFC4533) があります。しかし何らかの理由で、この機構は広く使われているわけではなく、クライアントのサポートも貧弱です。さらにアクセス log 機構があります。この機構の信頼性については、今のところ十分なデータがありません。(データをお持ちですか。ご連絡ください。)
Active Directory これは Microsoft ですから、当然 独自 機構があります。Microsoft 機構は DirSync と呼ばれます。これは規則的検索申請に追加される特殊な LDAP 制御です。かなり意外なことに、これは非常に単純で effective な機構であり、よく機能するようです。

同期に 修正Timestamp を使う選択肢は常にあります。 これは単純で広く使われている方法です。 唯一の問題は、実際には機能しないことです。 第一に、削除済みオブジェクトを detect できません。 第二に、良好な時間同期 (millisecond granularity) に機密性の高いです。 第三に、信頼できるにするには一部のオブジェクトを2回プロセスする必要があります。 全体として、これは非常に悪く 信頼できない方法です。 他に選択肢がない場合にのみ使ってください。

More

さらにいくつかあります。

  • アクセス制御リスト (ACL) は、エントリと属性へのアクセスを制御するためにほぼすべてのサーバーで使われます。 しかし ACL の syntax は互換性があるではありません。
  • ほぼすべてのサーバーがパスワード認証を実装しています。 ほとんどのサーバーでは LDAP 申請の大半がパスワードを確認する bind 申請になります。 しかしパスワードポリシーと ロックout 機構はすべてのサーバーで異なります。

何より重要なのは、ほとんどのサーバーが一般に LDAP 標準から逸脱していることです。 たとえば 389 ディレクトリサーバー (および iPlanet family member の多く) は、属性名に hash (#) を含む属性を許可します。 これによりデータは本質的に他サーバーへ portable ではなくなります。 Standard-compliant LDAP クライアントが 389 ディレクトリサーバーと inter運用することさえ妨げます。 Active Directory はさらに多くの liberty を取ります。 たとえば AD は、スキーマで許可されていない属性であっても、エントリに任意の属性を設定できます。 これは schema-aware LDAP クライアントにとって悪夢です。 すべてのサーバーには標準コンプライアンスに関する何らかの課題があります。 私の知る限り、100% standard-compliant な LDAP サーバーは存在しません。 つまり standard-compliant LDAP クライアントは完全に 役に立たなく なソフトウェアです。

What To Do About It?

これらと共に生きるしかありません。 すべてのサーバーには独自の方法があります。 すべてのサーバーには独自の quirk と 特性 があります。 そういうものです。 それらを学び、回避する必要があります。

相互運用性

"LDAPv3 準拠" やその他の marketing declaration に頼らないでください。 見てきたように、LDAP コンプライアンスは相互運用性の十分条件ではありません。 実際、strict LDAP コンプライアンスはしばしば障害です。

選択した特定のサーバー (および version) に合わせてソリューションを build してください。 そのサーバーでソリューションを テスト してください。 ベンダーから来たもので "LDAPv3 準拠" の stamp があるとしても、ソリューションを テスト してください。 Commitment する前に、すべてを テスト してください。

複数サーバーと 相互運用可能 な LDAP クライアントを作成することは巨大な undertaking です。 私はそれを midPoint LDAP コネクター の形で実際にやりました。 それには何人月もの intense 作業、何年もの時間、テスト 環境の構築、多くの trial と 誤りが必要でした。 Apache ディレクトリ API と Apache MINA に本格的なな修正を行う必要もありました。 それだけの作業の後でも、コネクターは主要 LDAP サーバーすべてと 100% 相互運用可能 ではありません。 将来さらに多くの作業が必要になります。

結論

これが現実です。 LDAP 標準に厳密に従うソフトウェアを作ろうとすることはできます。 しかし、そのようなソフトウェアは 役に立たなく になります。 LDAP 標準を知ることは重要です。 しかし、いつ標準から逸脱すべきかを知ることの方がさらに重要です。 生き残るためには標準から逸脱しなければなりません。

私は LDAP プロトコルの author を責めているわけではありません。 実際、私は彼らに大きな respect を持っています。 彼らは1990年代当時、最善を尽くしました。 事実として、もはや1990年代ではありません。 LDAP 標準には維持管理が必要です。 標準には 大幅な改訂 と 改善が必要です。 それは起こりませんでした。 いくつかの minor 更新や proposal はありました。 体系的な見直しはありませんでした。

私は長年、LDAP コミュニティのさまざまな member とこれらの課題について議論してきました。 残念ながら、コミュニティには問題を修正する interest がほとんどないように見えます。 私は数年前に最後の試みをしました。 私の努力はすべて 役に立たなく でした。 そのため私は、修正できないものを修正しようとするのをやめることにしました。 私たちは持っているものと共に生きなければなりません。

LDAP は今やレガシー技術です。 レガシー技術の特徴をすべて備えています。 欠陥があり、修正できず、扱うには文書化されていない難解な知識が必要です。 したがって LDAP は、その status に応じて扱う必要があります。

私の推奨は、LDAP 仕様化を 実際の ルールではなくガイドラインと考えることです。 LDAP は今でも多くの利用ケースに有用です。 しかし、ソリューションを機能させるには標準から逸脱する必要がある可能性が非常に高いです。 LDAP の世界 へようこそ。

Contributing

この文書には、明らかにいくつかの詳細が欠けています。 完全には正しくないこともあるかもしれません。 Correction や additional 詳細があれば、私たちに連絡してください。 私たちはこの文書を段階的に修正・更新していきます。 ただし comment は事実ual かつ 現実的 にしてください。

これがすべて間違っており、LDAP は完璧だと思う場合、私たちに連絡する必要はありません。 その opinion はあまりに頻繁に聞いています。 それでも現実は別の picture を示しています。

私が単に LDAP を嫌っているだけだと責めたい場合も、その必要はありません。 すでに何人かがあなたの代わりにそうしました。 しかし、それは真実からはほど遠いものです。 私は実際には LDAP が 好き です。 とても好きです。 LDAP は単純で、独自の方法で elegant であり、多くの良い点があると思います。 少数の悪い点が経験を完全に台無しにしているのは非常に残念です。 これらの多くは、ほぼ完全な互換性を保ちながらでも簡単に修正できます。 これらの問題を修正する will がないことは、ほとんど信じられません。

これらの問題は、エンジニア に仕様に違反 するよう導くのではなく、LDAP 仕様化で修正されるべきだと思うかもしれません。 その場合、あなたは正しいです。 私は完全に同意します。 LDAP コミュニティで声を上げるべきです。 私は何年も LDAP コミュニティとこれらの課題を議論しようとしてきました。 説明しようとし、ソリューションを提案しようとしましたが、効果はありませんでした。 LDAP コミュニティは深い denial の中にあります。 私は耳を貸さない人々を説得しようとすることを終えました。 しかし、あなたは試してみることができます。 あなたの方が運が良いかもしれません。 まだ LDAP を救う chance が残っているかもしれません。