Posted on 06-05-2015 07:17 AM
Hi, all.
I'm wondering about recommended methods for changing the password of the local management account, which is enabled for FV2. After running a policy that changes the management account password, the stored FV2 password is not updated and I have to login with the old password. Even after logging in at the login window (which should sync the FV2 password), I still continue to have to use the old password at the FV2 pre-auth screen.
I tried running another policy to enable the management account for FV2 but this hasn't changed anything.
Thoughts?
Thanks,
Eric
Solved! Go to Solution.
Posted on 06-09-2015 10:55 AM
So the final solution for changing the password on the FileVauly-enabled management account ended up being this:
1. Run the script above to change the password and ensure that FileVault is aware of the change
2. Also add Management Account > Specify New Password to the policy, with the same password as provided to the script
3. [optional] Take steps to mitigate issues with keychain password being out of sync for user
Thanks to everyone that weighed in!
Eric
Posted on 06-05-2015 07:24 AM
I'm not 100% sure, but I think if you're changing the account password through some means other than doing it through System Preferences > Users & Groups, this is, unfortunately, normal behavior. Using a scripted or command line method to change a password doesn't seem to trigger the FDESupport process that does the password sync on the account. There may be a way to do that from a command line driven process and have it work correctly, but if so, I don't know how. You might want to peruse through Rich Trouton's (@rtrouton) derflounder blog to see if he has anything posted about this - https://derflounder.wordpress.com
On top of all this, we have a consistent problem in our environment with user account password not getting properly synced into FileVault even when the client changes their password directly on the Mac in Users & Groups.
Posted on 06-05-2015 09:59 AM
In our environment, changing an AD password via Users & Groups seems to update FV2, but if they change anywhere else, we have them run a policy in Self Service that first quits all open browsers/Microsoft Office applications, deletes the contents of ~/Library/Keychains and deletes ~/Library/Preferences/com.apple.keychainaccess.plist (for all users), and then reboots. The new password will almost always sync up to FV2 after this, so that might be something to try.
Alternatively, when that hasn't worked, we've gone ahead and removed the user account from FV2 and then re-added, which seems to force a password sync:
sudo fdesetup remove -user SHORTNAME
sudo fdesetup add -usertoadd SHORTNAME
Posted on 06-05-2015 11:12 AM
Would ADPassMon run into issues updating the password for FV? Will probably be looking at FV later this year and just started using ADPassMon which has been working great. Just wondering if any issues would occur if the password is changed through that.
Posted on 06-08-2015 08:00 AM
@mm2270 Hmmm....that's what I was afraid of, that traditional command line methods of changing the password would not trigger an update in FileVault, and Apple doesn't seem to have provided us anything with fdesetup to do so. I'm a frequent reader of DerFlounder since @rtrouton is the de facto expert on FileVault, but haven't found anything there. JAMF Support has provided me with a script that they say is a workaround but I haven't had success with it yet and continue to work with them on it. If we have success, I will post it.
@NoahRJ I thought about disabling and re-enabling as well. This gets tricky, though, since you have to provide the recovery key (ours are individual and escrowed in the JSS, so I'd have to figure out if there is a way via the API to pull the key into a script) or the username password for another enabled user. We have the username, and password of another enabled user (our HelpDesk AD login) but the password for that user is also in need of updating (password recently changed in AD) and I haven't yet figured out whether there is a way to sequence everything so that both users can be updated.
@bpavlov You may want to start another thread where you ask your specific questions about ADPassMon. I'm not using that, nor is the user I'm trying to update an AD user, so it doesn't really apply in this case.
Thanks,
Eric
Posted on 06-08-2015 08:21 AM
@etippett There's no way to pull the Recovery key via the API. (See here and vote up if you agree with it)
But you can script removing/adding accounts into FileVault using an inputplist that contains the username/password of both an existing enabled FV2 account and the one you want to remove and add back in.
Posted on 06-08-2015 08:24 AM
@mm2270 Voted up! Yup, aware of the inputplist method and using it under different circumstances. Thanks for pointing it out, though!
Posted on 06-08-2015 08:30 AM
@etippett OK, so, I assume that to mean its not viable for you in this case, or at least you perceive it not to be?
You know the old password for the management account, right? And you just need to update it in FileVault? if so, its doable. I'm doing something similar for our users whose passwords get out of sync. Only difference is that since I don't know their password, I need to ask them for it (temporarily) via a cocoaDialog based script run from Self Service.
Posted on 06-08-2015 08:42 AM
@mm2270 Like in my previous response, I just haven't worked through it yet, as it requires a bit of juggling. Here's the scenario:
I suppose there is a way for me to disable/re-enable the #2 account using the #1 current credentials, then use the #2 account to disable/re-enable the #1 account using the #2 updated credentials. Do you know if reboots would be required in between some of these steps?
Thanks!
Eric
Posted on 06-08-2015 08:57 AM
Hi @etippett I currently have a script/policy users can run from Self Service to "fix" their FileVault password sync problem. While I'm not going to specifically post the script here, I can outline how it works, and maybe this will spark a way you can do the same thing, but completely automated. Since our users are actually the only account enabled for FileVault typically, and we have no idea what their AD passwords are, the script uses cocoaDialog and asks them for input along the way to do what it does. Here's the basic outline.
Hopefully the above steps will help you find a way to do the same for your management account. I'm pretty certain this can be done in a similar way.
Posted on 06-08-2015 10:02 AM
@mm2270 That's quite clever and I'll keep it in mind as a possible solution. Since I have more options available to me with FV-enabled users, I'll probably try to find a method which doesn't require composing such an impressive script! ;) Right now that is:
Here is the script from JAMF (note that it uses the base64 command to obfuscate the password for the account; you may need to modify this for your situation):
#!/bin/bash
##### HEADER BEGINS #####
#
# syncFileVaultPassword.sh
#
# Created: 2014-12-30
# Modified: 2015-01-05
#
#
#
# Priority: Before
# Category: User Accounts - No SS
# Info: This script will set the password for a specified account in such a way that FileVault will also be updated with this new password.
# Notes: Does not require knowledge of previous password.
#
# Requires the following parameters be set.
# ! setUsername: $4
# ! setPassword: $5
#
##### HEADER ENDS #####
# Set the mountpoint passed by Casper.
mountPoint="${1}"
# Set the computername passed by Casper.
computerName="${2}"
# Set the username passed by Casper.
username="${3}"
if [ -n "${4}" ]; then
setUsername="${4}"
else
echo 'This script requires a username.'
exit 1
fi
if [ -n "${5}" ]; then
setPassword="$(base64 --decode <<< "${5}")"
else
echo 'This script requires a password.'
exit 1
fi
# First, make sure that this is a FileVault enabled user. Otherwise, don't bother.
if [ "$(fdesetup list | grep -ic "^${setUsername},")" -eq '0' ]; then
exit 1
fi
# Then, set the password as root. And set it again as the user to update FileVault.
expect 1>/dev/null <<ENDEXPECT
set timeout -1
spawn dscl . passwd "/Users/${setUsername}"
expect "*:"
send -- {$setPassword}
send -- "
"
spawn sudo -iu "${setUsername}" dscl . passwd "/Users/${setUsername}"
expect "*:"
send -- {$setPassword}
send -- "
"
expect "*:"
send -- {$setPassword}
send -- "
"
ENDEXPECT
Thanks,
Eric
Posted on 06-08-2015 10:15 AM
@etippett did you try to just run
dscl . -passwd users/$setUsername "$setPassword"
expect scripts are neat and all but it seems like one more thing to break.
Posted on 06-08-2015 10:56 AM
@nessts Yes, that was the first thing I tried. It does not update the FV password for the user it is run against :( Even worse it seems to prevent the login window from properly updating the FV password after the fact.
I agree, I'm not huge on the expect script, but it's what is working for now. Apple haven't provided us a documented way of doing this, and JAMF has an open defect on it, so it is what it is unfortunately.
Posted on 06-08-2015 01:28 PM
cool, thank you for confirming.
Posted on 06-09-2015 10:55 AM
So the final solution for changing the password on the FileVauly-enabled management account ended up being this:
1. Run the script above to change the password and ensure that FileVault is aware of the change
2. Also add Management Account > Specify New Password to the policy, with the same password as provided to the script
3. [optional] Take steps to mitigate issues with keychain password being out of sync for user
Thanks to everyone that weighed in!
Eric
Posted on 02-22-2016 09:02 AM
So I just ran into this issue, and it is quite the issue. The solution above will not work in my environment.
@etippett - This solution will not work if the current (or future) admin password contains a dollar sign, due to how expect
works. This will also be an issue for any environments that wish to use JAMF's script to send FileVault 2 keys (learned that the hard way, fortunately, this can be resolved using -inputlist
).
The only solutions that I was able to come up with to resolve this issue were:
Creating a script that writes a local file that contains a list of computer names with their associated FileVault 2 individual keys (this would be extremely tedious, as I'd have to get these keys/computer names manually from the JSS web GUI). The base script would then remove the user requiring the password change from the list of FileVault 2 users, change that user's password using dscl . passwd "/Users/<username>"
, then add the user back as a FileVault 2 user. When prompted for credentials of a FileVault 2 user to add the user back as a FileVault 2 user, the script would then use grep
to find the line containing the current target computer's name and associated FileVault 2 individual key, assign the key to a variable, and then input it as the password to authenticate the add to FileVault 2 users. using the file containing keys to can then parse to use the keys as authentication. expect
can be used here if the new password does not contain a '$'.
The other option is manually changing all passwords via SSH, which I would hope I don't have to do.
As the first solution I came up with will be a very labor-intensive script to create and test, does anyone else have a better idea? I pretty diappointed that there isn't a better solution than using an expect
statement in a script to resolve this.
Posted on 03-01-2018 02:07 PM
I just spent a long time debugging the expect in the above script. The password expansions were including the braces so the expect statement should actually read as (at least in my environment of 10.12.6):
expect 1>/dev/null <<ENDEXPECT
set timeout -1
spawn dscl . passwd "/Users/${setUsername}"
expect "*:"
send -- "$setPassword"
send -- "
"
spawn sudo -iu "${setUsername}" dscl . passwd "/Users/${setUsername}"
expect "*:"
send -- "$setPassword"
send -- "
"
expect "*:"
send -- "$setPassword"
send -- "
"
ENDEXPECT
Also note to future me:
echo "password to encode" | base64
Then put that in the password field ($5) in your policy.
Posted on 05-09-2018 01:01 PM
I have been trying to get this script to work and so far have had no success. As I am not that great at debugging expect items, I figured I would throw my items here and see if anyone has thoughts. Basically the first command (spawn dscl . passwd "/Users/${setUsername}") is never really working. I have trimmed down the expect area to only that command and what to send.
expect -d 1>/dev/null <<ENDEXPECT
exp_internal -f /Users/robadmin/Desktop/expect.log 1
set timeout -1
spawn dscl . passwd "/Users/${setUsername}"
expect "*:"
send -- $setPassword
send -- "
"
## spawn sudo -iu "${setUsername}" dscl . passwd "/Users/${setUsername}"
# spawn dscl -u $setUsername -p . -passwd "/Users/$setUsername"
# expect "*:"
# send -- $setPassword
# send -- "
"
# expect "*:"
# send -- $setPassword
# send -- "
"
ENDEXPECT
I am creating a log file now to troubleshoot. That file produces...
spawn dscl . passwd /Users/superadmin
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {3476}
expect: does "" (spawn_id exp7) match glob pattern ":"? no
New Password:
expect: does "New Password: " (spawn_id exp7) match glob pattern ":"? yes
expect: set expect_out(0,string) "New Password:"
expect: set expect_out(spawn_id) "exp7"
expect: set expect_out(buffer) "New Password:"
send: sending "Password3" to { exp7 }
send: sending "
" to { exp7 }
To me, that means that superadmin should now have a password of Password3. It does not get that password. It will remain the old password. If I copy and paste the command in the terminal
dscl . passwd /Users/superadmin
It will ask for the New Password: and I can enter Password3 and that will work.
Does anyone have any idea what I am doing incorrectly here? I am running all commands as root.
Posted on 02-20-2019 12:53 PM
Hello,
This is perhaps too little, too late at this point but I ran into the same issue myself.
In my case, I'm implementing the local password updater/escrow tool located here:
https://github.com/jamf/JSS_Scripts
The problem is, when you update the local account password you've got an orphaned (old) password still set for that account in the pre-boot partition of that macOS computer.
Additionally, the password change portion of that script doesn't work anymore as of one of the more recent updates to 10.14.
#!/bin/sh
###################################################################################################
#
# Copyright (c) 2015, JAMF Software, LLC. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the JAMF Software, LLC nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY JAMF SOFTWARE, LLC "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL JAMF SOFTWARE, LLC BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
###################################################################################################
#
# DESCRIPTION
#
# This script is designed for a custom workflow to update local account passwords securely.
#
# Recommended usage:
# - Specify User Variables in JSS Parameters
# - Set Script to Run on a timed basis
# - Set Update Inventory to run as part of policy
#
####################################################################################################
#
# HISTORY
#
# - Created by Bram Cohen, JAMF Software, LLC, on September 30, 2015
# - Updated by Bram Cohen, JAMF Software, LLC, on October 1, 2015
# - Fixed an issue where delimiters were present after decoding hash
# - Fixed an issue where one could visually discern part of the string
# - Fixed an issue where the salt may cause a decode failure
# - Added additional notation and made the output pretty
#
####################################################################################################
###################################################################################################
# User Variable Section - Specify below or leave blank to fill in from the JSS in the next section
###################################################################################################
#Specify the user whose password will be updated
targetedUsername="useraccount"
#Specify the length of password we would like to generate
lengthOfPassword="32"
#Specify a salt value to throw into the hash. THIS MUST BE SPECIFIED IN THE E.A. AS WELL
salt="myreallycoolsalt"
#Specify where you would like the hash stored on the machine
configurationFile="/Library/Preferences/com.jamfsoftware.management.plist"
###################################################################################################
# JSS Variable Section - If above are null and we have values from the JSS, it will them fill in
###################################################################################################
if [ "$4" != "" ] && [ "$targetedUsername" == "" ]; then
targetedUsername="$4"
fi
if [ "$5" != "" ] && [ "$lengthOfPassword" == "" ]; then
lengthOfPassword="$5"
fi
if [ "$6" != "" ] && [ "$salt" == "" ]; then
salt="$6"
fi
if [ "$7" != "" ] && [ "$configurationFile" == "" ]; then
configurationFile="$7"
fi
####################################################################################################
# Functions Section - DO NOT MODIFY BELOW THIS LINE
####################################################################################################
###############################
# Function problemDetector
###############################
problemDetector() {
if [[ "$problem" == "1" ]]; then
echo "==================================================
A problem was detected in this script run:
"
echo "$problemDescription"
exit 1
fi
}
###############################
# Function populateVariables
###############################
populateVariables() {
binaryLocation=$(/usr/bin/type -a jamf | awk '{print $NF}')
machineUUID=$(/usr/sbin/system_profiler SPHardwareDataType | grep UUID | awk '{print $NF}' | base64)
if [ "$binaryLocation" == "" ]; then
problem=1
problemString=" - Unable to locate the jamf binary."
problemDescription=$(echo "$problemDescription
$problemString")
fi
if [ "$machineUUID" == "" ]; then
problem=1
problemString=" - Unable to locate locate the UUID of the computer."
problemDescription=$(echo "$problemDescription
$problemString")
fi
}
###############################
# Function verifyUser
###############################
verifyUser() {
userCheck=$(/usr/bin/dscl . -list /Users | grep "${targetedUsername}" | wc -l | awk '{print $NF}')
if [ "$userCheck" == "0" ]; then
problem=1
problemString=" - Unable to locate the username $targetedUsername on this computer"
problemDescription=$(echo "$problemDescription
$problemString")
fi
}
###############################
# Function checkForConfig
###############################
checkForConfig() {
echo "Checking for Configuration File"
if [ ! -f "$configurationFile" ]; then
echo " - Configuration not found, creating one"
/usr/bin/touch $configurationFile
/usr/sbin/chown root:wheel $configurationFile
else
echo " - Configuration Found
"
fi
}
###############################
# Function generatePassword
###############################
generatePassword() {
echo "Generating Password"
hundredDigits=$(/usr/bin/openssl rand -base64 100)
passwordString=$(echo "${hundredDigits}" | tr -cd '[[:alnum:]]._-' | cut -c1-${lengthOfPassword})
}
###############################
# Function obfuscatePassword
###############################
obfuscatePassword() {
echo " - Salting and Hashing password"
saltPassword=$(echo "${machineUUID}${passwordString}${salt}" | base64)
}
###############################
# Function writePasswordToConfig
###############################
writePasswordToConfig() {
echo " - Writing string to file
"
/usr/bin/defaults write $configurationFile string $saltPassword
echo "Confirming hash was written in a readable manner"
verifyHash=$(/usr/bin/defaults read $configurationFile string)
if [ "$saltPassword" == "$verifyHash" ]; then
echo " - Hash readability confirmed
"
else
problem=1
problemString=" - Failed to read the hash in the configuration file."
problemDescription=$(echo "$problemDescription
$problemString")
fi
}
###############################
# Function changePassword
###############################
changePassword() {
echo "Changing password and updating FileVault password for user ${targetedUsername}."
expect -c "
log_user 0
spawn dscl . passwd "/Users/${targetedUsername}"
expect "*:"
send "${passwordString}"
expect "*:"
send "YOUROLDBADPASSWORDHERE"
spawn sudo -iu "${targetedUsername}" dscl . passwd "/Users/${targetedUsername}"
expect "*:"
send "${passwordString}"
expect "*:"
send "YOUROLDBADPASSWORDHERE"
log_user 1
expect eof
"
}
###############################
# Function cleanUp
###############################
cleanUp() {
variablesInUse="targetedUsername
lengthOfPassword
salt
configurationFile
problem
problemString
problemDescription
binaryLocation
machineUUID
userCheck
hundredDigits
passwordString
saltPassword
verifyHash
debugFlag"
echo "Unsetting Variables
"
for vars in $variablesInUse; do
unset $vars
done
}
####################################################################################################
# Function Execution Section - SERIOUSLY, DO NOT MODIFY BELOW THIS LINE UNLESS YOU KNOW WHATS UP!
####################################################################################################
echo "
==========================================
Executing password randomization Script
=========================================="
populateVariables
problemDetector
verifyUser
problemDetector
checkForConfig
generatePassword
obfuscatePassword
writePasswordToConfig
problemDetector
changePassword
cleanUp
echo "==========================================
=========================================="
exit 0
The key(s) to all of this working is (1) using dscl to change the password and (2) supplying the OLD password instead of the new password twice in the sudo -iu dscl command (probably a timing issue, perhaps a sleep would resolve this as well):
expect -c "
log_user 0
spawn dscl . passwd "/Users/${targetedUsername}"
expect "*:"
send "${passwordString}"
expect "*:"
send "YOUROLDBADPASSWORDHERE"
spawn sudo -iu "${targetedUsername}" dscl . passwd "/Users/${targetedUsername}"
expect "*:"
send "${passwordString}"
expect "*:"
send "YOUROLDBADPASSWORDHERE"
log_user 1
expect eof
"
Hope this helps someone!
Jacob