Posted on 02-04-2021 07:26 AM
(Please pardon the piecemeal post; I'm presuming partial information is better than nothing.)
Thanks to AppleCare pointing out that:
When running the softwareupdate
command in a root shell on Apple Silicon users are being prompted for a password.
This is expected behavior and the recommendation is to use the Schedule an OS Update command via MDM. This is the method to use if you want to update Apple Silicon Macs without requiring user credentials.
In other words:
if [[ "$arch" == "arm64" ]]; then
scheduleOSUpdateViaAPI
else
/usr/sbin/softwareupdate --install --all --include-config-data --restart --force
fi
In my limited testing, users are still prompted:
####################################################################################################
#
# Variables
#
####################################################################################################
jamfProURL="https://company.jamfcloud.com" # No trailing forward slash
apiUsername="${5}"
apiPasswordEncrypted="${6}"
computerSerialNumber=$( /usr/sbin/system_profiler SPHardwareDataType | /usr/bin/grep Serial | /usr/bin/awk '{print $NF}' )
arch=$( /usr/bin/arch )
####################################################################################################
#
# Functions
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# xpath tool changes in Big Sur
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function xpath() {
# https://scriptingosx.com/2020/10/dealing-with-xpath-changes-in-big-sur/
# Thanks, Armin!
if [[ $(sw_vers -buildVersion) > "20A" ]]; then
/usr/bin/xpath -e "$@"
else
/usr/bin/xpath "$@"
fi
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Decrypt Password
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function decryptPassword() {
/bin/echo "${1}" | /usr/bin/openssl enc -aes256 -d -a -A -S "${2}" -k "${3}"
}
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Schedule OS Update via the API
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function scheduleOSUpdateViaAPI() {
echo "Schedule OS Update via the API …"
apiPassword=$( decryptPassword ${apiPasswordEncrypted} ${Salt} ${Passphrase} )
jamfProCompID=$( /usr/bin/curl -s -u ${apiUsername}:${apiPassword} ${jamfProURL}/JSSResource/computers/serialnumber/${computerSerialNumber}/subset/general | xpath "/computer/general/id/text()" )
# /usr/bin/curl -s -X POST -H "Content-Type: text/xml" -u ${apiUsername}:${apiPassword} ${jamfProURL}/JSSResource/computercommands/command/ScheduleOSUpdate/action/InstallForceRestart/id/${jamfProCompID}
/usr/bin/curl -s -X POST -H "Content-Type: text/xml" -u ${apiUsername}:${apiPassword} ${jamfProURL}/JSSResource/computercommands/command/ScheduleOSUpdate/action/Default/id/${jamfProCompID}
}
####################################################################################################
#
# Program
#
####################################################################################################
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Force Software Update Snippet only
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if [[ "$arch" == "arm64" ]]; then
scheduleOSUpdateViaAPI
else
/usr/sbin/softwareupdate --install --all --include-config-data --restart --force
fi
10-22-2021 11:41 AM - edited 07-01-2022 03:47 PM
I went ahead and deployed to a classroom last night and successfully updated 34 out of 36 stations from 11.5.2 to 11.6 while at the login window. I'm still at a loss as to why it's not 100%, but hopefully this will improve with Monterey. As best I can tell the Jamf side and API command is functioning, it just seems like something on the workstation(s) themselves related to softwareupdated, or other process is hindering the update. I'm still digging though logs, but I'm not coming up with anything yet.
fwiw- if it helps anyone following along, here's how I'm initiating the command via check-in from a Jamf policy script (sanitized for public view & using optional script parameters for testing... I would recommend using encrypted script parameters for production).
api user permissions are only:
Jamf Pro Server Objects: Computer: Create & Read
Jamf Pro Server Actions: Send Computer Remote Command to Download and Install macOS Update
- see newer script in thread below using updated API
Posted on 05-06-2022 10:46 AM
Love this script, thx for sharing. Working well for my tests so far with Monterey, but I have to manually click "Restart Now" in Software Update to get this to complete. Is that as intended or should this download, install and then restart automatically?
05-06-2022 11:48 AM - edited 05-06-2022 11:49 AM
Thanks Tom! My only thought is are you following up with a policy 'Restart Options' payload specifically set to 'MDM Restart with Kernel Cache Rebuild'?
I recently updated a few hundred lab stations to 12.3.1 at the login window so I know it's still working. However as I mentioned previously, I almost always have a few stations that despite receiving the mdm command never complete the update!? I suspect an Apple bug with softwareupdated, and lately I've been adding this earlier in the script. I feel like it's helping but I can't honestly say for sure. The word is that Apple patched some issues with softwareupdated in 12.3 but I've not hat time to follow up & test.
/bin/launchctl kickstart -k system/com.apple.softwareupdated
### give it 5 minutes to check for updates & sort itself out
sleep 300
Posted on 05-06-2022 12:48 PM
Ah I did not have the restart payload set in my policy! Testing now, first computer did not work, will keep working on it. Using this policy with the "Enrollment complete" trigger so when when start getting new laptops ready, one of the first things that happens is updating to latest macOS.
Where did you apply:
/bin/launchctl kickstart -k system/com.apple.softwareupdated ### give it 5 minutes to check for updates & sort itself out sleep 300
Posted on 05-06-2022 01:14 PM
@jonw actually it did work just now! Heading out for the wkd and letting another run now, will report back Monday.
05-06-2022 01:44 PM - edited 05-06-2022 01:46 PM
@TomDay Awesome! Glad to hear it.
I run the softwareupdated kickstart before everything else. I also should have mentioned the whole update process governed by api/mdm is annoyingly 'mysterious' at times, whether triggered via script or by the native Jamf action. I've seen it take up to an hour past the command being sent to see any obvious activity other than the Jamf log saying the command was successfully sent.
Posted on 02-10-2022 05:21 AM
Has anyone found a Jamf API to include the new deferral option when running the update MDM command?
03-10-2022 03:31 PM - edited 03-12-2022 02:30 PM
judging by the API commands I'm seeing, it doesn't seem like we can do this yet. =(
Posted on 03-12-2022 02:29 PM
Correction, just been noodling, and found it in the API docs.
Wrote up an advancedsearch to find machines needing 12.2.1, and then some quick powershell to grab the computers, and build the query. It SEEMS to work, but will need to test more.
Posted on 05-18-2022 12:39 PM
/bin/launchctl kickstart -k system/com.apple.softwareupdated ### give it 5 minutes to check for updates & sort itself out sleep 300
This seems to have made a big difference in the effectiveness of the ScheduleOSUpdate command for me.
Posted on 05-18-2022 01:58 PM
@jwaltonen Glad to hear it!
By the way, a new feature in the recently released Jamf 10.38.0 that looks really promising! "You can now force computers to immediately restart and install an available macOS update using the /v1/macos-managed-software-updates/send-updates endpoint via the Jamf Pro API."
I'm going to start testing asap.
Posted on 05-20-2022 07:18 AM
Maybe I spoke too soon.
With Monterey:
${jss}/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${jamfID}
Seemed to work pretty good on its own.
Adding
/bin/launchctl kickstart -k system/com.apple.softwareupdated
before the call seemed to make it work even better.
However it has done nothing for improving the situation on Big Sur endpoints.
/v1/macos-managed-software-updates/send-updates
In my limited testing this is working well for Monterey but it still very sporadic, leaning toward mostly not working for Big Sur endpoints.
I guess the solution is obvious, upgrade everything to Monterey.
07-01-2022 11:28 AM - edited 07-01-2022 11:30 AM
Hi! With Monterrey pretty sure you want to POST to
https://instance.jamfcloud.com/api/v1/macos-managed-software-updates/send-updates
https://developer.jamf.com/jamf-pro/reference/post_v1-macos-managed-software-updates-send-updates
We have tested and it works. But the thing is it's kind of just a random wait until it starts.... Wish there was a way to intercept the process start (downloading update + starting preinstall before logout) from the syslog or such other and show a notification that it's starting. Could be anywhere from 30 seconds to 15 minutes before the machine randomly reboots on the user.
07-01-2022 11:45 AM - edited 07-05-2022 03:08 PM
@BlackGloveEng1 Funny you should mention, I've actually been working on an improved script that uses the new endpoint you mention (my version above was built prior to this) which also incorporates the use of an auth bearer token.
Here's what I'm testing now. It seems pretty solid, but I'm happy to receive any constructive criticism. The only issue I've noticed is the same as before, periodically a computer will go through the motions, but no update actually occurs. I can see in the logs the API call was successfully sent, so I think this is an Apple/MDM issue, not Jamf. Running a second time almost always fixes it up. Obviously use at your own risk, you can see I only schedule this to run off hours in our unique student lab environment, ymmv.
#!/bin/bash
### Execute macOS update via MDM API - LAB
### latest update 2022.06.30 -JonW
### Use auth bearer token and new /v1/macos-managed-software-updates/send-updates endpoint found in Jamf Pro API 10.38.0+
### This is primarily intended for off hours, scheduled macOS updates while at the login window.
### Script will warn any logged-in user with a 5 minute timer, but will NOT provide an option to defer.
### Updating in this fashion eliminates the requirement for a local admin password on Silicon and also works with Intel.
### Adapting a few ideas & tips from deflounder, @talkingmoose, & @bwoods - THANK YOU!
### https://derflounder.wordpress.com/2022/01/04/basic-authentication-deprecated-for-the-jamf-pro-classic-api/
### https://community.jamf.com/t5/jamf-pro/force-a-computer-restart-to-install-macos-updates/td-p/265982
### required API permissions
### Jamf Pro Server Objects: Computer (read only - to obtain device ID)
### Jamf Pro Server Actions: Send Computer Remote Command to Download and Install macOS Update
### Ensure policy uses MDM Restart with Kernel Cache Rebuild payload
### SECURITY NOTE!!!
### We're calling the API from the local computer, and passing the API username & password...
### which can potentially expose them to a savvy local user looking at system processes!
### In this case, risk is minimized by running only while at the login window and using a unique API user & pass with limited permissions.
#################################################################################
### Jamf policy script parameters
#################################################################################
jss="$4"
apiUser="$5"
apiPass="$6"
macOSversion="$7" ### OPTIONAL - specify a macOS version to install (if not specified, latest available will apply)
applyMajorUpdate="$8" ### OPTIONAL - allow major macOS version upgrade (specify true or false)
#################################################################################
### If a user is logged in, warn to save & logout within 5 minutes!
### As we only run late on weekends, chances are slim the user is actually active,
### more likely a stuck app has halted the automatic logout process, but just to be sure...
#################################################################################
loggedInUser=$( scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ { print $3 }' )
if [[ -n "$loggedInUser" ]]; then
### Open JamfHelper dialog
buttonClicked=$(/Library/Application\ Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper \
-windowType utility \
-title "Weekly MacOS Update Policy" \
-heading "Attention! " \
-description "Automatic logout to perform updates will occur in 5 minutes! To prevent data loss, save all files and logout immediately." \
-defaultButton 1 \
-button2 "OK" \
-countdown \
-timeout 300 \
-alignCountdown center)
if [ $buttonClicked == 2 ]; then
### Button 2 clicked - user warning acknowledged
echo "User acknowledged, waiting 5 minutes for them to save & logout"
sleep 300
### Is user still logged in?
loggedInUser=$( scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ && ! /loginwindow/ { print $3 }' )
if [[ -n "$loggedInUser" ]]; then
echo "User acknowledged, but has yet to logout after 5 minutes, force logout now"
killall loginwindow ### No need to be delicate
sleep 30 ### wait for loginwindow to reload
else
echo "proceeding, user has logged out"
fi
else
### No click default = 1, the 5 minute countdown timed out
echo "proceeding, no user acknowledgement after 5 minutes, force logout now"
killall loginwindow ### No need to be delicate
sleep 30 ### wait for loginwindow to reload
fi
fi
#################################################################################
### kick softwareupdated, not required, but does 'seem' to help with success rate
#################################################################################
/bin/launchctl kickstart -k system/com.apple.softwareupdated
sleep 120 ### give it a few minutes to sort itself out
#################################################################################
### Generate Authorization Bearer Token
### (valid 30 minutes or until we invalidate)
#################################################################################
### (thanks again Der Flounder & @talkingmoose for the slick one-liner & parsing methods!)
if [[ $(/usr/bin/sw_vers -productVersion | awk -F . '{print $1}') -lt 12 ]]; then
### Pre Monterey, grab token & parse to remove quotes & expiration details
token=$(/usr/bin/curl -s "${jss}/api/v1/auth/token" -u "${apiUser}:${apiPass}" -X POST | python -c 'import sys, json; print json.load(sys.stdin)["token"]')
else
### As of Monterey, grab token and use updated plutil to pull raw token directly - no parsing necessary
token=$(/usr/bin/curl -s "${jss}/api/v1/auth/token" -s -u "${apiUser}:${apiPass}" -X POST | plutil -extract token raw -)
fi
echo "$token"
#################################################################################
### Determine Jamf Pro device id from the computer serial number (ID is required by /v1/macos-managed-software-updates endpoint)
### Note, I'm still unable to find a way to pull a device ID from the Pro API, continue using Classic for now.
#################################################################################
serialNumber=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}')
deviceID=$(/usr/bin/curl -s "${jss}/JSSResource/computers/serialnumber/${serialNumber}" -H "Authorization: Bearer ${token}" -H "Accept: text/xml" | xmllint --xpath '/computer/general/id/text()' -)
echo "Device ID" ${deviceID}
#################################################################################
### Check current macOS, and attempt to apply updates
##################################################################################
### If optional specified macOS version is equal to the current macOS, we're already up to date, exit 0
current_macOS=$( sw_vers -productVersion )
if [[ "$7" == "$current_macOS" ]]; then
echo "Specified macOS is $7"
echo "current macOS is $current_macOS"
echo "No update necessary, macOS is already at our specified version"
exit 0
fi
### If optional script parameter $8 (allow major macOS upgrade) is not explicitely set to true, force default to be false
if [[ "$8" != "true" ]]; then
applyMajorUpdate="false"
echo "allow major macOS upgrade? $applyMajorUpdate"
else
echo "allow major macOS upgrade? $applyMajorUpdate"
fi
### If the optionally specified macOS version is NOT EQUAL to the current macOS, apply it, else apply the most recently available update.
### Note! We're not validating cases where the specified version may be lower than the currently installed version.
### The internal update process 'should' automatically ignore these attempts, but I've not yet tested the theory!
if [[ $7 != "" ]]; then
echo "attempting to apply specified macOS version $7"
/usr/bin/curl -s -X POST \
--url "${jss}/api/v1/macos-managed-software-updates/send-updates" \
--header "Authorization: Bearer ${token}" \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--data @<(cat <<EOF
{
"deviceIds": [
"$deviceID"
],
"maxDeferrals": 0,
"version": "$macOSversion",
"skipVersionVerification": true,
"applyMajorUpdate": $applyMajorUpdate,
"updateAction": "DOWNLOAD_AND_INSTALL",
"forceRestart": true
}
EOF
)
else
echo "attempting to apply the latest available macOS version"
/usr/bin/curl -s -X POST \
--url "${jss}/api/v1/macos-managed-software-updates/send-updates" \
--header "Authorization: Bearer ${token}" \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--data @<(cat <<EOF
{
"deviceIds": [
"$deviceID"
],
"maxDeferrals": 0,
"skipVersionVerification": true,
"applyMajorUpdate": $applyMajorUpdate,
"updateAction": "DOWNLOAD_AND_INSTALL",
"forceRestart": true
}
EOF
)
fi
#################################################################################
### Invalidate our token
#################################################################################
/usr/bin/curl -s "${jss}/api/v1/auth/invalidate-token" -H "Authorization: Bearer ${token}" -X POST
Posted on 08-16-2022 04:58 PM
Man, you are a rock star! This was next on my list to tackle. I have a great script to do erase and install, but getting user boxes updated when the user isn't an admin has been a giant pain in the butt. I am thinking I can scope this to an item in Self Service so the user can click on the item, have it display the dialog to save any work, then have it do the update...that would be awesome. For the labs, run it on a schedule.
08-26-2022 08:11 AM - edited 08-26-2022 08:13 AM
@kwoodard Thanks! Sorry for the late response, it's been crazy busy around here. But yeah, my intention for this was unattended lab stations. It would need some tweaking for standard users due to the heavy-handed logout, and despite working well late at night in labs, there's no real indication that the MDM call is going to take effect. I still see about 10% of my computers randomly ignore the command and need a 2nd attempt. The command is successfully sent & logged, the update just doesn't kick off. I would probably suggest something else to notify/allow your standard users to kick off updates (upgrades are another issue).
Posted on 02-24-2023 08:58 AM
Hey Jon. I am attempting to implement your script for our MacOS updates. I am new to JAMF and Mac administration so bear with me. First, I can get the logout prompt to work and it will logout the user, but I think I might have the parameters for $4 $5 and $6 incorrect. For $4 I have our jss url https://mycompany.jamfcloud.com/ ; for $5 and $6 I am using our admin account that we have on all managed devices. So the current flow of everything is that it will log the user out automatically after the timer expires, but the updates never download and install automatically. Any potential help would be greatly appreciated. Thanks.
Posted on 02-13-2023 08:20 AM
I think this might be a good place to take this up.
I have been using the following API command with great success, to force OS updates in the middle of the night:
curl -X POST "https://ourJamfCloudAddress/api/v1/macos-managed-software-updates/send-updates" -H "accept: application/json" -H "Authorization: Bearer $api_token" -H "Content-Type: application/json" -d "{\"deviceIds\":[\"${computerID}\"],\"maxDeferrals\":0,\"skipVersionVerification\":true,\"applyMajorUpdate\":false,\"updateAction\":\"DOWNLOAD_AND_INSTALL\",\"forceRestart\":true}"
This has brought hundreds of computers up from 12.3 ish all the way up through 13.1 one point update at a time.
Personally I feel as if this command as written above should not have moved the machines from 12 to 13 given applyMajorUpdate is set to false. But it did. That's another story though.
Whats more upsetting is that now on 13.1 almost none of the intel machines will go to 13.2. Maybe 3 out of 300 made it. All of the Apple silicon macs did do the updates. I have way more intel classroom computers than Apple Silicon ones though.
Anyone else using a similar command and seeing similar results after 13.1 ?
Also of note, an MDM command with similarly optioned, pushed from the webui also does not work to move the intels past 13.1.
02-13-2023 08:42 AM - edited 02-13-2023 08:49 AM
Apple released macOS 13 as a minor update. So even if you didn't tick 'include Major updates', it would still upgrade the devices. 12.6.2 would upgrade whereas 12.6.3 would not, Apple realized what they had done and patched 12.6.3 to not auto upgrade, but for most people it was too late. There was an Apple Support article about this issue and how to block it but I can't find it right now.
I have the opposite problem, I have 25x arm64 iMacs stuck on 13.1
For Intel devices I try more draconian tactics using software update:
softwareupdate -i -a -R
If that doesn't work you can deploy the full 13.2 app installer out to the device and run the startosinstall command to auto upgrade the device.
/Applications/Install\ macOS\ Ventura.app/Contents/Resources/startosinstall --agreetolicense --nointeraction --forcequitapps
Add a restart command if its needed.
Use the 'Download Full Installer' app to download the 12.5Gb PKG installer from Apple.
https://github.com/scriptingosx/DownloadFullInstaller
You can also try:
softwareupdate --fetch-full-installer --full-installer-verson 13.2
and run the startosinstall command after that. Although this method isn't always successful at downloading the full installer app.
Also, make sure your Intel devices don't have pending MDM commands stuck in them (check the management tab is clear of pending & failed commands). If so, they will block the upgrade MDM commands as they will be added to the bottom of the list of pending commands. You may need to cancel all MDM commands on the Intel devices via a mass action before sending the upgrade OS MDM command.
Posted on 02-13-2023 10:44 AM
"softwareupdate -i -a -R"
Hasn't worked for me since Big Sur. A couple machines will update, most all just reboot without applying the update.
"25x arm64 iMacs stuck on 13.1"
How are you trying to update them?
"full installer app"
Was trying to avoid that but it looks like that may be the only option right now.
Posted on 02-13-2023 11:14 AM
yeah, that won't work for Apple silicon generally. use the API to push an MDM command is your best bet, or something like Nudge (https://github.com/macadmins/nudge) for user driven update, or Super (https://github.com/Macjutsu/super) for more IT driven side.
02-13-2023 11:16 AM - edited 02-13-2023 11:19 AM
Big Sur has issues with software update.
In some cases it will say there are no updates available. In other cases it will say it cannot reach the Apple servers. Yet, if you manually upgrade the same machine to macOS 12 using the same wall port, it will suddenly reach the Apple servers and find updates. O_o? Big Sur has bugs I guess.
25x arm64 - Using a mass action update command via Jamf GUI.
They all went through ADE, are all supervised, all have a bootstrap token escrowed in Jamf, none have pending or failed MDM commands and are all checking in regularly with the Jamf server.
I think for me it may be a network related issue (SCEP) as arm64 devices upgrade fine at one campus (using a mass action) but not at the other campus for those specific rooms.
Full installer app
I have found this to be the most reliable option on older machines that wont play ball and that don't work properly or reliably with softwareupdate.
Posted on 02-27-2023 11:25 AM
-ir --verbose
has been working for me on intel machines. Still working on Silicon.
Posted on 02-24-2023 07:44 AM
Hey all. Have you guys found that using a tool such as the "Download Full Installer" and then using script to run it as the most efficient way to get updates pushed? When going this route, would the user still be able to deny the update? As part of new security requirements at my company we have to be able to push the updates at "X" time and the user will be prompted, but can't defer past a certain time. We have a mixture of Apple and Intel silicon devices. I haven't specifically tested/tried any of the scripts posted here, but I am just trying to do more research before implementing any of them. Thanks.
Posted on 08-07-2023 01:55 AM
Morning All
Just testing this scripit out on some of our M1 devices can anyone help with what this means,
Script result: eyJhbGciOiJIUzI1NiJ9.eyJhdXRoZW50aWNhdGVkLWFwcCI6IkdFTkVSSUMiLCJhdXRoZW50aWNhdGlvbi10eXBlIjoiSlNTIiwiZ3JvdXBzIjpbXSwic3ViamVjdC10eXBlIjoiSlNTX1VTRVJfSUQiLCJ0b2tlbi11dWlkIjoiMTZhZGQ3MmMtNjc3Ny00OTE2LTk5OWYtNGI5MzdhZTY3ZTEzIiwibGRhcC1zZXJ2ZXItaWQiOi0xLCJzdWIiOiI2IiwiZXhwIjoxNjkxMzk5MzMwfQ.poPO9MR8WkBRU4Eusfp0TDraRPl9eUNDBk5qcpNEq0E
Device ID 2824 allow major macOS upgrade? false attempting to apply the latest available macOS version { "processManagerUuids" : [ "d4bb3d33-8747-4912-9282-7c106bc7be29" ], "errors" : [ ]
Thanks
Posted on 08-07-2023 05:29 AM
Posted on 08-07-2023 05:48 AM
@dan-snelson Im looking for something that can be run independently as I was hoping to use this in lab based enviorments out of hours.
We currently use MDM software update workflows but its not very reliable.
It seems to be going through the motions but never seems to be update.
Thanks