Quantcast
Channel: December 2017 – Der Flounder
Viewing all articles
Browse latest Browse all 2

Creating local user accounts with pycreateuserpkg

$
0
0

As part of setting up new Macs, you may want to add one or more local user accounts with a pre-determined password to those Macs. The reasons for this may include the following:

  • Setting up a local administrator account
  • Setting up a “loaner” user account for a pool of loaner laptops
  • Setting up a local user account that automatically logs at startup for a library kiosk
  • Setting up a generic “student” account for use in a school’s computer lab

Previously, it was possible to use the venerable CreateUserPkg utility to accomplish this goal, but the password scheme used by CreateUserPkg stopped working on macOS High Sierra. An alternative tool which works on macOS High Sierra is pycreateuserpkg, a Python script written by Greg Neagle which generates packages that create local user accounts when installed. For more information, see below the jump.

Using pycreateuserpkg:

1. Download pycreateuserpkg from GitHub using the link below:

https://github.com/gregneagle/pycreateuserpkg

2. Decide on the settings you want for the new user account, using the options available below:



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


Required User Options:
-n NAME, –name=NAME: User shortname. REQUIRED.
-u UID, –uid=UID: User uid. REQUIRED.
-p PASSWORD, –password=PASSWORD: User password. REQUIRED.
Note: If the password option is not selected, you will be prompted for a password for
the account during the package creation process.
Required Package Options:
-V VERSION, –version=VERSION: Package version number. REQUIRED.
-i IDENTIFIER, –identifier=IDENTIFIER: Package identifier. REQUIRED.
Optional User Options:
-f FULLNAME, –fullname=FULLNAME: User full name. Optional.
-g GID, –gid=GID: User GID, otherwise known as a group identifier. Optional.
-H HOME, –home=HOME: Path to user home directory. Optional.
-s SHELL, –shell=SHELL: User shell path. Optional.
-a, –admin: User account should be added to admin group.
-A, –autologin: User account should automatically login.
view raw

gistfile1.txt

hosted with ❤ by GitHub

As an example, let’s create an installer package which installs a local user account with the following characteristics:

Account’s shortname: kiosk
Account’s displayed name: Kiosk
UID: 604
Account shell: /bin/bash
Account should have admin rights: No
Account should auto-login: Yes

Since we also need to provide version and identifier information for the installer package, we’ll use the following characteristics:

Version number: 1.0
Package identifier: com.github.kiosk_user_setup

To create the installer package which installs the previously-defined local account, make sure you have a copy of pycreateuserpkg available, then use the command shown below:

/path/to/createuserpkg --name="kiosk" --uid=604 --fullname="Kiosk" --shell="/bin/bash" --version=1.0 --identifier="com.github.kiosk_user_setup" "Create Kiosk User Account.pkg" --autologin

Screen Shot 2017 12 23 at 9 24 30 PM

 

Since we have not defined what the account’s password will be as part of the command above, we will be prompted to enter the password then enter it again to verify:

Screen Shot 2017 12 23 at 9 26 05 PM

 

Screen Shot 2017 12 23 at 9 26 21 PM

 

That should generate a new installer package named Create Kiosk User Account.pkg.

Screen Shot 2017 12 23 at 9 27 52 PM 

Testing pycreateuserpkg-generated installers

Once the package has been built, test it by taking the pycreateuserpkg-generated installer package and install it on a Mac which does not have the local account set up on it. The end result should be that the local account is set up on the Mac and configured with the desired settings and account rights.

Screen Shot 2017 12 23 at 9 32 12 PM

Screen Shot 2017 12 23 at 9 32 16 PM

 

To give some additional examples, let’s create a local administrator account with the following characteristics:

Account’s shortname: admin
Account’s displayed name: Administrator
UID: 600
Account shell: /bin/bash
Account should have admin rights: Yes
Account should auto-login: No

Since we also need to provide version and identifier information for the installer package, we’ll use the following characteristics:

Version number: 1.0
Package identifier: com.github.admin_user_setup

To create the installer package which installs the previously-defined local account, make sure you have a copy of pycreateuserpkg available, then use the command shown below:

/path/to/createuserpkg --name="admin" --uid=600 --fullname="Administrator" --shell="/bin/bash" --admin --version=1.0 --identifier="com.github.admin_user_setup" "Create Local Admin User Account.pkg"

Screen Shot 2017 12 23 at 9 35 43 PM

 

 

Screen Shot 2017 12 23 at 9 36 15 PM

 

When the package is installed, an account like this should now appear in the Users & Groups preferences in System Preferences.

 

Screen Shot 2017 12 23 at 9 36 41 PM

Screen Shot 2017 12 23 at 9 36 44 PM

 

Finally, let’s create a standard user local account with the following characteristics:

Account’s shortname: standarduser
Account’s displayed name: Standard User
UID: 603
Account shell: /bin/bash
Account should have admin rights: No
Account should auto-login: No

Since we also need to provide version and identifier information for the installer package, we’ll use the following characteristics:

Version number: 1.0
Package identifier: com.github.standard_user_user_setup

To create the installer package which installs the previously-defined local account, make sure you have a copy of pycreateuserpkg available, then use the command shown below:

/path/to/createuserpkg --name="standarduser" --uid=603 --fullname="Standard User" --shell="/bin/bash" --version=1.0 --identifier="com.github.standard_user_user_setup" "Create Standard User User Account.pkg"

 

Screen Shot 2017 12 23 at 9 34 57 PM

 

Screen Shot 2017 12 23 at 9 30 59 PM

 

When the package is installed, an account like this should now appear in the Users & Groups preferences in System Preferences.

 

Screen Shot 2017 12 23 at 9 33 16 PM

Screen Shot 2017 12 23 at 9 33 21 PM

 

How pycreateuserpkg works

pycreateuserpkg works by creating a plist file for the specified local user account, which allows the account information to work on 10.8.x and later. The user’s account information is written to a plist file and stored in the directory listed below:

/private/var/db/dslocal/nodes/Default/users

Screen Shot 2017 12 23 at 9 00 05 PM

 

An example account plist is shown below:



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>ShadowHashData</key>
<array>
<data>
YnBsaXN0MDDRAQJfEBRTQUxURUQtU0hBNTEyLVBCS0RGMtMDBAUGBwhUc2Fs
dFdlbnRyb3B5Wml0ZXJhdGlvbnNPECAN9JFNQar3istN4qimB4Tp0j1uGmV5
rEfe9qUoLohPOU8QgEiRp6xYOrYgjZfmAhVlPzNReytc906hcOH2ZbDcOtW8
0c/ElK3n4Y0mkKd4UGJxC4/aYvknVVaEAaEVedCcvhub00HzHir16l7gYNbU
/QWrEo0JnIt93OIm2/Sgfm49arOqgqXM4r6msfu2uF6F4jAlTYYXytd8mgWC
MejFXD/nEcEDCAsiKS42QWTnAAAAAAAAAQEAAAAAAAAACQAAAAAAAAAAAAAA
AAAAAOo=
</data>
</array>
<key>_writers_UserCertificate</key>
<array>
<string>username</string>
</array>
<key>_writers_hint</key>
<array>
<string>username</string>
</array>
<key>_writers_jpegphoto</key>
<array>
<string>username</string>
</array>
<key>_writers_passwd</key>
<array>
<string>username</string>
</array>
<key>_writers_picture</key>
<array>
<string>username</string>
</array>
<key>_writers_realname</key>
<array>
<string>username</string>
</array>
<key>authentication_authority</key>
<array>
<string>;ShadowHash;HASHLIST:&lt;SALTED-SHA512-PBKDF2&gt;</string>
</array>
<key>generateduid</key>
<array>
<string>CB18DA2D-D70A-429D-9E76-413C5D0A54A2</string>
</array>
<key>gid</key>
<array>
<string>20</string>
</array>
<key>home</key>
<array>
<string>/Users/username</string>
</array>
<key>name</key>
<array>
<string>username</string>
</array>
<key>passwd</key>
<array>
<string>********</string>
</array>
<key>realname</key>
<array>
<string>User Name</string>
</array>
<key>shell</key>
<array>
<string>/bin/bash</string>
</array>
<key>uid</key>
<array>
<string>602</string>
</array>
</dict>
</plist>
view raw

gistfile1.txt

hosted with ❤ by GitHub

If the auto-login option is selected, an additional /etc/kcpassword file is also installed to facilitate the auto-login process.

Screen Shot 2017 12 23 at 9 00 11 PM

If the auto-login option is not selected, the /etc/kcpassword file will not be installed.

Screen Shot 2017 12 23 at 9 41 00 PM

Once the necessary file(s) are created by pycreateuserpkg, the utility then generates an installer package and post-installation script to install the account’s plist and the /etc/kcpassword file (if needed) into their proper places. An example postinstall script from a pycreateuserpkg-generated installer package is shown below:



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


#!/bin/bash
#
# postinstall for local account install
PlistArrayAdd() {
# Add $value to $array_name in $plist_path, creating if necessary
local plist_path="$1"
local array_name="$2"
local value="$3"
local old_values
local item
old_values=$(/usr/libexec/PlistBuddy -c "Print :$array_name" "$plist_path" 2>/dev/null)
if [[ $? == 1 ]]; then
# Array doesn't exist, create it
/usr/libexec/PlistBuddy -c "Add :$array_name array" "$plist_path"
else
# Array already exists, check if array already contains value
IFS=$'\012'
for item in $old_values; do
unset IFS
if [[ "$item" =~ ^\ *$value$ ]]; then
# Array already contains value
return 0
fi
done
unset IFS
fi
# Add item to array
/usr/libexec/PlistBuddy -c "Add :$array_name: string \"$value\"" "$plist_path"
}
ACCOUNT_TYPE=ADMIN # Used by read_package.py.
PlistArrayAdd "$3/private/var/db/dslocal/nodes/Default/groups/admin.plist" users "username" && \
PlistArrayAdd "$3/private/var/db/dslocal/nodes/Default/groups/admin.plist" groupmembers "CB18DA2D-D70A-429D-9E76-413C5D0A54A2"
if [ "$3" == "/" ]; then
# we're operating on the boot volume
# kill local directory service so it will see our local
# file changes — it will automatically restart
/usr/bin/killall DirectoryService 2>/dev/null || /usr/bin/killall opendirectoryd 2>/dev/null
fi
exit 0
view raw

gistfile1.txt

hosted with ❤ by GitHub

Note: The postinstall script may have different functionality, depending on which options are selected. For example, this is the postinstall script generated for an installer package which installs a standard user account which is set to auto-login:



This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters


#!/bin/bash
#
# postinstall for local account install
if [ "$3" == "/" ] ; then
# work around path issue with 'defaults'
/usr/bin/defaults write "/Library/Preferences/com.apple.loginwindow" autoLoginUser "kiosk"
else
/usr/bin/defaults write "$3/Library/Preferences/com.apple.loginwindow" autoLoginUser "kiosk"
fi
/bin/chmod 644 "$3/Library/Preferences/com.apple.loginwindow.plist"
if [ "$3" == "/" ]; then
# we're operating on the boot volume
# kill local directory service so it will see our local
# file changes — it will automatically restart
/usr/bin/killall DirectoryService 2>/dev/null || /usr/bin/killall opendirectoryd 2>/dev/null
fi
exit 0
view raw

gistfile1.txt

hosted with ❤ by GitHub

Once the pycreateuserpkg-generated package is installed, the account’s file(s) are put into the necessary places and the postinstall script handles any necessary preparation needed for the account to work properly.


Viewing all articles
Browse latest Browse all 2

Trending Articles