Thursday 17 October 2019

Auto-naming Mac computers using values from a database

Long time Mac admins may have used a tool like DeployStudio to 'build' Macs before issuing them to users.

DeployStudio can install the operating system, set various settings and install files and programs. One of the tasks it can perform as part of its workflow is to automatically set the name of the computer based on a 'database' stored within DeployStudio.

I always found this auto-naming of computers useful as it allowed using a name format that was completely under the control of the Mac administrator and therefore could be for example based on asset numbers rather than the computer serial number.

Unfortunately it seems with macOS Catalina Apple have finally put the last nail in the coffin for using DeployStudio as a tool. (I had been able to devise a way to use it for macOS Mojave even with T2 chip equipped Macs.)

Equally unfortunately it seems most other Mac management tools e.g. Jamf do not have a similar facility and at best leave you to write a script which typically names the computer based on its serial number.

Whilst using a serial number is a possibility and achieves the main goal of being a unique value and one that could be used to track computers on a network it is not the format I prefer and whilst macOS is perfectly happy with that as a computer name that format would not work as well in other operating systems especially Windows which would lead to a loss of consistency in naming computers.

I have therefore devised a script of my own to auto-name Macs using a database sourced value i.e. the way DeployStudio works. This script could be run via Jamf after enrolment. The example script listed below is using the database from DeployStudio. Clearly it would be massive overkill to setup and run a DeployStudio server solely for the purpose of running the database of computer names but if you have an existing DeployStudio server you can continue to use it for just this purpose. In theory this approach could be relatively easily modified to use an alternate database although directly using something like MySQL would then require having the MySQL client installed. In my case I am also considering using the free open source IT asset management system 'Snipe-IT' which like DeployStudio also has a REST API.

Note: In order to make this script as robust as possible and in particular more suitable for Jamf I went to considerable effort to process the XML returned by DeployStudio in a way that avoided having to write the results to a file, that is I have managed to do all the processing using pipes and stdin. This precluded using the defaults command for example. I also was careful to only use tools built-in to macOS.

#!/bin/sh

# DeployStudio connection settings
host='https://deploystudio.domain.com:60443'
adminuser='deploystudiouser'
adminpass='deploystudiopass'

# Get Mac serial number
# Your choice to use ioreg or system_profiler
# MAC_SERIAL_NUMBER=`/usr/sbin/ioreg -l | /usr/bin/grep IOPlatformSerialNumber | /usr/bin/awk '{print $4}' | /usr/bin/cut -d \" -f 2`
MAC_SERIAL_NUMBER=`/usr/sbin/system_profiler SPHardwareDataType | /usr/bin/grep 'Serial Number (system)' | /usr/bin/awk '{print $NF}'`

# Get Mac hostname from DeployStudio
# This is done using DeployStudio's REST API which returns a binary XML record, this then has to be converted to text XML and the host name key obtained from it
# It is assumed that your DeployStudio is using the default option to use a Mac serial number as the index, if you used MAC addresses this will not work
result=`/usr/libexec/PlistBuddy -c "Print $MAC_SERIAL_NUMBER:cn" /dev/stdin 2> /dev/null <<< $(/usr/bin/curl -s -k -u $adminuser:$adminpass "$host/computers/get/entry?id=$MAC_SERIAL_NUMBER" | /usr/bin/plutil  -convert xml1 -r -o - -- - )`

# If a result is returned from DeployStudio then use it, else use a generic name
if [ $? -eq 0 ]; then
echo "$result"
else
result=`/usr/sbin/system_profiler SPHardwareDataType | /usr/bin/grep "Model Name" | /usr/bin/awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'`
echo "$result"
fi

# Set Bonjour and Computer names
/usr/sbin/scutil --set LocalHostName "$result"
/usr/sbin/scutil --set ComputerName "$result"
/usr/bin/dscacheutil -flushcache

exit