LDAP - How to add an entry to a groupOfUniqueNames? (ERR_250_ENTRY_ALREADY_EXISTS)

2.3k views Asked by At

I'm trying to add a new member of a groupOfUniqueNames object but I get an "ENTRY_ALREADY_EXISTS" error.

The server is ApacheDS, and my code is Ruby, using using net-ldap:

ldap.add(dn: 'cn=janitors,dc=tidy,dc=example,dc=com', 
         attributes: 
          {
            :objectclass => "groupOfUniqueNames",
            :uniqueMember => 
              "uid=broom001,o=users,dc=tidy,dc=example,dc=com"
          }
)

There is already one member in janitors -- mop99 . When I call ldap.add, I get (reformatted slightly for readability):

ldap.response: ERR_250_ENTRY_ALREADY_EXISTS cn=janitors,dc=tidy,dc=example,dc=com already exists!
OpenStruct {
             :code => 68,
    :error_message => "ENTRY_ALREADY_EXISTS: failed for MessageType : ADD_REQUEST
                        Message ID : 2
                            Add Request :
                            Entry
                            dn[n]: cn=janitors,dc=tidy,dc=example,dc=com
                            objectclass: groupOfUniqueNames
                            uniqueMember: uid=mop99,o=users,dc=tidy,dc=example,dc=com
                            : ERR_250_ENTRY_ALREADY_EXISTS cn=janitors,dc=tidy,dc=example,dc=com already exists!
                      ",
       :matched_dn => "",
          :message => "Entry Already Exists"
}

I've tried changing ldap.add() to ldap.modify(), but that just replaces mop99 with broom001, leaving only one janitor. What I need is to add broom001, to end up an ever-growing army of janitors.

I could read the existing list from LDAP, append the new entry to the list in Ruby, and then write the list back to LDAP...but that introduces a race condition where a janitor could be lost when two try to add at the same time. My janitors are too valuable, so that is unacceptable.

I've searched the web extensively without finding much, and nothing related to net-ldap. I did find https://www.openldap.org/lists/openldap-software/199912/msg00164.html which describes a solution WRT .LDIF files, but I don't know how to translate that to net-ldap.

What am I missing?

2

There are 2 answers

2
user207421 On

Adding the object class doesn't make sense. It's already there.

Just add the unique member value.

0
David Hempy On

Ok...I feel a little dumb. Here is the correct answer:

ldap.add_attribute(dn, attribute, value)

Or specifically for my new janitor:

ldap.add_attribute('cn=janitors,dc=tidy,dc=example,dc=com', 
                   'uniqueMember',
                   'uid=broom001,o=users,dc=tidy,dc=example,dc=com')

Ba-boom. That's it. Just what I needed. blush

I'm leaving my previous ridiculous answer, as it is one way of populating a list from scratch, and might be useful in some scenarios.

I'm also leaving this whole embarrassing question, in case anyone else overlooks add_attribute() in the documentation and gets frustrated trying to search for this problem.

One remaining frustration with ruby-net-ldap that seems to remain is that delete_attribute() does NOT accept a third argument -- namely, the value to be deleted from the group. You can only use delete_attribute to delete the entire group, not individual entries. But I don't need to delete only a single value from the group, so la-ti-da...