Handling macOS Software Updates with Jamf Pro

Jamf Pro has not handled software updates successfully on all Mac hardware since Apple introduced the T2 processor with the iMac Pro back in December 2017. It’s been requested that they address this issue in a feature request, but it’s gone completely unacknowledged.

The problem with the software update process on Macs with T2 processors is that sometimes there is a bridgeOS update (the OS on the T2 processor) which requires a shutdown instead of a restart. The Mac will read the shutdown and automatically power back on to apply the bridgeOS update. However, not all software updates have a bridegeOS update which would mean a shutdown in those situations would actually leave the computer powered down. Unfortunately, Jamf Pro does not know how to handle this situation. Apple did introduce the --restart option for softwareupdate but that also comes with its own problems in that it hasn’t worked reliably in all scenarios. Since the solution to this isn’t particularly difficult to work around, I created a script to address this workflow in our environment.

Before continuing, I’d like to mention that we do leverage macOS’s ability to do automatic updates. This has one benefit of doing automated authenticated restarts which is important on Macs with FileVault enabled. However, we’ve found in our environment that after a month only 60% of computers running macOS 10.14 are up to date on the latest version. It’s a bit of a black box as to how macOS determines when to do automatic updates. Needless to say, the rate of updates is unacceptable.

This script is meant to be used with Jamf Pro and makes use of Jamf Helper. The idea behind this script is that it alerts the user that there are required OS updates that need to be installed. Rather than forcing updates to take place through the command line using “softwareupdate”, the user is encouraged to use the macOS GUI to update. When I say macOS GUI, I’m referring to the Software Update mechanism that Apple refers consumers to: https://support.apple.com/en-us/HT201541

In recent OS versions, Apple has done a poor job of testing command line-based workflows of updates and failed to account for scenarios where an end-user may or may not be logged in. The update process through the GUI has not suffered from these kind of issues. The script will allow end users to postpone/defer updates X amount of times and then will give them one last change to postpone. We run this script using the Once A Day policy frequency which means the user will get this once a day so long as it checks in.

This script should work rather reliably going back to 10.12 and maybe further, but at
this point the real testing has only been done on 10.14. Please note, that this script does NOT cache updates in advance. Sometimes Apple releases updates that get superseded in a short time frame. This can result in downloaded updates that are in the /Library/Updates path that cannot be removed in 10.14+ due to System Integrity Protection.

This script does make use of Jamf Pro Script Parameters:
Parameter 4: Optional. Number of postponements allowed. Default: 3
Parameter 5: Optional. Number of seconds dialog should remain up. Default: 900 seconds

Here is the expected workflow with this script:

  1. If no user is logged in, the script will install updates through the command line and
    shutdown/restart as required.
  2. If a user is logged in and there are updates that require a restart, the user will get
    prompted to update or to postpone.
  3. If a user is logged in and there are no updates that require a restart, the updates will get installed in the background (unless either Safari or iTunes are running.)

There are a few exit codes in this script that may indicate points of failure:
11: No power source detected while doing CLI update.
12: Software Update failed.
13: FV encryption is still in progress.
14: Incorrect deferral type used.

Below are some screenshots for what you will see on macOS Mojave. However the text is aware of at least 10.8 and higher where the instructions to get to Software Update might differ.

This is the initial message you will see when prompted to update:

Update1.png

When you click Continue, you will be taken to Apple’s Software Update:

Update3.pngUpdate4.png

This is the final message you will get when you’ve postponed the maximum number times:

Update2.png

Note: “Please make selection in HH:MM:SS” is not text I can modify. It serves as a countdown for the end user to know how much time they have before they are forced to update.

And lastly when the forced update is taking place, a headsup display window pops up:

Update5.png

The script is easy to modify if you don’t like the verbiage or if you want to use it for inspiration on other workflows. The script can be found here on my Github page.

Advertisements

How to set the icon for a folder or file with a little bit of PyObjC

There may be situations in which you need to set an icon for a folder or file. If you start searching online, you might run into a bunch of recommendations that rely on Xcode command line tools or methods that simply no longer work.

The following method is quite simple because it only relies on the Python Objective-C bridge which has been bundled with macOS for many years now. The relevant API is in the NSWorkspace.

For just the PyObjC code, here it is taken from a StackOverFlow answer:

#!/usr/bin/python
# https://developer.apple.com/documentation/appkit/nsworkspace/1529882-seticon?language=objc
# Argument 1: Path to icon
# Argument 2: Path to folder/file to set icon for

import Cocoa
import sys

Cocoa.NSWorkspace.sharedWorkspace().setIcon_forFile_options_(Cocoa.NSImage.alloc().initWithContentsOfFile_(sys.argv[1].decode('utf-8')), sys.argv[2].decode('utf-8'), 0) or sys.exit("Unable to set file icon")

 
And if you want to make use of that code in a Bash script, it’s not too hard:

#!/bin/bash
# This is PyObjC code that can be used in a bash script
# https://developer.apple.com/documentation/appkit/nsworkspace/1529882-seticon?language=objc

FolderIcon="/path/to/icon.icns"
PathToSetIconFor="/path/to/folder"

setFolderIcon (){
/usr/bin/python - "$1" "$2" << EOF
import Cocoa
import sys
Cocoa.NSWorkspace.sharedWorkspace().setIcon_forFile_options_(Cocoa.NSImage.alloc().initWithContentsOfFile_(sys.argv[1].decode('utf-8')), sys.argv[2].decode('utf-8'), 0)
EOF
}
setFolderIcon "$FolderIcon" "$PathToSetIconFor"

Enjoy!

Ignore a specific macOS update using softwareupdate

There are a few different ways you can go about managing updates for macOS. They’ll all have their pros and cons. In this post, I’m just going to focus on one method that may come in handy for you.

The command softwareupdate has an ignore flag which lets you specify an update you want to ignore when the OS tries to check for software updates. The man page for softwareupdate tries to explain it’s usage:

NAME
softwareupdate -- system software update tool

SYNOPSIS
softwareupdate command [args ...]

DESCRIPTION
......

--ignore identifier ...
Manages the per-machine list of ignored updates. The identifier is the first part of the item name (before the dash and version num-
ber) that is shown by --list. See EXAMPLES.

--reset-ignored
Clears the per-machine list of ignored updates.
......

EXAMPLES
The following examples are shown as given to the shell:

softwareupdate --list

Software Update Tool

Finding available software
Software Update found the following new or updated software:
* MacBookAirEFIUpdate2.4-2.4
MacBook Air EFI Firmware Update (2.4), 3817K [recommended] [restart]
* ProAppsQTCodecs-1.0
ProApps QuickTime codecs (1.0), 968K [recommended]
* JavaForOSX-1.0
Java for OS X 2012-005 (1.0), 65288K [recommended]
......

sudo softwareupdate --ignore JavaForOSX

Ignored updates:
(JavaForOSX)

The problem I’ve run into is that the “identifier” is not always very clear. For example, if you look at the example they provide, the identifier to ignore is “JavaForOSX” but the update is listed as “JavaForOSX-1.0” or “Java for OS X 2012-005 (1.0)” when you pull a list of all available software updates. Which one are you supposed to use? And why are they all different?

Someone on the MacAdmins Slack was nice enough to share a little bit of knowledge which I wanted to share forward.

  1. Find a Mac with updates you want to block. You can either open up Software Update or the App Store > Update tab or alternatively using sudo softwareupdate -l.
  2. Once you’ve got a list of updates, run the command: defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist which should list some of the updates available in a dictionary key:
    Below is an example. Pay attention to the Product Key value:

    {
    "Display Name" = Safari;
    "Display Version" = "12.0.2";
    Identifier = "Safari12.0.2HighSierraAuto";
    "Product Key" = "041-08765";
    }
  3. Technically, the Identifier is all you need there. The rest of the steps are not necessary. However for the sake of documentation, you can gain the same information elsewhere.
  4. Open up Finder and go to: /Library/Updates/
  5. Assuming there are available updates, you will find a folder containing a Product Key number (e.g. 041-20511). Each of those folders represents an available update. You can reconcile the Product Key IDs with what you found earlier.
  6. Open that directory and you should see a .dist file (e.g. 041-20511.English.dist). Open that .dist in a text editor. You will see that this file is simply XML.
  7. Do a find on the .dist file for the property tag suDisabledGroupID. This key is what holds the value you want. To continue with the example, suDisabledGroupID="Security Update 2018-003"

You can now use softwareupdate to ignore this specific update: sudo softwareupdate --ignore "Security Update 2018-003"

You can also update multiple updates at once:

sudo softwareupdate --ignore "Security Update 2018-002" "Security Update 2018-003"

Note: This does NOT prevent someone from manually downloading the update and installing it. It only prevents macOS from listing the specific ignored update as an available update via the command line and user interface (App Store, System Preferences).

If you want to reset the updates you’ve ignored, run the command sudo softwareupdate --reset-ignored

Or you can alternatively make use of a tool like SUS Inspector to give you this and more information.

Booting into macOS Recovery in VMware Fusion 10

I recently ran into a problem where I needed to boot into a Recovery Partition in VMware Fusion 10 to disable System Integrity Protection. The instructions from VMware are quite difficult to get just right. I’m not sure if it’s because of changes to VMware Fusion, but I simply could not get it to read CMD + R at boot when powering on the virtual machine.

I also tried following the instructions in this post: https://derflounder.wordpress.com/2017/08/01/setting-a-macos-vm-to-automatically-boot-to-recovery-hd-using-vmware-fusion/ including what is suggested in the comments.

However if I add the the line macosguest.forceRecoveryModeInstall = "TRUE" to end of the VM’s .vmx config file to force it to go into recovery mode, disable SIP, and then delete the line from the vmx file, it continuously reboots into Recovery. I’ve seen the recommendation to delete the .nvram file, but that re-enables SIP even if it boots me back into the regular OS.

I also found instructions that suggested I simply type the following in macOS:

sudo nvram "recovery-boot-mode=unused"
sudo reboot

But that also did not work.

I asked for help on MacAdmins Slack and found a solution that’s a lot more simple which I felt the need to share in case anyone else finds themselves in a similar position. Credit to the those that shared this with me.

1) Choose Power on to Firmware from the Virtual Machine menu
2) Select “Enter Setup”
3) Boot from a file
4) Arrow down to Recovery HD
5) Hit enter until you can pick boot.efi
6) Select boot.efi
7) Hit enter

From there you can then disable System Integrity Protection and then restart back into macOS.

The Importance Of Filing Feedback During Major OS Releases From Apple

It’s not going to be too long before Apple releases macOS Mojave 10.14. They’ve announced it’s release for Fall 2018 at WWDC earlier this year. On August 13, 2018, they released beta 7 and on August 20, 2018 they released beta 8 which indicates they might be making weekly releases up until the general public release of 10.14. Based on previous release dates for macOS, my guess is that Apple will release macOS 10.14 sometime in late September.

Beta testing

If you’ve been part of the beta program and you are in charge of managing Macs in an enterprise environment then hopefully you’ve been providing feedback to Apple about the issues you’ve been running into. If you are not a part of the developer program, then you should join it and provide feedback. You can even have your fee waived for the developer program in certain circumstances. Alternatively, you can also join the Apple Beta Software Program. Even better, if you haven’t already, look into joining the AppleSeed testing program. You can read more about that at Rich Trouton’s blog. There will be differences in how often you get releases and perhaps in the kind of release notes you receive, but it at least gets you access to the beta software.

The next step you need to take is to provide Apple with feedback. In fact, Apple lets you provide feedback for free by going to bugreporter.apple.com so long as you have an Apple ID. However, you should ideally use Feedback Assistant especially if you’re in the AppleSeed program.

Unfortunately, due to NDA, I cannot publicly post anything here that isn’t already public. However, the point of this post is to bring some awareness on things that have been made public by Apple that will have a MAJOR impact on any IT administrator managing Macs when macOS 10.14 releases.

Quick recap of changes in macOS 10.13

To give a quick recap, with macOS 10.13, Apple introduced the concept of User Approved MDM (UAMDM). The idea behind this is that devices that have UAMDM can then have their MDM server send out Configuration Profiles that mange specific settings that can only be managed if the device is UAMDM. This can happen one of two ways: 1) the user automatically installs an MDM profile and then approves it, or 2) the device is configured through the Device Enrollment Program.

Apple first started by restricting kernel extensions. Some of those changes during the 10.13 beta were pushed back until better management could be added to the public release. That management feature was the introduction of the User Approved Kernel Extension Loading. You can read more about that at Rich Trouton’s blog. If you notice a trend, Apple has been releasing more and more restrictions with each release of macOS in the name of security. UAMDM is here to stay and more MDM features will probably require it.

Upcoming changes in macOS 10.14

With macOS 10.14, Apple is introducing even more restrictions to what applications can do. I strongly recommend you watch the WWDC full video. The idea of user consent for certain actions taking place by apps or scripts make sense from a security standpoint. This has even bigger implications for IT administrators because often we rely on management tools that may access certain paths that may now require user consent. That’s what the beta is for, right? We can test these new features and the management tools that go with it and provide Apple with valuable feedback.

Unfortunately, although Apple announced these changes to macOS 10.14 on June 5, 2018, the MDM documentation was released August 13, 2018, exactly 69 days later. The relevant change that you will be looking for is Privacy Preferences Policy Control Payload (which according to the revision history was added to that PDF on August 6th, but that’s just not true). That means IT administrators have about 5-6 weeks until late September to test this out. This is absolutely very short notice on Apple’s part to put it mildly. Even more importantly, MDM vendors have 5-6 weeks for Apple to add this new payload (among other new MDM-related changes they’ve made). That means that in order to test this, you need to 1) manually create a Configuration Profile and upload it to your 2) MDM server to push out to your clients which will need 3) UAMDM.

How do I know if I’m impacted?

If you have no idea whether this will impact you, then I recommend the following: get access to macOS 10.14 beta with one of the methods discussed earlier. Run through an installation of macOS 10.14 on a computer and go through your provisioning process for Macs. Run all your tools and scripts that you normally use. Take note of the errors that you start getting and provide that feedback to Apple.

Just to give you an example, here is one discussion on the Apple developer forums on how these changes are effecting IT administrators already.

What do I need to do?

It’s important to provide that feedback to Apple because as it stands they are going to absolutely release these new security and management features in 10.14 as announced without providing sufficient time to test and have IT administrators give them feedback on what works and what doesn’t.

Here is a good example of feedback provided by a fellow Mac administrator on Slack:

macOS 10.14 – AppleSeed for IT
 – Problem Report

 

Basic Information
Please provide a descriptive title for your feedback:
Please delay the release of the new TCC security settings to the Sprint Release

 

Which area are you seeing an issue with?
Client Management

 

What type of issue are you reporting?
Suggestion

 

Details

 

Description
Please describe the issue and what steps we can take to reproduce it:

 

Yesterday Apple released Mojave beta 7, and also “silently” updated the MDM documentation to finally describe how to manage these new policies.

 

This is problematic for a few reasons.

 

1. We can only submit regressions/enhancements now, which means there is a high likelihood that they will not be fixed until after the GM release

 

2. Given Apple’s track record of releases in the past few years, this gives us less than 5 weeks to adequately test the impact this will have to our environment, our internal tools and any developer applications/tools we could deploy

 

3. This also gives MDM vendors less than 5 weeks to offer support for this

 

4. There is no documentation on what Apple deems protected vs unprotected (See Feedback 4813904)

 

This is very similar to what happened last year with High Sierra, User-Approved MDM and User-Approved Secure Kernel Extensions.

 

This documentation should have been available immediately following the session “Your Apps and the Future of macOS Security” – https://developer.apple.com/videos/play/wwdc2018/702/ – This session was live streamed on June 5th, 2018 and the MDM documentation was released August 13th, exactly 69 days later.

 

In which build did you encounter this bug?

 

macOS 10.14 – Beta 7 (18A365a)

 

As an aside, you should contact your MDM vendor to ensure they are aware of this important Configuration Profile payload feature that will be necessary for macOS 10.14. You can link them to the Configuration Profile Reference.

A special note for Jamf Pro customers: please sign your Configuration Profile when you upload it to Jamf Pro to avoid Jamf Pro messing with it. Also, if you’re a Jamf Pro customer, I’ve already made a feature request for them to support this new payload. I’m not entirely sure whether they will be able to release it by macOS 10.14’s release date, but at least it’s on their radar and marked as planned. Another thing to keep in mind: extension attributes are scripts in Jamf Pro that are meant to often collect data. Make sure these scripts/Extension Attributes are running properly in 10.14.

What else can I do?

You can participate in the Apple Developer Forums. There are also a few Mac administrators on Slack speaking about the changes which you can join for free: http://macadmins.org in #tcc channel. (Did you know TCC stands for Transparency, Consent, Control?) You can encourage other Mac administrators to spread the word and file feedback and bug reports with Apple so that they can understand how poorly timed their documentation on this has been for testing. Blog about this. Reach out to your Apple account reps. Basically, you need to do whatever you can so that Apple is aware that these changes are going to be absolutely showstopping for a lot of organizations that have been given little time to test these new features.

What’s the ideal outcome?

In a perfect world, Apple would have released these features and documentation in the very first beta. However, given how late it is now in the beta testing cycle, the next best thing that Apple can do is 1) fix whatever outstanding issues may exist with these new management features, 2) provide a complete whitelist for all UAMDM devices until it can be properly implemented, and 3) properly document what specific areas of the operating system will now require user consent. They’ve done this before with UAKEL where all Kernel Extensions were completely whitelisted in High Sierra until macOS 10.13.4 at which point you could whitelist specific Kernel Extensions.

IT administrators and MDM vendors simply need a little bit more time to these these out. In essence, give us at least those 69 days that you stole from our testing back. I’m not a fan of a moving target on major features in the middle of a major OS release, but at least this would provide organizations time to thoroughly test these features out. This is just my opinion of course. Comments welcomed below. You are more than welcome to provide a differing opinion on this as long as you provide feedback to Apple!

And hopefully for whatever Apple is planning in macOS 10.15, they will plan accordingly and release those management features in the very first beta for IT administrators and MDM vendors to test.

Update to macOS Upgrade Script

I’ve gone ahead and updated my OS Upgrade script for compatibility with macOS High Sierra (10.13). If you’re curious on how to use it, please read my blog post here. There’s one major change to report on other than the compatibility with the new OS installer app.

Filevault Authenticated Restarts

Currently, the macOS Installer does not support authenticated Filevault restarts. This creates a situation where your user would have to run the installer, wait until the restart, authenticate and then walk away. The process now makes it so that the user is prompted for their Filevault credentials before the upgrade even starts. This is so that the user can walk away and not have to wait for the installer app to prepare the computer for the upgrade.

The script will automatically detect if Filevault is turned on. If it’s not, then the user will not see the authentication prompt. I understand some folks might not like this so with that in mind, if you wish to disable this part of the script, comment out lines 521 – 524. I would have added more JSS parameters and made this an option you could disable, but I ran out of parameters to use (vote up this feature request for more JSS parameters).

Conversion to APFS

I’ve been asked to add an option to allow APFS to be turned off or on. I did enforce conversion to APFS using the command: --converttoapfs YES (if you want to disable it, just put NO instead of YES) early on in my update to my script. But ultimately after asking for feedback from other admins, I opted to not force it and just let the app installer take care of the logic on whether to upgrade the drive to APFS. The reasoning here is that Apple knows what conditions best support APFS and which ones don’t. However, I did make a comment in my script in line 500 for those who want to always enforce it or disable APFS conversion entirely. It would have been nice to make this an option that could be toggled with a JSS parameter, but like I said earlier, I ran out of JSS parameters to use (vote up this feature request for more JSS parameters).

Additional changes include:

  • new dialogs for Filevault authenticated restarts
  • new exit codes
  • code clean up

The script referenced above can be downloaded from my GitHub repo. Please let me know if you run into any issues or have any questions regarding the script.

Using JAMF Helper for policies

Jamf Pro has a couple of triggers, events that cause that computer to check-in with the Jamf Pro server to run policies. Those include: Startup, Login, Logout, Network State Change, Enrollment Complete, Recurring Check-in, and Custom. You can read the description for each of those triggers by creating a new policy (you don’t have to save it) and read the descriptions for each of them in the General policy payload.

Recently, I had a situation where we wanted to run an update that’s pretty big on logout. This has the benefit of ensuring the software isn’t running. There are pros and cons to this trigger which I won’t get into here. However, one thing that I’ve always found unacceptable is the JAMF Helper HUD dialog in the bottom right corner that shows up.

Screen Shot 2017-04-27 at 2.07.18 PM.png

I’ve submitted a feature request on JAMF Nation to improve this functionality: https://www.jamf.com/jamf-nation/feature-requests/5980/login-and-logout-policies-should-have-a-more-descriptive-message

The Jamf Pro administrator will know what the dialog means, but end users will be clueless. It’s not descriptive and quite confusing. You can try to educate your end-users on what this means, but you shouldn’t have to and naturally many of them may not remember.

Continue reading Using JAMF Helper for policies

startosinstall updated in macOS 10.12.4 app installer and can no longer target a volume

I recently blogged about my upgrade process with Jamf Pro. The script I had worked well with 10.12.3. One would assume it would work well with the 10.12.4 macOS app installer as well. However it appears that Apple has removed a flag. Specifically, you can no longer specify what volume you want to target for the installation.

The command that you could use previously in 10.12.3 looked like:

"/Applications/Install macOS Sierra.app/Contents/Resources/startosinstall" --applicationpath "/Applications/Install macOS Sierra.app" --volume / --rebootdelay 30 --nointeraction

In 10.12.4, it now looks like:

"/Applications/Install macOS Sierra.app/Contents/Resources/startosinstall" --applicationpath "/Applications/Install macOS Sierra.app" --rebootdelay 30 --nointeraction

Those are just examples of some of the flags you could use. Basically they’ve removed --volume /. All this to say I had to update my script to account for this. This led to a bunch of other code I saw that I could optimize. I have added some additional exit codes and added additional functions to reduce code re-use. The updated script can be downloaded from my GitHub repo. For instructions on how to use it, please refer to my previous blog post.