Bug 56107

Summary: udm modules stores wrong representation for binary properties (icon, jpegPhoto, background)
Product: UCS Reporter: Moritz Bunkus <m.bunkus>
Component: UMC (Generic)Assignee: UMC maintainers <umc-maintainers>
Status: NEW --- QA Contact: UMC maintainers <umc-maintainers>
Severity: normal    
Priority: P5 CC: best
Version: UCS 5.0Keywords: python3-migration
Target Milestone: ---   
Hardware: Other   
OS: Linux   
See Also: https://forge.univention.org/bugzilla/show_bug.cgi?id=47316
What kind of report is it?: --- What type of bug is this?: ---
Who will be affected by this bug?: --- How will those affected feel about the bug?: ---
User Pain: Enterprise Customer affected?:
School Customer affected?: ISV affected?:
Waiting Support: Flags outvoted (downgraded) after PO Review:
Ticket number: Bug group (optional):
Max CVSS v3 score:
Attachments: test script for reproducing the issue

Description Moritz Bunkus 2023-05-31 18:08:13 CEST
Created attachment 11069 [details]
test script for reproducing the issue

I'm trying to use the UDM modules in order to modify portal entries & portals. One of the steps is assigning icons for entries, background images for portals. This doesn't work, though, as the UDM modules don't store the actual binary data in LDAP, but a stringified representation of how a base64 encoded string would be output by Python.

Too abstract? Here's an example. If I have an SVG file that base64-encodes to the following data (intentionally shortened in the middle):

> PHN2ZyB4b…jwvc3ZnPg==

Using the UDM modules the following is actually stored in LDAP:

> b'PHN2ZyB4b…jwvc3ZnPg=='

This does not happen if I use the "udm" command-line utility, though — it only happens with my own, very simple program that I'll attach in a second. The program basically does the following:

------------------------------------------------------------
cn = "vbm-ucs-classes"
dn = "cn={0},cn=entry,cn=portals,cn=univention,{1}".format(cn, ucr["ldap/base"])
content = open("/root/.local/linet/portal_entry_images/entry-icon-vbm-ucs-classes.svg", "rb").read()

entry = UDM.admin().version(2).get('portals/entry').get(dn)
entry.props.icon = content
entry.save()
------------------------------------------------------------

OK, here's more in-depth information.

THIS WORKS: using the "udm" CLI (again intentionally shortened in the middle):

[0 root@dc-primary.ucs.schulen1.myschool.bildungslogin.de ~] dn=cn=vbm-ucs-classes,cn=entry,cn=portals,cn=univention,dc=ucs,dc=schulen1,dc=myschool,dc=bildungslogin,dc=de
[0 root@dc-primary.ucs.schulen1.myschool.bildungslogin.de ~] udm portals/entry modify --dn $dn --set "icon=$(base64 < ~/.local/linet/portal_entry_images/entry-icon-vbm-ucs-classes.svg | tr -d '\n')"
Object modified: cn=vbm-ucs-classes,cn=entry,cn=portals,cn=univention,dc=ucs,dc=schulen1,dc=myschool,dc=bildungslogin,dc=de
[0 root@dc-primary.ucs.schulen1.myschool.bildungslogin.de ~] univention-ldapsearch -b $dn | grep -i icon
univentionNewPortalEntryIcon: PHN2ZyB4…Pjwvc3ZnPg==

Looks good.

THIS DOES NOT WORK: With my very simple program the following occurs:

[0 root@dc-primary.ucs.schulen1.myschool.bildungslogin.de ~] ~/.local/linet/testme.py
[0 root@dc-primary.ucs.schulen1.myschool.bildungslogin.de ~] univention-ldapsearch -b cn=vbm-ucs-classes,cn=entry,cn=portals,cn=univention,dc=ucs,dc=schulen1,dc=myschool,dc=bildungslogin,dc=de | grep -i icon
univentionNewPortalEntryIcon: b'PHN2ZyB4…jwvc3ZnPg=='


What else have I tried:

• assigning a Unicode string object of the base64-encoded content instead of a bytes object: "PHN2ZyB4…Pjwvc3ZnPg==" (as in entry.props.icon = base64.b64encode(content).decode("utf8")) ; this results in an exception that some API expects bytes, not str
• assigning a bytes string of the base64-encoded content (as in entry.props.icon = base64.b64encode(content)); this results in my provided value being base64-encoded _again_ and the LDAP attribute still having the "b'…'" wrapper)
• assigning an instance of Base64BinaryProperty("icon", raw_value=content) ; same result…


It's quite possible that I'm doing something incredibly stupid. If so, I apologize.
Comment 1 Moritz Bunkus 2023-05-31 18:09:40 CEST
BTW, the other bug I was referring to where I got that syntax from is 47316.
Comment 2 Moritz Bunkus 2023-06-01 09:13:43 CEST
Fun addendum: if I use the attached script with Python 2 instead of Python 3 I get:

[0 root@dc-primary.ucs.schulen1.myschool.bildungslogin.de ~] univention-ldapsearch -b cn=vbm-ucs-classes,cn=entry,cn=portals,cn=univention,dc=ucs,dc=schulen1,dc=myschool,dc=bildungslogin,dc=de | grep -i icon
univentionNewPortalEntryIcon:: PHN2ZyB4…jwvc3ZnPg==

…which indicates that the LDAP attribute is now set to actual binary data, not to a base64-encoded string of binary data.