Preventing alarms from going off on MDM’ed iPads

If you have alarms set on iPads (either an actual alarm or an alarm from the "bedtime" portion of the Alarm app), you can't disable the alarm by blocking the app. All blocking the app does is prevent the user from launching up the app.

To prevent the alarm itself from going off, you have to block notifications from the Clock app.

Bulk-extracting and combining audio from .mov to .mp3

If you aren't able to use an audio recording app on your iPad for whatever reason and need to resort to using the Camera app to record audio (long story), you will get a bunch of .MOV files.

So I wrote up a script that employs ffmpeg to extract just the audio from each file in a subdirectory, and then combine the separate audio files from that subdirectory into one audio file.

Script here:

CrashPlan 6.5 stuck on Connecting… and never times out

We had a couple of clients who would just never do an initial connection to CrashPlan after the upgrade from CrashPlan 4 to CrashPlan 6.5. But they would never time out or give an error message either.

Restarting the CrashPlan service didn't help. Restarting the computer didn't help. Uninstalling and reinstalling the client didn't help.

Turns out it if the detect-a-user script can't find a CP_USER_HOME, it will just keep trying to connect instead of erroring out. We modified our script, and now those clients are good (we did have to uninstall and reinstall the client after modifying the script, though).

P.S. Someone pointed out that I don't actually share the original or modified script. The point of this blog post isn't to say "Here's a script that works." There are lots of scripts that work. The point is more that if you're experiencing this issue ("connecting" and never timing out or providing an error message), you likely need to fix your script to output a CP_USER_HOME).

Considerations when upgrading CrashPlan with Munki

I had a great workflow for installing CrashPlan with Munki for older versions of CrashPlan (we were on versions 3 and 4 before).

We recently made the jump to CrashPlan 6.5, though, and that workflow no longer applies. Now you have to use a file instead of and files.

We had some added complications to our "upgrade" process, because our new CrashPlan server is a completely different server, and we weren't migrating everyone at once, so we couldn't just change the DNS to point to the new server. I'm not sure a jump from 4 to 6.5 would have been possible as just an installation upgrade anyhow.

So what were those complications?

  • We couldn't use an installs array any more to tell Munki whether CrashPlan was installed or not. Keeping the installs array would (without managed_updates) prompt users to upgrade to CrashPlan 6.5 or, worse, just upgrade them automatically (with managed_updates). So I changed CrashPlan 4 and 6.5 to use an installcheck_script instead.
  • Since CrashPlan 6.5 isn't just an update but an actual upgrade for us (think Microsoft Office 2016 vs. Microsoft Office 2011), it's a separate item in Munki altogether, which means we also had to remove the old version from the client's SelfServeManifest before installing the new version (otherwise, the old version would just reinstall).
  • Likewise, as part of the preinstall_script for 6.5, we had to invoke the /Library/Application Support/CrashPlan/ script to remove 4 first.
  • Lastly, we had to have a temporary place to hold the file before copying it to /Library/Application Support/CrashPlan—otherwise, the old installation of CrashPlan would somehow make it disappear or be unusable by the new installer. Not sure exactly what was happening, but it wasn't being recognized when just being delivered there directly as a payload. We also tried including the file in the .dmg itself, but that didn't work either (prompted for server and registration key).
  • Annoyingly, if you choose not to use SSO, you can't fully automate user account creation or sign-in, so some user interaction for the upgrade is required.

Ours may be a very niche scenario (upgrading from CrashPlan 4 to CrashPlan 6.5 and not using single sign-on), but in case anyone else is in that same situation and using Munki, maybe this blog entry can save you some time in planning your rollout.

Getting the Team ID of kernel extensions in macOS 10.13 (and higher?)

Why do you need Team IDs?

Beginning with macOS 10.13 (High Sierra), Apple is now blocking kernel extensions unless you, in recovery mode (or recovery mode–like environment), change the policy on the machine itself or use an MDM profile to approve certain KEXTs by Team ID.

How do you find these Team IDs, though?


One way is to install the KEXTs on a 10.13 machine, user approve them, and then check the sqlite database to see what the Team IDs are:

sqlite3 /var/db/SystemPolicyConfiguration/KextPolicy
SELECT * FROM kext_policy;

Here's an example of some of the output you might see:

EQHXZ8M8AV||1|Google, Inc.|8
In this example, EQHXZ8M8AV is the Team ID and is the bundle ID.

You can use Control-D to exit the sqlite3 session.

Acknowledgements: Got commands from Enabling Kernel Extensions in High Sierra


Another way is to run this command on an existing bundle from the vendor:

codesign -dv --verbose=4 /PATH/TO/

For example, if you run

codesign -dv --verbose=4 /Applications/Google\ Drive\ File\
you should see in the output a line like

This approach can be helpful in fringe cases (you just need the Team ID and not the bundle ID, which may be the case, and the KEXT you're looking for has an associated bundle you can run codesign on.

Acknowledgements: Got command from MunkiReport-PHP extensions module

Isn't there a list somewhere of all these Team IDs?

There is a list, actually. There's a spreadsheet that a bunch of Mac admins are sharing with each other. Unfortunately, at this point, it's a spreadsheet that anyone with the link can edit, so I wouldn't really count on that. At this point, I don't see anything malicious in there (and I haven't verified every single Team ID, of course), but I would probably play it safe and just get the Team IDs yourself. Chances are that you'll have to do it only once or twice a year at the most.

Selecting a startup disk when you put a firmware password on a Windows single-boot Mac

Usually, when you put a firmware password on a Mac, you can double-check in System Preferences > Startup Disk to see if the proper startup disk (or any startup disk) is selected.

Since the default behavior of the firmware password is you needing to enter the password in order to boot from anything other than the startup disk, you probably want to have a startup disk selected (otherwise, you'll get the folder with a question mark inside of it when you boot up).

In most cases, this isn't that difficult, but if you set up a single-boot Windows installation, you may not always see it available for selection if you boot to recovery mode or boot to macOS from an external drive.

Instead, you may want to just boot into Windows (hold down the option key and enter the firmware password if you need to this one time), and then launch up the Bootcamp Control Panel, and you can set the startup disk there.

BlacklistRegex and WhitelistRegex on Santa


Thanks once again to @bur on the Mac Admins Slack for the info I'm documenting here.

BlacklistRegex and WhitelistRegex

In a previous blog entry, I talked about using Santa to block apps by certificate (and I briefly mentioned blocking by binary).

You can also block by path using regular expressions. Binary takes precedence over certificate, which takes precedence over regex, so unfortunately you can't really block Apple apps (like Safari) using regex, because Santa automatically whitelists them by certificate—you can block them only by binary.

You may notice in the Santa documentation for configuration that both WhitelistRegex and BlacklistRegex are listed as string types instead of arrays of strings. That is absolutely true, so if you wanted to whitelist a whole bunch of app paths, you'd have to have a massively long string like this:

<string>^(?:/Applications/Adobe Acrobat DC)/.*|^(?:/Applications/LockDown*|^(?:/Applications/Microsoft*|^(?:/Applications/Microsoft*|^(?:/Applications/Microsoft*</string>

Same deal for a BlacklistRegex string.

Create a .mobileconfig profile for a certificate

If you want to create .mobileconfig profile from a certificate (for example, to import into Munki), you can use Apple Configurator 2 to do so.

If you have your certificate already in your keychain, launch up Keychain and find the certificate you want to make into a .mobileconfig profile.

Right-click the certificate and select Export NAMEOFTHECERTIFICATE (export it as a .cer).

Then launch up Apple Configuration

Select File and then New Profile

Select Certificates and then Configure.

Find and select the certificate you exported earlier.

Select File and then Save.

Pick a filename for your .mobileconfig, which you can deploy however you want (as I previously mentioned, you can import this into a Munki repo).

Using Santa to block an .app


Special shoutout to @bur on the Mac Admins Slack for help with some command-line syntax.

Santa can be complicated, but doesn't need to be

Google has a project on GitHub called Santa, which is quite powerful and complicated. As the project's readme says, though: Documentation: This is currently limited..

I just wanted to do something simple: block an app, but I didn't see any straightforward documentation on how to do that. The closest I could find was the docs on certificate rules, but that was a bit incomplete.

So, first of all, something I was confused about at first was whether a configuration profile was necessary or not. It is not necessary. There are some default settings that just go by themselves. You need to configure settings only if you need to configure settings.

Blocking an app by certificate

If you have a blocking application rule, you can block by binary or by certificate. By binary may not be as helpful, because newer versions of an app will be a different binary. Let's say you want to block MacKeeper by certificate. (Install Santa first, so you can actually use it, including the santactl command.)

santactl fileinfo /Applications/ --key "Signing Chain"
Signing Chain:
1. SHA-256 : 2df1460a9c76c4a63fa2d0d043fb0254f8fa69a99374f2a0b1e8eee885872614
SHA-1 : 2664b71c3db787226ff9715da4de32e9ad3e364f
Common Name : Developer ID Application: KROMTECH ALLIANCE CORP. (64424ZBYX5)
Organizational Unit : 64424ZBYX5
Valid From : 2013/10/14 04:00:13 -0700
Valid Until : 2018/10/15 04:00:13 -0700

2. SHA-256 : 7afc9d01a62f03a2de9637936d4afe68090d2de18d03f29c88cfb0b1ba63587f
SHA-1 : 3b166c3b7dc4b751c9fe2afab9135641e388e186
Common Name : Developer ID Certification Authority
Organization : Apple Inc.
Organizational Unit : Apple Certification Authority
Valid From : 2012/02/01 14:12:15 -0800
Valid Until : 2027/02/01 14:12:15 -0800

3. SHA-256 : b0b1730ecbc7ff4505142c49f1295e6eda6bcaed7e2c68c5be91b5a11001f024
SHA-1 : 611e5b662c593a08ff58d14ae22452d198df6c60
Common Name : Apple Root CA
Organization : Apple Inc.
Organizational Unit : Apple Certification Authority
Valid From : 2006/04/25 14:40:36 -0700
Valid Until : 2035/02/09 13:40:36 -0800

Then, add a block rule for it:

sudo santactl rule --blacklist --certificate --sha256 2df1460a9c76c4a63fa2d0d043fb0254f8fa69a99374f2a0b1e8eee885872614

You can always check on the other parameters by running

sudo santactl rule
which will output something like this:
No state specified

Usage: santactl rule [options]
One of:
--whitelist: add to whitelist
--blacklist: add to blacklist
--silent-blacklist: add to silent blacklist
--remove: remove existing rule
--check: check for an existing rule

One of:
--path {path}: path of binary/bundle to add/remove.
Will add the hash of the file currently at that path.
Does not work with --check. Use the fileinfo verb to check.
the rule state of a file.
--sha256 {sha256}: hash to add/remove/check

--certificate: add or check a certificate sha256 rule instead of binary
--message {message}: custom message

If you then try to run MacKeeper, you'll get a block message like this:

That's pretty much it. That isn't everything Santa can do. That's about the simplest thing you can do with Santa, but most of the documentation for Santa is about all of the other stuff you can do. I didn't see much about just how to simply block an .app, hence this blog post.