Self Service Script to Disable FileVault

joelsenders
New Contributor III

Just wanted to share this. I've had some specific use case scenarios where people have enabled FileVault outside of Jamf, and it's necessary to decrypt the machine and then perform encryption over again to get the recovery key escrowed in Jamf properly. It's not perfect, but I wrote this script to be used in Self Service by the user. Since the fdesetup disable command requires the user's password, you can't remotely disable FileVault (unless you know a FV enabled user's password or recovery key on the machine, which chances are you won't know if FV was enabled improperly). This seemed to be the next best option in my case so I didn't have to go around to every machine and run it. Tested on 10.13 and 10.14 machines. Cheers.

#!/bin/sh

# Get logged in user
USER=$( ls -l /dev/console | awk '{print $3}' )

# Check if FileVault is already off - no need to run script if so

if fdesetup status | grep -q Off; then
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "FileVault is already Off. Exiting" buttons {"OK"} default button 1
if button returned of result is "OK" then
end if
end tell
EOT
exit 0
fi

# Prompt user for credentials

PASS=$(/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "Please enter your password to disable FileVault:" default answer "" with hidden answer
if button returned of result is "OK" then
set pw to text returned of result
return pw
end if
if button returned of result is "Cancel" then
error number -128
end if
end tell
EOT)

# end script if no password is entered or cancel is pressed
if [ -z "$PASS" ]
then
exit 0
fi

# Disable FileVault

/usr/bin/expect <<EOT
spawn fdesetup disable
expect ":"
sleep 1
send -- "$USER
"
expect ":"
sleep 1
send -- "$PASS
"
expect ":"
sleep 1
send -- "
"
EOT

# Sleep for 2 seconds to allow time for command to complete
sleep 2

# Check if computer is decrypting, display results to user

if fdesetup status | grep -q Decryption; then 
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "Your computer is currently decrypting. You can check the status in System Preferences > Security & Privacy > FileVault." buttons {"OK"} default button 1
if button returned of result is "OK" then
end if
end tell
EOT
else
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "There was a problem disabling FileVault. Please try again or contact your System Administrator." buttons {"OK"} default button 1
if button returned of result is "OK" then
end if
end tell
EOT
fi

exit 0
6 REPLIES 6

mack525
Contributor II

Thanks for this. I'll definitely keep it for those "you never know" cases

NicholasKing
New Contributor

Did you try to make this policy runnable as a script outside of Self Service?

Hey Guys,

due to the current issue with macOS-Updates I changed the script a bit and it works. There is an error which I cannot resolve. Maybe someone of you can help.

#!/bin/bash

# Get logged in user
USER=$( ls -l /dev/console | awk '{print $3}' )
export US3RN4M3=$USER
export ADMUSER='secure-token-admin-user'
export ADMPASS='secure-token-admin-password'

# Check if FileVault is already off - no need to run script if so
if fdesetup status | grep -q Off; then
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "FileVault is already OFF. Exiting." buttons {"OK"} default button 1
if button returned of result is "OK" then
end if
end tell
EOT
exit 0
fi

# Make user temporarily sudo for fdesetup
touch /etc/sudoers.d/filevault
echo "$USER ALL=(ALL) NOPASSWD: /usr/bin/fdesetup" >> /etc/sudoers.d/filevault


# Prompt user for credentials
PASS=$(/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "Bitte gib zum Deaktivieren von FileVault das Passwort des aktuell angemeldeten Benutzers ein:" default answer "" with hidden answer
if button returned of result is "OK" then
set pw to text returned of result
return pw
end if
if button returned of result is "Cancel" then
error number -128
end if
end tell
EOT)

export P455W0RD=$PASS

# end script if no password is entered or cancel is pressed
if [ -z $P455W0RD ]
then
exit 0
fi

# Disable FileVault
/usr/bin/expect <<'EOT'
spawn sudo -u $env(ADMUSER) sudo fdesetup disable
expect ":"
sleep 1
send -- "$env(ADMPASS)
"
expect ":"
sleep 1
send -- "$env(US3RN4M3)
"
expect ":"
sleep 1
send -- "$env(P455W0RD)
"
expect ":"
sleep 1
send -- "
"
EOT

# Sleep for 10 seconds to allow time for command to complete
sleep 10

rm -Rf /etc/sudoers.d/filevault
export US3RN4M3=''
export P455W0RD=''
export ADMUSER=''
export ADMPASS=''

# System restart (Optional)
msgprompthead="Title for Restart"
msgrestart="Description why to restart"
dialogicon="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/Resources/Message.png"
jamfhelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"
restartprompt=$("${jamfhelper}" -windowType hud -lockHUD -heading "${msgprompthead}" -description "${msgrestart}" -icon "${dialogicon}" -timeout 300)
reboot -q

The error message was that the user is not permitted to make changes. And the user had a secure token enabled and was admin user. 

 

A configuration profile is also installed that FileVault cannot be enabled afterwards.

I took it as a workaround for the moment.

Thanks for your help

By the way... Just wanted to add a comment -> I used environment variables because I was stuck with passwords including for example a dollar-sign, when you use these passwords with 

send -- "$PASS

it will raise an error that there is no value for the variable $1 (<-example) and the script will fail, so these environmental variables is maybe a better option. or is there a reason not to use them?

 

I'm pretty new to this, so I would appreciate every kind of hint or help :)

DanielMa
New Contributor III
New Contributor III

@joelsenders rather than decrypting the machine have you looked at regenerating the Filevault key once the redirection profile is down?

Here is a example script on the Jamf GitHub that will prompt the user for their credentials and then perform the "fdesetup changerecovery -personal" command

https://github.com/jamf/FileVault2_Scripts/blob/master/reissueKey.sh

Hope that helps,

Daniel MacLaughlin

wylan_swets
New Contributor II

@joelsenders Thank you for your work on this, and @daniel.maclaughlin for pointing out the rotation command to reissue a recovery key. In our environment with encryption turned on in the event a user forgets their password we need to give out their recovery key for them to get in and reset it. Great, now it's out there in some form or another which is not the point. I've adapted your initial script to simply rotate the key. When the policy runs I also force an inventory update which pushes that new key up to Jamf. Now we don't have to be too worried about handing out the keys as needed to get someone in, we just need to make sure either the user does a key rotation in self service or can force this scrip to execute on login for them.

(Edit) - I forgot to mention that I wrapped the password in curly braces and dropped the " " to a new line because in my testing my password had a character that broke the script as it was interpreting it as a command. The curly braces turn it in to a string literal making it function with my password.

Thanks again on the great working script - here's my revisions:

#!/bin/sh

# Get logged in user
USER=$( ls -l /dev/console | awk '{print $3}' )

# Check if FileVault is already off - no need to run script if so

if fdesetup status | grep -q Off; then
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "FileVault is Off. Exiting" buttons {"OK"} default button 1
if button returned of result is "OK" then
end if
end tell
EOT
exit 0
fi

# Prompt user for credentials

PASS=$(/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "Please enter your computer login password to rotate the FileVault key:" default answer "" with hidden answer
if button returned of result is "OK" then
set pw to text returned of result
return pw
end if
if button returned of result is "Cancel" then
error number -128
end if
end tell
EOT)

# end script if no password is entered or cancel is pressed
if [ -z "$PASS" ]
then
exit 0
fi

# Use fdesetup to rotate the personal recovery key
# Grab result in to OUTPUT to check later.

OUTPUT=$(/usr/bin/expect <<EOT
spawn fdesetup changerecovery -personal
expect ":"
sleep 1
send -- {$USER}
send -- "
"
expect ":"
sleep 1
send -- {$PASS}
send -- "
"
expect "New*"
puts $expect_out(0,string)
return $expect_out
EOT)


# If the output has key = in it, then the key has been rotated
# Running a jamf recon will also submit this new key to jamf

if [ `echo $OUTPUT | grep -c "key =" ` -gt 0 ]
then
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "Recovery key was successfully rotated." buttons {"OK"} default button 1
if button returned of result is "OK" then
end if
end tell
EOT
else
# Most likely the password was wrong, but we can't be fully certain
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "Your password was incorrect or some other error occurred. Please try again." buttons {"OK"} default button 1
if button returned of result is "OK" then
end if
end tell
EOT
fi