SWY's technical notes

Relevant mostly to OS X admins

Category Archives: Uncategorized

Spurious “you don’t have permission to use the application” errors

For far too long, I’ve been irritated with these digital rocks in my shoes, which would appear on wake from sleep, telling me I didn’t have permission for a wide variety of executables:

If you tried either kind of allow, you’d end up at an administrator credential request for Parental Controls.  Except this was going on with company owned machines- there were no Parental Controls in place, so things didn’t add up.

Thankfully, my friend Stephen Boyle answered my Slack query: check for an application restriction profile, and pull it.  Sure enough, I had a profile to prevent my users from attempting to install High Sierra. After pulling that profile, the rocks are out of my shoes.



A better way to update a DeployStudio .nbi

Earlier this week, my employer bought our first 2017 iMac, and the first new Apple hardware we’d purchased in quite some time.  My normal workflow is to boot a new machine to DeployStudio, where I do just a few tasks, such as machine naming, installing munki, installing a default manifest, and telling it to look for software on first boot.

I did a presentation about this a few years ago.

Since I hadn’t updated my DeployStudio netboot image in a while, I wasn’t shocked when the brand new hardware couldn’t be booted from a 10.12.2 image- the hardware is newer than that OS release, AND Apple has been doing forked builds for 2017 gear- OS releases tweaked for that hardware, instead of 1 Image to Rule Them All.  The result of trying to netboot the iMac from the older image is the “circle-slash” logo that means “not gonna happen”.

Fortunately, this turned out to be the day that 10.12.6 dropped.  Hoping that this would be a unified build, I updated my mac mini DS/Autopkg/other duties as assigned server to 10.12.6, to using the boot volume to generate a new DS .nbi.  When starting to make the image, I received the DS warning that the boot OS and recovery partition OS don’t match, and that this could be a problem.  This is expected behavior, as OS updates don’t bump up the version of the OS on the recovery partition.  I decided to roll the dice, and try making the DS netboot image despite the error.

When trying to boot from this one, the iMac got as far as showing the apple logo, but never a progress bar.  The DS OS version mismatch warning was a valid heads up.

My next effort was to get the recovery partition of my mini updated to  10.12.6. After getting in a fight with Create Recovery Partition Installer and discussing my experiences with the #deploystudio channel in the macadmins Slack, user maurits shared a great idea:

@swy: you try to create a 10.12.6 DSR .nbi? My tip: create an image using AutoDMG from the fresh Install macOS 10.12.6 app, mount this image, and use that as source for creating the .nbi . On the image (and thus on the mounted volume) there is a fresh 10.12.6 Recovery HD partition. Using updates, the Recovery is usually not updated.


This was great advice I wanted others to see.  If you wish to create the latest DeployStudio Runtime netboot image, get the latest Install macOS.app and AutoDMG.  Build a disk image, mount that image, and when you make the DS .nbi, choose the mounted disk to generate the NetBoot image from.

This worked perfectly, and I was able to netboot the iMac, install the basics, and have munki do the rest of the configuration automatically.

A fix for high idle CPU use in Outlook 2016 15.28

I recently noticed a displeasing behavior of Outlook 2016: while idle, in the background, it was taking up an unacceptable amount of CPU time:Screen Shot 2016-12-02 at 11.12.15 AM.png

I started digging around the #microsoft-office channel in the MacAdmins slack team, and was provided with this workaround that has solved it in every situation we’ve tried:

  1. Start a new email
  2. Click on the Options tab
  3. Click Language
  4. At the bottom, there’s an option for “detect language automatically”.  Uncheck this option.

I can only see a downside to this if you compose in multiple languages.

Credit to macadmin Michael Clark from Cisco for first posting this fix in Slack, and Paul Bernicchi for seeing my query and pointing this out.

Update 1: @mrexchange tells us we can expect to see this fixed soon- here’s the schedule for when it will hit the 3 tiers of Office releases:

just to confirm, the Outlook CPU issue is currently present in all channels. Here’s the schedule for when you’ll see it fixed:
Insider Fast – 15.30 on 12/7
Insider Slow – 15.29 on 12/5
Production – 15.29 on 12/13

Mounting a Synology SMB share as a local account

Earlier this month, I moved my munki repository from my Mac Mini server to web services on a Synology rackstation.  My biggest reason is for redundancy: the Syno has networking, power and drive failure redundancies beyond what a Mac Mini can provide.  However, one service that a Synology cannot provide is autopkg, which requires a Mac- therefore, the mini still has a use.

In order for the autopkg output to be directed into the Synology munki server, I configured the MUNKI_REPO string to point to the SMB mounted path: /Volumes/Synologyserver/munki/path .  To authenticate to that path, I made a local account on the NAS that the Mini would authenticate with.  Unfortunately, when I first tried to mount the path via the Finder, I could not authenticate properly- all efforts were rejected as invalid attempts, despite my most carefully audited text entry.

Eventually I realized the issue: the Synology was only searching the directory structure of the AD domain it was bound to, and was not looking at local accounts to validate the SMB connection.  In order to make it look at the local account, I needed to authenticate to the SMB share in the following format:


With the login in that format, the .\ indicates “use local directory, not a directory service”, and :* indicates “bring up the SMB server login window”.

In regret of Auto-VoIP

Due to a remodeling project at work, it came to be that I needed to provide temporary Ethernet drops to a lot of areas that weren’t designed to have a human and a VoIP phone sitting there.  To make this happen, we added 8 Netgear GSTP110TP switches to our network- PoE, managed, endorsed by a friend, and not expensive- as these are a temporary fix, not years of infrastructure to rely on.  Configuration was not complicated: each of these had to handle just the main wired client vLAN and the VoIP vLAN, so the task list boiled down to

  • Bring firmware current (who wants to troubleshoot something potentially fixed in last week’s update?)
  • Add the OUI for our Polycom phones, since that was not a vendor it recognized out of the box
  • Enable LLDP on ports 2-8 (1 was declared to be the uplink to the core stack)
  • Add vLANS to the switch, using the Voice VLAN option to match our VoIP vLAN and apply to all ports.

Soon we had streams of Cat5e running in all sorts of ways that would make any self-respecting admin hang his head in shame.

You don't really want to do this.

You don’t really want to do this.

Or this

Or this

During the setup, one other option caught my eye: “auto-VoIP”.  Per the Netgear documentation:

The Auto-VoIP automatically makes sure that time-sensitive voice traffic is given priority over data traffic on ports that have this feature enabled. Auto-VoIP checks for packets carrying the following VoIP protocols:

• Session Initiation Protocol (SIP)

• H.323

• Signalling Connection Control Part (SCCP)

• Media Gateway Control Protocol (MGCP)

Reading this, it sounded like a fine idea to enable this option, and that was done.  With the above configuration set, we started testing switches and plugging phones in, and all worked as expected.  LLDP allowed the switches and phones to establish that there was a device with a qualifying OUI attached to a port, and therefore put its traffic in the voice vLAN, and despite being a cabling mess, all seemed well with the world.

Then the tickets started trickling in- only from staff using phones attached to the Netgears:

  • Lost audio in one direction while on a call (call stays connected, voice transit suddenly became ONE direction only)
  • No dialtone
  • url calling disabled shown on the Polycom screen
  • More one-way audio issues

The events were unlike any other networking oddities I’ve tackled: sometimes they’d be magically fixed before my fellow IT staff or I could get down to witness them. We configured our PRTG monitoring to scan the VoIP subnet and start tracking if phones were pingable or not, and we ended up with 2 day graphs that showed that at approximately 24 hour-ish intervals, we’d loose connectivity with phones, in clusters, all members of the same Netgear.  They didn’t all go offline at the same moment, but a wave of failure would wash over the group: it might loose G2 at 2P, G3 at 2:04, G5 at 2:07, then G3 would work again, G4 would drop pings, G2 would start working… no pattern that we could see, just a wave of “nope, no traffic going to/from that phone” ranging from 2 to 20+ minutes, that would eventually resolve without our input.  Naturally, this never happened in the dark of night: there was the 2P cluster, the 3:45P cluster, and the 6P cluster.

With some guidance from our VoIP provider, we finally determined the culprit: Auto-VoIP.  While this might help improve the experience in high-traffic conditions where the voice device isn’t in a prioritized vLAN of its own (such as a small deployment, where this 8 port switch is the only switch), it’s not a benefit when there’s a dedicated voice vLAN that has its own prioritization rules.  Not only “not a benefit”, but enabling it caused one of the most unique network issues I’ve ever met. Since disabling auto-VoIP on all ports, this issue has not returned.

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.

Old NetExtender client is not supported yet (or, why VM’s are *usually* awesome)

I recently set out on a project to preconfigure the SonicWall Mobile Connect VPN client on the MacOS machines I manage.  As is now expected on MacOS, the proper route to accomplish this goal is with a Profile.  With some guidance via documentation shared by Eric Franklin, a Profile was generated via Profile Manager, and appropriate postinstall.sh for the munki installation was generated.  However, when I applied them to my testing VM and tried to authenticate, I got this very curious error message:

Pasted_Image_7_31_15__9_53_AMNoooo… I’m not asking you to do anything related to an “Old NetExtender”, this is the evolution from NetExtender into SonicWall Mobile Connect.  It seemed that the SWMC no longer needed an Admin to set things up, started a communications exchange with my SonicWall, but could never authenticate, only able to give the above alert.  After some fruitless Googling, a “what if?” hit me: “could this be behaving oddly because it’s a VM?”

Turns out, the answer is yes.  Installing SWMC from the Mac App Store and configuring it with a profile works exactly as would be hoped on real hardware, and gives a perplexing error when tested in a VM.  Virtual Machines are awesomely useful, until they give a goofy result that differs from the actual hardware you’d be deploying to.

Don’t test installers from a VMWare Fusion shared folder

As I prepared to upgrade my workplace’s Creative Cloud installations to CC 2014, I built a virtual machine in Fusion 6 using the same methods I would use to deploy a machine to a new creative hire- because snapshots make life easier for testing installs and configurations.  On a separate build machine, I grabbed Creative Cloud Packager, and used it to build an installer for the full suite.

In order to save time, I copied the CCP output .pkg to the same external USB3 storage as the VM, and used Fusion’s Shared Folders feature to share that directory.  The VM was happy to see the installer there, and run it from the GUI.  The install started out as normal, but unexpectedly halted with a “The installation failed, contact vendor for assistance” dialog.

I started digging into /Library/Logs/Adobe/Installers, and saw that Adobe InDesign CC 2014 10.0 <datestamp>.log was the most recently written to log, so I examined it for details about the fail.  Looking in the log, the following caught my attention

10/07/14 19:35:07:861 | [ERROR] |  | OOBE | DE |  |  |  | 63746 | DS015: Unable to read symlink target of source file “/Volumes/VMware Shared Folders/SeagateUSB3/Adobe CC 2014-all but Acrobat/Build/Adobe CC 2014-all but Acrobat_Install.pkg/Contents/Resources//Setup/IDSN10.0en_US/payloads/AdobeInDesign10AppBase-mul/OEM_/Adobe InDesign CC 2014/Plug-Ins/InCopyWorkFlow/Assignment UI.InDesignPlugin/Assignment UI”(Seq 11962)

So I see we couldn’t find the target of a simlink.  Digging down that path in the pkg from the VM, we see

Screen Shot 2014-10-09 at 4.39.01 PM

Yep, Assignment and Resources are broken.  So what if we look at the same path from the mac that hosts the VM?

Screen Shot 2014-10-09 at 4.42.27 PM

Assignment has the same icon, but if I follow the symlink while viewing the content in the host OS, it resolves to:

Screen Shot 2014-10-09 at 4.47.52 PM

You can see the icon difference between Resources, and it too works.

To move on, I copied the .pkg onto the VM’s boot disk, which had to be done via an AFP share- a copy from the shared folder failed with an Error 41.  That copied pkg installed without errors.

Bottom line: things can go wrong with your testing VM if your source .pkg is stored on a shared folder in VMWare Fusion.

iOS8 Family Sharing with an Apple ID for a child

It’s a happy coincidence that my < 13 year old kid accumilated the savings to buy the iPod Touch he’s wanted right as iOS 8 with Family Sharing hit the market.  Here’s my experience with the process:

1) Upgrade a device of mine to iOS8.  Pretty straightforward process- but always make a backup anyway.

2) In Settings: iCloud, there’s now a new “Set Up Family Sharing…” link2014-09-17_16_09_38



3) Since my kid is under 13, the “Create an Apple ID for a child” option is the right choice:



4) Yep, this seems like exactly what I want:



5) But this isn’t.  I have my own domain. I don’t need a proliferation of email addresses.  Even if email is mostly dead to young people these days, and full of spam, email still isn’t going away.  Oh well, the THOU SHALT USE ICLOUD DOMAIN rule appears to be non-negotiable, so I begrudgingly complied.



6) After the standard, mandatory Security Questions (should I answer for me? For him? Must be me, since he couldn’t yet have a favorite singer in High School), I can enable Ask To Buy.




7) With that, my kid has an Apple ID.  The next day, his iPod Touch arrives, and out of the box, we attempt to authenticate with the new Apple ID.  Being a refurb, and day 1 after iOS 8 release, it ships with iOS7.  I’m not sure if that’s the cause, but when trying to use his new Apple ID, we get the most confusing error dialog I’ve ever received from an Apple product.  And I’ve received a few.


I eventually gave in on trying to authenticate with his Apple ID, it consistently gave the above.  I signed in with my ID, attached to iTunes, and started downloading the iOS 8 update.  Following that install, I signed out, and now it was happy to accept his Apple ID credentials on the first try.


8) With that configured, it was time to see the electronic  “please dad, may I have an app?” conversation.  The Buy button gets a new behavior in this situation:



And promptly over on my device, I see an alert from Family, which links to this page in the App Store:




9) I approve and authenticate to the App Store, and with this, the installation proceeds on his Touch:


Just because it isn’t logged…

… doesn’t prove it’s not working.

With the release of iOS8 this week, I wanted to make use of Caching Server on work’s guest WiFi, as I figure I’ll have a few early adopter staff looking to upgrade their personal devices.  In my setup, the guest SSID is tagged with a VLAN, which is routed straight out to the internet.  My Caching Server had no connection to that VLAN, so the first step was to add that VLAN to the switch port the OS X Server running Caching Server was connected to.

With the Guest WiFi VLAN now available to the Caching Server, it needed a new network interface associated with that VLAN.  That is done via System Preferences: Network: Gear button: Manage Virtual Interfaces:




Screen Shot 2014-09-16 at 9.52.16 AM

Then the [+] to Add a new VLAN:

Screen Shot 2014-09-16 at 9.53.29 AM

Name it usefully, associate it with the proper tag and interface for your environment (probably Ethernet), and [create].

With this, my new virtual interface came up with an IP on the Guest wireless subnet, as would be expected.

Per OSX Server documentation, the default behavior for Caching Server is to listen on all interfaces.  To confirm this was happening, I put Caching Server into verbose mode via

sudo serveradmin settings caching:LogLevel = verbose

And restarted the service, while tailing /Library/Server/Caching/Logs/Debug.log .  This is where I got concerned: the log only acknowledged “registering” on the local subnet, with no mention of the VLAN network.  After some troubleshooting, I was able to confirm it really was listening on the VLAN, by noting what port the HTTP server was started on (as listed in the log), and pointing a browser from a machine on the Guest WiFi to that Caching Server:port combination.

When you do this, the client browser will return a blank page, and Debug.log on the Caching Server will record a Error 400 – Bad Request from that source machine, citing a non-whitelisted URL.  This confirms that the service is listening on the added VLAN, despite not being mentioned in the verbose log.  Therefore, the documentation is correct: unless overridden, Caching Server is active on all interfaces. Don’t let the fact that the log doesn’t acknowledge multiple interfaces bother you, as I did.

If you wish to use Caching Server for multiple networks in this way, it’s important to make sure they both appear to the internet from the same WAN IP.  Caching Server will only be available to clients that contact Apple from the same network that the Caching Server did.


And then it turns out that Caching Server can’t/won’t/doesn’t cache iOS8.  Sometimes you just can’t get ahead of the game.