Tag: Active Directory

Controlling Munki via Workspace ONE and Active Directory

I got something working recently, and I thought it was interesting enough that it’d be worth sharing.

Our MDM server is a SaaS instance of Workspace ONE UEM, and we have the AirWatch Cloud Connector installed in an on-prem VM to provide integration with Active Directory. Although WS1 bundles its own (modified) version of Munki, we don’t use it – we have a separate on-prem VM for our vanilla Munki server.

Unfortunately, this post is partially about printers (sorry). The challenge with setting up LPD printers on the macOS, is that the drivers need to be installed before the printer is added (or the printer is added with a generic driver, and must be removed and reinstalled). Munki is an excellent use case for this, as the requires and update_for pkginfo keys are perfect for setting up dependencies.

For several years, I used Graham Gilbert’s printer-pkginfo script to deploy printers with Munki. That, combined with my NoMAD group condition script, allowed me to deploy printers to only certain people’s devices – their user accounts in AD needed to be a member of a particular group.

With macOS 12.3 dropping Python 2 from the OS, I needed another solution. I landed on wyncomco’s fork of Nick McSpadden’s PrinterGenerator script. It works well, but with our move from NoMAD to Jamf Connect, how would we be able to leverage our AD groups to deploy these printers?

Thanks to the AirWatch Cloud Connector, I was able to add the AD security group to WS1 (in Accounts > User Groups > List View). The group in WS1 syncs periodically with AD, so users added to AD will appear in the WS1 group after a few hours.

In my case, though, I needed a Smart Group (sometimes called an “Assignment Group”) to actually make use of the user group. In Groups & Settings > Groups > Assignment Groups, add a new Smart Group where the first criteria is the Organization Group that contains your devices. Scroll down to User Group, and select the group you’re synching from AD. Name your Smart Group and click Save.

The last piece was how I’d get the printer to these users. Around the same time, VMware added the ability to run scripts through Workspace ONE. I had remembered Nick McSpadden’s post about Local-Only Manifests in Munki, which was perfect for this. I’d set up a separate manifest for WS1 to write to, and Munki would install the printer driver and the printer automatically.

First, in your Munki configuration profile, add this:

<key>LocalOnlyManifest</key>
<string>LocalOnlyManifest.plist</string>

This tells Munki to check this additional manifest for potential items to install. There’s no need to create the file – if it doesn’t exist, Munki proceeds as normal, without printing any warnings/errors.

Lastly, add this script to WS1 (in Resources > Scripts), and assign it to your Smart Group. Set the language to Bash, and the execution context to System.

#!/bin/bash

defaults="/usr/bin/defaults"
grep="/usr/bin/grep"

printer_installed=$(${defaults} read "/Library/Managed Installs/manifests/LocalOnlyManifest" managed_installs | ${grep} "MyPrinter")

if [ ! "${printer_installed}" ]; then
 ${defaults} write "/Library/Managed Installs/manifests/LocalOnlyManifest" managed_installs -array-add "MyPrinter"
else
    exit 0
fi

exit

In my case, I have it run immediately upon device enrollment, as well as when the network interface changes. The code runs a check to see if the Munki item MyPrinter is in the LocalOnlyManifest, and if not, it adds it. The next time Munki runs a background check, it will install the driver and printer automatically.

The end result is that when a user requires our printer, any AD admin can add the user to a particular group. Some time later, the user will receive the printer without needing to do anything. If the user already has our printer, but receives a new computer, the printer will be added as soon as the computer is set up – no additional admin work necessary.

I hope someone finds this useful for more than just printers!

Binding Macs to AD using Munki’s Configuration Profile support

Update, 2020-06-11: I’ve changed the code back to a script. Please see the GitHub repo for an explanation and the updated code.


Although the trend is to move away from binding Macs to Active Directory (most commonly using NoMAD), we’re still binding for various reasons:

  • Being able to authenticate with domain credentials for doing things that require admin privileges.
  • Being able to connect remotely using domain credentials.
  • Computer labs and other multi-user Macs.
  • We’re still using AD mobile accounts, for now.

Originally, we would bind Macs to AD as part of our DeployStudio imaging workflow. Unfortunately, we faced a couple of drawbacks with this approach:

  • By installing/configuring something only when imaging, you’re not enforcing the setting – it’s a one-shot thing. In the future, the setting could change, or the application might require an update, but you’re not going to reimage your entire fleet every time that happens.
  • When we moved from DeployStudio to Imagr, we needed to trim our workflows to be as slim as possible.

With the help of Graham Gilbert’s tutorial, we were able to move AD binding to Munki. This also gave us an unexpected benefit: in the past, we frequently found that the binding on Macs would randomly break. This was a major issue in the classrooms, where students and faculty would not be able to login to computers and start class. Moving this to Munki with a custom installcheck_script made it “self-healing” – every 1-2 hours, Munki will rebind the Mac, if necessary (or prompt the user to do this through Managed Software Center).

For the past year, there’s been a big push to move to configuration profiles for applying settings. Luckily, you can use the “directory” payload to bind to AD! However, it’s just running dsconfigad in the background anyway, so it’s entirely possible for your Mac’s binding to be broken, but the AD profile to show as successfully installed. The MDM protocol currently has no method of determining if the AD profile should be reinstalled, so Munki is a much more logical choice for deploying this. Armin Briegel’s tutorial was instrumental in assisting with this transition.

Code and usage instructions are available in my GitHub repository.

Resolving a freezing problem on lab Macs

This post has been brewing for a while, and a MacEnterprise thread from today finally got me to write about this problem, and how we resolved it.

Our university has many computer labs – some in public, open spaces, and some in classrooms. Although we don’t use roaming profiles (a technology that Apple finally removed in macOS 10.12), we do bind to Active Directory and create mobile accounts upon logging in with a valid AD account.  To prevent the buildup of cruft, we remove student and faculty accounts periodically. In the public labs, we do it overnight, using a script based off of this one from Marnin Goldberg:

#!/bin/bash
# This script works well for removing local accounts that are older than 1 day.
# Obviously the 1 day timeframe can be modified (-mtime +1).
# Runs using Launch Daemon – /Library/LaunchDaemons/edu.org.deleteaccounts.plist
# version .7
DATE=`date "+%Y-%m-%d %H:%M:%S"`
# Don't delete local accounts
keep1="/Users/admin"
keep2="/Users/admin2"
keep3="/Users/Shared"
currentuser=`ls -l /dev/console | cut -d " " -f 4`
keep4=/Users/$currentuser
USERLIST=`/usr/bin/find /Users -type d -maxdepth 1 -mindepth 1 -mtime +1`
for a in $USERLIST ; do
[[ "$a" == "$keep1" ]] && continue #skip admin
[[ "$a" == "$keep2" ]] && continue #skip admin2
[[ "$a" == "$keep3" ]] && continue #skip shared
[[ "$a" == "$keep4" ]] && continue #skip current user
# Log results
echo ${DATE} – "Deleting account and home directory for" $a >> "/Library/Logs/deleted user accounts.log"
# Delete the account
/usr/bin/dscl . -delete $a
# Delete the home directory
# dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }' | grep -v Shared | grep -v admin | grep -v admin1 | grep -v .localized
/bin/rm -rf $a
done
exit 0
view raw gistfile1.txt hosted with ❤ by GitHub
<?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">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>Label</key>
<string>edu.org.deleteaccounts</string>
<key>ProgramArguments</key>
<array>
<string>/Library/Scripts/delete-accounts.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>7</integer>
<key>Minute</key>
<integer>30</integer>
</dict>
<key>StartInterval</key>
<integer>86400</integer>
</dict>
</plist>
view raw gistfile2.txt hosted with ❤ by GitHub

The most important parts of that script are:

# Delete the account
/usr/bin/dscl . -delete $a

This deletes the cached Active Directory account from the system.

# Delete the home directory
/bin/rm -rf $a

This deletes the home folder, freeing up space for more accounts.

We noticed something strange, though. After a couple of weeks of usage, the iMacs in our public labs would freeze at random points: at boot, at login, when using applications, when logging out, even when shutting down. Here’s a list of things we noted while trying to resolve the issue:

  • We use Munki to deploy software, so one by one, we removed potential culprits from the manifests.  Eventually, we whittled down the manifest items to three things we could not remove from this particular lab: Microsoft Office, the Xerox printer driver, and Active Directory binding.
  • We investigated if this was an issue with our network, power, or Active Directory setup.  For a few weeks, all iMacs were plugged into UPSs.
  • We replaced all of the iMacs with brand new models – some with SSDs, and some not.
  • As this issue persisted over ~3 years or so, we tested against multiple macOS versions – including 10.9, 10.10, and 10.11 (and the minor versions in between).
  • We enabled OD debug logging, but couldn’t make much sense of the logs.  They were very, very verbose.
  • Ultimately, the best fix was to reimage the Mac.  This would hold off the freezing for at least another week or two.
  • The freezing seemed linked to computer usage.  If an entire lab was reimaged at the same time, the first Macs to freeze were located near the printers. During the summer, when usage was decreased, we rarely had reports of freezing issues in the public labs.

We were in the process of reaching out to our Apple Systems Engineer, when we found a long-running thread on Jamf Nation, detailing the exact problems we were facing.  It was a relief to see others were trying similar tactics, too.  Then, towards the bottom of the thread, Frank Kong noted that with every use login, some files were being left behind – and the script we were using did not clear those out.  In System Preferences > Sharing > File Sharing, you could see a long list of shares, all named things similar to “Mike Solin’s Public Folder”.  Bingo, there’s our culprit.

Alan Petty, in the same thread, added this code to his profile deletion script:

/usr/bin/find /private/var/db/dslocal/nodes/Default/sharepoints -name "*" -type f -delete
/usr/bin/find /private/var/db/dslocal/nodes/Default/groups -name "com.apple.sharepoint*" -type f -delete

We found this code can be run while a user is logged in, so we don’t need to exclude the current user from this part of the script. It will, however, delete all file shares present on the computer (whether they are for public folders or not). This isn’t an issue in our labs, but it’s still worth mentioning.

We’ve had this fix in production for just over a month, and I can safely say the freezing problems haven’t returned.

Long-term, it might be best to look into deleting profiles using a configuration profile – Marnin posted his here.  For now, we’re sticking with the script, as it gives us more control over where and when it runs.

Powered by WordPress & Theme by Anders Norén