LECTURE 3 ディレクトリエントリの登録/削除

○ はじめに

今回は、LDAP サーバに接続してディレクトリエントリを登録する、あるいはディレクトリエントリを削除する方法について説明します。登録されたエントリの確認、あるいは削除されたことの確認に使用する検索処理については次回説明します。ここでは LDAP サーバ側、あるいは LDAP サーバに付いているツールなどで確認してもらえればと思います。

○ サンプルプログラム

LDAP サーバに接続し、指定された DN を使ってディレクトリエントリを登録、あるいは削除するサンプルプログラム LDAPAddDel.java です。登録するディレクトリエントリの属性内容は固定です。

コンパイルが終了したら

java LDAPAddDel [LDAPサーバ名/IPアドレス] \
                [bindユーザのDN] \
                [bindユーザのパスワード] \
                [add(追加) / del(削除)] \
                [エントリの DN]

で実行です。正常に処理が終了した場合はその旨が表示されます。何らかの例外が発生したら、その内容が表示されます。

なお、はじめに のページから全てのサンプルプログラムを固めた tar ボールをダウンロードすることもできます。

--- LDAPAddDel.java ---

    1	import org.ietf.ldap.LDAPAttribute;
    2	import org.ietf.ldap.LDAPAttributeSet;
    3	import org.ietf.ldap.LDAPConnection;
    4	import org.ietf.ldap.LDAPEntry;
    5	import org.ietf.ldap.LDAPException;
    6	
    7	
    8	/**
    9	 * LDAP サーバに接続し、指定された DN でエントリを登録する。
   10	 * あるいは指定 DN のエントリを削除する。エントリ登録時の属性値に
   11	 * ついては、本クラス内部で固定の内容。
   12	 *
   13	 * @version 19 May 2002
   14	 * @author  Ryo Ichinose
   15	 */
   16	public class LDAPAddDel
   17	{
   18		/**
   19		 * LDAP Protocol Version 3
   20		 */
   21		public static final int LDAP_V3 = 3; // LDAPv3
   22	
   23	
   24		/**
   25		 * LDAP サーバに接続し、指定された DN でエントリを登録する。
   26		 * エントリ登録時の属性値については固定の内容。
   27		 *
   28		 * @param host    ホスト名もしくは IPアドレス
   29		 * @param binddn  bind ユーザの DN
   30		 * @param bindpw  bind ユーザのパスワード
   31		 * @param dn      登録エントリの DN
   32		 */
   33		public void add( String host, String binddn, String bindpw, String dn )
   34		{
   35			// 登録するエントリの各属性値を設定する。
   36			LDAPAttributeSet attrset = new LDAPAttributeSet();
   37	
   38	
   39			// posixAccount の必須属性
   40			String objcls[] = { "posixAccount" };
   41			String cn[]     = { "name1" };
   42			String uid[]    = { "123456" };
   43			String uidnum[] = { "501" };
   44			String gidnum[] = { "502" };
   45			String home[]   = { "/home/123456" };
   46	
   47			attrset.add( new LDAPAttribute( "objectclass", objcls ) );
   48			attrset.add( new LDAPAttribute( "cn", cn ) );
   49			attrset.add( new LDAPAttribute( "uid", uid ) );
   50			attrset.add( new LDAPAttribute( "uidNumber", uidnum ) );
   51			attrset.add( new LDAPAttribute( "gidNumber", gidnum ) );
   52			attrset.add( new LDAPAttribute( "homeDirectory", home ) );
   53	
   54	
   55			// DN と属性値で登録するエントリを LDAPEntry のインスタンス
   56			// として作成。
   57			LDAPEntry entry = new LDAPEntry( dn, attrset );
   58			LDAPConnection lc = new LDAPConnection();
   59	
   60			try {
   61				// LDAP サーバに接続する。ポートはデフォルト(389番)を使う。
   62				lc.connect( host, LDAPConnection.DEFAULT_PORT );
   63				System.out.println( "Connected to " + host );
   64				System.out.println();
   65	
   66	
   67				// 指定された DN およびパスワードでバインド(認証)する。
   68				// これを実行しない場合、anonymous 状態で操作することになる。
   69				lc.bind( LDAPAddDel.LDAP_V3, binddn, bindpw );
   70	
   71	
   72				// 指定エントリの登録を実行する。
   73				lc.add( entry );
   74				System.out.println( "Successfully added" );
   75	
   76				// 接続を切断する。
   77				lc.disconnect();
   78				System.out.println();		
   79				System.out.println( "Disconnected" );
   80			}
   81			catch( LDAPException e ) {
   82				System.out.println( "LDAPException occured : " + 
   83						    e.toString() );
   84			}
   85		}
   86	
   87	
   88		/**
   89		 * LDAP サーバに接続し、指定された DN のエントリを削除する。
   90		 *
   91		 * @param host    ホスト名もしくは IPアドレス
   92		 * @param binddn  bind ユーザの DN
   93		 * @param bindpw  bind ユーザのパスワード
   94		 * @param dn      削除エントリの DN
   95		 */
   96		public void del( String host, String binddn, String bindpw, String dn )
   97		{
   98			LDAPConnection lc = new LDAPConnection();
   99	
  100			try {
  101				// LDAP サーバに接続する。ポートはデフォルト(389番)を使う。
  102				lc.connect( host, LDAPConnection.DEFAULT_PORT );
  103				System.out.println( "Connected to " + host );
  104				System.out.println();
  105	
  106	
  107				// 指定された DN およびパスワードでバインド(認証)する。
  108				// これを実行しない場合、anonymous 状態で操作することになる。
  109				lc.bind( LDAPAddDel.LDAP_V3, binddn, bindpw );
  110	
  111				// 指定エントリの登録を実行する。
  112				lc.delete( dn );
  113				System.out.println( "Successfully deleted" );
  114	
  115				// 接続を切断する。
  116				lc.disconnect();
  117	
  118				System.out.println();		
  119				System.out.println( "Disconnected" );
  120			}
  121			catch( LDAPException e ) {
  122				System.out.println( "LDAPException occured : " + 
  123						    e.toString() );
  124			}
  125		}
  126	
  127	
  128		/**
  129		 * エントリポイント
  130		 *
  131		 * @param args 
  132		 *    <ul>
  133		 *      <li>args[0] --- ホスト名もしくは IP アドレス
  134		 *      <li>args[1] --- bind ユーザの DN
  135		 *      <li>args[2] --- bind ユーザのパスワード
  136		 *      <li>args[3] --- 登録( add )/削除( del )
  137		 *      <li>args[4] --- 登録/削除エントリの DN
  138		 *    </ul>
  139		 */
  140		public static void main( String[] args )
  141		{
  142			LDAPAddDel obj = new LDAPAddDel();
  143	
  144			if ( args[3].equals( "add" ) ) {
  145				obj.add( args[0], args[1], args[2], args[4] );
  146			} 
  147			else if ( args[3].equals( "del" ) ) {
  148				obj.del( args[0], args[1], args[2], args[4] );
  149			}
  150		}
  151	}


○ サンプルプログラムの説明

では、サンプルプログラムについて説明していきます。

  • 1 〜 5 行目

    使用するクラスライブラリのパッケージ指定を行っています。LDAPAddDel.java では、前回の LDAPConnect.java で使用したクラスの他に、LDAPAttribute、LDAPAttributeSet、LDAPEntry の 3 つのクラスを新たに使用します。

  • 24 〜 85 行目 ( LDAPAddDel#add() )

    LDAPAddDel#add() メソッドで、ディレクトリエントリの登録処理を行います。各ヶ所について 以降で説明します。

    • 35 〜 36 行目

      登録するディレクトリエントリに設定する属性および属性値の組を格納するために、 LDAPAttributeSet クラスのインスタンスを作成しています。LDAPAttributeSet クラスには、 複数の LDAPAttribute クラスのインスタンスを格納することが出来ます。LDAPAttribute クラスのインスタンスが各々の属性名および属性値の情報を保持します。

    • 39 〜 52 行目

      登録するディレクトリエントリに設定する属性および属性値の組を LDAPAttributeSet クラス のインスタンスに格納するまでの処理を行っています。ここでは posixAccount というオブジェクトクラスでディレクトリエントリを登録します。

      posixAccount というオプジェクトクラスは RFC 2307 で定義されています。 これによると、cn、uid、uidNumber、gidNumber、homeDirectory という属性は必須であると されています。よってこれらの属性に対する値を 40 〜 45 行目でそれぞれ String の配列 として作成しています( objectclass という属性は全てのエントリで必須 )。

      何故配列かというと、属性名と値の情報を実際に保持する LDAPAttribute クラスの コンストラクタがそれを要求しているからです。 これは、各々の属性が複数の属性値を持つことができるためです。よって、属性値が 1 つの場合でも配列として扱う必要があります。

      47 〜 52 行目で、属性名と属性値を引数として LDAPAttribute クラスのインスタンスを 作成した上で、それを LDAPAttributeSet クラスのインスタンス が保持する要素に 追加しています。

    • 55 〜 57 行目

      必要な属性名と属性値の情報を格納した LDAPAttributeSet クラスのインスタンスと登録 するエントリの DN を指定して、 LDAPEntry クラスのインスタンスを作成しています。JLDAP (以外の Directory SDK でも多分同様)でディレクトリエントリを登録する場合は、この LDAPEntry クラスのインスタンスが登録する単位となります。

    • 72 〜 74 行目

      LDAPEntry クラスのインスタンスを使って、LDAP サーバにディレクトリエントリを登録 しています。エントリを登録するには、LDAPConnection#add() メソッドを使用します。

        public void LDAPConnection#add( LDAPEntry entry )
               throws LDAPException
      
        entry : 登録するエントリ情報
      
      

      何らかの理由で登録に失敗した場合、LDAPException が throw されます。LDAPException の 内容については後述します。

      add() メソッドは上の形式以外の形でいくつかオーバーロードされています。それぞれの 詳細については JLDAP の API ドキュメントを参照して下さい。

    • 81 〜 84 行目

      ここまでの処理で発生した LDAPException を catch して、内容を表示しています。ここまで の新たな処理によって発生する可能性のある例外内容について、自分が確認できた範囲 で以下にまとめておきます。これで全てという意味ではありません。

      番号 エラーコードの定数名(LDAPException.XXX の形で参照可) 内容
      17 UNDEFINED_ATTRIBUTE_TYPE 指定された属性が LDAP サーバ側のスキーマに存在しない。つまり、LDAPAttributeSet クラスのインスタンスに設定した属性名が正しくないことを表している。使用したオブ ジェクトクラス(ここでは posixAccount )が、対象の LDAP サーバで定義されていない 可能性もある。
      32 NO_SUCH_OBJECT add() に指定した DN で識別されるオブジェクトを参照することができない。登録する DN が存在しないのはある意味当然で、ここで発生するのは DN を登録するためのディ レクトリが存在しないことを意味している。仮に "uid=foo,ou=people,dc=sample,dc=jp" という DN でエントリを登録しようとしていたなら、"ou=people,dc=sample,dc=jp" という DN で識別されるディレクトリが存在しないことを表している。
      34 INVALID_DN_SYNTAX 指定した DN の構文が正しくない。
      65 OBJECT_CLASS_VIOLATION オブジェクトクラスに適用される規則に反した処理を行おうとしている。必須属性の値 を指定せずにエントリを追加した、定義されていない属性と値を設定してエントリを追 加/修正した、必須属性を削除しようとした、などの場合に発生する。

  • 88 〜 125 行目 ( LDAPAddDel#del() )

    LDAPAddDel#del() メソッドで指定エントリの削除を行います。新しい部分は 113 行目の lc.delete( dn ); という所のみです。エントリの削除には、LDAPConnection#delete() を使います。

      public void LDAPConnection#delete( String dn )
             throws LDAPException
    
      dn : 削除するエントリを示す DN
    
    

    何らかの理由で削除に失敗した場合、LDAPException が throw されます。自分で確認した範囲 では、以下の例外内容が発生します。なお、これが全てという意味ではありません。

    番号 エラーコードの定数名(LDAPException.XXX の形で参照可) 内容
    32 NO_SUCH_OBJECT delete() に指定した DN で識別されるオブジェクトを参照することができない。 つまり、指定したエントリが存在しないということである。
    34 INVALID_DN_SYNTAX delete() に指定した DN の構文が正しくない。

以上で LDAPAddDel.java についての説明は終わりです。次は最も使用されると思われるディレクトリエントリの検索処理について説明していきます。