If a teacher is a member of multiple mapped schools the ID-Connector scrambles the primary school on sync. To me it looks like the primary school used for creation is just the first one sorted alphanumerically by name. ID-Connector Log sample: 2022-02-10 09:46:11 INFO [bbKelvinPerSAUserDispatcher(HPI).handle_create_or_update:134] Going to create or update ListenerUserAddModifyObject('users/user', 'uid=primaerschuleKaputt1,cn=lehrer,cn=users,ou=SchuleB,dc=mydomain,dc=intranet', None). 2022-02-10 09:46:11 INFO [bbKelvinPerSAUserDispatcher(HPI)._get_role_specific_mapping:190] Using users for the user mapping 2022-02-10 09:46:11 INFO [bbKelvinPerSAUserDispatcher(HPI).do_create_or_update:260] User does not exist on target system, creating it. 2022-02-10 09:46:11 INFO [bbKelvinPerSAUserDispatcher(HPI).do_create:128] Going to create user 'primaerschuleKaputt1': {'udm_properties': {'SchulCloudAdmin': False, 'displayName': 'XX XX', 'e-mail': ['primaerschulekaputt1@xx.de']}, 'birthday': datetime.date(1971, 11, 3), 'disabled': False, 'firstname': 'XX', 'lastname': 'XX', 'email': 'primaerschulekaputt1@xx.de', 'roles': ['teacher'], 'school': 'SchuleA', 'school_classes': {}, 'schools': ['SchuleA', 'SchuleB'], 'record_uid': 'primaerschuleKaputt1', 'source_uid': 'GLOBAL-SUID', 'name': 'primaerschuleKaputt1', 'kelvin_password_hashes': <ucsschool.kelvin.client.user.PasswordsHashes object at 0x7f8884ac1e50>}... 2022-02-10 09:46:18 INFO [bbKelvinPerSAUserDispatcher(HPI).do_create:134] User created: User('name'='primaerschuleKaputt1', dn='uid=primaerschuleKaputt1,cn=lehrer,cn=users,ou=SchuleA,dc=schulcloud,dc=intranet'). As you can see the teacher is assigned to SchuleB on the sender site whereas he is created below SchuleA at the school_authority. For completeness: The receivers Kelvin API does not seem to be aware of SchuleB being the primary school so my guess is that the error happens within the ID-Connector Kelvin-Plugin. Logs: 2022-02-10 09:46:11 INFO 172.17.42.1:54276 - "GET /ucsschool/kelvin/v1/users/?record_uid=primaerschuleKaputt1&source_uid=GLOBAL-SUID HTTP/1.1" 200 2022-02-10 09:46:13 INFO uldap.search filter=(&(ucsschoolSourceUID=GLOBAL-SUID)(ucsschoolRecordUID=primaerschuleKaputt1)) base= scope=sub attr=['dn'] unique=0 required=0 timeout=-1 sizelimit=0 2022-02-10 09:46:13 INFO Going to create ImportTeacher(name='primaerschuleKaputt1', school='SchuleA', dn='uid=primaerschuleKaputt1,cn=lehrer,cn=users,ou=SchuleA,dc=schulcloud,dc=intranet') with {'$dn$': 'uid=primaerschuleKaputt1,cn=lehrer,cn=users,ou=SchuleA,dc=schulcloud,dc=intranet', 'objectType': 'users/user', 'school': 'SchuleA', 'ucsschool_roles': ['teacher:school:SchuleA', 'teacher:school:SchuleB'], 'name': 'primaerschuleKaputt1', 'schools': ['SchuleB', 'SchuleA'], 'firstname': 'XX', 'lastname': 'XX', 'birthday': '1971-11-03', 'expiration_date': None, 'email': 'primaerschulekaputt1@xx.de', 'password': '********', 'disabled': False, 'school_classes': {}, 'source_uid': 'GLOBAL-SUID', 'record_uid': 'primaerschuleKaputt1', 'display_name': 'XX XX', 'type_name': 'Teacher', 'type': 'importTeacher', 'action': 'A', 'entry_count': 0, 'udm_properties': {'SchulCloudAdmin': False, 'displayName': 'XX XX', 'e-mail': ['primaerschulekaputt1@xx.de'], 'overridePWHistory': True, 'overridePWLength': True}, 'input_data': [], 'old_user': None, 'in_hook': False, 'roles': ['teacher']}...
One thing I had in mind was that the primary school attribute `school` could have been unmapped, but the school_authorities mapping for users contains both "school": "school", "schools": "schools", So everything needed to create a user with the right primary school is given.
Fixed in https://git.knut.univention.de/univention/components/ucsschool-id-connector/-/commit/001f113b0aeecd929a9164683d641f97eaf7d374 Will be released with next ID-Connctor app update. If required before that, apply this patch *inside* the Docker container (there is no 'patch' command, so just use 'vi'): =============================================================================== --- /ucsschool-id-connector/src/plugins/packages/ucsschool_id_connector_defaults/user_handler_base.py.ori +++ /ucsschool-id-connector/src/plugins/packages/ucsschool_id_connector_defaults/user_handler_base.py @@ -264,6 +264,8 @@ """ target_schools = await self.schools_ids_on_target schools = sorted(set([obj.school] + obj.schools)) + schools.remove(obj.school) + schools.insert(0, obj.school) for school in schools: try: return target_schools[school] ===============================================================================
Added a comment to explain fix. [master 001f113] Bug #54439: fix users with multiple schools being created in alphabetical first, instead of same as in source domain [master 9e72b1a] Bug #54439: explain reordering of OUs
It looks good to me. I applied the patch manually and could successfully sync a teacher on schools B and A so that B was the primary school. Since this code is already merged into the main branch I will set the Bug to VERIFIED and move the corresponding issue into waiting for release. A release will most likely happen when the necessary work for the id broker is also done.
A fix for this has been released in version 2.2.2. If this error occurs again, clone this bug.