LDAPのエントリーの操作のうち、検索、追加、削除は、比較的簡単でした。
サンプル:
Search and Add: http://www.knowd.co.jp/yamazaki/?q=node/134
Search and Delete: http://www.knowd.co.jp/yamazaki/?q=node/136
次は、エントリが持っている属性を操作するサンプルをあげます。
属性を操作するには、まず、対象のエントリを取得(検索)した後、対象のエントリに対して、属性の追加、更新、削除などの操作を行っていきます。
この際、Net::LDAP->modify を使用します。
属性の追加: Net::LDAP->modify( $dn, add... )
エントリに対して、"mail: xxxx" という属性を追加します。
test-ldap3.pl
use Net::LDAP;
#
# bind as priviledged user for modify.
#
$ldap = Net::LDAP->new( "localhost" );
$message = $ldap->bind( "cn=Directory Manager", password=>"password" );
if( $message->code == 0 ) {
print "bind success\n";
} else {
warn "error with bind: " . $message->error ."\n";
exit( 1 );
}
#
# search entry.
#
$uid = "test.0";
$dn = "uid=$uid,ou=People,dc=example,dc=com";
$result = $ldap->search( base=>$dn, scope=>"base", filter=>"objectclass=*" );
@entries = $result->entries;
$entry = $entries[0];
if( !defined( $entry ) ) {
$ldap->unbind;
warn "$user not found.\n";
exit( 1 );
}
#
# add mail attribute to the entry.
#
$result = $ldap->modify( $entry,
add => {
mail => [ $uid.'@example.com' ]
}
);
if( $result->code != 0 ) {
$ldap->unbind;
warn $result->error;
exit( $result->code );
}
$ldap->unbind;
もし、属性がマルチバリューを許可していれば、次のように複数の値をまとめて追加することもできます。
...
# add mail attribute to the entry.
#
$result = $ldap->modify( $entry,
add => {
mail => [ $uid.'@example.com', $uid.'@example.net' ]
}
);
...
もし、すでに、同一の属性に同一の値がある場合、つまり、属性に重複した値が存在するような追加を試みた場合、以下のようなエラーとなり、結果としてadd操作は実行されません。
# perl test-ldap3.pl
bind success
エントリ uid=test.0,ou=People,dc=example,dc=com を変更できません。変更により、属性 mail の重複する値が 1 つ以上生成されます: uid=test.0@example.com, uid=test.0@example.net at test-ldap3.pl line 45, line 466.
一見して、コードが長くなってきているように感じられます。エントリの検索に加え、属性操作が加わるためでしょう。。
これまでのサンプルは、プログラムをサブルーチン化せず、べたーっと書いてきましたが、この辺から、Perlのテクニックが必要になってきそうです。
属性の削除: Net::LDAP->modify( $dn, delete... )
属性を削除します。以下のように記述すると、mail属性に複数の値が設定されていたとしても、すべて削除します。
test-ldap4.pl
use Net::LDAP;
#
# bind as priviledged user for modify.
#
$ldap = Net::LDAP->new( "localhost" );
$message = $ldap->bind( "cn=Directory Manager", password=>"password" );
if( $message->code == 0 ) {
print "bind success\n";
} else {
warn "error with bind: " . $message->error ."\n";
exit( 1 );
}
#
# search entry.
#
$uid = "test.0";
$dn = "uid=$uid,ou=People,dc=example,dc=com";
$result = $ldap->search( base=>$dn, scope=>"base", filter=>"objectclass=*" );
@entries = $result->entries;
$entry = $entries[0];
if( !defined( $entry ) ) {
$ldap->unbind;
warn "$user not found.\n";
exit( 1 );
}
#
# delete mail attribute from the entry.
#
$result = $ldap->modify( $entry,
delete => ['mail']
);
if( $result->code != 0 ) {
$ldap->unbind;
warn $result->error;
exit( $result-code );
}
$ldap->unbind;
mail属性から、特定の値だけを削除したければ、削除対象として値を指定します。
たとえば、mail属性にxxx@example.com, xxx@example.netの2つの値があるときに、xxx@example.netだけを削除したい場合の例です。
...
# delete paticular mail attribute from the entry.
#
$result = $ldap->modify( $entry,
delete => { mail=> $uid.'@example.net' }
);
...
もし、指定した属性に指定した値が存在しない場合は、エラーになります。
# perl test-ldap4.pl
bind success
エントリ uid=test.0,ou=People,dc=example,dc=com を変更できません。属性 mail の更新を試みると、存在しない属性から 1 つ以上の値が削除されます: uid=test.0@example.net at test-ldap4.pl line 43, line 466.
属性の置換: Net::LDAP->modify( $dn, replace... )
値の置き換え(replace)は、特定の属性を指定した単数あるいは複数の値に置き換えます。
現行の値がどうであれ、置き換えるので、上記のadd, deleteに比較するとエラーが発生しにくい操作です。
以下の例は、mail属性をxxx@example.co.jpに置き換えます。
mail属性に値があろうがなかろうが、エラーなしに置き換えてくれます。
use Net::LDAP;
#
# bind as priviledged user for modify.
#
$ldap = Net::LDAP->new( "localhost" );
$message = $ldap->bind( "cn=Directory Manager", password=>"password" );
if( $message->code == 0 ) {
print "bind success\n";
} else {
warn "error with bind: " . $message->error ."\n";
exit( 1 );
}
#
# search entry.
#
$uid = "uid=test.0";
$dn = "$uid,ou=People,dc=example,dc=com";
$result = $ldap->search( base=>$dn, scope=>"base", filter=>"objectclass=*" );
@entries = $result->entries;
$entry = $entries[0];
if( !defined( $entry ) ) {
$ldap->unbind;
warn "$user not found.\n";
exit( 1 );
}
#
# replace mail attribute from the entry.
#
$result = $ldap->modify( $entry,
replace => { mail=> $uid.'@example.co.jp' }
);
if( $result->code != 0 ) {
$ldap->unbind;
warn $result->error;
exit( $result-code );
}
$ldap->unbind;
複数の値を指定する場合は、以下のように指定できます。
...
$result = $ldap->modify( $entry,
replace => { mail=> [ $uid.'@example.co.jp',
$uid.'@example.com',
$uid.'@example.net' ]
}
);
...
また、属性の値を空にする、つまり、値を削除するには次のように指定できます。
...
$result = $ldap->modify( $entry,
replace => { mail=> [] }
);
...
つまり、replaceは、追加、削除を含みます。
値の追加時の値の重複、削除時の値が存在しない場合、それぞれでエラーを出したい(つまり操作をキャンセルしたい)場合は、add, deleteを使えばよいのでしょうが、エラーを出さない操作を行いたい場合はreplaceが便利でしょう。