Skip to content

Commit

Permalink
Merge pull request #52 from kc9wwh/v2.6
Browse files Browse the repository at this point in the history
v2.6
  • Loading branch information
kc9wwh committed May 1, 2018
2 parents 34ec0f3 + babf384 commit 543103c
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 57 deletions.
39 changes: 36 additions & 3 deletions README.md
@@ -1,27 +1,50 @@
# macOS Self Service Upgrade Process
###### Workflow for doing an in-place upgrade without user interaction.

![OS X 10.10 Client Tested](https://img.shields.io/badge/OS%20X%2010.10-OK-brightgreen.svg)
![OS X 10.11 Client Tested](https://img.shields.io/badge/OS%20X%2010.11-OK-brightgreen.svg)
![OS X 10.12 Client Tested](https://img.shields.io/badge/OS%20X%2010.12-OK-brightgreen.svg)
![macOS 10.13 Client Tested](https://img.shields.io/badge/macOS%2010.13-OK-brightgreen.svg)
![OS X 10.12 Installer Tested](https://img.shields.io/badge/Sierra%20Installer-10.12.4%2B-yellow.svg)
![macOS 10.13 Installer Tested](https://img.shields.io/badge/High%20Sierra%20Installer-OK-brightgreen.svg)
___
This script was designed to be used in a Self Service policy to ensure specific requirements have been met before proceeding with an inplace upgrade to macOS, as well as to address changes Apple has made to the ability to complete macOS upgrades silently.
This script was designed to be used in a Self Service policy to ensure specific requirements have been met before proceeding with an in-place upgrade to macOS, as well as to address changes Apple has made to the ability to complete macOS upgrades silently.

Requirements:
* Jamf Pro
* A logged in user
* macOS Clients on 10.10.5 or later
* macOS Installer 10.12.4 or later
* `eraseInstall` option is ONLY supported with macOS Installer 10.13.4+ and client-side macOS 10.13+
* Look over the USER VARIABLES and configure as needed.

*This workflow will **not** work if a user is not logged in since the `startosinstall` binary requires a user to be logged in. Tested with macOS 10.13.4 and you will get errors in that the process couldn't establish a connection to the WindowServer.*

___

**Why is this needed?**

Starting with macOS Sierra, Apple has begun enforcing the way in which you can silently call for the OS upgrade process to happen in the background. Because of this change, many common ways that have been used and worked in the past no longer do. This script was created to adhere to Apple's requirements of the startosinstall binary.
Starting with macOS Sierra, Apple has begun enforcing the way in which you can silently call for the OS upgrade process to happen in the background. Because of this change, many common ways that have been used and worked in the past no longer do. This script was created to adhere to Apple's requirements of the `startosinstall` binary.

*This script has been tested on OS X 10.10.5, 10.11.5 and macOS 10.12.5 clients upgrading to 10.12.6 and 10.13.3. As of v2.5 of this script FileVault Authenticated reboots work again!*

**Scope**

When you start deploying this script to your end-users you will want to ensure that it is scoped properly. At that very least, you'll want to create a Smart Group to determine if the target system(s) meet the system requirements for the macOS upgrade.

* [laurentpertois/High-Sierra-Compatibility-Checker](https://github.com/laurentpertois/High-Sierra-Compatibility-CheckerÂ)

Also, if you are encrypting your macOS devices (which I hope you are), you will want to ensure your scope also includes devices that are not currently encrypting. While the devices are encrypting, you will not be able to upgrade to macOS High Sierra until encryption is complete.

| And/Or | Criteria | Operator | Value |
| :---: | :---: | :---: | :---: |
| | FileVault 2 Partition Encryption State | is not | Encrypting |

**Configuring the Script**

When you open the script you will find some user variables defined on lines 60-99. Here you can specify the message that is displayed to the end user while the script is running and preparing the computer to upgrade to macOS Sierra, as well as the variables used to determine the version and path for the macOS Installer. Also, don't forget to setup a policy with a custom trigger specified as defined in the user variables.
When you open the script you will find some user variables defined on lines 60-118. Here you can specify the message that is displayed to the end user while the script is running and preparing the computer to upgrade to macOS Sierra, as well as the variables used to determine the version and path for the macOS Installer. Also, don't forget to setup a policy with a custom trigger specified as defined in the user variables.

*Added in v2.6.0 - You can now specify to use the `--eraseInstall` parameter when using macOS Installer 10.13.4 or later and the client is running macOS 10.13 or later. Essentially this will wipe and reload the system to factory defaults. Yay \o/*


**Staging the macOS Installer**
Expand All @@ -36,6 +59,16 @@ In order for this script to work, you will have to have a copy of the macOS Inst
![alt text](/imgs/selfservice.png)


**Example of Factory Reset Self Service Description**

![alt text](/imgs/factoryReset.png)


**Example of HUD Displayed if Installer is Downloaded**

![alt text](/imgs/downloadHUD.png)


**Example of FullScreen Dialog**

![alt text](/imgs/fullScreen.png)
Expand Down
Binary file added imgs/downloadHUD.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added imgs/factoryReset.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added imgs/fullScreen-Sierra.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified imgs/fullScreen.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added imgs/selfservice-Sierra.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified imgs/selfservice.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added imgs/utility-Sierra.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified imgs/utility.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
171 changes: 117 additions & 54 deletions macOSUpgrade.sh
Expand Up @@ -35,47 +35,61 @@
# as well as to address changes Apple has made to the ability to complete macOS upgrades
# silently.
#
# VERSION: v2.5.1
# VERSION: v2.6.0
#
# REQUIREMENTS:
# - Jamf Pro
# - macOS Clients running version 10.10.5 or later
# - macOS Installer 10.12.4 or later
# - eraseInstall option is ONLY supported with macOS Installer 10.13.4+ and client-side macOS 10.13+
# - Look over the USER VARIABLES and configure as needed.
#
#
# For more information, visit https://github.com/kc9wwh/macOSUpgrade
#
#
# Written by: Joshua Roskos | Professional Services Engineer | Jamf
# Written by: Joshua Roskos | Jamf
#
# Created On: January 5th, 2017
# Updated On: February 5th, 2018
# Updated On: April 30th, 2018
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# USER VARIABLES
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

##Erase & Install macOS (Factory Defaults)
##Requires macOS Installer 10.13.4 or later
##Disabled by default
##Options: 0 = Disabled / 1 = Enabled
eraseInstall=0

##Enter 0 for Full Screen, 1 for Utility window (screenshots available on GitHub)
userDialog=0

#Specify path to OS installer. Use Parameter 4 in the JSS, or specify here
#Example: /Applications/Install macOS High Sierra.app
##Specify path to OS installer. Use Parameter 4 in the JSS, or specify here
##Example: /Applications/Install macOS High Sierra.app
OSInstaller="$4"

##Version of OS. Use Parameter 5 in the JSS, or specify here.
#Example: 10.12.5
##Example: 10.12.5
version="$5"

#Trigger used for download. Use Parameter 6 in the JSS, or specify here.
#This should match a custom trigger for a policy that contains an installer
#Example: download-sierra-install
##Trigger used for download. Use Parameter 6 in the JSS, or specify here.
##This should match a custom trigger for a policy that contains an installer
##Example: download-sierra-install
download_trigger="$6"

#Title of OS
#Example: macOS High Sierra
##MD5 Checksum of InstallESD.dmg
##This variable is OPTIONAL
##Leave the variable BLANK if you do NOT want to verify the checksum (DEFAULT)
##Example Command: /sbin/md5 /Applications/Install\ macOS\ High\ Sierra.app/Contents/SharedSupport/InstallESD.dmg
##Example MD5 Checksum: b15b9db3a90f9ae8a9df0f81741efa2b
installESDChecksum="$7"

##Title of OS
##Example: macOS High Sierra
macOSname=`echo "$OSInstaller" |sed 's/^\/Applications\/Install \(.*\)\.app$/\1/'`

##Title to be used for userDialog (only applies to Utility Window)
Expand All @@ -85,22 +99,70 @@ title="$macOSname Upgrade"
heading="Please wait as we prepare your computer for $macOSname..."

##Title to be used for userDialog
description="
This process will take approximately 5-10 minutes.
description="This process will take approximately 5-10 minutes.
Once completed your computer will reboot and begin the upgrade."

#Description to be used prior to downloading the OS installer
##Description to be used prior to downloading the OS installer
dldescription="We need to download $macOSname to your computer, this will \
take several minutes."

##Jamf Helper HUD Position if macOS Installer needs to be downloaded
##Options: ul (Upper Left); ll (Lower Left); ur (Upper Right); lr (Lower Right)
##Leave this variable empty for HUD to be centered on main screen
dlPosition="ul"

##Icon to be used for userDialog
##Default is macOS Installer logo which is included in the staged installer package
icon="$OSInstaller/Contents/Resources/InstallAssistant.icns"

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# FUNCTIONS
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

downloadInstaller() {
/bin/echo "Downloading macOS Installer..."
/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper \
-windowType hud -windowPosition $dlPosition -title "$title" -alignHeading center -alignDescription left -description "$dldescription" \
-lockHUD -icon "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/SidebarDownloadsFolder.icns" -iconSize 100 &
##Capture PID for Jamf Helper HUD
jamfHUDPID=$(echo $!)
##Run policy to cache installer
/usr/local/jamf/bin/jamf policy -event $download_trigger
##Kill Jamf Helper HUD post download
kill ${jamfHUDPID}
}

verifyChecksum() {
if [[ "$installESDChecksum" != "" ]]; then
osChecksum=$( /sbin/md5 -q "$OSInstaller/Contents/SharedSupport/InstallESD.dmg" )
if [[ "$osChecksum" == "$installESDChecksum" ]]; then
echo "Checksum: Valid"
break
else
echo "Checksum: Not Valid"
echo "Beginning new dowload of installer"
/bin/rm -rf "$OSInstaller"
sleep 2
downloadInstaller
fi
else
break
fi
}

cleanExit() {
kill ${caffeinatePID}
exit $1
}

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# SYSTEM CHECKS
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

##Caffeinate
/usr/bin/caffeinate -dis &
caffeinatePID=$(echo $!)

##Get Current User
currentUser=$( stat -f %Su /dev/console )

Expand All @@ -118,8 +180,9 @@ else
fi

##Check if free space > 15GB
osMinor=$( /usr/bin/sw_vers -productVersion | awk -F. {'print $2'} )
if [[ $osMinor -ge 12 ]]; then
osMajor=$( /usr/bin/sw_vers -productVersion | awk -F. {'print $2'} )
osMinor=$( /usr/bin/sw_vers -productVersion | awk -F. {'print $3'} )
if [[ $osMajor -eq 12 ]] || [[ $osMajor -eq 13 && $osMinor -lt 4 ]]; then
freeSpace=$( /usr/sbin/diskutil info / | grep "Available Space" | awk '{print $6}' | cut -c 2- )
else
freeSpace=$( /usr/sbin/diskutil info / | grep "Free Space" | awk '{print $6}' | cut -c 2- )
Expand All @@ -134,32 +197,33 @@ else
fi

##Check for existing OS installer
if [ -e "$OSInstaller" ]; then
/bin/echo "$OSInstaller found, checking version."
OSVersion=`/usr/libexec/PlistBuddy -c 'Print :"System Image Info":version' "$OSInstaller/Contents/SharedSupport/InstallInfo.plist"`
/bin/echo "OSVersion is $OSVersion"
if [ $OSVersion = $version ]; then
downloadOS="No"
else
downloadOS="Yes"
##Delete old version.
/bin/echo "Installer found, but old. Deleting..."
/bin/rm -rf "$OSInstaller"
fi
else
downloadOS="Yes"
fi

##Download OS installer if needed
if [ $downloadOS = "Yes" ]; then
/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper \
-windowType utility -title "$title" -alignHeading center -alignDescription left -description "$dldescription" \
-button1 Ok -defaultButton 1 -icon "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/SidebarDownloadsFolder.icns" -iconSize 100
##Run policy to cache installer
/usr/local/jamf/bin/jamf policy -event $download_trigger
else
/bin/echo "$macOSname installer with $version was already present, continuing..."
fi
loopCount=0
while [[ $loopCount -lt 3 ]]; do
if [ -e "$OSInstaller" ]; then
/bin/echo "$OSInstaller found, checking version."
OSVersion=`/usr/libexec/PlistBuddy -c 'Print :"System Image Info":version' "$OSInstaller/Contents/SharedSupport/InstallInfo.plist"`
/bin/echo "OSVersion is $OSVersion"
if [ $OSVersion = $version ]; then
/bin/echo "Installer found, version matches. Verifying checksum..."
verifyChecksum
else
##Delete old version.
/bin/echo "Installer found, but old. Deleting..."
/bin/rm -rf "$OSInstaller"
sleep 2
downloadInstaller
fi
((loopCount++))
if [ $loopCount -ge 3 ]; then
/bin/echo "macOS Installer Downloaded 3 Times - Checksum is Not Valid"
/bin/echo "Prompting user for error and exiting..."
/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -title "$title" -icon "$icon" -heading "Error Downloading $macOSname" -description "We were unable to prepare your computer for $macOSname. Please contact the IT Support Center." -iconSize 100 -button1 "OK" -defaultButton 1
cleanExit 0
fi
else
downloadInstaller
fi
done

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# CREATE FIRST BOOT SCRIPT
Expand All @@ -170,7 +234,7 @@ fi
/bin/echo "#!/bin/bash
## First Run Script to remove the installer.
## Clean up files
/bin/rm -fdr "$OSInstaller"
/bin/rm -fdr \"$OSInstaller\"
/bin/sleep 2
## Update Device Inventory
/usr/local/jamf/bin/jamf recon
Expand Down Expand Up @@ -215,9 +279,9 @@ EOF
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

##Determine Program Argument
if [[ $osMinor -ge 11 ]]; then
if [[ $osMajor -ge 11 ]]; then
progArgument="osinstallersetupd"
elif [[ $osMinor -eq 10 ]]; then
elif [[ $osMajor -eq 10 ]]; then
progArgument="osinstallersetupplaind"
fi

Expand Down Expand Up @@ -255,10 +319,6 @@ EOP
# APPLICATION
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

##Caffeinate
/usr/bin/caffeinate -dis &
caffeinatePID=$(echo $!)

if [[ ${pwrStatus} == "OK" ]] && [[ ${spaceStatus} == "OK" ]]; then
##Launch jamfHelper
if [[ ${userDialog} == 0 ]]; then
Expand All @@ -278,7 +338,13 @@ if [[ ${pwrStatus} == "OK" ]] && [[ ${spaceStatus} == "OK" ]]; then
fi
##Begin Upgrade
/bin/echo "Launching startosinstall..."
"$OSInstaller/Contents/Resources/startosinstall" --applicationpath "$OSInstaller" --nointeraction --pidtosignal $jamfHelperPID &
##Check if eraseInstall is Enabled
if [[ $eraseInstall == 1 ]]; then
/bin/echo " Script is configured for Erase and Install of macOS."
"$OSInstaller/Contents/Resources/startosinstall" --applicationpath "$OSInstaller" --eraseinstall --nointeraction --pidtosignal $jamfHelperPID &
else
"$OSInstaller/Contents/Resources/startosinstall" --applicationpath "$OSInstaller" --nointeraction --pidtosignal $jamfHelperPID &
fi
/bin/sleep 3
else
## Remove Script
Expand All @@ -293,7 +359,4 @@ else

fi

##Kill Caffeinate
kill ${caffeinatePID}

exit 0
cleanExit 0

0 comments on commit 543103c

Please sign in to comment.