For objects with "+" in the DN (uid=test_user,cn=users,ou=+1,dc=ucs,dc=test) we we save them in the LDAP like "uid=test_user,cn=users,ou=\2B1,dc=ucs,dc=test". When we use the oxDeputyPermissionGivenTo property we save the DN of a user to it. When we use the encoding with "\2B" (as it is in LDAP) it gets automaticylly converted by UDM to "uid=test_user,cn=users,ou=\+1,dc=ucs,dc=test". Later when the ox-connector sets the permissions it uses the DN for a search in the database and can't find the correct entry due to the mismatch "\+" vs "\2B". Most likely this applies to other special character in DNs. This might be connected to display issues in the UMC where the "Stellvertreter" field is visually empty. We debugged it directly in a python shell as follows: >>>from univention.udm import UDM >>>user_mod = UDM.admin().version(2).get("users/user") >>>fupo_user = user_mod.get_by_id("fupo_user_isOxUser_01") >>>fupo_user.props.oxDeputyPermissionGivenTo = [['uid=user_isOxUser_02,cn=users,ou=\\2B1,dc=ucs,dc=test', '02400', '02440', '1']] >>>fupo_user.save() >>>fupo_user = user_mod.get_by_id("fupo_user_isOxUser_01") >>>fupo_user.props.oxDeputyPermissionGivenTo [['uid=user_isOxUser_02,cn=users,ou=\\+1,dc=ucs,dc=test', '02400', '02440', '1']] whereas ldapsearch results in "\2B": # univention-ldapsearch -LLL uid="fupo_user_isOxUser_01" dn oxDeputyPermissionGivenTo dn: uid=fupo_user_isOxUser_01,cn=users,ou=\2B1,dc=ucs,dc=test oxDeputyPermissionGivenTo: uid=user_isOxUser_02,cn=users,ou=\+1,dc=ucs,dc=test |:$:| 02400 |:$:| 02440 |:$:| 1 # univention-ldapsearch -LLL uid="user_isOxUser_02" dn oxDeputyPermissionGivenTo dn: uid=user_isOxUser_02,cn=users,ou=\2B1,dc=ucs,dc=test
We have to do LDAP DN normalization in certain places in UDM: >>> ldap.dn.dn2str(ldap.dn.str2dn(r'uid=user_isOxUser_02,cn=users,ou=\+1,dc=ucs,dc=test')) 'uid=user_isOxUser_02,cn=users,ou=\\+1,dc=ucs,dc=test' >>> ldap.dn.dn2str(ldap.dn.str2dn(r'uid=user_isOxUser_02,cn=users,ou=\2B1,dc=ucs,dc=test')) 'uid=user_isOxUser_02,cn=users,ou=\\+1,dc=ucs,dc=test'
Both DN's are valid and equal. # univention-ldapsearch -LLLb 'uid=foobar,ou=\2B1,dc=ucs,dc=test' 1.1 univentionObjectType dn: uid=foobar,ou=\2B1,dc=ucs,dc=test univentionObjectType: users/user # univention-ldapsearch -LLLb 'uid=foobar,ou=\+1,dc=ucs,dc=test' 1.1 univentionObjectType dn: uid=foobar,ou=\2B1,dc=ucs,dc=test univentionObjectType: users/user > Later when the ox-connector sets the permissions it uses the DN for a search in the database and can't find the correct entry due to the mismatch "\+" vs "\2B". So how does the connector do its search?
Patch suggestion, please test: diff --git app/listener_trigger app/listener_trigger index 9f34e43..a0d0414 100755 --- app/listener_trigger +++ app/listener_trigger @@ -42,6 +42,8 @@ from collections import defaultdict from datetime import datetime from pathlib import Path +import ldap.dn + from univention.ox.provisioning import helpers, run from univention.ox.provisioning.key_value_store import KeyValueStore @@ -68,9 +70,15 @@ logger.addHandler(handler) # logger.setLevel(logging.DEBUG) # logger.addHandler(handler) +def normalize_dn(dn): + return ldap.dn.dn2str(ldap.dn.str2dn(dn)) + + def _get_old_object(distinguished_name): - path_to_old_user = mapping.get(distinguished_name.lower()) + path_to_old_user = mapping.get(normalize_dn(distinguished_name)) # be backwards compatible + if not path_to_old_user: + path_to_old_user = mapping.get(distinguished_name.lower()) if not path_to_old_user: path_to_old_user = mapping.get(distinguished_name) if not path_to_old_user: @@ -333,8 +341,8 @@ def objects_from_files(delete_files=True, move_files=False): logger.info("Object was deleted. Deleting %s", path) path.unlink() if obj.old_distinguished_name: - mapping.set(obj.old_distinguished_name.lower(), None) - mapping.set(obj.distinguished_name.lower(), None) + mapping.set(normalize_dn(obj.old_distinguished_name)), None) + mapping.set(normalize_dn(obj.distinguished_name), None) else: logger.info("mv %s -> %s", path, old_file_path) old_file_path.parent.mkdir(parents=True, exist_ok=True) @@ -345,8 +353,8 @@ def objects_from_files(delete_files=True, move_files=False): ) obj.dump(old_file_path) if obj.old_distinguished_name and obj.old_distinguished_name != obj.distinguished_name: - mapping.set(obj.old_distinguished_name.lower(), None) - mapping.set(obj.distinguished_name.lower(), old_file_path) + mapping.set(normalize_dn(obj.old_distinguished_name)), None) + mapping.set(normalize_dn(obj.distinguished_name), old_file_path) elif delete_files: logger.info("Deleting %s", path) path.unlink()
err, change into: +def normalize_dn(dn): + return ldap.dn.dn2str(ldap.dn.str2dn(dn)).lower()
Instead of fixing it in the OX-Connector, shouldn't the mechanism ( https://docs.software-univention.de/app-center/5.2/en/identity_management.html#automatically-via-idm-notifications-push ) that writes the original JSON files normalize the DN?
(In reply to Johannes Königer from comment #6) > Instead of fixing it in the OX-Connector, shouldn't the mechanism ( > https://docs.software-univention.de/app-center/5.2/en/identity_management. > html#automatically-via-idm-notifications-push ) that writes the original > JSON files normalize the DN? yes, that's fine for me and sounds correct. I only looked into the function, which has the concrete error in looking up the file.
We fixed this in UDM by changing the DN representation in attributes from "normalized" to "untouched". univention-directory-manager-modules.yaml 84089a9d4a90 | Bug #58261: Do not normalize DNs in attributes. This led to different string representations between attribute values and the actual DNs of objects, causing problems in UMC not finding the already set items in ComboBoxes and made lookups error prone when using different data structures than LDAP (e.g., database cache). univention-directory-manager-modules (17.0.37) 84089a9d4a90 | Bug #58261: Do not normalize DNs in attributes. This led to different string representations between attribute values and the actual DNs of objects, causing problems in UMC not finding the already set items in ComboBoxes and made lookups error prone when using different data structures than LDAP (e.g., database cache). ucs-test (12.1.14) 84089a9d4a90 | Bug #58261: Do not normalize DNs in attributes. This led to different string representations between attribute values and the actual DNs of objects, causing problems in UMC not finding the already set items in ComboBoxes and made lookups error prone when using different data structures than LDAP (e.g., database cache).
Code review: OK YAML: OK Tests: Exist, pass, OK Changes itself: ~OK, strictly speaking this would require a data migration. But it is only necessary in case such objects exist (e.g., an object below a ou=+1) and is referenced with its DN somewhere else. This is most probably not the case, as the problems would have shown up before: * Problems in users (primary group) * Problems in groups (users) * ... (e.g., portal objects like tiles in categories) And even then it may only be a problem if you want to work with these values. Maybe you can even get away with those values being in a slightly misaligned format. So, in conclusion, I do not think we need a data migration for every customer.