Reputation: 528
I have this ldap entry:
cn=blah,ou=apples,ou=people,dc=yay,dc=edu
I need to move that entry to:
cn=blah,ou=oranges,ou=people,dc=yay,dc=edu
My scripts are all PHP so I've been trying to use php.net/ldap_rename
ldap_rename($connection, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", "ou=oranges,ou=people,dc=yay,dc=edu", true);
Does not work. It returns false.
This https://www.php.net/manual/en/function.ldap-rename.php#82393 comment mentions that eDirectory wants to leave the parent as NULL. Like:
ldap_rename($connection, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", NULL, true);
That returns TRUE but does not actually move the entry. Not surprising since it's not changing the parent... I'm sure it could change the cn=blah to something else...
I have thought of deleting the entry and recreating it. But that's a painful way to go about it. Writing out and running a LDIF file would also be painful.
So, how do I move an entry from one OU to another, in php, without the pain of my other two options?
What I'm running:
So, I found this:
The modrdn change type cannot move an entry to a completely different subtree. To move an entry to a completely different branch, you must create a new entry in the alternative subtree using the old entry's attributes, and then delete the old entry.
From http://www.centos.org/docs/5/html/CDS/ag/8.0/Creating_Directory_Entries-LDIF_Update_Statements.html
I found a couple other pages with similar statements.
So it sounds like I have to make a new entry, copying the attributes, the delete the old one. Like the second painful option I mentioned above.
Upvotes: 3
Views: 1549
Reputation: 637
Try this:
ldap_rename($ldapconn, "cn=blah,ou=apples,ou=people,dc=yay,dc=edu", "cn=blah", "ou=oranges,ou=people,dc=yay,dc=edu", true);
Upvotes: 0
Reputation: 1
There actually isn't a need to recreate in eDir. Doing a recreate causes problems in an environment that runs IDM as the object will have a new GUID and the IDM engine will not see the event as a true "move".
The following code moves users fine (tested eDir 8.8.x & eDir 9.x):
$olduserdn = "cn=userid,ou=container1,o=org";
$newdestdn = "ou=container2,o=org";
if (preg_match('/^(cn=[A-Za-z0-9]+)\,(.+)/i', $olduserdn, $rdnmatches))
{
if (ldap_rename($ldapconn, $olduserdn, $rdnmatches[1], $newdestdn, TRUE))
{
print("Moved $olduserdn to $rdnmatches[1],$newdestdn");
}
else
{
print("Failed move because " . ldap_error($ldapconn));
}
}
Don't forget to give a bit of time for replication...
Also consider constraints around modifying/moving objects that are still being replicated from a previous move event.
Upvotes: 0
Reputation: 528
Well, I ended up using the "create new entry, delete old one" method. I still think I had another way working a while back, but I can't remember what. So here's a basic move function.
function move($connection, $ldapEntryReference, $new_dn){
//First, get the values of the current attributes.
$attributes = array(); //start attributes array
$firstattr = ldap_first_attribute($connection, $ldapEntryReference);
$value = ldap_get_values($connection, $ldapEntryReference, $firstattr);
$attributes[$firstattr] = $value;
while($attr = ldap_next_attribute($connection, $ldapEntryReference)) {
if (strcasecmp($attr, 'ACL') !== 0) { //We don't want ACL attributes since
//eDir/ldap should deal with them for us.
if (strcasecmp($attr, 'jpegPhoto') === 0) {
//binary values need to use the ldap_get_values_len function.
$value = ldap_get_values_len($this->connection, $ldapEntryReference, $attr);
} else {
$value = ldap_get_values($this->connection, $ldapEntryReference, $attr);
}
$attributes[$attr] = $value;
}
}
//Create a new entry array with the values.
$entry = array(); //start entry array.
foreach($attributes as $key => $value) {
foreach($value as $key2 => $value2) {
if (strcasecmp($key2, 'count') !== 0) {//get rid of 'count' indexes
//ldap_add chokes on them.
$entry[$key][$key2] = $value2;
}
}
}
//Add the new entry.
if (ldap_add($connection, $new_dn, $entry)) {
//Delete the old entry.
if (ldap_delete($connection, ldap_get_dn($connection, $ldapEntryReference)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
Hopefully this helps someone, sometime.
Upvotes: 2