Using the personal recovery key to unlock/reset a user password on a FileVault-encrypted Mac

In a previous blog post, I wrote about Why you should use FileVault personal recovery keys instead of institutional recovery keys.

If you have a personal recovery key, this is how you can use it to unlock a FileVault-encrypted machine that's been reboot (useful for organizations that doesn't have their local admin accounts as FileVault-enabled ones) or how you can use it to reset a user's forgotten password. The steps for both procedures are very similar and differ only at the very end.

When you boot up the Mac and get to the FileVault prompt for the user, click the question mark button next to the password field.

Then, click the arrow next to If you forgot your password, you can reset it using your Recovery Key.

You'll then be prompted to enter your recovery key.

Go ahead and enter the recovery key when prompted. It won't be the one you see in the screenshot. It'll be one that you have escrowed somewhere (Crypt Server, your MDM, MunkiReport, etc.). And, don't worry—that recovery key is for a VM'ed Mac, and I rotated the key to be a new one anyway.

Wait for macOS to boot up.

At this point, the procedures for "unlock a machine that you want to reboot but don't know the user password to" and for "user has forgotten her password and needs a new one" diverge.

If the user has forgotten her password, have her simply enter a new password, verify it, and then click Reset Password.

If you just wanted to unlock the encrypted computer so you can log into another account (e.g., local admin that isn't a FileVault-enabled user), click Cancel, and you can log into another account on the computer.

Finding 32-bit applications on Macs

In macOS 10.13 (High Sierra), Apple started warning users about 32-bit applications by saying those applications were "not optimized" for their Macs. The warnings continued in macOS 10.14 (Mojave). Starting with macOS 10.15 (Catalina), 32-bit applications will cease working altogether.

Hopefully, vendors still producing 32-bit applications for Macs will get their acts together and create 64-bit versions soon.

In the meantime, you might want to check your Macs for what 32-bit applications they have installed so you can pressure vendors to update their apps, start looking for 64-bit alternatives to those apps, or consider whether you even still need to use those apps.

Checking for 32-bit apps on an individual machine

I'm not sure how useful this would be to Mac admins, but you can check for 32-bit applications on a single machine by going to System Information.app

Then scroll down on the left side to find, under Software, Applications.

It might take a while for the list to load.

Once the list is loaded, you can sort by 64-bit (Intel), and then sort again, so all the No entries are at the top.

Checking for 32-bit apps for multiple machines via MunkiReport

If you're using Munki and MunkiReport, you can go to Listings > Applications to see which apps in your fleet are 64-bit or not.

If you want to query the MunkiReport database directly, you can also run

SELECT DISTINCT path
FROM applications
WHERE has64bit=0
ORDER BY name, path
and that will give you only distinct results. You could go distinct with name instead of path if you don't want the actual name of the app bundle but just the name of the app.

Acknowledgements

Thanks to eholtam and gmarnin on the MacAdmins Slack for pointing me to the right place in MunkiReport.

TCC in Mojave doesn’t prevent deleting local folders for AD-bound Macs

Note: We're currently using a setup of Force local home directory on startup disk for AD-bound Macs instead of Create mobile account at login or Use UNC path from Active Directory to derive network home location—so if you're using either of those other options, your mileage may vary—definitely do some testing! This is also as of 10.14.5 (Mojave); Apple very well may change things for 10.15 (Catalina) and beyond.

I was worried that TCC would mean we wouldn't be able to delete local home folders for AD users without jumping through some code signing hoops, but apparently a regular old

/bin/rm -rf /Users/USERNAME
command in a root-run script seems to do just fine there, whereas it would choke on a regular (non-AD) user with an Operation not permitted TCC error

If you do need to code-sign a script, though, eventually, you may want to have a look at Code Signing Scripts for PPPC Whitelisting. It has a detailed walkthrough using Outset as an example.

Reinstall macOS using installr

Now that Mac imaging is essentially dead and the new T2 chips make it more complicated to boot from external drives, reinstalling macOS to re-deploy a Mac can be a bit trickier.

installr is a tool to do a clean reinstall of macOS via recovery mode (and install additional packages, too, if you'd like).

The actual usage of installr is fairly straightforward and explained well in its README on GitHub.

Here are a couple additional notes from my own testing on a late 2014 Mac Mini, though...

Listen to the README on http vs. https

https is definitely not something you can rely on if you're using installr over the network. If you try to serve up the installr.dmg over https, and then attach it via recovery mode, you may get this as a response:

Usage: hdiutil attach [options] <image>
       hdiutil attach -help

One more step for FileVault-encrypted drives

Installr will prompt to erase the drive before installing macOS, but you installr won't see drives that are unmounted, so if the drive you're trying to reinstall macOS on is an encrypted drive, you'll either have to unlock/mount the drive first... or erase it first.

Once the drive is mounted, installr will recognize it (and prompt you to erase it again).

installr from USB not that much faster than over network

Using installr over USB (even from a portable SSD) doesn't make the re-installation process go much faster.

When I ran installr of http (over wireless), it took 4 minutes and 27 seconds from confirming erasure of the drive to the installer finishing and then needing to reboot to complete the installation.

When I ran installr off a USB portable SSD, it took 1 minute and 48 seconds from confirming erasure of the drive to the installer finishing and then needing to reboot to complete the installation.

So, it's a difference of less than 3 minutes. When you still have another 17 to complete the installation after that, 3 minutes is not a huge gain for choosing USB installr over http installr, but that small gain is something to consider when choosing how you decide to use installr in your own environment.

One huge advantage to using http is having the installr files or disk images in one place instead of a variety of USB drives. How you choose to use installr will greatly depend on the needs and means of your organization.

What the installr process looks like in Recovery Mode

To run installr, you might have to boot into Recovery Mode (especially on a T2 Mac), as opposed to running it from an external drive.

As I mentioned before, erasing the drive ahead of time isn't strictly necessary (it may be a FileVault-encrypted one), so if the drive is already mounted and isn't encrypted, you can skip launching Disk Utility.

If you did have to go through all that to erase the disk first, go ahead and Quit Disk Utility.

Go to Utilities > Terminal

In this example, we're running the http installr instead of the USB one, but either way, you're going to end up doing some version of

/Volumes/install/run

Once the first part of the installation process finishes, your Mac should automatically reboot and finish the rest of the installation of macOS.

Once it's done, you should be at the start of Setup Assistant.

Google Forms preview gives “resource unavailable” error message

We had a situation in which someone created a Google Form and the preview for it would always come up with a resource unavailable error.

This wouldn't happen for any other form. And it wouldn't happen on another computer.

Clearing the cache didn't fix it, but clearing just Google cookies did fix it.

Something definitely worth trying, since most of the results for this indicate a problem with the Google Docs service being down and nothing to do with cookies being corrupted.

Changing the boot order on a VM in vSphere

If you want to change the boot order on a virtual machine in vSphere, it's not a setting in the vSphere interface. You have to force it to bring up the BIOS menu, and then change the order in the BIOS once you've booted up the VM.

Go to Edit Settings > Options > Advanced > Boot Options > Force BIOS Setup and check The next time the virtual machine boots, force entry into the BIOS setup screen

That setting will automatically revert to being unchecked once you've booted up the machine once with it on.

Let’s Encrypt certificate “expired” even though it’s not?

One of our servers (Ubuntu 18.04 with Nginx) is using Let's Encrypt's certbot to renew its SSL certificate regularly via script. Recently, it reported in web browsers as having an expired certificate. When I ran

certbot renew

it showed as having the certificate set to expire months from now.

Just on a lark, I rebooted the server, and then it was fine, and the web browsers showed the new certificate. Usually, a reboot isn't necessary. I'm not sure why it was all of a sudden this time. But just FYI: if you're using Let's Encrypt to renew your site's certificate, and it's definitely renewed but randomly not showing that way to client machines, try a reboot.

Using GAM to delete erroneously sent emails

Sometimes someone sends an email and wants to unsend it. It doesn't happen very often, and usually there isn't much you can do about if the email has been sent to an external recipient. If your organization uses G-Suite, though, you can delete internally sent emails. Just be careful. And also know that it's still possible that the recipient may see the deleted message anyway.

First, install GAM or Advanced GAM if you haven't already.

Then you can search for the message:

gam user recipient@school.edu delete messages query 'subject:"Totallyatestmessage"'
Searching messages for recipient@school.edu
Got 1 messages for user recipient@school.edu
would try to delete 1 messages for user recipient@school.edu (max 1)
Once you're confident that's the message you want, append doit to the command to actually delete the message:

gam user recipient@school.edu delete messages query 'subject:"Totallyatestmessage"' doit
Searching messages for recipient@school.edu
Got 1 messages for user recipient@school.edu
delete 1 messages
delete 1 of 1 messages

This won't move the message to the trash. It will straight up delete it. (There are options to just trash a message, though.)

Based on some testing I did, if you have Gmail set up in an external email program, the preview of the message may still be there, even after the message is deleted.

Once you delete it, the cached message will remain in the external email program for a while. If you tap on the cached message, you see the body of the message for a split second, and then the whole message disappears.

P.S. A previous version of this didn't have single quotes around the subject. Kudos to Stace Felder for doing testing on this and finding that without the single quotes, GAM won't look for a subject with that exact string—only subjects that have all the words.

Dealing with iCloud accounts on DEP-enrolled iOS devices

I'm not sure how many other schools deal with this, but we found out something rather curious the other day, and it's been confirmed by Mosyle (our MDM) and a couple of folks on the MacAdmins Slack.

My understanding was that a DEP-enrolled MDM'ed iOS device would not allow an iCloud account (regular Apple ID, not a managed Apple ID) to be locked to it. In other words, you can sign in with an iCloud account, but anyone can just sign out of it without a password. That behavior would totally make sense (after all, it's not your device—it's the organization's, and it's a supervised device).

Apparently, that's not actually the case at all.

If you sign in with an iCloud account, you cannot remove the account without getting the password to the iCloud account or wiping the device.

One additional weird piece to this is that even though you can't sign out of the iCloud account without a password, you don't actually need the activation lock bypass code after a device wipe. It just re-enrolls in the MDM via DEP. So the iCloud account is locked to the device (until you wipe it), but the device itself isn't activation locked.

That may be fine if you're in a school-owned one-to-one iPad program: Student shows up first day of school, gets a DEP-enrolled iPad, signs into her iCloud account, uses it the whole year, and then the school's tech department wipes it at the end of the school year.

However, we have at the moment a one-to-one bring-your-own-iPad program, and so the school-owned iPads are for special temporary uses (in carts for certain academic programs, as short-term loaners in certain circumstances). So allowing students to sign in with iCloud accounts can be really inconvenient.

The only options we have are:

  • Let people sign into their iCloud accounts and then track them down later to remove their accounts. (A lot of tracking down of people.)
  • Pre-emptively sign into a generic iCloud account to prevent others from signing into their own iCloud accounts. (A lot of manual labor.)
  • Preventing all account sign-ins via MDM restriction. (This also shuts down the ability for people to sign into Mail or Google Apps, though, so it's a non-starter.).
  • Wipe the device every time there's a lock.
Right now, it's looking as if the last option is the least worst option. Not sure how many other schools are in this sort of situation, but until Apple changes the MDM spec, that's what we have to deal with.

Referencing a PHP variable by using another variable as part of the name

This is kind of a niche scenario, but when you Google making a variable from another variable php, most of the examples involve using a double dollar sign, which may not be what you want to do.

Yes, whenever possible, it makes sense to use arrays instead of weirdly-constructed variable names, but that may depend on the type of data you're working with and how it's stored in the (possibly legacy) database.

$variableaspartofname=1;
${'firstpartofname_'.$variableaspartofname.'_lastpartofname'}='whatevervalueyouwanttoassign';
That's it. If you do that, it will assign whatevervalueyouwanttoassign as the string value to a variable called $firstpartofname_1_lastpartofname.