Change Local Admin Password Using Policy

fotofojo
New Contributor III

Hi all. I have searched for this specific issue on here and got conflicting results, so I thought I'd post. Two things that we are trying to achieve: 1) Change the prestage enrollment local admin password - this one is pretty self explanatory and can easily be done, however will only take effect for newly enrolled computers. Which brings me to 2) Creating a policy that changes the local admin password. I thought I was successful in this and sort of was. Scoping the policy to a couple of test machines resulted in successful change to admin password when authenticating for things such as software installs and preference changes. The new password even works when changing users in terminal (su administrator). However, the password does not work for initial login to the machine. In fact, it breaks the old password as well, so we are left with a machine that the user "administrator" is unable to log in. 

I realize this was long winded, so thanks in advance.

9 REPLIES 9

athomson
New Contributor III

Is the administrator account token authorized? 

/usr/sbin/sysadminctl -secureTokenStatus administrator

fotofojo
New Contributor III

It is disabled

athomson
New Contributor III

Assuming you have FileVault enabled, that would account for not being able to login at startup (if I am understanding the issue clearly). You can "Enable Users" from System Settings under Privacy & Security to see if that fixes the issue with administrator account.

fotofojo
New Contributor III

Thanks. I did that on one machine and it was successful in allowing the administrator login. However, my goal is to scope that to several machines via policy or config profile. Is that possible?

athomson
New Contributor III

It is possible but not (yet) as simple as we administrators would like. I don't use Jamf Connect, but it may be useful to help with this. Absent of that, if you know the account name and password of the token authorized account you can script the process. Even if you don't, it can still be scripted but would require a password prompt of the already authorized account to complete the process. If you have swiftDialog installed in your environment, below is an example script that might help you. 

 

#!/bin/bash
set +x


#	This script is intended to be used via JAMF Pro to ensure a  
#	specified account has token authority.

#	Author:        Andrew Thomson
#	Date:          2023-08-02


TOKEN_ACCOUNT="$4"
TOKEN_PASS="$5"
DEBUG="FALSE"
ICON="/System/Library/PrivateFrameworks/SystemPolicy.framework/Versions/A/Resources/KextAlert.icns"
OVERLAY="/Library/Company/company_logo.png"
EVENT_TRIGGER="install_dialog"

function getCurrentUser () {
    
    local CURRENT_USER=$(/usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | /usr/bin/awk '/Name :/ && ! /loginwindow/ {print $3}')
    
    if [ -z "$CURRENT_USER" ]; then  
        echo "ERROR: No current user logged in." >&2
        return $LINENO
    else
        echo "$CURRENT_USER"
        return 0
    fi
}


function isAdmin() {

    #    0=admin
    #   64=user not found
    #   67=not admin

    if ! local USER_NAME="$1"; then
        echo "ERROR: Username not specified." >&2
        return $LINENO
    fi

    #   verify user is admin
    local RC=$(/usr/sbin/dseditgroup -o checkmember -m $USER_NAME admin &> /dev/null; echo $?)

    #   64 means username not found
    if [[ "$RC" -eq "64" ]]; then
        echo "ERROR: Specified username not found." >&2
    fi

    return $RC
}


function isRoot() {

    #   verify script run as root
    if [[ $UID -ne 0 ]]; then

        echo "ERROR: Script must run with root privileges." >&2
        echo -e "\\tUSAGE: sudo \"$0\"" >&2
        return $LINENO
    else
        return 0
    fi
}


function isTokenAccount() {

	ACCOUNT="$1"

	if ! [[ $(/usr/sbin/sysadminctl  -secureTokenStatus $ACCOUNT 2>&1) =~ "ENABLED" ]]; then return $LINENO; fi
}


function main() {
	
	if ! isRoot; then exit $LINENO; fi

	if ! verifyDialog; then exit $LINENO; fi	

	#	verify architecture is apple silicon
	if [[ ! "$(/usr/bin/arch)" =~ "arm64" ]]; then
		echo "Architecture not compliant." >&2
		exit 0
	fi

	#	verify file vault is enabled
	if [[ "$(/usr/bin/fdesetup status)" == "FileVault is On." ]]; then 
		echo "ERROR: FileVault was not enabled. Log out/in before trying agian." >&2
		/usr/bin/fdesetup enable
		exit $LINENO
	fi

	#	verify specified account is not already token authorized
	if isTokenAccount $TOKEN_ACCOUNT; then 
		echo "The specified account already has token authority [$TOKEN_ACCOUNT]." >&2
		exit 0
	fi	

	#	verify specified account has a known password
	if ! /usr/bin/dscl . authonly "$TOKEN_ACCOUNT" "$TOKEN_PASS" &> /dev/null; then
		echo "ERROR: Unknown password for specified account [$TOKEN_ACCOUNT]." >&2
		exit $LINENO
	fi

	#	get current user name
	if ! CURRENT_USER=$(getCurrentUser); then exit $LINENO; fi

	#	verify current user account is token authorized
	if  isTokenAccount $CURRENT_USER; then
			#	get current user password
			for ((i=1; i<=5; i++)); do
				IFS=": " PASSWORD=($("/Library/Application Support/Dialog/Dialog.app/Contents/MacOS/Dialog" \
							    --button1text "OK"                                                          \
							    --height 275                                                                \
							    --icon "$ICON"                                                              \
							    --message "Please enter your password [$CURRENT_USER]."                     \
							    --ontop                                                                     \
							    --overlayicon "$OVERLAY"   												    \
							    --small                                                                     \
							    --title "FileVault Verification"                                            \
							    --textfield "Password:",required,secure))
			
				#	verify credentials for local user with token authority
				if /usr/bin/dscl . authonly "$CURRENT_USER" "${PASSWORD[2]}" &> /dev/null; then
					break
				fi
			done

			#	if current user is not an admin then add to admin group
			if ! isAdmin $CURRENT_USER; then
				if ! /usr/sbin/dseditgroup -o edit -a $CURRENT_USER -t user admin 2> /dev/null; then
					echo "ERROR: Unable to add user to admin group [$CURRENT_USER]." >&2
					exit $LINENO
				else
					echo "User made temporary admin [$CURRENT_USER]." >&2
				fi
				WAS_ADMIN="false"
			else
				WAS_ADMIN="true"
			fi			

			#	make account token authorized
			if ! /usr/sbin/sysadminctl -secureTokenOn $TOKEN_ACCOUNT -password $TOKEN_PASS -adminUser $CURRENT_USER -adminPassword ${PASSWORD[2]}; then
				echo "ERROR: Unable to assign token to account [$TOKEN_ACCOUNT]." >&2
				RC=$LINENO
			fi

			#	if current user was not an admin then remove from admin group
			if  [[ "$WAS_ADMIN" = "false" ]]; then
				if ! /usr/sbin/dseditgroup -o edit -d $CURRENT_USER -t user admin 2> /dev/null; then
					echo "ERROR: Unable to remove user from admin group [$CURRENT_USER]." >&2
					exit $LINENO
				else
					echo "User removed as temporary admin [$CURRENT_USER]." >&2
				fi
			fi			
	else
		echo "ERROR: No token authorized account found." >&2
		exit $LINENO
	fi
}


function verifyDialog() {

    if [[ ! -x "/Library/Application Support/Dialog/Dialog.app" ]]; then
        if ! /usr/local/jamf/bin/jamf policy -event $EVENT_TRIGGER -forceNoRecon 2> /dev/null; then
            echo "ERROR: Unable to install a required dependency [Dialog]." >&2
            return $LINENO
        fi
    fi
}


if [[ "$BASH_SOURCE" == "$0" ]]; then
    main $@
    exit
fi

 

fotofojo
New Contributor III

Thanks. We don't have that installed and have a relatively smallish Mac footprint. I thought by creating a policy that used the "Local accounts --> reset account password" would suffice. Is there a similar policy that I could use to enable the authorization of the local admin account? Apologies, pretty new to Jamf

fotofojo
New Contributor III

Oh, and we do use Jamf connect if that helps

athomson
New Contributor III

There is an old provision for it under Local Accounts in Policies but as soon as your click on it, it reveals that "Beginning with macOS 10.13, you cannot use this method to enable a user for FileVault." Jamf does escrow the token when created but there is not yet a way to pass it on via a Jamf Policy or Configuration Profile. 

From what I understand (someone can correct me if I am wrong) but with Ventura, you should be able to initially login  using whatever account can unlock FileVault, and then logout from that account. That should leave you with a login prompt that doesn't require FileVault access. Using an existing, unauthorized account to login to that prompt should authorize it upon successful login. Of course, that doesn't help you address the issue en masse. Wish there was an easier way.

fotofojo
New Contributor III

Thanks for your efforts, I appreciate your time. If anyone else has ideas, I would gladly entertain them as I cannot be the only one in this situation.