A Beginner’s Guide to MacOS Support for a UEM Engineer

A Beginner’s Guide to MacOS Support for a UEM Engineer

apple, scripting, tools
Helpful Tools on MacOS

Over the last few years, I’ve written a number of articles on MacOS, such as my article on perfecting DEP enrollments. Frequently, I’ve written articles based on things that I am working on. I’ve come to realize that many people are starting to migrate and converge their UEM infrastructure. Let me help with your transition as you start to learn how to manage and develop your MacOS skills as you migrate off JAMF and toward a single platform for all of your devices. We will discuss some helpful tools, writing scripts, an introduction to app configuration, app deployments, kernel extensions, privacy permissions, and some helpful resources to learn more.

Helpful Tools on MacOS

When I think about the tools that are the the most useful for new MacOS admins, I flock to xCode, TextWrangler, and the JAMF PPPC Utility. Let’s dig into them and see how they can help you.

xCode to the Rescue

So what exactly is xCode? xCode is the IDE (Integrated Development Environment) for Apple devices. Depending on who you are, you may use xCode to write iOS or MacOS apps, capture iOS logs (not anymore but we miss it), and create things. xCode is important to MacOS admins because it will be the best place to write your bash scripts, which we will cover in more detail later. You will go to File > New > File to choose the Shell Script template for building your scripts. It’s likely you may already use xCode today to sideload iOS apps, capture identifiers, etc. but it’s important to call out its role for you as a MacOS administrator.

Let’s Wrangle Some Text

I know its called BBEdit now, but TextWrangler is an excellent product. The cardinal rule of MacOS is to NEVER use TextEdit for anything. It has a huge track record of screwing things up. BBEdit is a rich HTML and text editor that I use to do most of my code, editing, and work. Some of the great features for administrators are:

BEdit offers the System Administrator and UNIX user powerful tools as well:

  • Authenticated saves
  • Access and manipulate locked and hidden unix files for system administration both locally and on remote volumes, even files that are only writeable by administrative users.
  • Shell Worksheets provide a unique command-line experience, complete with sudo support. Use BBEdits powerful editing to manipulate and execute Unix command lines, and then use the same editing capabilities to manipulate the output
  • Transparently search, open, and save gzip (.gz) and bzip2 (.bz2) compressed text files
  • bbedit command-line tool: invoke BBEdit from anywhere in the Unix command line to open files or sftp/ftp URLs
  • Invoke Find Differences from the command line with bbdiff
  • Use the command line for multi-file searching with bbfind
  • Pipe command-line tool diagnostic output into bbresults for a GUI errors/warnings/notes results browser
  • Emacs keybinding support (for basic navigation and commands)

Additionally, you may just want to leverage BBEdit for editing files, searching, and authoring. It’s an incredibly powerful tool if you buy it. Most times, I just use it to look at logs, write XML, Json, or scripts and more. BBEdit is a very compelling product that is very reliable.


I don’t often use many JAMF tools truthfully, but their PPPC utility is a HUGE deal. When Catalina came out, we had to start worrying about privacy preferences. We have learned frequently that PPPC is a blessing where we can avoid a ton of historical noise. We’re here to discuss a special tool. You don’t need to use JAMF to find it incredibly useful. We will be uploading a video soon to show how cool it is, but we will break it down for now.

You can see below, that you select your Application, the access rights, and the Apple Events to build an exportable mobileconfig file that it builds a nice little package that will grant your application the rights you need for the specific events.

You can see upon opening the mobile config file how it builds it all into this nice little package, which you can double-click on and install locally to test before deploying via MDM:

Writing Shell Scripts

Whenever people hear scripting, they run for the hills literally and figuratively.

Scripting doesn’t have to be scary. Let’s be honest about what scripting is: “Scripting is just an unattended list of instructions you send a computer to accomplish something in an automated fashion.” Let’s discuss the different parts of a script and how it comes together.


The variable is the most important aspect to a script. Variables are a way of pulling a piece of information off your Mac so that you can pass it to the command in your script. Let’s look at a few examples of variables that I use in my scripts

##Store the Hostname in all caps##
myHost=$(hostname -s | /usr/bin/awk '{print toupper($0) }')
##Store the SHA for your user certificate##
cert=`security find-certificate -c $myHost -Z | grep SHA | awk '{print $3}'`
##Store the Logged in User##
loggedInUser=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`

After you build your variables, you reference them with $ + the variable name e.g. $myHost translates to the value of your script. Variables are a crucial part to your script and truthfully without them it would be useless. One riff on this concept that all Workspace ONE engineers should look at is Paul Evans’ script found here, which lets you pass lookup values from your console to Macs directly. I strongly recommend it to elevate your variable game.

Writing the Script Body

Once you have your variables set, you need to start thinking about the commands in your script. We need to think about our goal. You can use scripts for various things, like renaming your Macs, setting configuration settings, deploying parts of apps to get rid of admin rights, and more. The primary goal about writing MacOS scripts in my opinion is reducing friction. You may use scripts to handle things that require sudo but don’t want to give full admin rights to your people. A nice example is this script that let’s you eliminate the admin prompts in the initial xCode setup:

##Stores Local User as a Variable
loggedInUser="$(defaults read '/Library/Application Support/AirWatch/Data/CustomAttributes/CustomAttributes' 'EnrollmentUser')"
##Adds Local User to Developer Group
sudo dscl . append  /Groups/_developer GroupMembership $loggedInUser
##Accepts EULA
sudo /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild --license accept
## Performs Initial Component Install
sudo /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -runFirstLaunch

Now, we can focus on the parts of a single line of code. The structure is as follows:

  1. Access Rights invocation e.g. Sudo or not
  2. The command itself e.g. dscl, security, or something similar
  3. Parameters are found via our friend the hyphen e.g. –license accept
  4. Other miscellaneous actions, such as piping the command to Awk or grep to get the exact formatting/syntax you are looking for

Some Suggestions on Scripting

I wanted to give a few tips to make you think about how you should operate.

  • You should use terminal and test each line of your command to ensure the syntax works as expected.
  • You want to make sure you don’t have admin rights when testing to ensure your expected behavior actually happens.
  • Test your scripts manually before deployment everytime!

Application Deployment on MacOS

When we deploy apps on MacOS, there are 3 ways to do it and they are all valid. Don’t let anyone tell you that you should only use traditional app deployment, or VPP, or scripts, etc. You can use any of these methods regardless of what people tell you. Let’s cover each real quickly.

Traditional App Deployment on MacOS

Your traditional app deployment is likely based on Munki which is a great open source standard, which is comprised of an application binary and proeprty list aka plist to deploy the application to an enterprise application catalog. Your plist looks like this below, which has metadata for your package. You will just want to make sure you properly edited your display_name and name attributes to look human-friendly:

Most of this data is pulled out of the info.plist inside of the contents folder of the application, similar to this below:

Sometimes, you may need to modify the Info.plist to make things work right if the vendor does a poor job, but overall it tends to go fairly well. My rule of thumb with application deployment is if it goes bad, then find a better way. There is no right or wrong way. The main exception shifts to VPP deployments.

Deploying MacOS Apps via VPP

The top reason that I use VPP is for auto updates, but sometimes it can be preferable to a traditional app deployment. The top example of an app that SHOULD always go VPP is Office 365 because it will hit those monthly patches automatically without needing to manage the Microsoft AutoUpdate nightmare. I’m not going to cover Apple Business Manager as you should be up-to-speed on that if you support iOS, but you can deploy MacOS apps in the same fashion.

You will want to make the right decisions from the get-go. Flipping apps from App Deployment to VPP is basically black magic and doesn’t work most of the time. Some people go with the mentality that if it’s in the Mac App Store you should VPP it. I think that’s a completely fair strategy, but it’s up to you and what you think is best.

Application Script Deployment

Sometimes I will do application deployments via scripts because traditional app deployments are not reliable for some apps or you need more complex logic. I’ve found that some security tools and printer drivers just run better in this way. You will find below a nice example of one of these deployments:

##Copy PKG##
cp /tmp/SEP.pkg /usr/local/SEP.pkg
##Install Application##
sudo installer -pkg /usr/local/SEP.pkg -target /

I’ve found thie method just works well for some applications and can be completely viable. Let’s remember that nothing is absolute. You have many tools in your toolbelt. I’m just here to provide those tools to help you crush it!

Configuring Apps on MacOS

in MacOS, you have a folder called Application Support. You will find a folder for your system and a folder for your users. The path difference is separated by the ~ (which means logged in user folder):

  • /Library/Preferences
  • ~/Library/Preferences

In this folder, you have configuration files called plists. We discussed those minorly earlier. This is sort of like the registry of MacOS in a way. You can see a nice list of all your fancy config files:

Now that you see all of those fancy files that hold the configuration of your apps, let’s look at one of them. You will notice in my config file that I setup Office to automatically download updates and set it to the BETA channel:

The Best Way to Change App Preferences

The ideal way to modify your plists is via terminal. Below, you will see an example of a script that I wrote, which backs up your existing plist and then uses the /usr/bin/defaults write command to set the plist to automatically use your certificates for Single Sign On.

# backup current file
/bin/cp "/Users/$loggedInUser/Library/Preferences/com.google.Chrome.plist" "/Users/$loggedInUser/Library/Preferences/com.google.Chrome.plist.backup"
/bin/echo "Preference archived as: /Users/$loggedInUser/Library/Preferences/com.google.Chrome.plist.backup"

/usr/bin/defaults write /Users/$loggedInUser/Library/Preferences/com.google.Chrome.plist AuthNegotiateDelegateWhitelist $tld
/bin/echo "AuthNegotiateDelegateWhitelist set to $tld for $loggedInUser"
/usr/bin/defaults write /Users/$loggedInUser/Library/Preferences/com.google.Chrome.plist AuthServerWhitelist $tld
/bin/echo "AuthServerWhitelist set to $tld for $loggedInUser"
/usr/bin/defaults write /Users/$loggedInUser/Library/Preferences/com.google.Chrome.plist AutoSelectCertificateForUrls -array-add -string "{\"pattern\":\"https://cas-aws.vmwareidentity.com\",\"filter\":{}}"
/usr/sbin/chown $loggedInUser /Users/$loggedInUser/Library/Preferences/com.google.Chrome.plist

Kernel Extensions

Kernel Extensions (kext) aren’t a part of Big Sur, but I think it’s good for you to understand what they are. A kext is a bundle that runs in kernel space to run low-level tasks. By running in kernel space, they can run as elevated that traditional users cannot. The best way to check your kext needs for your environment is to examine the existing kexts. A few lines of code in terminal will help you:

sudo sqlite3 /var/db/SystemPolicyConfiguration/KextPolicy   
Select * from kext_policy;

This code will read the SQLite database to list your kexts like this:

Once you have that information, you build out KEXT payloads to whitelist the kernel extensions, which eliminates unnecessary noise for your users and reduces your tickets. It’s good to call out that the output of your SQLite database is the Team ID and the Bundle ID, which you add to the profile below to proactively handle your application security needs:

MacOS Privacy Preferences Policy Control

The new MacOS PPPC payloads introduced in MacOS Catalina are focused on transparency, consent, and control being in the hands of the users. This is a great step forward and aligns with Apple’s strategy around being more privacy conscious. The challenge is that we need to account for this or applications aren’t going to work correctly and it gets noisy quickly. You may realize you need a PPPC payload is getting admin prompts or requests for privacy enablement. Some of the settings that you can set with PPPC are:

  • Accessibility
  • Address Book
  • Admin Files
  • Full Disk Access
  • Calendar
  • Camera
  • Desktop Folder
  • Documents Folder
  • Downloads Folder
  • File Provider
  • Listen Event
  • Media Library
  • Microphone
  • Network
  • Photos
  • Post Events
  • Reminders
  • Removable Volumes
  • Screen Capture
  • Speech Recognition

As I mentioned earlier, JAMF’s tool makes this a breeze by giving you the values that you will build into your MDM profile:

Slapping together that PPPC payload is going to be a breeze as you can see below. Truthfully, you will find its a bunch of trial and error:

Some Useful Resources for MacOS Administration

Final Thoughts

I hope that you feel this is a good start. There is so much to cover on MacOS and are certainly plenty of things we didn’t discuss like Caching Servers, Apple Configuration, Terminal, Various MDM Payloads, and more. Don’t let anyone tell you that MacOS is easy or “it’s just like iOS” You can’t easily operationalize MacOS or just throw it at someone who isn’t versed in MacOS. MacOS expertise is very sparse and with information like you read today, you can provide value and help your team grow.



Social Media

Get The Latest Updates

Subscribe To Our Weekly Newsletter

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