Revisiting: A macOS upgrade method using Jamf Pro Self Service

Back in 2017, I released my script that I use to do macOS upgrades in my organization through Self Service. Since the script I wrote has changed, I thought a new post was deserved to account for the changes I’ve made.

At my organization, we leverage the macOS installer app from Apple which has a neat little command line tool called startosinstall. There are quite a few scenarios that need to be accounted for to avoid running the upgrade in a situation where it would ultimately fail. With that in mind, here are some of the requirements I came up with that the upgrade script needed to solve:

  1. Computer has sufficient free drive space.
  2. Ensure the user is plugged into a power source.
  3. Confirm that the volume is not presently undergoing encryption/decryption.
  4. Provide a way for the end user to do FileVault authenticated restarts if possible.
  5. Provide dialogs to give the user feedback such as a time estimate and dialogs on what to expect next.
  6. Make use of Jamf Pro script parameters to allow for customization and potential re-use for future operating systems releases.
  7. Provide logging to see where failures may appear.
  8. Allow use of an install package that can be used with macOS 10.13+ installers.
  9. Make sure that the macOS installer app does not have expired certificates.
  10. Perform a jamf recon immediately after upgrade.

Continue reading Revisiting: A macOS upgrade method using Jamf Pro Self Service

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:

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

Another method for macOS upgrades via the JSS using Self Service

There are quite a few methods that people use to make macOS updates available to their end users. My method takes a little inspiration from those posts with a few differences. This time around I wanted to use the macOS installer app from Apple which has a neat little command line tool call startosinstall. There was no particular reason to use this method other than there were no requirements to install any particular packages post-install which you can do with a tool like createOSinstallerPKG. We had a few requirements:

  1. Computer has sufficient free drive space.
  2. User is not logged in to avoid the new iCloud Drive Document Sync feature.
  3. Ensure the user is plugged into a power source.
  4. Provide dialogs to give the user feedback such as a time estimate and dialogs on what to expect next.
  5. Make use of the JSS parameter to allow for customization and potential re-use for future operating systems.

Continue reading Another method for macOS upgrades via the JSS using Self Service

JSS Parameters

JSS script parameters are a great feature that allow you to create scripts that can be flexible in the values that are gathered. I’m not sure how often they are used but suffice to say they can be very useful when you have scenarios where common commands are used repeatedly and just need variables changed. Parameter labels can also be assigned to JSS parameters as shown in Rich Trouton’s blog post. Parameter labels can also be set by going to Settings > Computer Management > Scripts > clicking on the script and selecting the Options tab. This allows you to go from the generic Parameter 4, Parameter 5, etc. and have something more descriptive like “Free Space Required” or “Custom Trigger”.

However, JSS parameters have a few limitations. Below I’ll go over some of those limitations and the associated feature requests that would address them.

Continue reading JSS Parameters

JSS does not accurately report installed profiles

A year ago or so ago I discovered a bunch of computers at my previous job would drop all profiles. We could never find the cause, but what was alarming is that the JSS would report the computer as having profiles installed when in fact none are.

There two simple ways to confirm this:
1. Type sudo profiles -H
2. Open up System Preferences and see if the Profiles pref pane shows up

Unfortunately, I was never able to reproduce the issue or find the cause. Therefore I could never get any further in troubleshooting with Jamf. Fast forward a year later, through some other issues I was reporting and troubleshooting, I was able to finally reproduce the issue. The steps are real simple:

  1. Type sudo rm -rf /var/db/ConfigurationProfiles in Terminal. This command will remove the profiles from the computer.
  2. Confirm profiles are not installed by checking System Preferences (if you had it opened, quit and reopen it) and running sudo profiles -H via CLI
  3. Type sudo Jamf recon -saveFormTo ~/Desktop/noProfilesInstalled in Terminal.
  4. Check inventory record for computer and see Profiles. How many profiles do you see?
  5. Type sudo Jamf mdm in Terminal
  6. Type sudo Jamf recon -saveFormTo ~/Desktop/ProfilesInstalled in Terminal.
  7. Check inventory record for computer and see Profiles. How many profiles do you see?

This is reproducible in the latest version of the JSS and probably goes back quite sometime since configuration profiles were supported in the JSS. For some extra data, the recon command in steps 3 and 6 should reproduce XML of all the inventory information getting collected by the Jamf binary. The jamf binary is ACCURATELY reporting whether profiles are installed. If profiles are installed the info will be enclosed in the <ns2:configProfiles> DATA HERE </ns2:configProfiles> tags and if profiles are not installed then it will simply list <ns2:configProfiles/>. In short, the issue is not on the jamf binary.

The implications of this are huge. Your end users could delete that directory and completely bypass configuration profile enforcement. Let’s take IBM as an example. All their users have admin access. Say they enforce filevault 2 key re-direction, some password complexity requirements, and some restrictions via profiles. Their end users could bypass all of that.

What does Jamf have to say:

Currently, the list of profiles that we see in a Computer Record is generated not through ‘Jamf recon’ or through utilizing the ‘profiles’ binary; but through the MDM command ‘ProfileList’. The MDM command would need to come from the JSS, and unfortunately, would inevitably fail considering the machine removed its MDM profile. Considering this, and what you mentioned with the need to know what profiles are currently on the client computer, what would be needed is essentially a feature within the Jamf binary framework that detects whether or not the MDM framework has been broken. And, if it is broken, repair it. In the end, an end user with admin privileges would be able to do just about anything. We have lots of customers that utilize a home brewed type of ‘self repair’ using LaunchDaemons. That too though, can be broken by an admin user.

What can you do in the meantime? Create an extension attribute. Extension attributes allow you to collect data in the JSS that is not otherwise gathered by the jamf binary. This data is collected at inventory or when you run the jamf recon command on a client. There are two that I like to use, but there are even more out there that list out ALL configuration profiles if you want to get even more granular.

Profile Count


profiles="$(profiles -C | wc -l)"
profile_count="$(echo $profiles - 1 | bc)"

if [ "$profile_count" -gt 0 ]; then
    echo "<result>$profile_count</result>"

if [ "$profile_count" -le 0 ]; then
    echo "<result>0</result>"

Profile Status:


#If profiles are on the computer it spits out:
#profiles are installed on this system
#profiles are not installed on this system

profile_status="$(/usr/bin/profiles -H)"

echo "<result>$profile_status</result>"

Create a smart group with the extension attribute as the criteria and then scope a policy to those groups. The policy should make use of the Files and Process payload option “Execute command”. Run the command:

jamf mdm

to re-enable mdm on the client.

If I can create an extension attribute, what’s the problem? The JSS is supposed to report accurate inventory information for each computer client. It should be accurate up to the last recon/inventory update it did on that client. If we cannot trust the inventory records in the JSS, what good is it? Apple is the one pushing MDM and our reliance on it. Jamf is supposed to be the biggest cheerleader behind that given their quick implementation on almost all mdm/dep/vpp features that Apple introduces. However, how can we trust MDM if the JSS isn’t reporting things accurately?

You might argue: just don’t give your users admin access. Unfortunately, that’s not possible in all environments, and usually there are some exceptions that need to be made. But even so you then start getting into how far down do you lock your computers. You might argue, if the user is removing profiles, they can just remove the jamf binary altogether. Yes, this is true, but that then becomes more of an organizational policy (HR) issue than a technical (IT) issue. The problem here is with reporting and gaining insight. If someone removes the jamf binary, at least the JSS can at least run reports on the last check-in for clients based on the data the JSS has and you can trust the record is accurate. But you cannot do this by looking at the JSS profile record for clients.

Feature Request
I was told to submit a feature request on JAMF Nation and so I did. I encourage you to up vote it if you are a Casper/Jamf Pro customer who uses MDM / Configuration Profiles through the JSS. The data that the jamf binary collects on installed profiles should be what is reported by the JSS. Do not rely only and primarily on the mdm command “ProfileList”. Currently, the JSS does NOT even properly report anything useful or accurate on locally installed profiles either. By allowing the JSS to display what the jamf binary reports based on actual profiles installed, companies can get accurate and insightful data.

The second part of this is that, the jamf binary SHOULD re-enable MDM of course IF AND ONLY MDM isn’t supposed to be disabled from the client.

Here are the feature requests regarding locally installed profiles and scoping to config profiles which I strongly encourage you to upvote as well:

iCloud: Is it being used in your environment?

With the introduction of Sierra, Apple has introduced a few new features to iCloud Drive that business environments may want to gather data on in order to remediate. Rich Trouton has documented the inner workings of the Desktop and Documents Folder sync feature on his blog so I will spare you the details on that. The other feature that Apple introduced is the ability to optimize storage which Anandtech covers.

Depending on your environment there may also be other concerns with employees using iCloud accounts on their company equipment. For example, Find My Mac is a service that could allow a person to locate a device and erase/lock the device. Perhaps a disgruntled employee sends the Lock/Erase command to the device or maybe the employee’s account gets compromised because they didn’t have 2 Factor Authentication enabled on their Apple ID. Whatever the reason, only Apple will be able to unlock the device for you after meeting their requirements (which may include proof purchase, identification, etc.) and perhaps you want to remediate against that.

There may be additional iCloud features that you might also want to disable such as “Back to My Mac” which allows a person to remote into their device.

You can draw your own conclusions as to whether these are important in your business environment, but the short of it is that if you have requirements that company data stay on company managed devices or managed cloud services then some of these iCloud features are going to be non-starting propositions in your environment.

And that’s not to even mention, no brand new OS release is without its share of bugs. There have been some few reported issues online that seem to be linked with users upgrading to Sierra while their iCloud accounts are enabled.

With some of the iCloud features that Apple has introduced, I thought it might be prudent to collect some information on computers before we start deploying Sierra so that we can gather information on whether iCloud is being used and if so what features that may matter to a business are enabled.

I currently work in a Casper environment and decided to write extension attributes that would gather this information which would then allow us to create smart groups that make use of this specific criteria (results from those extension attributes). Extension attributes are essentially scripts that run on a computer when inventory on the computer is collected. Therefore, if you work with other inventory/management systems it shouldn’t be too hard to modify these scripts so that it feeds into your management system of choice. I tried to comment as best as possible each script.

Here are the ones that I cared about:

  1. Determine iCloud account status
  2. Determine iCloud account details
  3. Determine iCloud Drive status
  4. Determine iCloud Document Sync status
  5. Determine iCloud Drive optimization status
  6. Determine Find My Mac status
  7. Determine Back to My Mac status

Some of these features feed off each other, but they do not necessarily have to be used all together. For example, you can’t have iCloud Drive enabled without your iCloud account being signed in and therefore none of the Drive Optimization or Document Sync features will be enabled.

I don’t blog often and this blog post actually prompted me to use Github for the first time so let me know if you’ve got any feedback. Hopefully you find this somewhat helpful.

Edit: One thing to note, is that some of these extension attributes do look for the logged in user to pick up the iCloud preferences. So the assumption here is that usually a user will be logged in when recon/inventory is collected from the computer and that there is one single user typically using the computer. It wouldn’t be too far fetched to go further and perhaps create arrays to get respective iCloud values for each user accounts through a loop.