2017-09-13 160 views
0

我想添加一個groupOfUniqueNames對象的新成員,但我得到一個「ENTRY_ALREADY_EXISTS」錯誤。LDAP - 如何將條目添加到groupOfUniqueNames? (ERR_250_ENTRY_ALREADY_EXISTS)

服務器是ApacheDS中,我的代碼是紅寶石,使用使用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" 
      } 
) 

中已經有門衛一個成員 - mop99。當我打電話ldap.add,我得到(格式化略有可讀性):

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" 
} 

我試圖改變ldap.add()來ldap.modify(),但只是替換mop99與broom001,只留下一個看門人。我需要的是add broom001,最終成爲一支不斷增長的門衛隊伍。

我可以從LDAP中讀取現有列表,將新條目附加到Ruby中的列表中,然後將列表寫回到LDAP中......但是這引入了一種競爭狀態,在兩種情況下可能會丟失管理員同時添加。我的看門人太貴了,所以這是不可接受的。

我已經廣泛地搜索了網頁,但沒有發現太多內容,也沒有涉及net-ldap。我找到了https://www.openldap.org/lists/openldap-software/199912/msg00164.html,它描述了一個解決方案WRT .LDIF文件,但我不知道如何將其轉換爲net-ldap。

我錯過了什麼?

+1

就協議而言,ldapadd操作是在目錄中創建一個新條目。如果你想**修改一個屬性的值(即在'uniqueMember'列表中添加一個新值,你必須使用'ldapmodify'操作。我不知道它是如何轉化爲ruby的,但是這是LDAP協議的方式 – Esteban

回答

0

添加對象類沒有意義。它已經在那裏。

只需添加唯一的成員值即可。

+0

這就是我最初的......但是我得到一個錯誤,「ERR_60條目不包含STRUCTURAL ObjectClass」代碼:65.一些研究和測試導致添加objectclass屬性來解決這個問題,但是當我解決所有其他問題時,我會嘗試將它退出,看看它是否是一條紅色鯡魚 –

+0

現在我理解你的意思了,我忽略了「add_attribute」方法正如你所描述的那樣。謝謝你的提示,EJP。 –

0

[更新 - 忽略本答案。看到我的新答案,開始,「好吧,我感到愚蠢......」]

據我所知,你不能像我試圖做的那樣添加到groupOfUniqueNames。我懷疑那些使你看起來可以做的只是用瓷器覆蓋管道的工具。

簡單的方法是從LDAP讀取當前列表,操作它(添加/刪除值),並將整個列表寫回到LDAP。如果您的應用不關心在同步更新之間的競賽中丟失數據,那很可能是好的。

從這裏開始的一個步驟是在代碼中使用序列化的阻塞,以確保沒有同時更新。這很棘手(特別是在集羣或異構系統進行更新時),但是可行。

我最終做的是完全避開所有這些問題,在我的應用程序中從頭開始重建列表,然後覆蓋列表。當然,這取決於你有源數據來建立列表。在我的情況下,源數據從LDAP本身來了,像這樣的查詢:

def janitor_user_dns 
    # Looks up all janitors. 
    # returns a list of DN's, not full User records. 

    role_filter = Net::LDAP::Filter.eq(:role, janitor_role_dn) 
    entries = mc_ldap.search(base: ldap_base, filter: role_filter, attributes: 'dn', 
          scope: Net::LDAP::SearchScope_SingleLevel) {} 
    entries.map { |user| user[:dn][0] } 
    end 

就這樣,實在是小巫見大巫寫入新列表返回的groupOfUniqueNames:

def update_janitor_users 
    mc_ldap.save(true, janitor_role_dn, objectclass: 'groupOfUniqueNames', uniqueMember: janitor_user_dns) 
end 

有了這個方法,在競爭條件下仍然可能會丟失數據,但下一次更新時會自行修復。如果這是不可接受的,你可以讀回列表並測試它是否正確寫入。如果不是,只需再次重新生成列表(從競爭對手中選擇更改),然後重複。

0

好吧......我覺得有點笨。下面是正確答案:

ldap.add_attribute(dn, attribute, value) 

或者專門爲我的新的看門人:

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

鋇熱潮。而已。正是我需要的。 臉紅

我要走了我以前的答案可笑的,因爲它是從頭開始填充列表的一種方式,而可能是在某些情況下非常有用。

我也離開了這個令人尷尬的問題,以防其他人忽略了文檔中的add_attribute(),並且在嘗試搜索這個問題時感到沮喪。

對ruby-net-ldap似乎仍然存在的一個挫折是delete_attribute()不接受第三個參數 - 即要從組中刪除的值。您只能使用delete_attribute刪除整個組,而不是單個條目。但我不需要刪除組中的單個值,所以la-ti-da ...