Posted on 04-16-2013 02:32 PM
Is there a way to prevent unencrypted time machine backups?
If possible, is there a way to standardize encryption key similar to FileVault2?
Posted on 02-24-2014 07:26 AM
@xDunes did you ever get anywhere with this idea?
Posted on 02-24-2014 10:37 AM
I Think it's one that we have to wait for Apple to resolve..
As far as I can see, trying to 'hack' a solution would raise too many problems..
If Apple does come up with a solution to this - then I think it would not be included until at least OS X 10.10..
- and maybe not even then..
Posted on 02-25-2014 10:48 AM
We contacted Apple about this at one point as well, and they said the best they had to offer was tmutil and diskutil corestorage. Using those tools, I built a POC for verifying employees are backing up to approved drives and their Time Machine drives are encrypted. The script is triggered by a launchdaemon that's activated by drives being mounted or changes to /Library/Preferences/com.appleTimeMachine.plist. This POC was built around using a specific company approved USB drive, so you'll see that in the script below.
The script forces encryption on the Time Machine drive and ejects and removes unapproved drives listed in Time Machine. I found it consistently works within a matter of seconds after plugging in an external drive or setting up a drive in Time Machine, and it seemed to be pretty quiet too, running without blowing up the system logs. This was a POC, and I think I tweaked the script a little more in testing, but this is pretty close to a final version:
#!/bin/bash
####### Time Machine drive detection and encryption script.
####### Written by Matt Bauer with contributions by Nick Kalister, 2013
############################## Variables Defined Here ##############################
## Cocoa Dialog Detection
CocoaDialog=`detect cocoa dialog here`
## Get names of drives being used with Time Machine and assign them to TMDestCheck array variable
IFS=$'
'
TMDestCheck=(`tmutil destinationinfo | grep Name | cut -d ':' -f 2 | sed -e 's/^[ ]*//'`)
echo --- Drives being used with Time Machine ---
echo ${TMDestCheck[@]}
echo ${TMDestCheck[@]} > /private/tmp/tmdestcheck.txt
############################## End Variable Definitions ##############################
############################## Functions Defined Here ##############################
## Quit backup and notify user of unsupported drive
function DriveKill {
VerbotenDrive=`cat /private/tmp/verbotendrive.txt`
tmutil stopbackup
VerbotenDriveTMID=`tmutil destinationinfo | sed "1,/$VerbotenDrive/d" | grep -m 1 "ID" | cut -d ":" -f 2 | sed -e 's/^[ ]*//'`
tmutil removedestination $VerbotenDriveTMID
echo $VerbotenDrive removed from Time Machine
WarningDialog=`$CocoaDialog msgbox --title "Unsupported Time Machine Drive" --x-placement "center" --y-placement "center"
--button1 "Ok"
--text "Backing up to '$VerbotenDrive' is prohibited."
--informative-text "Please connect a company provided USB drive and try again. Contact the Help Desk
at 866-555-1212 if you have questions or need help ordering an approved drive."`
if [ "$WarningDialog" = "1" ]; then
echo User accepted prohibited drive dialogue
fi
}
## Check the encryption status of the Company Time Machine drive
function DriveCheck {
tmutil stopbackup
GutenDrive=`cat /private/tmp/gutendrive.txt`
EncryptionCheck=`diskutil cs list | grep -s -om 1 "$GutenDrive"`
if [[ "$EncryptionCheck" == "" ]]; then
echo Drive needs to be encrypted
EncryptionDialog=`$CocoaDialog msgbox --title "Encrypt Your Company Drive" --x-placement "center" --y-placement "center"
--button1 "Ok"
--text "Encrypt '$GutenDrive' to continue backing up."
--informative-text "You must encrypt '$GutenDrive' to proceed. Please choose a strong password to use for encrypting your drive.
Only you will know this password, and it will be unrecoverable if your boot drive fails, so make note of this password in a secure location."`
if [ "$EncryptionDialog" = "1" ]; then
echo User accepted encryption dialogue
PasswordEntry
fi
else
echo Drive '$GutenDrive' is already encrypted, exiting script.
fi
}
## Dialogue to warn of mismatched passwords
function TryAgain {
TryAgainDialogue=`$CocoaDialog msgbox --title "Password Error" --x-placement "center" --y-placement "center"
--button1 "Retry"
--text "Passwords do not match."
--informative-text "The passwords you entered for '$GutenDrive' do not match. Please try again."`
if [ "$TryAgainDialogue" = "1" ]; then
echo User trying again
PasswordEntry
fi
}
## Password entry dialogues here
function PasswordEntry {
PasswordDialogue=`$CocoaDialog secure-inputbox --title "Enter Your Password" --x-placement "center" --y-placement "center"
--informative-text "Please enter a password for '$GutenDrive'." --button1 "Ok"`
FirstPass=`echo $PasswordDialogue | cut -d " " -f 2`
SecondPasswordDialogue=`$CocoaDialog secure-inputbox --title "Enter Your Password" --x-placement "center" --y-placement "center"
--informative-text "Please re-enter your password for '$GutenDrive'." --button1 "Ok"`
SecondPass=`echo $SecondPasswordDialogue | cut -d " " -f 2`
if [[ $FirstPass == $SecondPass ]]; then
DriveEncryption
elif [[ $FirstPass != $SecondPass ]]; then
TryAgain
fi
}
## Encrypt the Company Time Machine drive and resume the Time Machine backup
function DriveEncryption {
GutenDrive=`cat /private/tmp/gutendrive.txt`
EncryptionDialogue=`$CocoaDialog msgbox --title "Encrypting Drive" --x-placement "center" --y-placement "center"
--button1 "Ok"
--text "'$GutenDrive' is ready to be encrypted."
--informative-text "Please click 'Ok' to convert '$GutenDrive' to an encrypted volume and complete this process."`
diskutil cs convert $GutenDrive -passphrase $SecondPass
CompletionDialogue=`$CocoaDialog msgbox --title "Drive Encrypted" --x-placement "center" --y-placement "center"
--button1 "Ok"
--text "'$GutenDrive' is ready to be used."
--informative-text "Please click 'Ok' to enable this drive for Time Machine."`
tmutil startbackup
}
## Check the type of drive connected and write out to temp files
function DriveType {
for i in "${TMDestCheck[@]}"; do
DriveName=(`system_profiler SPStorageDataType | grep -A 33 "$i" | grep -m 1 "Media Name:" | cut -d ":" -f 2 | sed -e 's/^[ ]*//'`)
for n in "${DriveName[@]}"; do
if [[ "${DriveName[@]}" != "Name of approved drive" ]]; then
echo Verboten drive connected, shutting down Time Machine
echo "$i" > /private/tmp/verbotendrive.txt
DriveKill
elif [[ "${DriveName[@]}" == "Name of approved drive" ]]; then
echo "$i" > /private/tmp/gutendrive.txt
DriveCheck
fi
done
done
}
############################## End Function Definitions ##############################
################################ Script Begins Here ################################
DriveType
echo Removing temporary files
rm -f /private/tmp/tmdestcheck.txt
rm -f /private/tmp/verbotendrive.txt
rm -f /private/tmp/gutendrive.txt
echo Script complete. Exiting now
exit
Here's the launchdaemon from /Library/LaunchDaemons too. Really straightforward, and easy to create with Lingon or LaunchControl.
<?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>Label</key>
<string>com.company.TMChecker_1.0</string>
<key>Program</key>
<string>/path/to/script</string>
<key>StartOnMount</key>
<true/>
<key>WatchPaths</key>
<array>
<string>/Library/Preferences/com.apple.TimeMachine.plist</string>
</array>
</dict>
</plist>
-Matt
Posted on 10-08-2014 06:01 AM
@Bauer, I have to admit, this scripting is above me. Could you possibly post the script without the Approved drive section? I just need to force encryption on time machine drives.
Truly appreciated.
Posted on 10-08-2014 10:37 AM
Here's a retooled version that doesn't require a specific drive, and I also added in some icons and tidied things up a bit to make it easier to parse out for editing. I tested it out this AM, but definitely proof and test thoroughly to make sure it works in your environment.
#!/bin/bash
####### Time Machine drive detection and encryption script.
####### Written by Matt Bauer with contributions by Nick Kalister, 2013
############################## Variables Defined Here ##############################
## Cocoa Dialog Detection goes here. Cocoa Dialog v3 is recommended.
## Set the variable $CocoaDialog as the path to CocoaDialog.app/Contents/MacOS/CocoaDialog on your workstations.
## Get names of drives being used with Time Machine and assign them to TMDestCheck array variable.
IFS=$'
'
TMDestCheck=(`tmutil destinationinfo | grep Name | cut -d ':' -f 2 | sed -e 's/^[ ]*//'`)
echo --- Drives being used with Time Machine ---
echo ${TMDestCheck[@]}
echo ${TMDestCheck[@]} > /private/tmp/tmdestcheck.txt
############################## End Variable Definitions ##############################
############################## Functions Defined Here ##############################
## 1 - Check the encryption status of the Time Machine drive.
function DriveCheck {
for i in "${TMDestCheck[@]}"; do
DiskAttached=`diskutil info "$i" | grep "Could not find"`
if [ "$DiskAttached" == "" ]; then
EncryptionCheck=`diskutil cs list | grep -s -om 1 "$i"`
if [[ "$EncryptionCheck" == "" ]]; then
echo "$i" needs to be encrypted.
tmutil stopbackup
echo "$i" > /private/tmp/timemachinedrive.txt
EncryptionDialog=`$CocoaDialog msgbox --title "Encrypt Your Time Machine Drive" --x-placement "center" --y-placement "center"
--icon-file "/System/Library/PreferencePanes/TimeMachine.prefPane/Contents/Resources/TimeMachineGraphic@2x.png"
--icon-height 72
--icon-width 72
--button1 "Ok"
--text "Encrypt '$i' to continue backing up."
--informative-text "You must encrypt '$i' to proceed. Please choose a strong password to use for encrypting your drive.
Only you will know this password, and it will be unrecoverable if your boot drive fails, so make note of this password in a secure location."`
if [ "$EncryptionDialog" = "1" ]; then
echo User accepted encryption dialogue
PasswordEntry
fi
else
echo ""$i" is already encrypted, exiting script."
fi
else echo ""$i" not attached."
fi
done
}
## 2 - Password entry dialogues here.
function PasswordEntry {
AttachedDrive=`cat /private/tmp/timemachinedrive.txt`
PasswordDialogue=`$CocoaDialog secure-inputbox --title "Enter Your Password" --x-placement "center" --y-placement "center"
--icon "notice"
--informative-text "Please enter a password for '$AttachedDrive'." --button1 "Ok"`
FirstPass=`echo $PasswordDialogue | cut -d " " -f 2`
SecondPasswordDialogue=`$CocoaDialog secure-inputbox --title "Enter Your Password" --x-placement "center" --y-placement "center"
--icon "notice"
--informative-text "Please re-enter your password for '$AttachedDrive'." --button1 "Ok"`
SecondPass=`echo $SecondPasswordDialogue | cut -d " " -f 2`
if [[ "$FirstPass" == "1" ]] || [[ "$SecondPass" == "1" ]]; then
BlankPass
elif [[ "$FirstPass" != "$SecondPass" ]]; then
TryAgain
elif [[ "$FirstPass" == "" ]] || [[ "$SecondPass" == "" ]]; then
echo "User attempted to bypass password entry. Exiting."
elif [[ "$FirstPass" == "$SecondPass" ]]; then
DriveEncryption
fi
}
## 3 - Dialogue to warn of mismatched passwords.
function TryAgain {
TryAgainDialogue=`$CocoaDialog msgbox --title "Password Error" --x-placement "center" --y-placement "center"
--icon "stop"
--button1 "Retry"
--text "Passwords do not match."
--informative-text "The passwords you entered for '$AttachedDrive' do not match. Please try again."`
if [ "$TryAgainDialogue" = "1" ]; then
echo User trying again
PasswordEntry
fi
}
## 4 - Function to warn of blank password.
function BlankPass {
BlankPassword=`$CocoaDialog msgbox --title "Password Error" --x-placement "center" --y-placement "center"
--icon "stop"
--button1 "Retry"
--text "Passwords cannot be blank."
--informative-text "The passwords you entered for '"$i"' are blank. Please try again."`
PasswordEntry
}
## 5 - Encrypt the Time Machine drive and resume the Time Machine backup.
function DriveEncryption {
AttachedDrive=`cat /private/tmp/timemachinedrive.txt`
EncryptionDialogue=`$CocoaDialog msgbox --title "Encrypting Drive" --x-placement "center" --y-placement "center"
--icon-file "/System/Library/PreferencePanes/TimeMachine.prefPane/Contents/Resources/TimeMachineGraphic@2x.png"
--icon-height 72
--icon-width 72
--button1 "Ok"
--text "'$AttachedDrive' is ready to be encrypted."
--informative-text "Please click 'Ok' to convert '$AttachedDrive' to an encrypted volume and complete this process."`
diskutil cs convert $AttachedDrive -passphrase $SecondPass
CompletionDialogue=`$CocoaDialog msgbox --title "Drive Encrypted" --x-placement "center" --y-placement "center"
--icon-file "/System/Library/CoreServices/Installer.app/Contents/PlugIns/Summary.bundle/Contents/Resources/Success.tiff"
--button1 "Ok"
--text "'$AttachedDrive' is ready to be used."
--informative-text "Please click 'Ok' to enable this drive for Time Machine and begin backing up."`
tmutil startbackup
}
############################## End Function Definitions ##############################
################################ Script Begins Here ################################
DriveCheck
echo Removing temporary files
rm -f /private/tmp/tmdestcheck.txt
rm -f /private/tmp/timemachinedrive.txt
echo Script complete. Exiting now
exit
Posted on 02-24-2016 12:45 AM
@Bauer Do you have any idea how to modify this script for checking/enabling encryption on a Network volume (Like Time Capsule / Synology)?
Regards,
Ronald
Posted on 02-25-2016 09:40 AM
@rblaas If I remember correctly, Time Capsule stores the backups in sparsebundle disk images, and it's the disk image that's encrypted on Time Capsule, not the whole disk. If that's the case, hdiutil can verify if a sparsebundle or plain disk image is encrypted, but I'm not sure that you can "see" the disk image itself when the Time Machine backup runs, as the OS will probably only mount and display the disk image's volume, without exposing the disk image itself.
I don't have this setup to test on my own right now, but I would recommend testing with diskutil and hdiutil to see if either of them will report back encryption information on that sparsebundle. If not, try looking in the sparsebundle itself to see if maybe there's a hidden preference file at the root of the volume that indicates whether or not encryption has been enabled.
If I find some time to set up a test, I'll report back if I figure something out, and if you figure something out, please let me know what you found.
Posted on 02-29-2016 02:03 AM
I have found a way.. I have rebuild your script.
The thing you need to do is add a password in the system keychain. When the first Time Machine backup starts it will use this password for encryption.
and although the GUI is not saying that the backup is encrypted it still is. (you can try mounting the sparsebundle on a machine. It will ask for a password. )
I have included my (your rebuild) script. Sorry for the dialogs to be in Dutch.. But I think you can guess what it's saying :)
I do want to say that the script is not completely done. Some tuning is still in place. But that's just how you want it to be.
Things to keep in mind:
Still have to find a way to limit the sparsebundle (for lets say 500GB)
still need to create some escapes in case of loops :)
there may be better ways for doing this script.
I have not yet tested this script with Casper. I just ran the script as root on a client. (logged on with a simple user)
thanks for the help!
#!/bin/bash
## Set all Variables
CocoaDialog="/Library/Application Support/JAMF/bin/CocoaDialog.app/Contents/MacOS/CocoaDialog"
username=`stat -f '%u %Su' /dev/console | awk '{print $2}'`
tmserver="IP Address"
servervol="TimeMachine"
Retry=0
TMPass=1
Encpass=1
#### Functions
## 1 - Function to get Userpass for TimeMachine Server
function TMvolPass {
PasswordDialogue=`"$CocoaDialog" secure-inputbox --title "Voer uw inlog wachtwoord in" --x-placement "center" --y-placement "center"
--icon "notice"
--informative-text "Geef uw wachtwoord op voor de TimeMachine Server" --button1 "Ok"`
TMPass=`echo $PasswordDialogue | cut -d " " -f 2`
if [[ "$TMPass" == "1" ]]; then
BlankPass1
elif [[ "$TMPass" != "1" ]]; then
SetTMDest
fi
fi
}
## 2 - Function for Blank Password (TMvolPass)
function BlankPass1 {
BlankPassword=`"$CocoaDialog" msgbox --title "Password fout" --x-placement "center" --y-placement "center"
--icon "stop"
--button1 "Retry"
--text "Wachtwoord kan niet leeg zijn!"
--informative-text "Je hebt geen wachtwoord ingevuld. Probeer het opnieuw"`
TMvolPass
}
## 3 - Function for Password MisMatch
function TryAgain {
TryAgainDialogue=`"$CocoaDialog" msgbox --title "Password fout" --x-placement "center" --y-placement "center"
--icon "stop"
--button1 "Retry"
--text "Wachtwoorden niet gelijk"
--informative-text "De wachtwoorden komen niet overeen. Probeer het opnieuw."`
EncryptPass
}
## 4 - Set Time Machine Destination
function SetTMDest {
tmutil setdestination afp://$username:$TMPass@$tmserver/$servervol
if [[ $? -gt 0 ]]; then PassIncorrect=`"$CocoaDialog" msgbox --title "Wachtwoord Fout" --x-placement "center" --y-placement "center"
--icon "stop"
--button1 "Retry"
--text "Wachtwoord is niet correct!"
--informative-text "Het wachtwoord voor de TimeMachine Server is niet correct. Probeer het opnieuw."`
TMvolPass
fi
CompletionDialogue=`"$CocoaDialog" msgbox --title "Time Machine Server verbinding gelukt" --x-placement "center" --y-placement "center"
--icon-file "/System/Library/CoreServices/Installer.app/Contents/PlugIns/Summary.bundle/Contents/Resources/Success.tiff"
--button1 "Ok"
--text "Server verbinding gelukt"
--informative-text "Klik op OK om door te gaan."`
}
## 5 - Function to get Time Machine Encryption Password
function EncryptPass {
EncryptPassDialog=`"$CocoaDialog" secure-inputbox --title "Geef een wachtwoord op voor Encryptie" --x-placement "center" --y-placement "center"
--icon "notice"
--informative-text "Geef uw wachtwoord op voor de Encryptie"
--button1 "Ok"`
Encpass=`echo $EncryptPassDialog | cut -d " " -f 2`
if [[ "$Encpass" == "1" ]] ; then
BlankPasswordDialog
else
EncryptPassDialog2=`"$CocoaDialog" secure-inputbox --title "geef uw wachtwoord nogmaals op!" --x-placement "center" --y-placement "center"
--icon "notice"
--informative-text "Geef uw Encryptie wachtwoord nogmaals op."
--button1 "Ok"`
Encpass2=`echo $EncryptPassDialog2 | cut -d " " -f 2`
if [[ "$Encpass" != "$Encpass2" ]]; then
TryAgain
fi
fi
}
## 6 - BlankPassword (Encryption)
function BlankPasswordDialog {
BlankPassword=`"$CocoaDialog" msgbox --title "Wachtwoord Fout" --x-placement "center" --y-placement "center"
--icon "stop"
--button1 "Retry"
--text "Wachtwoord kan niet leeg zijn."
--informative-text "Het wachtwoord voor de Encryptie kan niet leeg zijn. Probeer het opnieuw."`
EncryptPass
}
### Scripting
# Get UserPass for Time Machine Server connection and Set Destination
TMvolPass
# Exclude all System folders
tmutil addexclusion -p /Applications
tmutil addexclusion -p /Library
tmutil addexclusion -p /System
# Exclude any other users on the computer (Edit for your specifics)
tmutil addexclusion -p /Users/admin
tmutil addexclusion -p /Users/Shared
tmutil addexclusion -p /Users/casperadmin
tmutil addexclusion /Users/$username/Downloads
# Exclude hidden root os folders
tmutil addexclusion -p /bin
tmutil addexclusion -p /cores
tmutil addexclusion -p /etc
tmutil addexclusion -p /Network
tmutil addexclusion -p /private
tmutil addexclusion -p /sbin
tmutil addexclusion -p /tmp
tmutil addexclusion -p /usr
tmutil addexclusion -p /var
tmutil addexclusion -p /.Spotlight-V100
tmutil addexclusion -p /.Trashes
## Make Entry in the System.Keychain for disk encryption
#Get ID for destination
TMID=`tmutil destinationinfo | grep ID | awk '{print $3}'`
# Get password for encryption
EncryptPass
# Set EncryptPassword in KeyChain
security add-generic-password -a $TMID -l "Time Machine" -s "Time Machine" -w "$Encpass" -A /Library/Keychains/System.keychain
if [[ $? -gt 0 ]]; then
Error=`"$CocoaDialog" msgbox --title "Error" --x-placement "center" --y-placement "center"
--icon "stop"
--button1 "Retry"
--text "Error"
--informative-text "De volgende Error. Probeer het opnieuw."`
exit 1
fi
# Enable timemachine to start auto backing up
tmutil enable
tmutil enablelocal
tmutil startbackup --auto
Posted on 02-29-2016 02:21 AM
Ow, The above script does NOT detect a Time Machine Backup on a network location and set encryption.
It just setup Time Machine on a Network location with encryption!
Just so you know :)
Posted on 07-24-2018 05:57 AM
Hi @rblaas, thanks for the script! But I cant get i to work in High Sierra 10.13.6, getting syntax error: "line 28: syntax error near unexpected token `fi'".
Did you test this on HighSierra? or would it be possible for you to revise it when you have time?
Thank you very much!
Posted on 07-27-2018 03:50 AM
@PatCMP I am currently on a holiday :) When I get back I will take a look at this (please note that we currently don't actually use the script)
Posted on 08-06-2018 04:10 AM
Thank you!
@rblaas
Posted on 08-08-2018 04:14 AM
@PatCMP A quicklook at the script :)
in line 27/28 there is a double fi
Please remove either the fi from line 27 or 28 :)