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

26 REPLIES 26

draeconis
New Contributor II

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.

DBrowning
Valued Contributor

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.

gforsyth
New Contributor III

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!

joseph_english
New Contributor II

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. 😞

DBrowning
Valued Contributor

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.

kendalljjohnson
Contributor II

@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.

DBrowning
Valued Contributor

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
                "

kendalljjohnson
Contributor II

Much appreciated, thanks!

user-yMHedFrxlU
New Contributor

The solution worked for me thanks to the community and the members for the solution.

EdLuo
Contributor

@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}”

EdLuo
Contributor

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

DBrowning
Valued Contributor

@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

fredrik_virding
Contributor

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.
8a7bbffa80c34ea082b6779de80edcc0

EdLuo
Contributor

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

cbruce
New Contributor III

@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.

dlbrabb
New Contributor III

@EdLuo - Nice script! I did run this and it looks like Self Service needs to quit before it restarts.

EdLuo
Contributor

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.

sgrall
New Contributor III

Deleted

xan_ps
New Contributor

@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?

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?

xan_ps
New Contributor

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.

 

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.

cbruce
New Contributor III

 

 

xan_ps
New Contributor

.

rblaas
Contributor II

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 🙂 

jlombardo
New Contributor III

When I added @EdLuo's script to my policy, I appear to be stuck in a loop.. Has anyone experienced this?