pycreateuserpkg icon indicating copy to clipboard operation
pycreateuserpkg copied to clipboard

Python3 uses b'username' syntax

Open davidbpirie opened this issue 3 years ago • 4 comments

When building a package with python3 (tested with python 3.10.2 and munki-python 3.9.5) the string applied for the username is in the syntax "b'username'".

Python 3:

% munki-python --version
Python 3.9.5
% munki-python ./createuserpkg.py -n localadmin -u 501 -a -i com.foo.localadminpkg -V 1.0 localadmin.pkg
Password: 
Password (again): 
pkgbuild: Inferring bundle components from contents of /var/folders/cb/bcvrwgk113n46ysk4kgwr5t40000gn/T/tmpyn_opl_v/create_user
pkgbuild: Adding top-level postinstall script
pkgbuild: Wrote package to localadmin.pkg
% pkgutil --expand localadmin.pkg expanded
% ls expanded/Scripts
b'localadmin'.plist     config                  createuser              postinstall
% cat expanded/Scripts/config 

USERNAME="b'localadmin'"
UUID=E2E8155B-7932-4E40-BFDA-A59D8907A66E
USER_IS_ADMIN=True
ENABLE_AUTOLOGIN=False

Python 2:

% python --version
Python 2.7.16
% python ./createuserpkg.py -n localadmin -u 501 -a -i com.foo.localadminpkg -V 1.0 localadmin.pkg
Password: 
Password (again): 
pkgbuild: Inferring bundle components from contents of /var/folders/cb/bcvrwgk113n46ysk4kgwr5t40000gn/T/tmpVeLLDR/create_user
pkgbuild: Adding top-level postinstall script
pkgbuild: Wrote package to localadmin.pkg
% pkgutil --expand localadmin.pkg expanded
% ls expanded/Scripts
config                  createuser              localadmin.plist        postinstall
% cat expanded/Scripts/config

USERNAME="localadmin"
UUID=1AC7EED3-E114-4D23-8FF5-52774B4AE4B4
USER_IS_ADMIN=True
ENABLE_AUTOLOGIN=False

From my minimal testing, this appears to have no negative impact when the pkg target is not the boot volume (eg via bootstrappr), but does when target the boot volume (eg installr). Areas I identified as impacted in pkg_scripts/postinstall are inside lines 45-66 - the createuser binary (line 47) executes successfully as the contents of the plist are correct, but the subsequent lines using "$USERNAME" will have unexpected results.

I believe this ultimately is because string.encode('utf-8') results in a byte object, not a string, and the differences in how python2 and python3 handle byte objects. This is used in locallibs/userpkg.py.

I could have a crack at a PR if you like, but I am not exactly sure where the need for UTF-8 encoding comes from, so might make a complete hash of it.

Thanks for all you do and share with the community.

davidbpirie avatar Mar 24 '22 06:03 davidbpirie

Removing the .encode('utf-8') "fixes" the issue as long as the username contains only ASCII characters, but leads to errors/problems if there are non-ASCII characters in the name. I'll need to experiment some more.

gregneagle avatar Mar 24 '22 15:03 gregneagle

I've made (and minimally tested) a change that addresses the issue on Python 3. I have not yet tested to see if it breaks things under Python 2. (This machine is running macOS 12.3 and I don't have Python 2 available.)

gregneagle avatar Mar 24 '22 15:03 gregneagle

...and these changes break on Python 2. As tempting as it might be to abandon Python 2 right now, I suspect a fair number of people are still using it.

gregneagle avatar Mar 25 '22 20:03 gregneagle

OK. Latest push seems to work under both Python 2 and 3; tested under both with a username containing non-ASCII characters, and a password containing non-ASCII characters.

gregneagle avatar Mar 25 '22 22:03 gregneagle