SWY's technical notes

Relevant mostly to OS X admins

VPN Profiles at loginwindow under Yosemite

Unlike 10.9, Mac OS 10.10 has an unfortunate behavior regarding installing a Profile that configures a VPN while at loginwindow: it doesn’t work.  I’m not the first to find this, it was documented on munki-dev in October 2014.  I became aware of this when I ran my first out of box configuration after producing a working Profile and postinstall script for my SonicWall Mobile Connect VPN client, when the profile that had installed perfectly at testing via MSC, but looped endlessly at the end of the firstboot process.

To address this problem, it takes 3 steps:

  • Augment munki’s conditional items with a custom condition
  • Deploy that script to every client
  • Add that check to the pkginfo

The first involves adding a script to /usr/local/munki/conditions – any and all scripts that exist in that directory are executed in every munki run.  For this goal, we need a script that determines if there’s currently a user logged in.  If there is, the install should happen, and if not, don’t try.  Fortunately, this script had already been done and blogged by Patrick Fergus, and was the perfect starting point.  When run, (at every munki run), if a user isn’t logged in, it writes a key of false to /Library/Managed Installs/Conditional Items.plist, and true if they are.


plistLocation=/Library/Managed\ Installs/ConditionalItems

#Verify a user is logged in
loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'`

if [ ! -z "${loggedInUser}" ]
  defaults write "${plistLocation}" isUserLoggedIn -bool true
  defaults write "${plistLocation}" isUserLoggedIn -bool false

With that script written, the next step was to get every munki client to have it. My preferred route to this is via The Luggage, but with an addition: Mike Solin pointed me to a very useful bit of code to drop into /usr/local/share/luggage/luggage.local, which makes it quite easy to pack up both Munki conditional items and Outset scripts.  With that added to luggage.local, I could make the following Luggage makefile:

include /usr/local/share/luggage/luggage.make

With that makefile and the isUserLoggedIn.sh script in the same folder, a run of make pkg builds a package to be munkimported.  After distributing that package to all the machines I manage, it was a small matter of adding the following to the Profile installer’s pkginfo:

<string>isUserLoggedIn == TRUE</string>

With these parts, every time munki runs, it runs the above Python to ask if there’s a currently logged in user or not.  If yes, then it writes the key above to the Conditional Items.plist .  The installable_condition must match for the install to continue.  Therefore, when it first tries to run at loginwindow, Python has written the false key, the installable_condition isn’t met, and the endless cycle at loginwindow is avoided.  managedsoftwareupdate will soon do a background run while the user is logged in, and will then invisibly install the profile, and we have a configured VPN.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: