Perfecting a Zero-Touch Deployment of MacOS via MDM

Perfecting a Zero-Touch Deployment of MacOS via MDM


We are quickly seeing that convergence of endpoints in the technology space today. No longer is it about SCCM or MDM or the other million acronyms that make normal people cringe. We have quickly entered the world of “Unified Endpoint Management” aka UEM. VMWare has been this clear with their ditching of AirWatch for WorkspaceONE UEM as the new brand. Microsoft opened the door for this possibility by delivering powerful APIs for Windows 10 management creating special opportunities for their competitors to close the gap.

My focus as of late has been on engineering a near albatross known as zero-touch deployment on a non-mobile device. This is next to impossible especially on a Mac. We have so many challenges, with some of them being:

  • Can’t set computer names remotely! (remember they aren’t supervised iOS devices)
  • Can’t push VPN profiles (despite there being VPN profiles for Macs…)
  • Limitations and challenges for running scripts and delivering automation OTA (over-the-air)

I am going to take you through my journey of taking a MacBook using DEP and deploying everything without needing any manual configuration whatsoever. I suppose its time to get started!

The Many Parts of MacBook Management

We can break down the different aspects to deploying/delivering a Mac cleanly into various parts:

  • Device Enrollment
  • Enterprise Integration
  • Application Deployment
  • Daemons

These different pieces that I mentioned above will help you to understand the things you need to account for. This blog post encompasses dozens of factory wipes, decisions, and engineering. Many times I was about to give up and just accept “this will be manual” but I’m stubborn. That is probably the best way to sum it all up!

Device Enrollment

The actual enrollment itself is all about setting the stage for everything else to work correctly. This is vital because if you make the wrong decisions here then the entire thing is a hot mess. So let’s talk about why Apple sucks and how you can work around it! Please don’t smite me Apple fanboys for being honest 🙂

Apple does not support any APIs for setting the computer name. You may be unaware but by default the “Reported Name” by the agent is basically the computer name that is passed to AirWatch and ends up being the “Friendly Name” that most of the proper design will be based on. So, I figured out how to do this properly. There are a few parts to making this work right:

  • Token-Based Enrollment
  • The Proper Local Account Name/RegEx Hacks
  • DEP Profiles

You will want to create an Org Group container for your Macs and place it in a sub-OG. Something like a container under your Corporate Devices called Macs. By doing this, you can enable token-based enrollment and custom lookup values only for that container without breaking the rest of your environment.

Token-Based Enrollment

Your token enablement will look like this below. This will enable enrollment tokens for you.

Screen Shot 2018-05-31 at 8.09.38 AM

Now, you ask why in the hell are we doing this? The reason is because as Peppa Pig would say “Jon is a clever clogs.” Yes I have small children 🙂

Once you have done this, you go click “Add Device” and you configure the Device field specifically with the computer name you plan on using. (This is important for later) and set the Organization Group for that new OG you created.

Screen Shot 2018-05-31 at 8.12.38 AM.png

Local Account Name and Custom Lookup Values

So you set the expected friendly name, which will stick at the beginning of your enrollment, but that will quickly change. For you to make this actually work correctly, you want to set the local account to match your computer name. So PC12345 would be the local account name that you create because the OS will automatically make your PC called PC12345’s MacBook Pro. By doing this, we have something we can manipulate and get a friendly name that can actually be used to automate other aspects we will discuss later.

If you don’t do anything, your device name in AirWatch will be called PC12345’s MacBook Pro but that sort of computer name will make people quite unhappy with you. Next, you go into Settings > Devices & Users > General > Lookup Fields and create this lookup field below.

Screen Shot 2018-05-31 at 8.19.50 AM

This will strip everything after the ‘ in your computer name and set it as the device’s reported name in AirWatch (e.g. PC12345’s MacBook Pro is now seen as just PC12345). You can then go one menu item up to Friendly Name and set your Mac OG to use Device Reported Name as the Friendly Name.

Screen Shot 2018-05-31 at 8.23.14 AM.png Now, you finally have a friendly name that you can actually work with. This will set you up for success for the rest of your device enrollment. The DEP portion to finish up the enrollment prep is simply just going to Settings > Devices & Users > Apple > Device Enrollment Program and creating a separate profile for your Macs to be placed into the Mac organization group you created.

Enterprise Integration

So, why did you do all of that annoying work in the previous section? That is a good question! The reason is so you can pass the friendly name to the two most important profiles: Directory and Wi-Fi. I’m not going to show you my profiles because I like being employed, but I will give you a few tips for those profiles and a few others.

Directory Profile Tips

  • Your {DeviceFriendlyName} goes in the Client ID
  • Under User Experience, select “Create Mobile Account at Login” and uncheck “Use UNC Path” as that tends to make your machine crap out when its off the network
  • Under Computer Administrators, select your various admin AD groups to setup admin access.

WiFi Profile Tips

  • Don’t forget you need to integrate a CA preferably using DCOM and set it up for the correct Subject Name so it can correctly authenticate.
  • You need to add the trusted roots to your WiFi profile to ensure it can properly connect via EAP-TLS or whatever your protocol is (hopefully its EAP-TLS).

FileVault Tips

  • Setup FileVault as an optional profile and only push it after the user has logged in the first time. Failing to do so would require them having full admin access to the box, which is bad obviously. Alternatively, you can setup the profile to install after midnight via scheduling.
  • Use Enterprise FileVault Keys (don’t be lazy!)
  • Use “Personal” as the key type
  • Store the Recovery Key in AirWatch

Miscellaneous Tips

A few other things that I will point out as a recommendation to manage things properly:

  • Setup Gatekeeper as “Mac App Store and identified developers”
  • Don’t use Firmware Passwords
  • Use Firewall Profiles to ensure bad actors aren’t pinging/hurting your user’s machine

Application Deployment

VMWare has released a very useful new tool call the VMWare AirWatch Admin Assistant which can be used to convert your Mac applications to a format that can be uploaded directly to the catalog and get you away from the VERY evil product provisioning for applications. I strongly recommend using it 100%

A few tips on the Admin Tool:

  • You must disable Gatekeeper or it won’t work
  • After it creates the PList go in and edit the display_name and name fields to what you ACTUALLY want people to see in the catalog. Trust me you don’t want something to be called Microsoft_Office_2016_16.10.18021001_Installer

Typically the way I manage application deployment in general is everyone gets a baseline package that is automatically installed and then certain roles will get subsets of applications. The most important thing to remember is that if you can do an application via VPP then absolutely DO it. You will save yourself so MANY headaches.

Recommended Scripts

I have a few scripts that I swear by for my MacBook rollout. These scripts are huge and make your Macs enterprise grade:

AnyConnect Config File Script (Just set your hostname, address, and group)


# Variables

myHost=$(networksetup -getcomputername)

cert=`security find-certificate -c $myHost -Z | grep SHA | awk ‘{print $3}’`

loggedInUser=`/bin/ls -l /dev/console | /usr/bin/awk ‘{ print $3 }’`

#Create .anyconnect config file

echo “<?xml version=\”1.0\” encoding=\”UTF-8\”?>













</AnyConnectPreferences>” > /Users/$loggedInUser/.anyconnect

Google Chrome Kerberos Setup Script (Just set the TLD attribute for your domain)


# Variables

loggedInUser=`/bin/ls -l /dev/console | /usr/bin/awk ‘{ print $3 }’`

loggedInUserHome=`dscl . -read /Users/$loggedInUser NFSHomeDirectory | awk ‘{print $NF}’`


# Google Chrome

# backup current file

/bin/cp “/Users/$loggedInUser/Library/Preferences/” “/Users/$loggedInUser/Library/Preferences/”

/usr/bin/defaults write /Users/$loggedInUser/Library/Preferences/ AuthNegotiateDelegateWhitelist $tld

/usr/bin/defaults write /Users/$loggedInUser/Library/Preferences/ AuthServerWhitelist $tld

/usr/sbin/chown $loggedInUser /Users/$loggedInUser/Library/Preferences/

# Respawn cfprefsd to load new preferences

/usr/bin/killall cfprefsd

Kerberos Ticket Cleanup




sudo /usr/bin/kdestroy


I’ve found that these scripts are very useful. You also want to modify the authorization file in pam.d with this to ensure kerberos tickets are created automatically at logon.

# authorization: auth account
auth optional use_first_pass use_kcminit default_principal
auth optional use_first_pass
auth required use_first_pass nullok
account required

Overall using these scripts will automatically setup Cisco AnyConnect, configure Kerberos, and setup Chrome for Kerberos to make your MacBook enterprise grade.


I felt like Daemons really deserve their own section as they are vital to your success. Basically a daemon is something that can run at startup as either the logged-in user or root.

Basically, I wrote a few daemons for the scripts I mentioned previously to make this work correctly and achieve a zero-touch deployment. You place these PLists in the correct folder. They go in either:

  • /Library/LaunchDaemons (Run as Root)
  • /Library/LaunchAgents (Run as Logged in User)

I placed my Kerberos Daemon under LaunchDaemons and the other two under Launch Agents. I found this worked as desired. I had to do it with AnyConnect otherwise it sets the logged in user as root which obviously is an epic fail.

An example of one can be found below:

<?xml version=”1.0″ encoding=”UTF-8″?><?xml version=”1.0″ encoding=”UTF-8″?><!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “”><plist version=”1.0″><dict> <key>Label</key> <string>com.anyconnect.daemon</string> <key>ProgramArguments</key> <array> <string>/usr/local/</string> </array> <key>RunAtLoad</key> <true/> <key>StandardErrorPath</key> <string>/tmp/com.anyconnect.daemon.err</string> <key>StandardOutPath</key> <string>/tmp/com.anyconnect.daemon.out</string></dict></plist>

There are a few vital takeaways that you want to realize to make Daemons work correctly:

  • Scripts should never be stored in /tmp as that is emptied on reboot
  • You must execute a chmod +x on any scripts that daemons need to run
  • When deploying via AirWatch, you want to use this command via a RUN action to enable the daemon: sudo launchctl load -w /Library/LaunchAgents/com.anyconnect.plist

In Closing

I hope this will end up being useful for some of you. I spent hours trying to perfect the various aspects of Mac deployment. A lot of this has to do with a lack of documentation on the AirWatch side, lack of knowledge at a deep level on Mac architecture, and just some of the shortcomings that we deal with on Macs. This has certainly been an enlightening experience for me that I hope will make things easier on you.



Social Media

Get The Latest Updates

Subscribe To Our Weekly Newsletter

No spam, notifications only about the latest posts and updates.