Categories
Mac admin'ing

A way to install macOS Catalina guest on VirtualBox on a Mac host

Why this blog post?

I won’t say this is the way to install macOS Catalina on VirtualBox, but it’s certainly a way, and it’s difficult to find information about a way to do it. There are a lot of posts indicating that 10.15 or 10.15.1 worked but 10.15.2 and beyond don’t. Or that there are difficulties with VirtualBox and APFS. There are also, if you look for blog posts about macOS guests, many blog posts about Apple-unsanctioned “hackintosh” setups on Windows or Linux hosts.

So there may be a way easier way to set up Catalina as a guest on a Mac host, but at least this is something (happy to link to better tutorials if people post them).

Install macOS High Sierra

I did a modified version of How to Install macOS High Sierra in VirtualBox on Windows 10 to get High Sierra installed on VirtualBox. These are the key parts:

Creating the .iso

hdiutil create -o /tmp/HighSierra.cdr -size 7316m -layout SPUD -fs HFS+J
hdiutil attach /tmp/HighSierra.cdr.dmg -noverify -nobrowse -mountpoint /Volumes/install_build
asr restore -source /Applications/Install\ macOS\ High\ Sierra.app/Contents/SharedSupport/BaseSystem.dmg -target /Volumes/install_build -noprompt -noverify -erase
hdiutil detach /Volumes/OS\ X\ Base\ System
hdiutil convert /tmp/HighSierra.cdr.dmg -format UDTO -o /tmp/HighSierra.iso
mv /tmp/HighSierra.iso.cdr ~/Desktop/HighSierra.iso

Creating the VM

Call the VM macOS (the tutorial says to use High Sierra, but we’ll be upgrading this later). Use two processors and 128 MB of video memory. Add the .iso to the optical drive part of storage.

Configuring the VM

Run these commands:
VBoxManage.exe modifyvm "macOS" --cpuidset 00000001 000306a9 04100800 7fbae3ff bfebfbff
VBoxManage setextradata "macOS" "VBoxInternal/Devices/efi/0/Config/DmiSystemProduct" "MacBookPro11,3"
VBoxManage setextradata "macOS" "VBoxInternal/Devices/efi/0/Config/DmiSystemVersion" "1.0"
VBoxManage setextradata "macOS" "VBoxInternal/Devices/efi/0/Config/DmiBoardProduct" "Mac-2BD1B31983FE1663"
VBoxManage setextradata "macOS" "VBoxInternal/Devices/smc/0/Config/DeviceKey" "ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc"
VBoxManage setextradata "macOS" "VBoxInternal/Devices/smc/0/Config/GetKeyFromRealSMC" 1

Installing High Sierra

The tutorial mentions having to deal with the EFI Internal Shell. You shouldn’t have to. Installing High Sierra at this point with HFS+ (not APFS) should work.

Upgrading to Catalina

Once you’ve booted up to Setup Assistant and answered all the questions, you should be logged in and able to go to the Mac App Store to download and install the macOS Catalina upgrade.

Booting to recovery mode

I didn’t find Cmd-R to be a very reliable way to boot to recovery mode. And Rich Trouton’s trick to booting to recovery mode using VMWare doesn’t really apply to VirtualBox.

Another blog post (How to boot into recovery mode on mac without holding Command + R Key on keyboard ?) did have the solution, though. Just run
sudo nvram "recovery-boot-mode=unused"
and then reboot. That will do a one-time boot to recovery mode. Then when you reboot again, it should boot back to regular mode.

Enabling FileVault… sort of

If you want to enable FileVault, you’ll have to do so from the command-line (it’ll be greyed out in the GUI), but FileVault will basically be unusable (unless you just want to test in recovery mode):
sudo fdesetup enable
Don’t do this unless you already have your VM snapshotted or backed up. It will likely make your VM unbootable.

Changing the serial number

By default, the macOS VirtualBox guest serial number is 0, but you can change it (make sure the VM is powered off first). h/t to Utsav Dusad on Superuser.com:
VBoxManage setextradata "macOS" VBoxInternal/Devices/efi/0/Config/DmiSystemSerial "ACTUALSERIALNUMBER"

Categories
Mac admin'ing

What can you do at the password prompt in Catalina’s recovery mode?

The mysterious password prompt

Starting in macOS 10.15 (Catalina), Apple started requiring a password to do anything useful after booting into recovery mode:


It’s not exactly clear what this password is for. T2-chip Macs have hardware-based encryption, and that encryption is able to turn on instantaneously. Without mounting the encrypted drive, you can’t really reset a password or have access to the data on the drive. This prompt just seems like a rather odd choice, especially since it appears to act as almost some kind of firmware lock… except it’s not.

Option 1: Erase without password or recovery key

If you don’t know the password to a user account and also don’t know the recovery key to FileVault, you can still use recovery mode to erase the current installation and reinstall macOS. Yes, that’s that menu item hidden in the top-left corner.


You can just click Recovery Assistant and then select Erase Mac….

You’ll then be prompted to join a wireless network, and then some kind of Internet recovery is downloaded and booted to, and then you’ll be back at recovery mode with a prompt to activate your Mac, and then with the opportunity to reinstall macOS on the freshly wiped drive.

Option 2: Use FileVault recovery key with no password

But let’s say you don’t want to wipe the drive necessarily—you just want to do other recovery mode stuff, and you don’t know any user passwords. Well, you can click Forgot all passwords?

Then you can enter the FileVault recovery key for the drive.

Option 3: User FileVault-enabled user password

And if you do know a user password, of course, you can select the user, and then enter a password when prompted.

The only odd thing about that is it doesn’t actually get you past FileVault encryption.

That’s right. Even though you’ve entered a user password, if you want to mount the Macintosh HD – Data partition, you’ll still be prompted for a FileVault-enabled user’s password again.

Categories
Other Computer Stuff

Changing ownership of files in Google Drive via Google Apps Script

This was a fun little exercise in Google Apps Script to essentially transfer ownership of Google Drive files from one user to another.

Here’s a script that the old user should run to change ownership of those files to the new user:
ChangeFileFolderOwnership.js

And here’s a script that the new user user should run to remove the old user as editor from the newly changed-ownership files:
RemoveEditorFromDriveFiles.js

Note: You cannot use the file.removeEditor() command to remove yourself as an editor, so that actually has to be run from the new owner’s account.

Another Note: Just as when you change ownership or add editorship manually, scripting will also produce a ton of emails to the new editor/owner that you’ve add that person, so the new editor/owner may want to set up some temporary Gmail filters to mark those as read and put into the trash.

Categories
Mac admin'ing

Fixing Jamf device signature error

Even though this Jamf Nation thread is five years old, as of this writing, it’s still got the solution to the Device Signature Error - A valid device signature is required to perform the action error message.

In my experience, the actual working solution is to run sudo jamf enroll -prompt and then enter credentials when prompted. Repeatedly running sudo jamf recon (even after a reboot) or sudo jamf policy doesn’t fix the issue, nor does verifying that the system clock time is correct.

Now why this comes up in the first place on a freshly factory-reset computer that DEP-enrolled in Jamf—who knows but Jamf?

Categories
Mac admin'ing

Running commands as a user when scripting for Munki or Jamf

Munki and Jamf run as root, so scripts they execute execute as root, not user.

One great way around this is to use Outset‘s login scripts (login-once, login-every), but sometimes you may have occasion to actually run a script immediately as the logged-in user.

Obviously, you’ll want to get the currently logged-in user into a variable you can use—several methods for that are described in How To: Get the currently logged in user, in a more Apple approved way—and you’ll want to watch out for the “logged in user” being _mbsetupuser, root, or just blank.

Then, you can use su to substitute a user identity:
/usr/bin/su -l "$loggedInUser" -c "commandyouwanttorunastheuser"

This is kind of a hack, so whether you’re using this as a postinstall_script in a Munki nopkg or a script that a Jamf policy is calling, you’ll definitely want to thoroughly test it to make sure it does what you want it to do

Categories
Mac admin'ing

Using a Munki nopkg to disable Chrome 80’s ScrollToTextFragment feature

What is ScrollToTextFragment

With Chrome 80, Google has introduced a new ScrollToTextFragment feature that allows you to reference an anchor link by any phrase that’s in a webpage, even if the author of the page hasn’t created an anchor link.

You can see this setting by going to chrome://flags in your Chrome browser (assuming you’re using version 80+).


By default, Chrome 80 has the setting enabled.


And, for example, you can create a direct link to the Recent Posts part of my blog by just appending #:~:text=Recent%20Posts to the end of the website URL.


If you disable this setting, however, the regular old webpage behavior returns.


So visiting the URL with that appended part will do nothing but show you the top of the webpage.

Why might you want to disable ScrollToTextFragment?

David Bokan (from Chromium, the open source project Chrome is based on) wrote up a Google Doc called Scroll-to-text Fragment Navigation – Security Issues (PUBLIC) that explains some potential issues.

How can I automate disabling ScrollToTextFragment?

Well, as of this writing (March, 2020), there doesn’t appear to be a way you can disable this via policy, so the best way I’ve come across to do so is via script. It’s a bit convoluted, but it works—here’s my Munki nopkg for disabling ScrollToTextFragment.

Because changing that setting requires a relaunch of Chrome, the nopkg has GoogleChrome as a blocking application, which means if you want to enforce this, you may have to add a force_install_after_date key to the pkginfo, because the chances that your users will see a pending Managed Software Center update, quit of Chrome, install the update, and then launch up Chrome again are probably fairly low.

Categories
Mac admin'ing

Fix for custom user icons freezing up System Preferences

Even though there is some flexibility in terms of what sizes and resolutions you can use for custom user icons (to select for user pictures), if your icon’s resolution is way off, you may see a frozen blank, grey screen when trying to change the picture from that too-high-res picture to something else:

To get out of that, you’ll have to force-quit System Preferences, and then delete the picture manually with the terminal:
sudo dscl . delete /Users/username JPEGPhoto

The fix to prevent this from happening again is rather simple. Just make sure your image matches the size and pixels-per-inch that the macOS system user icons have:


Then, you should be able to select another image after your image is selected.

Categories
Mac admin'ing

Introduction to Nudge

What is Nudge?

In 2018, Erik Gomez created Nudge, which is open source and has nine other contributors as of this writing.

Part of the beauty of Nudge is its simplicity—it doesn’t actually install any updates itself (it does invoke the softwareupdate binary to check for or download Apple software updates, but it doesn’t actually install anything). That means if Apple changes how it does updates so as to make it particularly difficult for tools like Munki (yay!) or Jamf (eh…) to manage updates, you can just… nudge… users to install their updates via System Preferences.

How does it work?

There is a launch agent that checks to see if your major OS is up to date (e.g., 10.15) or if your minor OS is up to date (e.g., 10.15.2 build 19C57). It will pop up a window if the OS isn’t “up to date” (however you define it), and get more aggressive as the cut-off date (something you also define) gets closer (or has passed).

You build it with munkipkg, though I’d recommend distributing separately from the package both the nudge.json (renamed from example_config.json) and the update_ss.png image. The former you can even host online (not on the user’s machine), but both you may want to update from time to time, even if the rest of the Nudge package (including scripts, launch agent, your company logo) stay the same.

The Nudge script will check to see if the major OS and/or minor OS/build are/is up to date, and, if not, nudge the user to install the updates.

What does this look like to the user

Every half hour, the user will get a window that appears over whatever she is working on, and the window isn’t moveable and can’t be closed with a red X button.


Initially, there will be a Close button readily available.

With the default timer settings, the window will come back to the front once every 4 hours.


Once it’s within three days of the cut-off date, the user will have to click I understand in order to get the Close button to appear.


Then, the user is okay to click the Close button. Of course, your hope is that the user will just click Update Machine instead to actually get the machine to update instead of just dismissing the dialogue.

With the default timer settings, the window will come back to the front once every 2 hours.


The same click-I-understand-before-you-click-close-but-really-please-just-update-your-machine routine shows up, too, when there is only one day left.

With the default timer settings, the window will come back to the front once every 10 minutes.

If the cut-off date is within an hour or if it’s passed already, there is no option to close or say you understand. You can’t dismiss the window.

With the default timer settings, within an hour of the cut-off date, the window will be brought back to the foreground every 1 minute.

And with the default timer settings, when the cut-off date has passed, the window will be brought back to the foreground every 10 seconds.

What can you configure via the .json file?

I’m a huge fan of Munki, but one downside to using Munki to install Apple software updates is you can’t really add a preupgrade_alert for a non-optional item, which means you can’t really alert users that, say, a particular Apple software update may have the screen turn black for a full minute.

With Nudge, you can configure pretty much any of the text using the .json file.

You can also have the Update Machine button go wherever you’d like it to go. You can even have it invoke Munki or Jamf.

If you don’t want it to invoke up Munki or Jamf, or to launch up a pre-downloaded update or upgrade installer, you can also have this in your .json file:
"path_to_app": "/System/Library/PreferencePanes/SoftwareUpdate.prefPane",
so it just launches up System Preferences > Software Update, so the user can install updates via the “Apple sanctioned” way.

If you don’t want to bother the user every half hour, you can set the days_between_notifications preference. This goes by actual day and not necessarily a full 24 hours. For example, if the user was notified Thursday afternoon and dismissed the Nudge notification, she may see the notification again on Friday morning (since Friday is the next day after Thursday).

You can also adjust the timer settings to be more or less aggressive with how quickly the open window will be brought back to the foreground.

What else is there about Nudge?

This blog post isn’t intended to be a comprehensive Nudge handbook—just an introduction to Nudge.

You can (and should), of course, read the Nudge README.

I’d also highly recommend just reading the actual Nudge code, since it gives you a sense of the sequence of things and how it all works (especially if you read the comments in the code).

Finally, check out the #nudge channel on the MacAdmins Slack if you have any questions about how to use Nudge.

Categories
Mac admin'ing

Upping the logging level in Munki

As noted in the Troubleshooting section of the Munki wiki, you can increase the logging level for Munki clients.

The default logging level is 1, which looks like this:
Dec 12 2019 20:04:20 -0800 GoogleChrome version 79.0.3945.79 (or newer) is already installed.

If you increase the logging level to 4, it will look like this:
Dec 12 2019 20:08:23 -0800 DEBUG1: Found GoogleChrome, version 79.0.3945.79 in catalog testing
Dec 12 2019 20:08:23 -0800 DEBUG1: Found Info.plist at /Applications/Google Chrome.app/Contents/Info.plist
Dec 12 2019 20:08:23 -0800 DEBUG1: Checking /Applications/Google Chrome.app/Contents/Info.plist for CFBundleShortVersionString 79.0.3945.79...
Dec 12 2019 20:08:23 -0800 DEBUG1: Using version_comparison_key CFBundleShortVersionString
Dec 12 2019 20:08:23 -0800 DEBUG1: Installed item has version 79.0.3945.79
Dec 12 2019 20:08:23 -0800 DEBUG1: Installed item is the same.
Dec 12 2019 20:08:23 -0800 DEBUG1: Found Info.plist at /Applications/Google Chrome.app/Contents/Info.plist
Dec 12 2019 20:08:23 -0800 DEBUG1: Checking /Applications/Google Chrome.app/Contents/Info.plist for CFBundleShortVersionString 79.0.3945.79...
Dec 12 2019 20:08:23 -0800 DEBUG1: Using version_comparison_key CFBundleShortVersionString
Dec 12 2019 20:08:23 -0800 DEBUG1: Installed item has version 79.0.3945.79
Dec 12 2019 20:08:23 -0800 DEBUG1: Installed item is the same.

which looks very similar to the output from a manual sudo managedsoftwareupdate -vvv run:

Found GoogleChrome, version 79.0.3945.79 in catalog testing
Found Info.plist at /Applications/Google Chrome.app/Contents/Info.plist
Checking /Applications/Google Chrome.app/Contents/Info.plist for CFBundleShortVersionString 79.0.3945.79...
Using version_comparison_key CFBundleShortVersionString
Installed item has version 79.0.3945.79
Installed item is the same.
Found Info.plist at /Applications/Google Chrome.app/Contents/Info.plist
Checking /Applications/Google Chrome.app/Contents/Info.plist for CFBundleShortVersionString 79.0.3945.79...
Using version_comparison_key CFBundleShortVersionString
Installed item has version 79.0.3945.79
Installed item is the same.

So if you want to see the equivalent of managedsoftwareupdate -vvv in the /Library/Managed Installs/Logs/ManagedSoftwareUpdate.log, I’d recommend using LoggingLevel 4.

Categories
Mac admin'ing

Yes, Munki’s makecatalogs runs on Linux

You can’t run all of Munki‘s admin tools on Linux, because some of the things the tools use involve Mac-specific tools, which is why even Munki admins who host their Munki servers on a Linux server will use a Mac for things like munkiimport.

You can, however, run makecatalogs on Linux, though. Here’s just a quick test you can do on a vanilla Ubuntu 18.04 LTS server…

Clone the latest Munki from GitHub

git clone https://github.com/munki/munki

Create a symlink for Python 3

sudo ln -s /usr/bin/python3 /usr/bin/python

Copy the Munki command-line tools to a directory

sudo mkdir -p /usr/local/munki
sudo cp -R munki/code/client/* /usr/local/munki

Run makecatalogs

/usr/local/munki/makecatalogs /path/to/munki_repo

P.S. Your mileage may vary, but I found without making the symlink for Python 3 that I would get a

/usr/bin/env 'python': No such file or directory

error.