Apple M1 issue with softwareupdate -aiR

gforsyth
New Contributor III

I currently leverage a smart group, softwareupdate -aiR, custom notifications and the deferral option for an automated OS patching workflow both myself and user base are really happy with.

In testing the m1 chipset I am finding softwareupdate -aiR isn't functional in the workflow. Looks like there is an additional prompt for a password prior to downloading??? Anyone seen this or have any ideas as to why?

263e24affc164d3eb6374f0c71b8557e

62 REPLIES 62

Aw nuts. My bad. I'll have to get that set up. thanks!

And I'm back again, just to report what I've got so far.

My test machine has bootstrap token enabled and escrowed. The API user has the correct permissions. The little script is setup to be run from self service in a simple policy. Here's the script:

#!/bin/sh
# apiMDMupdatesoftware.sh
# api call to send MDM command to a machine to update apple system software.
apiUsername=$4
apiPassword=$(echo ${5} | base64 --decode)
jamfProURL="https://jamf01.spimageworks.com:8443"
macSerial=$(system_profiler SPHardwareDataType | awk '/Serial Number/{print $4}')
jamfProCompID=$(curl -s -u $apiUsername:$apiPassword -H "Accept: text/xml" "$jamfProURL"/JSSResource/computers/serialnumber/"$macSerial" | xmllint --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/install/id/${jamfProCompID}


I get this little pop-up when I first run the policy:

Screen Shot 2022-02-15 at 5.15.55 PM.png

Which is fine for now, I'm just trying to get this to work. 

Here's the output from the logs on JAMF:

Script result: <?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>ScheduleOSUpdateScan</name><command_uuid>10ac1fea-25df-4b15-a69e-ca8b66432025</command_uuid><computer_id>3706</computer_id></command></computer_command>

But then nothing happens. I let my test machine run for hours and there was no update. I also kept an eye on the update processes in Activity Monitor under Network and nothing really seemed like it was downloading.

Any help would be much appreciated. Thanks!

Aw nuts. I just had a thought. We disable the Software Update Pref Pane in system prefs with the Restrictions payload, as well as Software Update Notifications.  I'm not sure if this effects the MDM command. 

bwoods
Valued Contributor

The next time you run this command, look up the computer you ran it on and navigate to the management tab. Post a screenshot of what you see. 

Sorry, I got side tracked testing out Nudge, which turns out to be a bit of a waste for my environment. 

I guess it's back to the MDM command. I'll get that screenshot.

Here you go, is this what I'm looking for?
Screen Shot 2022-02-23 at 2.38.36 PM.png

Ok it finally actually ran. Here's the history of the commands:
Screen Shot 2022-02-23 at 3.17.21 PM.png

It took a while for the machine to actually restart, and when it did restart there was no warning, so right away my users will be pissed. Then it went through a few blank screens and some fits and starts, and the login screen popped up, then it actually installs the update after logging in.

I need a way to show my users what is happening during the time that our JAMF server is running various commands and the update is downloading and then warn them before the machine actually restarts, so they can save their work.  Most of our users are artists, so they expect the system to just work and never lose data. There's alot of hand holding involved in even the smallest task. I really hope apple or JAMF can clean this mess up.

I hate to revive this dead horse, but I was wondering if anyone had a way to warn users before their machine restarts after the MDM command runs?  Otherwise the user gets like 45mins of nothing then BAM their machine just reboots. I've had complaints. My users need alot of hand holding.

bwoods
Valued Contributor

Late response, but I just let them know that information with a jamf helper window. "Your machine will reboot anywhere between 15-60 minunutes." 

 

roach
New Contributor III

@bwoods, can you send messages thru MDM commands? If so where is the input?

roach
New Contributor III

For hand holding, I run the API script using a 30 day deferral policy. The 'User Interaction' tab will give you all the necessary messaging.

corrymc
New Contributor

So, this script does a download only and I still need to login and finish the updates?  It seems it just takes the place of running the Management command on every computer, right? Until the 'InstallForceRestart'  is supported?

+1 on this question. 

bwoods
Valued Contributor

It downloads and updates the mac. From what I can see, the user must be logged in.

alv2015591
New Contributor III

#!/bin/bash
## Documentation Text V3
## 

## Logging during runtime
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>/private/var/Path/to/Local/Log/ScheduleOSUpdate.log 2>&1
exec 2>>/private/var/Path/to/Local/LogScheduleOSUpdateErr.log 4>&2

jssurl="JamfProURL"
jamfManagementURL="JamfproURL"
apiuser="apiuser"
apipass="apipassword"
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')

<<'DOCUMENTATION'

Note the – The computer needs to be on power, or nothing happens
The user will be prompted for their password if it's on power added to your saved items

curl -sSu "$destinationJSSuser:$destinationJSSpw" $JSSURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${id} -X "POST"

Also the machine needs to be supervised
If it's not supervised doing the FileVault 2 key re-escrow will supervise it in macOS 11

DOCUMENTATION

clearfailedmdmcommands() {
    /usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443/JSSResource/commandflush/computers/id/"$computerID"/status/Failed -X DELETE
}
getjsscomputerid() {
    computerID=$(/usr/bin/curl -u "$apiuser":"$apipass" "$jssurl":8443/JSSResource/computers/serialnumber/"$serial" -H "accept: text/xml" | /usr/bin/xpath -e "/computer[1]/general/id/text()")
}

getfailedmdmcommands() {
    xmlresult=$(/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443//JSSResource/computerhistory/serialnumber/"$serial"/subset/Commands -X GET -H "accept: application/xml" | /usr/bin/xpath -e "/computer_history/commands/failed")
}

startupdate() {
    #curl -s -f -X "POST" "$jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/$jamfComputerID"
    #curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
    curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
}

echo "updating device"
####### SCRIPT

getfailedmdmcommands

# An empty failed XML node will look like this: <failed />
parseresult=$(/bin/echo "$xmlresult" | /usr/bin/grep "<failed />")
exitcode=$(/bin/echo $?)

# Clear failed MDM commands if they exist
if [ "$exitcode" != 0 ]; then
   
    getjsscomputerid
   
    /bin/echo "Removing failed MDM commands ..."
   
    clearfailedmdmcommands
   
    result="Removed Failed MDM Commands"
    echo "starting MacOS SoftwareUpdate"
    startupdate
else
    /bin/echo "No failed MDM commands exist."
   
    result="No Failed MDM Commands Exist"
    echo "starting MacOS SoftwareUpdate"
    getjsscomputerid
    startupdate
fi

/bin/echo "<result>$result</result>"

exit

Does this work for you in your environment? Is it reliable?

Here I formatted your script for this thread, easier to read that way.

#!/bin/bash
## Documentation Text V3
## 

## Logging during runtime
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>/private/var/Path/to/Local/Log/ScheduleOSUpdate.log 2>&1
exec 2>>/private/var/Path/to/Local/LogScheduleOSUpdateErr.log 4>&2

jssurl="JamfProURL"
jamfManagementURL="JamfproURL"
apiuser="apiuser"
apipass="apipassword"
serial=$(/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice | /usr/bin/awk -F'"' '/IOPlatformSerialNumber/{print $4}')

<<'DOCUMENTATION'

Note the – The computer needs to be on power, or nothing happens
The user will be prompted for their password if it's on power added to your saved items

curl -sSu "$destinationJSSuser:$destinationJSSpw" $JSSURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${id} -X "POST"

Also the machine needs to be supervised
If it's not supervised doing the FileVault 2 key re-escrow will supervise it in macOS 11

DOCUMENTATION

clearfailedmdmcommands() {
    /usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443/JSSResource/commandflush/computers/id/"$computerID"/status/Failed -X DELETE
}
getjsscomputerid() {
    computerID=$(/usr/bin/curl -u "$apiuser":"$apipass" "$jssurl":8443/JSSResource/computers/serialnumber/"$serial" -H "accept: text/xml" | /usr/bin/xpath -e "/computer[1]/general/id/text()")
}

getfailedmdmcommands() {
    xmlresult=$(/usr/bin/curl -sfku "$apiuser":"$apipass" "$jssurl":8443//JSSResource/computerhistory/serialnumber/"$serial"/subset/Commands -X GET -H "accept: application/xml" | /usr/bin/xpath -e "/computer_history/commands/failed")
}

startupdate() {
    #curl -s -f -X "POST" "$jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/$jamfComputerID"
    #curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
    curl -sSu "$apiuser:$apipass" $jamfManagementURL/JSSResource/computercommands/command/ScheduleOSUpdate/action/install/id/${computerID} -X "POST"
}

echo "updating device"
####### SCRIPT

getfailedmdmcommands

# An empty failed XML node will look like this: <failed />
parseresult=$(/bin/echo "$xmlresult" | /usr/bin/grep "<failed />")
exitcode=$(/bin/echo $?)

# Clear failed MDM commands if they exist
if [ "$exitcode" != 0 ]; then
   
    getjsscomputerid
   
    /bin/echo "Removing failed MDM commands ..."
   
    clearfailedmdmcommands
   
    result="Removed Failed MDM Commands"
    echo "starting MacOS SoftwareUpdate"
    startupdate
else
    /bin/echo "No failed MDM commands exist."
   
    result="No Failed MDM Commands Exist"
    echo "starting MacOS SoftwareUpdate"
    getjsscomputerid
    startupdate
fi

/bin/echo "<result>$result</result>"

exit



alv2015591
New Contributor III

yes it works as long as the device is on and available it works... 

 

bwoods
Valued Contributor

Moving away from the classic API to utilize the new features in the json version. Will use something similar to the function below to run the update. This does take bearer tokens into account. Still waiting for 10.38 to release to use the new force update feature. Updated progress can be found here

 

 

 

 

 

 

 

#!/bin/bash
# server connection information
URL="https://your.jamfcloud.com"
username="username"
password="password"

# created base64-encoded credentials
encodedCredentials=$( printf "${username}:${password}" | /usr/bin/iconv -t ISO-8859-1 | /usr/bin/base64 -i - )
	
# Generate new auth token
authToken=$( curl -X POST "${URL}/api/v1/auth/token" -H "accept: application/json" -H "Authorization: Basic ${encodedCredentials}" )
	
# parse authToken for token, omit expiration
token=$(/usr/bin/awk -F \" 'NR==2{print $4}' <<< "$authToken" | /usr/bin/xargs)
	
echo ${token}
	
# Execute software update
curl -X POST "${URL}/api/v1/macos-managed-software-updates/send-updates" -H "accept: application/json" -H "Authorization: Bearer ${token}" -H "Content-Type: application/json" -d "{\"deviceIds\":[\"1444\"],\"maxDeferrals\":0,\"version\":\"12.3.1\",\"updateAction\":\"DOWNLOAD_AND_INSTALL\"}"
	
# Invalidate existing token and generate new token
curl -X POST "${URL}/api/v1/auth/keep-alive" -H "accept: application/json" -H "Authorization: Bearer ${token}"

 

 

 

 

 

 

Do you have a Gist or Github like that you keep updated @bwoods ? I'd like to follow this and see what comes of it.

bwoods
Valued Contributor

@nwagner I do not have Gist or Github. But you can help me work on this here

PhillyPhoto
Contributor III

I tried to get this working, but it prints the password before it actually prompts for it. My script:

 

userpassword=$(osascript -e 'display dialog "Please enter your login password." default answer "" with icon stop buttons {"Cancel", "Continue"} default button "Continue" with hidden answer' | awk -F ':' '{print $3}')
    
expect -c "
    spawn softwareupdate -i \"$4\" -R
    expect "Password*"
    send "{${userpassword}}"
    expect "Password*"
    send "{${userpassword}}"
    expect eof
    "

 

 From Terminal (1234 is the password I'm trying with):

 

spawn softwareupdate -i macOS Monterey 12.6-21G115 -R
Software Update Tool

Finding available software
1234Downloading macOS Monterey 12.6
Password: 

 

When I add the "set timeout -1" part in the expect section, it doesn't print the password early, but it doesn't seem to print it at all either since it just sits on the Password: prompt.

roach
New Contributor III

@PhillyPhoto I recommend you abandon ship and use Nudge: https://github.com/macadmins/nudge/wiki/Jamf-Pro-Guide

I needed to migrate users from BigSur to Monterey on Intels and M1s using a deferral. Nudge checked all the boxes for me, and it's highly customizable. Make sure you set it up to ping your Self Service policy rather than the installer from the applications folder.  I used this for the policy execute command:

echo "password" | /Applications/Install\ macOS\ Monterey.app/Contents/Resources/startosinstall --user admin --stdinpass --agreetolicense --nointeraction --forcequitapps --pidtosignal

 

bwoods
Valued Contributor

@PhillyPhoto I completely agree with @roach. Use Nudge or S.U.P.E.R.M.A.N to get your updates out reliably.