APFS and fdesetup adduser -plist error

dcgagne
Contributor

APFS and fdesetup seem to be the order of the day in testing the new OS.

Currently our organization has a workflow to manage the password for an admin account on every Mac.
1. jamf management account is added to FV
2. The local admin account password is reset via script
3. A second script runs to remove the admin account from filevault, then re-add it with the current password utilizing a plist and with the jamf management account as the FV authenticated user
4. The plist is cleaned
5. The jamf management account is removed from FV

This workflow runs without issue on any device with FileVault 2 enabled that has HFS+ as its filesystem (including 10.13).

However, when we try the same workflow with an APFS volume we receive an error. Specifically, it references the currently logged in user for some reason.

Script Result: Error: Unable to add one or more users to FileVault. (-69578) OD user '<logged in user name>' could not be authenticated

I would assume the plist would negate any reference to the logged in user, but I'm guessing this changed for APFS?

For reference, here is a sanitized version of what we deploy:

#!/bin/bash

# JAMF Parameters
# $4 = Managaement account
# $5 = Management account password
# $6 = admin account
# $7 = admin account password suffix

prefix=someprefix



# Command to remove the existing user from FileVault
fdesetup remove -user $6

# create the FileVault 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>'$4'</string>
<key>Password</key>
<string>'$5'</string>
<key>AdditionalUsers</key>
<array>
    <dict>
        <key>Username</key>
        <string>'$6'</string>
        <key>Password</key>
        <string>'$prefix $7'</string>
    </dict>
</array>
</dict>
</plist>' > /tmp/fvreadd.plist

# Imports the plist into FileVault

fdesetup add -inputplist < /tmp/fvreadd.plist

# remove fvreadd.plist
rm /tmp/fvreadd.plist

exit 0

Forgot to mention this has been tested on 10.13 GM build 17A362a and JamfPro 9.101.0.

11 REPLIES 11

andrewdempsey
New Contributor

We're experiencing the same problem, where the AdditionalUsers key no longer works. Haven't found a workaround yet.

dcgagne
Contributor

Our only work around for the time being is to create an EA identifying the filesystem used on the boot drive and exempting APFS via smart group from any policy that may alter FileVault. It's not ideal, but it will have to do until a new method can be found

#!/bin/sh

FS=$(diskutil info / | awk '/File System Personality/{print $NF}')


echo "<result>$FS</result>"

exit 0

Results should show up as HFS+ or APFS

prodservices
New Contributor III

We're running into this as well - one more reason to put the brakes on users "getting high".

Sonic84
Contributor III

Hello, anyone find any workarounds?

bpavlov
Honored Contributor

You may be running into this issue here: https://babodee.wordpress.com/2017/10/05/sysadminctl-changes-in-10-13/

The gist of is that all accounts you are enabling for file vault need to have a secure token.

Sonic84
Contributor III

yep.... that's the issue I'm seeing...

thanks for the link!

dcgagne
Contributor

@bpavlov Wow, that is the best lead yet. I can't wait to get started on this after the JNUC.

It looks like it's going to require some rethinking of our workflow considering each account needs to be either retroactively granted a secure token or created with the -secureTokenOn flag.

The wreckage has been moved away from the brick wall and can shamble down the street for now!

edit 1 Right out of the gate I see what is causing the problem. This happens when we create a new account via scripting or when we reset a user account, thereby removing and attempting to re-add them to FV using fdesetup.

The new account, per the blog, will not be granted a secure token when created outside of the GUI/DEP workflow. However any account removed from FV will have its token stripped away. If the account is manually added to FV using the Security and Privacy pane, the SecureToken is generated once again.

stutz
Contributor

I'm just now running into the same issue. Has anyone worked through this yet and come up with a working script?

dcgagne
Contributor

@stutz

Short answer: sorta?

Long answer: Thanks to the link provided by @bpavlov it looks like fdesetup is right out for manipulating user accounts in FV on APFS volumes. To work at all with FileVault, it either needs to be done through the GUI of macOS or leverage the credentials of an account with secureToken enabled.

Below is a quick and dirty script I am testing to prompt the currently logged in user to enter their password and tokenize an admin account used on all of our machines, then update the preboot volume

#!/bin/bash

# Set cocoaDialog location
CD="/private/var/somedir/bin/CocoaDialog.app/Contents/MacOS/CocoaDialog"

# Script parameters
USERNAME=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`
PREFIX=someprefix
# $5=suffix set in the JamfPro Server

# Dialog to enter the current user password and the create $PASSWORD variable
rv=($($CD secure-standard-inputbox --title "SomeAdmin FileVault Access" --no-newline --informative-text "Enter the password for $USERNAME"))

PASSWORD=${rv[1]}

if [ "$rv" == "1" ]; then echo "User said OK"
elif [ "$rv" == "2" ]; then echo "Canceling" exit
fi


# Add a secure token to the "SomeUser" account
sysadminctl -adminUser "$USERNAME" -adminPassword "$PASSWORD" -secureTokenOn "SomeAdmin" -password "$PREFIX $5"

# Update the Preboot volume with the newly tokenized account
diskutil apfs updatePreboot /

exit 0

To break it down a bit, the currently logged in user is assumed to have a valid token and is prompted to enter their password via CocoaDialog. The password is then set as the $PASSWORD variable. sysadminctl is invoked with the credentials of the current user to leverage "secureTokenOn" to provide a secure token to our admin account "SomeAdmin". After that, the APFS preboot volume is updated using disktuil to push all tokenized accounts to the preboot volume and allow them to unlock FileVault when the device is turned on.

This is... not a fix. At least not a good one. It's a work around to Apple's new security model. In the past we would be able to use the jamf management account to manipulate FileVaut, but that account does not have a secure token when it is added via the JamfPro server.

Some logic could be added to verify the current account has a secure token and you wouldn't necessarily need the prompt if you have an account on your devices you know the password to AND have a secure token. One bonus is the systemctl command resets the password for the newly tokenized user in preboot and the OS, so there is no weird double login issues.

Again, this is a stop-gap/proof-of-concept and I wouldn't consider it any sort of long term fix for properly managing FileVault users. Apple and/or Jamf need to step it up and make proper tools for managing secured devices.

Rikky
New Contributor II

Hi Guys, I've updated the script to use the fdesetup command.

#!/bin/bash

#Parameters in Jamf Pro
#$4=Managment Account Name
#$5=Managment Account Password

# Set cocoaDialog location
CD="/path/to/CocoaDialog.app/Contents/MacOS/CocoaDialog"

# Script parameters
USERNAME=$(/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }')

# Dialog to enter the current user password and the create $PASSWORD variable
rv=($($CD secure-standard-inputbox --title "FileVault Repair" --no-newline --informative-text "Enter the password for $USERNAME"))

PASSWORD=${rv[1]}

if [ "$rv" == "1" ]; then echo "User said OK"
elif [ "$rv" == "2" ]; then echo "Canceling" exit
fi

#create the FileVault 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>'$USERNAME'</string>
<key>Password</key>
<string>'$PASSWORD'</string>
<key>AdditionalUsers</key>
<array>
    <dict>
        <key>Username</key>
        <string>'$4'</string>
        <key>Password</key>
        <string>'$5'</string>
    </dict>
</array>
</dict>
</plist>' > /tmp/fvreadd.plist

# Imports the plist into FileVault
fdesetup add -inputplist < /tmp/fvreadd.plist

# remove fvreadd.plist
rm /tmp/fvreadd.plist

# Update the Preboot volume with the newly tokenized account
diskutil apfs updatePreboot /

exit 0

arism
New Contributor

Hi Guys, I modified the script and got this to work for me. If anybody is interested see below:

!/bin/sh

Pass the credentials for an admin account that is authorized with FileVault 2

adminName=$1
adminPass=$2

if [ "${adminName}" == "" ]; then
echo "Username undefined. Please pass the management account username in parameter 1"
exit 1
fi

if [ "${adminPass}" == "" ]; then
echo "Password undefined. Please pass the management account password in parameter 2"
exit 1
fi

Get the logged in user's name

username=$3
if [ "${username}" == "" ]; then
echo "Username undefined. Please pass the user's to add account username"
exit 1
fi

This first user check sees if the logged in account is already authorized with FileVault 2

userCheck=$(sudo fdesetup list | grep -F $username)
if [ "$userCheck" != "" ]; then
echo "This user is already added to the FileVault 2 list."
exit 3
fi

Check to see if the encryption process is complete

encryptCheck=fdesetup status
statusCheck=$(echo "${encryptCheck}" | grep "FileVault is On.")
expectedStatus="FileVault is On."
if [ "${statusCheck}" != "${expectedStatus}" ]; then
echo "The encryption process has not completed, unable to add user at this time."
echo "${encryptCheck}"
exit 4
fi

Get the logged in user's password via a prompt

userpass=$4
if [ "${userpass}" == "" ]; then
echo "Userpass undefined. Please pass the user's password to add account"
exit 1
fi

expect -c "
spawn sudo fdesetup add -usertoadd $username -user $adminName -password $adminPass
expect "Enter the password for the added user '$username':"
send ${userpass}
expect"

exit 0