Posted on 12-01-2020 08:14 AM
Our prestage enrollment is set to create a hidden admin account and sets the account created via Setup Assistant to be a standard account. Here's the catch-22 I've run into:
The hidden admin account will only get a SecureToken if it is the first account to log in.
I can't escrow a bootstrap token to the hidden admin account, since the only other account on the system with a Securetoken is a standard user.
Has anyone else run into this issue? If so, what is your workflow?
Posted on 12-01-2020 09:01 AM
I have a policy that happens as part of the config process that prompts the user for their password and then uses this to add the admin account to FV2 and get them a secure token along with doing a bunch of other stuff.
Here are the relevant parts of that script:
#!/bin/bash
adminName=$4
adminPass=$5
loggedInUser=$( echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ && ! /loginwindow/ { print $3 }' )
if [[ -z "$loggedInUser" ]] || [[ "$loggedInUser" == 'root' ]] || [[ "$loggedInUser" == "loginwindow" ]] ; then
echo "Failed to gather loggedInUser correctly"
exit 1
else
echo "loggedInUser is $loggedInUser"
fi
loggedInUID=$(id -u "$loggedInUser")
#### SET UP DISPLAY DIALOG FUNCTION
DisplayDialog(){
local dialogText="$1"
echo "Display Dialog: $dialogText"
cmd="Tell app "System Events" to display dialog "$dialogText""
/usr/bin/osascript -e "$cmd"
}
echo " "
echo "Checking Admin User"
adminCheck=$(id -u "$adminName")
if [[ "$adminCheck" == *"no such user"* ]] || [[ -z "$adminCheck" ]] ; then
echo "admin user not installed"
jamf policy -trigger installadmin0417
sleep 5
fi
adminCheck=$(id -u "$adminName")
if [[ "$adminCheck" == *"no such user"* ]] || [[ -z "$adminCheck" ]] ; then
echo "admin user still not installed"
DisplayDialog "$adminName not installed. Exiting"
exit 1
fi
echo " "
echo "Checking admin passsword"
adminPassCheck=$(/usr/bin/dscl /Local/Default -authonly "$adminName" "$adminPass")
if [[ -z "$adminPassCheck" ]]; then
echo "Continue"
else
echo "admin Password not set correctly"
exit 1
fi
echo " "
echo "checking Filevault Status"
fvStatus=$(fdesetup status)
if [[ "$fvStatus" == *"FileVault is On."* ]] ; then
echo "Verified Filevault Enabled"
else
jamf policy -trigger catalina_fv -forceNoRecon
sleep 5
DisplayDialog "Filevault Not Yet Enabled. Once the rest of your setup is complete please restart your computer to enable filevault."
exit 1
fi
### CHECK SECURE TOKEN STATUS:
if [[ $("/usr/sbin/diskutil" apfs listcryptousers / 2>&1) =~ "No cryptographic users" ]]; then
tokenStatus="false"
else
tokenStatus="true"
fi
echo " "
echo "Token Status: $tokenStatus"
#################
# We should have everything we need from the system if it gets passed here
##################
secureTokenUserCheck() {
local userToCheck="$1"
if [[ $("/usr/sbin/sysadminctl" -secureTokenStatus "$userToCheck" 2>&1) =~ "ENABLED" ]]; then
userToken="true"
else
userToken="false"
fi
echo "$userToken"
}
addSecureToken() {
local tokenUser="$1"
local tokenUserPass="$2"
local addUser="$3"
local addUserPass="$4"
echo "adding token to $addUser with credentials from $tokenUser"
sysadminctl -adminUser "$tokenUser" -adminPassword "$tokenUserPass" -secureTokenOn "$addUser" -password "$addUserPass"
tokenAdded=$(secureTokenUserCheck "$tokenUser")
echo "Token Added to $tokenUser : $tokenAdded"
diskutil apfs listcryptousers /
}
fileVaultUserCheck() {
userToCheck="$1"
fdeList=$(fdesetup list | grep "$userToCheck")
echo "checking Filevault list $fdeList for $userToCheck"
if [[ "$fdeList" == *"$userToCheck"* ]] ; then
echo "FV2 Check for $userToCheck passed. Continuing"
else
DisplayDialog "$userToCheck not Filevault Enabled. Rectify this BEFORE you restart!"
exit 1
fi
}
###################
# Get get password from the user
#####################
echo " "
echo "Getting user password"
userPass="None"
loopCount=0
while [ $loopCount -lt 3 ]; do
passCheck=$(/usr/bin/dscl /Local/Default -authonly "$loggedInUser" "$userPass")
if [[ -z "$passCheck" ]]; then
echo "Gathered Password"
else
echo "prompting user for Account Password"
userPass=$(/bin/launchctl asuser "$loggedInUID" sudo -iu "$loggedInUser" /usr/bin/osascript<<END
tell application "System Events"
activate
set the answer to text returned of (display dialog "Enter $loggedInUser's Current Account Password:" default answer "" with hidden answer buttons {"Continue"} default button 1)
end tell
END
)
fi
passCheck=$(/usr/bin/dscl /Local/Default -authonly "$loggedInUser" "$userPass")
if [[ -z "$passCheck" ]]; then
echo "Continue"
break
else
echo "Authorization failed"
DisplayDialog "Password Check for $loggedInUser failed. Please Try again."
((loopCount++))
fi
done
rm -f "$passLocation"
if [[ -n "$passCheck" ]] ; then
DisplayDialog "$loggedInUser Password failed three times. Exiting"
exit 1
fi
# create the plist file:
echo '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Username</key>
<string>'$loggedInUser'</string>
<key>Password</key>
<string>'$userPass'</string>
<key>AdditionalUsers</key>
<array>
<dict>
<key>Username</key>
<string>'$adminName'</string>
<key>Password</key>
<string>'$adminPass'</string>
</dict>
</array>
</dict>
</plist>' > /tmp/fvenable.plist ### you can place this file anywhere just adjust the fdesetup line below
# now enable FileVault
fdesetup add -i < /tmp/fvenable.plist
rm -r /tmp/fvenable.plist
########### MANAGE SECURE TOKENS
echo " "
echo "checking secure tokens"
adminToken=$(secureTokenUserCheck "$adminName")
userToken=$(secureTokenUserCheck "$loggedInUser")
if [[ "$tokenStatus" == "false" ]] ; then
echo "No Secure Tokens, adding admin and logged in user to secure token"
addSecureToken "$adminName" "$adminPass" "$loggedInUser" "$userPass"
adminToken=$(secureTokenUserCheck "$adminName")
userToken=$(secureTokenUserCheck "$loggedInUser")
fi
### CHECK SECURE TOKEN STATUS:
if [[ $("/usr/sbin/diskutil" apfs listcryptousers / 2>&1) =~ "No cryptographic users" ]]; then
tokenStatus="false"
echo "Secure token still not enabled. This should never happen. Failing"
DisplayDialog "There has been an error enabling this computers encryption. If you see this error more than once please inform Helpdesk."
exit 1
else
tokenStatus="true"
fi
## setting this variable to false so it exists later
demoteUser="false"
if [[ "$adminToken" = "true" ]] ; then
tokenUser="$adminName"
tokenPass="$adminPass"
echo "admin user has a token, setting as tokenUser"
elif [[ "$userToken" = "true" ]] ; then
tokenUser="$loggedInUser"
tokenPass="$userPass"
echo "logged in user is only one with a token, this is bad. But will be attempted to be fixed automatically right now."
### Make sure this user is an Admin
if [[ $("/usr/sbin/dseditgroup" -o checkmember -m "$loggedInUser" admin / 2>&1) =~ "yes" ]]; then
echo "$loggedInUser is an admin"
else
echo "$loggedInUser is not an admin"
demoteUser="true"
##Promoting user to admin
echo "promoting user to admin"
dscl . -append /groups/admin GroupMembership "$loggedInUser"
fi
addSecureToken "$loggedInUser" "$userPass" "$adminName" "$adminPass"
## remove admin if it was added
if [[ "$demoteUser" = "true" ]] ; then
echo "demoting User from admin"
dscl . -delete /groups/admin GroupMembership "$loggedInUser"
fi
adminToken=$(secureTokenUserCheck "$adminName")
if [[ "$adminToken" = "false" ]] ; then
echo "adding admin user failed"
DisplayDialog "There has been an error enabling this computers encryption. If you see this error more than once please inform Helpdesk."
exit 1
else
tokenUser="$adminName"
tokenPass="$adminPass"
fi
fi
if [[ "$adminToken" = "false" ]] ; then
addSecureToken "$tokenUser" "$tokenPass" "$adminName" "$adminPass"
fi
if [[ "$userToken" = "false" ]] ; then
addSecureToken "$tokenUser" "$tokenPass" "$loggedInUser" "$userPass"
fi
fileVaultUserCheck "$adminName"
exit 0
Other thing that I do, which may break this workflow, is that all users are created as local admin, and then they are demoted if they shouldn't be admins once the initial setup is complete. I plan on changing that once Jamf Connect gets their Laps Password feature fixed...
Posted on 12-21-2020 02:45 PM
Hey there @strayer,
Would you mind sharing what your catalina_fv trigger is doing?
I'm running into the same issue, have an M1 MacBook Air (first one on-site) and after doing some generic testing, discovered that there are no users with a Secure Token, so FileVault isn't happy.
Thanks for your time!
Have a great day!
Jacob
Posted on 12-22-2020 06:43 AM
i dont have an answer for existing secure token issues, are you using anything like jamf connect?
are you able to deploy the hidden admin account after the first user created account? Our current workflow is user account is created through DEP, they are prompted for FileVault and we demote to a standard user account once enrollment/DEPNotify is completed. I haven't had issues with that process...so perhaps just another approach/perspective.
Posted on 12-22-2020 10:16 AM
@pitcherj
catalina_fv is pretty basic. but basically turns on Filevault and asks the user to restart. It's mostly a backup for when automatic filevault enabling fails
Posted on 12-22-2020 11:54 AM
@pitcherj I too had issues with securetoken and bootstrap on M1 mac. Not with filevault but with software update. Have to have a bootstrap enabled user to run software Update!
I ended up changing my DEP process to create a hidden local admin (won't be used) then on enrollment complete run a script that creates runs Jamf createaccount to create a local admin that our techs will use to setup the mac for the user. Since it will be the first user to login (interactively) then it gets the securetoken and bootstrap.
Posted on 12-22-2020 06:13 PM
@cvangorp Interestingly, our DEP process already creates a hidden local admin, so perhaps that create account portion is all I need.
Thanks for pointing me in the right direction!
I'll report back with my results.
Have a great day!
Jacob
Posted on 12-23-2020 05:29 AM
I'm going to do some more testing, but I just did a basic enrollment with a new script using the create account command, but it didn't create a local admin account, it created a standard user.
Neither the hidden local admin or the standard user has a secure token, though.
Posted on 12-23-2020 11:12 AM
@pitcherj jamf createaccount -username {username} -realname {my real name} -password {mypassword} -admin
The -admin will set the account to an admin. I found the yes setup assistant can create the admin account but that account does not get secure or bootstrap token. https://travellingtechguy.blog/filevault-securetoken-and-bootstrap-in-macos-11-0-1-big-sur/
Posted on 01-07-2021 01:07 PM
Is it possible this issue is being triggered because I am using the "Create a local administrator account before the Setup Assistant" option in my PreStage Enrollment?
Posted on 01-25-2021 12:10 PM
@pitcherj Did you ever find a solution? I'm having the same issue, and I also suspect it's caused by creating the local admin account before Setup Assistant.
What's odd is that it works (in that the admin account being created as part of PreStage as a secure token ) about half the time,and the other half it does not. I have not yet figured out what dictates which way it will go. There seems to be some race condition here.
One thing I have been doing before each test is the following:
1. Get into Recovery by holding down the power button
2. When there, open Terminal
3. Type "resetpassword"
4. From the menu, choose to Erase the Mac.
I have found that if you fail to do this, your admin account may stick around even after deleting the partitions/volumes. This seems to be the way to fully wipe out everything. If the account sticks around, it seems that it likely won't get a token
I'm currently trying the following:
1. In PreStage, give the admin account a different name. So, if your normal admin account is called "admin", call this one "tempAdmin"
2. Create the local admin via a policy, with the user name of "admin", and set this to happen on enrollment completion
It's running through the OS install now, so I'll know in about an hour if this worked or not. The downside of this approach is that your admin account won't be a FileVault user, but I'm trying to get away from having a local admin account anyway, so this works for me. You will still be able to get in with the recovery key of course.
Posted on 01-25-2021 12:12 PM
I did!
It was weird issue with the M1 firmware.
Had to do a restore, not a revive, from apple configurator.
Jacob
Posted on 01-25-2021 12:51 PM
@pitcherj So you're saying if I do the following:
1. Wipe the Mac by doing a restore from Apple Configurator
2. Leave my PreStage creating the standard admin account
That it will create that admin account with the secure token every time? I'm curious if you have done multiple runs with this, as my experience with my current method is that it works half the time.
Posted on 01-25-2021 12:59 PM
Yup.
Posted on 01-28-2021 01:47 PM
@pitcherj It's been a week for me, but I think I got all of my bugs worked out.
For anyone that might run into the same issues, here is what I found:
The account I was creating in PreStage was the same as the one that is set in the user-initiated enrollment section. Why I had it set this way I don't know, but I have since corrected it by changing the user-initiated account to something else. Why I kept getting the variable behavior, I think, was due to a race condition. If I got in fast enough, the flag for this account to not get a secure token was not yet set. See https://travellingtechguy.blog/filevault-securetoken-and-bootstrap-in-macos-11-0-1-big-sur/ that @cvangorp already noted for more details on this
The account created in PreStage won't get a token. This isn't a problem, because you can just use a policy that creates another admin account.
Now with all that sorted, I was still having issues, ie my admin account getting created after the setup assistant was done was still not getting a secure token. After trying so many things I lost count, I tried moving the Mac I was testing on to a different PreStage to try some other stuff with the account. When that didn't work out I moved it back to my original PreStage, and ever since it has worked perfectly. Why this makes a difference I don't know; my guess is that something got messed up either on the Jamf or Apple side, and moving it out and back into the PreStage refreshed it all.
This wasn't it at all. Back when CVE-2017-13872 was an issue I packaged @rtrouton 's script here and left it in place ever since for all devices, as I figured it would be a good precaution. The issue here was that if that policy ran before my policy to make the admin account, that admin account didn't get the secure token. This jives with my results while trying to find a user with a secure token; root showed as not having a secure token but it's UUID was listed when running
diskutil apfs listcryptousers /
and
fdesetup list -extended
For now I'm keeping the root block in place, but running it after the admin is created. This gives a secure token
I still have yet to test FV and verify I'm getting bootstrap, but when I did get secure token before those worked so hopefully that remains true.