Posted on 03-12-2021 07:03 AM
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?
Posted on 03-12-2021 07:40 AM
iOS and Apple Silicon both act the same with updates; they need to be approved by a user process, or via an APNS command.
You either have to pass credentials to this process using something like 'expect' (not a great idea), or rely on your MDM service to send download/download and install calls via an API call.
Posted on 03-12-2021 07:41 AM
Check this out.. Having the same issues. I'm able to use some trickery to get it working on Big Sur on Intel, but for M1, the updates are downloading but not installing.
Posted on 03-12-2021 07:52 AM
Ugh... The API call is something I was looking into but that actually throws the unit into a recovery mode and requires user credentials which is clunky and confusing from a UX perspective... I will keep digging and call Apple. Thanks to you both!
Posted on 04-28-2021 05:18 PM
Same issue with M1s. I've been using this setup for patching and it's super slick, but on the M1s, it stalls out because it's waiting for a password. :(
Posted on 04-29-2021 04:30 AM
I've got it working now with prompting the user for their password and then using an except script to run the softwareupdates -iaR command. Not the best thing in the world, but at least I can run the updates via command line. Only downside is if the user doesn't read the warning/prompt saying you'll be asked for your password and don't enter it. Then the command will not run.
Posted on 04-29-2021 08:16 AM
@DBrowning Would you mind sharing the logic you are using to utilize the user input? I have scripts that can prompt for user input, but don't know how to take that and pass it into the -iaR component.
Posted on 04-29-2021 08:19 AM
Here you go @kendalljjohnson
echo "Running updates for Apple Silicon Mac"
expect -c "
set timeout -1
spawn login $LoggedInUser
expect "Password:"
send "{${USER_PASS}}"
send
spawn sh -c {sudo /usr/sbin/softwareupdate -iaR}
expect "Password:"
send "{${USER_PASS}}"
send
expect "Password:"
send "{${USER_PASS}}"
send
expect eof
"
Posted on 04-29-2021 08:22 AM
Much appreciated, thanks!
Posted on 05-03-2021 08:52 AM
The solution worked for me thanks to the community and the members for the solution.
Posted on 05-03-2021 01:42 PM
@DBrowning I tried your script and I am getting this error as shown in the policy log. I'm trying to update my M1 MBA with 11.3.1 just released. What am I doing wrong? Is there a way to hide error output to prevent the password from being logged?
Script result: Password Check: PASSED
Running updates for Apple Silicon Mac
send: spawn id exp48 not open
while executing
"send {MyPassword}”
Posted on 05-03-2021 01:52 PM
Here is the full script that I am using. I made a few changes from script that I found on Jamf.
Credit goes to you and Mauricio
https://www.jamf.com/jamf-nation/discussions/35899/verify-password-is-correct
#!/bin/bash
#########################################################################################
#
# FUNCTIONS
#
#########################################################################################
wrongUserPassword() {
userResponce=$(sudo -u "$userName" osascript <<EOF
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set theTextReturned to "nil"
set theIcon to POSIX file "/Users/Shared/logo.png" as alias
set appTitle to "macOS update"
set okTextButton to "OK"
set enterPassword to "Enter your password to start the update"
set passwordWrong to "Incorrect Password"
set errorPasswordText to passwordWrong & return & enterPassword
set theResponse to display dialog {errorPasswordText} default answer "" buttons {okTextButton} default button 1 with title {appTitle} with icon theIcon with hidden answer giving up after 600
set theTextReturned to the text returned of theResponse
if theResponse is gave up then
return "cancelled"
else if theTextReturned is "" then
return "nopassword"
else
return theTextReturned
end if
EOF
)
validatePassword "$userResponce"
}
noUserPassword() {
userResponce=$(sudo -u "$userName" osascript <<EOF
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set theTextReturned to "nil"
set theIcon to POSIX file "/Users/Shared/logo.png" as alias
set appTitle to "macOS update"
set okTextButton to "OK"
set enterPassword to "Enter your password to start the update"
set passwordEmpty to "The password is empty."
set errorPasswordText to passwordEmpty & return & enterPassword
set theResponse to display dialog {errorPasswordText} default answer "" buttons {okTextButton} default button 1 with title {appTitle} with icon theIcon with hidden answer giving up after 600
set theTextReturned to the text returned of theResponse
if theResponse is gave up then
return "cancelled"
else if theTextReturned is "" then
return "nopassword"
else
return theTextReturned
end if
EOF
)
validatePassword "$userResponce"
}
promptUserPassword() {
userResponce=$(sudo -u "$userName" osascript <<EOF
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set theTextReturned to "nil"
set theIcon to POSIX file "/Users/Shared/logo.png" as alias
set appTitle to "macOS update"
set okTextButton to "OK"
set changesText to "One or more Apple Updates are availalbe." & return & "It may take 30-60 minutes to complete." & return & "To continue with macOS update" & return & return & "Enter login password for $userName"
set theResponse to display dialog {changesText} default answer "" buttons {okTextButton} default button 1 with title {appTitle} with icon theIcon with hidden answer giving up after 600
set theTextReturned to the text returned of theResponse
if theResponse is gave up then
return "cancelled"
else if theTextReturned is "" then
return "nopassword"
else
return theTextReturned
end if
EOF
)
}
verifyPassword() {
dscl . authonly "$userName" "$userResponce" &> /dev/null; resultCode=$?
if [ "$resultCode" -eq 0 ];then
echo "Password Check: PASSED"
else
# Prompt for User Password
echo "Password Check: WRONG PASSWORD"
wrongUserPassword
fi
}
validatePassword() {
case "$userResponce" in
"nopassword" ) echo "Password Check: NO PASSWORD" & noUserPassword ;;
"cancelled" ) echo "Password Check: Time Out" ;;
* ) verifyPassword ;;
esac
}
##########################################################################################
#
# SCRIPT CONTENTS
#
##########################################################################################
# Get the Username of the currently logged user
userName=$(ls -la /dev/console | cut -d " " -f 4)
# Ask the logged user for the password
promptUserPassword "$userName"
# Check is password is correct
validatePassword "$userResponce"
if [ $userResponce = "cancelled" ]; then
echo "Password entry was cancelled"
else
echo "Running updates for Apple Silicon Mac"
expect -c "
set timeout -1
log_user 0
spawn login $userName
expect "Password:"
send "{${userResponce}}"
send
spawn sh -c {sudo /usr/sbin/softwareupdate -iaR}
expect "Password:"
send "{${userResponce}}"
send
expect "Password:"
send "{${userResponce}}"
send
expect eof
"
fi
01-22-2022 12:59 PM - edited 01-23-2022 09:35 PM
Hi, I am currently getting this on a M1 MacBook Air using the above script. Can anyone help to execute the script fully?
Thx, Alex
Posted on 02-11-2022 03:54 PM
I had to edit out the blank send commands, like so:
AdminUser=$4
AdminPass=$5
#Hope this works for Intel & Apple Silicon
echo "Running updates"
expect -c "
set timeout -1
spawn login $AdminUser
expect "Password:"
send "{${AdminPass}}"
spawn sh -c {sudo /usr/sbin/softwareupdate -iaR --verbose | tee -a /var/log/jamf.log}
expect "Password:"
send "{${AdminPass}}"
expect "Password:"
send "{${AdminPass}}"
expect eof
"
Credit to @DBrowning
I figured the "send " parts of that little expect block weren't acting like newlines or returns or anything so I removed them.
Then I thought I'd just use a local admin:pass to run the update. That way we get around the fact that our users don't have sudo rights.
It appears to be working on an intel I'm testing right now, and I'll test on an M1 as soon as I get a chance.
Note the parameter numbers so you don't have to have user names or passwords written into a script.
Hope that helps.
Posted on 05-03-2021 03:32 PM
@EdLuo Here is the code from my script that works. I'm not sure how not to show the password in the instance of a failure.
#!/bin/sh
LoggedInUser=`ls -l /dev/console | cut -d " " -f4`
archType=$(/usr/bin/arch)
CURRENT_USER="$(stat -f%Su /dev/console)"
USER_ID=$(id -u "$CURRENT_USER")
jamfHelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
#Prompting logged in user for password
USER_PASS="$(launchctl asuser "$USER_ID" osascript -e 'display dialog "Please enter your computer password to begin the monthly patching process:" default answer "" with title "Monthly Patching Big Sur" giving up after 86400 with text buttons {"OK"} default button 1 with hidden answer' -e 'return text returned of result')"
#Testing password. Fails after 3 invalid attempts
TRY=1
until dscl /Search -authonly "$CURRENT_USER" "$USER_PASS" &>/dev/null; do
(( TRY++ ))
echo "Prompting $CURRENT_USER for their Mac password (attempt $TRY)..."
USER_PASS="$(launchctl asuser "$USER_ID" osascript -e 'display dialog "Please enter your computer password to begin the monthly patching process:" default answer "" with title "Monthly Patching Big Sur" giving up after 86400 with text buttons {"OK"} default button 1 with hidden answer' -e 'return text returned of result')"
if (( TRY >= 3 )); then
echo "[ERROR] Password prompt unsuccessful after 3 attempts. Displaying "forgot password" message..."
launchctl asuser "$USER_ID" "$jamfHelper" -windowType "utility" -title "Password Invalid" -description "You made three incorrect password attempts.
Please reach out to your local Desktop Support Group or Chat for assistance" -button1 'OK' -defaultButton 1 -timeout 300 -startlaunchd &>/dev/null &
exit 1
fi
done
if [ $archType == "i386" ]; then
echo "Running updates for Intel Mac"
/usr/bin/su -l $LoggedInUser -c "echo $USER_PASS | sudo -S /usr/sbin/softwareupdate -iaR --verbose" | tee -a /var/log/jamf.log
else
echo "Running updates for Apple Silicon Mac"
expect -c "
set timeout -1
spawn login $LoggedInUser
expect "Password:"
send "{${USER_PASS}}"
send
spawn sh -c {sudo /usr/sbin/softwareupdate -iaR --verbose | tee -a /var/log/jamf.log}
expect "Password:"
send "{${USER_PASS}}"
send
expect "Password:"
send "{${USER_PASS}}"
send
expect eof
"
fi
Posted on 05-04-2021 04:22 AM
Hi,
Also trying this out.
Anyone else getting this on M1 Airs? (see image)
Also, possible to not post the password in the script result? Would love to not see the Users passwords.
Posted on 05-26-2021 01:07 PM
I got it working. Here is my update script minus some personalization.
#!/bin/bash
#########################################################################################
#
# FUNCTIONS
#
#########################################################################################
runAsUser() {
if [ "$currentUser" != "loginwindow" ]; then
launchctl asuser "$uid" sudo -u "$currentUser" "$@"
else
echo "no user logged in"
exit 1
fi
}
wrongUserPassword() {
userResponce=$(runAsUser osascript <<EOF
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set theIcon to POSIX file "/Users/Shared/PNG/Logo.png" as alias
set appTitle to "macOS update"
set okTextButton to "OK"
set enterPassword to "Enter your password to start the update"
set passwordWrong to "Incorrect Password"
set errorPasswordText to passwordWrong & return & enterPassword
set theResponse to display dialog {errorPasswordText} default answer "" buttons {okTextButton} default button 1 with title {appTitle} with icon theIcon with hidden answer giving up after 600
set theTextReturned to the text returned of theResponse
if theResponse is gave up then
return "cancelled"
else if theTextReturned is "" then
return "nopassword"
else
return theTextReturned
end if
EOF
)
validatePassword "$userResponce"
}
noUserPassword() {
userResponce=$(runAsUser osascript <<EOF
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set theIcon to POSIX file "/Users/Shared/PNG/Logo.png" as alias
set appTitle to "macOS update"
set okTextButton to "OK"
set enterPassword to "Enter your password to start the update"
set passwordEmpty to "The password is empty."
set errorPasswordText to passwordEmpty & return & enterPassword
set theResponse to display dialog {errorPasswordText} default answer "" buttons {okTextButton} default button 1 with title {appTitle} with icon theIcon with hidden answer giving up after 600
set theTextReturned to the text returned of theResponse
if theResponse is gave up then
return "cancelled"
else if theTextReturned is "" then
return "nopassword"
else
return theTextReturned
end if
EOF
)
validatePassword "$userResponce"
}
promptUserPassword() {
userResponce=$(runAsUser osascript <<EOF
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set theIcon to POSIX file "/Users/Shared/PNG/Logo.png" as alias
set appTitle to "macOS update"
set okTextButton to "OK"
set changesText to "One or more Apple Updates are available." & return & "Depending on the speed of the internet connection, it may take 30-90 minutes to complete." & return & return & "Warning! Update will take place in the background and a reboot will likely take place when done without warning." & return & return & "To continue with macOS update, enter login password for $currentUser"
set theResponse to display dialog {changesText} default answer "" buttons {okTextButton} default button 1 with title {appTitle} with icon theIcon with hidden answer giving up after 600
set theTextReturned to the text returned of theResponse
if theResponse is gave up then
return "cancelled"
else if theTextReturned is "" then
return "nopassword"
else
return theTextReturned
end if
EOF
)
}
verifyPassword() {
dscl . authonly "$currentUser" "$userResponce" &> /dev/null; resultCode=$?
if [ "$resultCode" -eq 0 ];then
echo "Password Check: PASSED"
# DO THE REST OF YOUR ACTIONS....
else
# Prompt for User Password
echo "Password Check: WRONG PASSWORD"
wrongUserPassword
fi
}
validatePassword() {
case "$userResponce" in
"nopassword" ) echo "Password Check: NO PASSWORD" & noUserPassword ;;
"cancelled" ) echo "Password Check: Time Out" ;;
* ) verifyPassword ;;
esac
}
##########################################################################################
#
# SCRIPT CONTENTS
#
##########################################################################################
#Check for Company Logo
if [ -e /Users/Shared/PNG/Logo.png ]; then
echo "Logo exist"
else
echo "Installing logo"
# You will need to create a seperate policy that deploys your company logo with event trigger DeployLogo
jamf policy -event DeployLogo
fi
# Get the Username of the currently logged user
currentUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }' )
uid=$(id -u "$currentUser")
echo "Logged in user: $currentUser"
# Ask the logged user for the password
promptUserPassword "$currentUser"
# Check is password is correct
validatePassword "$userResponce"
# Automated Install of Update
if [ $userResponce = "cancelled" ]; then
echo "Password entry was cancelled"
else
echo "Running updates for Apple Silicon Mac"
runAsUser expect -c "
set timeout -1
spawn sudo /usr/sbin/softwareupdate -iaR
expect "Password:"
send "$userResponce"
expect "Password:"
send "$userResponce"
expect eof
"
fi
08-26-2021 06:59 AM - edited 08-27-2021 06:17 AM
@EdLuo Hello, I'm not a scripter by far. I'm attempting to utilize your script. I have created another package and added DeployLogo to Execute Command. So this part works. What else do I need to have occur to get patching underway for M1? I'm not sure what 'expect script' does. Can someone reach out to me to assist? Thanks very much.
Posted on 05-26-2021 03:05 PM
@EdLuo - Nice script! I did run this and it looks like Self Service needs to quit before it restarts.
Posted on 05-27-2021 10:07 AM
I didn't use my script in Self Service. I just basically scoped it to Apple Silicon computer with one or more updates. I have also setup a deferral so our users can delay the installation.
Posted on 06-23-2021 01:27 PM
Deleted
Posted on 08-02-2021 07:07 AM
@EdLuousing the expect script, my M1 outputs that its "Restarting", but doesn't restart.
After reboot, I have to re-run it to download the update and install it which again might not re-start automatically. Did you face a similar issue?
Posted on 08-02-2021 09:42 AM
I just try update my M1 from 11.5 to 11.5.1 and it kicked off the process without any issue. It is still updating. How are you running the script? Policy Trigger, Self Service, or from Terminal?
08-02-2021 09:46 AM - edited 08-02-2021 09:51 AM
It's an expect script and I trigger it via bash in background using: bash -c "script.exp"
#! /usr/bin/expect -f
set password "mypassword"
set timeout -1
exp_internal -f /tmp/expect.log 0
spawn sudo /usr/sbin/softwareupdate -iR "macOS Big Sur 11.5.1-20G80"
expect "Password*"
send "$password\r"
expect "Password*"
send "$password\r"
expect eof
Output:
Downloading: 98.56%
Downloading: 99.90%
Downloading: 100.00%
Downloaded: macOS Big Sur 11.5.1
Restarting...
Sometimes when it does restart, the OS isn't updated.
Posted on 08-02-2021 11:23 AM
Not sure why it is not working for you. I had trouble getting the expect command to work until I incorporated that runAsUser() function. See if you can add that into your code. I'm thinking that the softwareupdate -iR needs to be run with the logged in user's account.
08-26-2021 12:12 PM - edited 08-27-2021 06:13 AM
08-02-2021 09:45 AM - edited 08-02-2021 09:50 AM
.
Posted on 09-14-2021 06:30 AM
I maybe wrong or misreading the script..
But when you apple sudo the user must be on the Sudoers list (as in be an Admin on the machine)
In our office users are NOT admins. we do have a local admin on every machine.
That said , It is unclear to me why 'softwareupdate' should work like this. When I run the command manually it is just stuck with no output (other then downloading and installing updates)
Guess apple does not like SysAdmins 🙂
Posted on 11-09-2021 10:39 AM
When I added @EdLuo's script to my policy, I appear to be stuck in a loop.. Has anyone experienced this?
01-24-2022 11:51 AM - edited 02-22-2022 08:05 AM
If you don't want to prompt the user at all, you can make a bash or python script that runs the Download and Install Updates management command for you. Add the script to a user interaction policy to give the user the option to defer the update.
apiUsername="apiaccount"
apiPassword="apipassword"
jamfProURL="https://yourorg.jamfcloud.com"
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}
Posted on 02-03-2022 04:44 PM
The script communicates but doesn't fully execute. The command completes but the computer doesn't update. I'm still on 11.6.2. I thought there was something wrong with:
action/Default/
but I tried this one as well:
/action/InstallForceRestart/
Posted on 02-11-2022 10:22 AM
Use "install" instead of "Default". I need to fix my post.
Posted on 01-24-2022 11:59 AM
I gave up on my script. I'm using Nudge for macOS 11.x and 12.x. It is fairly reliable.
https://marketplace.jamf.com/details/nudge/
Posted on 02-10-2022 06:09 PM
I hate to revive an old thread, but I was curious to see if anyone settled on a way to install software updates, but still do it though self service?
We are working on the API call to initiate the MDM command that @bwoods posted, but we have some setup to do. We're a little (aka alot) behind on the OS and hardware front, we are running mostly Catalina and intel because the pandemic has had us working from home for two years and users, well you know users. But we are about to get a bunch of Apple Silicon machines.
Thanks!
Posted on 02-11-2022 10:58 AM
@bwoods is correct. I changed it to "install" after I spoke to JAMF support. I have had success everytime since then.
/action/install/
They told me this was their official recommendation for updating the OS. They shared this API doc. https://developer.jamf.com/jamf-pro/reference/createcomputercommandbycommandandaction
I was also told,
"The default actions for updates are "latest, non-major" version when done via the API.
The new feature in 10.36 will make major updates possible.
The reason 'InstallForceRestart' didn't work is because it isn't supported yet (it will be in 10.36), so it just generates a DownloadOnly action.
So instead we should use just 'Install" which generates an 'InstallASAP' action."
Posted on 02-11-2022 12:44 PM
@bwoods @cucaracha When I run the command to actually install the update, I keep getting this response:
<html>
<head>
<title>Status page</title>
</head>
<body style="font-family: sans-serif;">
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Unauthorized</p>
<p>The request requires user authentication</p>
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">here</a>.<br>
Please continue your visit at our <a href="/">home page</a>.
</p>
</body>
</html>
The api user I created works fine for getting the machine ID, so I dunno what I am doing wrong here.
Did I screwed something up with the settings in our JAMF Server for the account I put in here:
apiUsername="apiaccount"
I don't want to open everything up, cause I won't know what worked and it's not very secure to have godmode enabled.
Any ideas? Thanks.
Posted on 02-11-2022 05:05 PM
I have everything turned on, but I would think "Send Computer Remote Command to Download and Install macOS Update" needs to be on. Under Privileges > Jamf Pro Server Actions. Also "View MDM command information in Jamf Pro API"
Posted on 02-12-2022 04:07 PM
It looks like your api account may not have the proper permissions. Give it a try with your admin creds for testing.
Posted on 02-14-2022 02:52 PM
I tried it with a different user and I was able to run it as a local script and got to this output:
<?xml version="1.0" encoding="UTF-8"?><computer_command><command><name>ScheduleOSUpdateScan</name><command_uuid>5c3de1d2-ab73-40bf-8638-b58d67c154f4</command_uuid><computer_id>3695</computer_id></command></computer_command>
Then I got a pop-up that needed admin authentication for SoftwareUpdate to be allowed to make some change or other. I didn't get a screenshot, sorry. This is as far as I've gotten with trying to update an M1 with a script or policy.
Is the update just supposed to install right after I run this, or is there something else I need to do?
Thanks!
02-15-2022 07:46 AM - edited 02-15-2022 07:50 AM
Are your bootstrap tokens escrowed and are your macs supervised? The update downloads and updates the computer automatically after about 20-40 minutes. (some have even reported longer)