-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathEncryptExternalVolume.sh
More file actions
464 lines (386 loc) · 17.4 KB
/
EncryptExternalVolume.sh
File metadata and controls
464 lines (386 loc) · 17.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
#!/bin/sh
##########################################
# Encrypt External Volume
# Josh Harvey | June 2017
# josh[at]macjeezy.com
# GitHub - github.com/therealmacjeezy
# JAMFnation - therealmacjeezy
##########################################
####### CocoaDialog Required ######################################################
# This script requires CocoaDialog to be installed and the location added to the
# variable after this section. If you do not have CocoaDialog installed, you can
# comment out the Progress section in each of the functions that use it. If you opt
# to do this, I can not guarentee the script will function as intended and there
# will not be a progress prompt for the user unless you manually add another one
###### AppleScript Icons #########################################################
# This script uses the default icons for AppleScript. If you want to use your own
# be sure to replace them with either alias paths or POSIX paths
##################### ISSUES / USAGE #############################################
# If you have any issues or questions please feel free to contact
# using the information in the header of this script.
#
# Also, Please give me credit and let me know if you are going to use
# this script. I would love to know how it works out and if you find
# it helpful.
##################################################################################
#### Variables ###################################################################
# Variable for the cocoaDialog path
# Example: /path/to/CocoaDialog.app/Contents/MacOS/CocoaDialog
cocoaD=""
# Variable for the log. This will need to be the full path and the name for the
# log file.
# Example: /path/to/log/volumeLog.txt
logPath=""
##################################################################################
#=========== Script Funtions ==========#
volumeChecks() {
#Finds the disk number
diskNumber=`diskutil info "$pickVolume" | grep "Part of Whole:" | awk {'print $4'}`
#Finds the volume name
volumeName=`diskutil info "$pickVolume" | grep "Volume Name" | sed 's/.*://g' | awk '{$1=$1};1'`
#Finds the disk location (Internal / External)
deviceLocation=`diskutil info "$pickVolume" | grep "Device Location:" | awk {'print $3'}`
#Finds the parition map of the volume
partitionScheme=`diskutil info "$diskNumber" | grep "Content (IOContent)" | awk {'print $3'}`
#Checks to see if the volume is already encrypted
encryptionCheck=`diskutil info "$diskNumber" | grep "Encrypted" | sed 's/.*://g' | awk '{$1=$1};1'`
#Finds the Logical Volume Group UUID
LVGuuid=`diskutil info "$pickVolume" | grep "LVG UUID:" | sed 's/.*://g' | awk '{$1=$1};1'`
#Finds the Logival Volume UUID
LVuuid=`diskutil info "$pickVolume" | grep "LV UUID:" | sed 's/.*://g' | awk '{$1=$1};1'`
#Finds the capacity of the volume
diskSize=`diskutil info "$pickVolume" | grep "Disk Size:" | sed 's/.*://g' | awk '{$1=$1};1' | awk {'print $1'}`
}
renameVolume() {
#Sets a variable from the new name the user enters
newName=`/usr/bin/osascript <<'APPLESCRIPT'
set renameOption to display dialog "Would you like to rename the volume?" with title "Rename Volume?" buttons {"Yes - Rename", "No"} default button "No" with icon 2
if button returned of renameOption is "No" then return
if button returned of renameOption is "Yes - Rename" then
set updatedName to display dialog "Enter the new name for the volume:" with title "Enter Name" default answer "" buttons {"Rename"} with icon 2
set selectedName to text returned of updatedName
selectedName
end if
APPLESCRIPT`
}
encryptedVolume() {
#Prompt that will appear asking the user to select an option if the volume is encrypted
encryptAgain=`/usr/bin/osascript <<'APPLESCRIPT'
set encryptionFound to display dialog "The volume you have selected is already encrypted.
If you have forgotten the passphrase for the volume, select \"Exit\" and contact your IT Admin to have the passphrase pulled from the JSS.
If you would like to change the passphrase and know the current passphrase, select \"Change Passphrase\"
If you would like to erase the volume and encrypt it again select \"Erase Volume\"
" with title "Encryption Exists" buttons {"Exit", "Change Passphrase", "Erase Volume"} default button "Exit" with icon file "Library:VA:passwordsuccess_icon.png"
if button returned of encryptionFound is "Erase Volume" then
set eraseVolume to "Yes"
end if
if button returned of encryptionFound is "Change Passphrase" then
set eraseVolume to "Change"
end if
if button returned of encryptionFound is "Exit" then
set eraseVolume to "Exit"
end if
eraseVolume
APPLESCRIPT`
#If statements to handle the user's selection
if [[ "$encryptAgain" == "Yes" ]];
then
verifyErase
echo "Erasing Encrypted Volume.."
eraseCS
startEncryption
elif [[ "$encryptAgain" == "Change" ]];
then
echo "Changing Passphrase"
changePassphrase
elif [[ "$encryptAgain" == "Exit" ]];
then
echo "$encryptAgain"
exit 0
fi
}
changePassphrase() {
#Captures the current passphrase
oldPass=`/usr/bin/osascript <<'APPLESCRIPT'
set oldPassword to display dialog "Please the current passphrase used to unlock the volume:" default answer "" with title "Current Encryption Passphrase" buttons {"Continue"} default button 1 with icon 1 with text and hidden answer
set oldPass to (text returned of result)
APPLESCRIPT`
#Captures and validates the new password
newPass=`/usr/bin/osascript <<'APPLESCRIPT'
--Verifies that the password for FileVault is more than 8 characters
set repeatPrompt to true
--Repeat statement to check for 8 characters and repeat if not found
repeat while (repeatPrompt = true)
set newPassword to display dialog "Please enter a new passphrase to use for encryption:" default answer "" with title "New Encryption Passphrase" buttons {"Use Passphrase"} default button 1 with icon 1 with text and hidden answer
set userPass to (text returned of result)
--if statement to check the input length
if length of (text returned of newPassword) is less than 8 then
display dialog "Please enter a passphrase that is 8 characters or longer" buttons {"Re-Enter Passphrase"} default button "Re-Enter Passphrase" with icon 1
else if length of (text returned of newPassword) is greater than 7 then
set verifyPassword to display dialog "Please Re-Enter Your New Passphrase:" default answer "" with title "Verify New Encryption Passphrase" buttons {"Continue"} default button 1 with icon 1 with text and hidden answer
--if statement to verify that the password has been entered correctly and matches
if text returned of result is equal to userPass then
set repeatPrompt to false
display dialog "Your new passphrase matches and has been applied." with title "Encryption Passphrase Updated Successfully" buttons {"Continue"} default button "Continue" with icon file 1 giving up after 5
userPass
else
display dialog "The passphrases you have entered do not match. Please enter matching passphrases." with title "Encryption Passphrase Validation Failed" buttons {"Re-Enter Passphrase"} default button "Re-Enter Passphrase" with icon stop
end if
end if
end repeat
APPLESCRIPT`
#Takes the password and encodes it with base64
pMask=`echo "$newPass" | base64`
### Progress Dialog ###
#//Create pipe
rm -f /tmp/hpipe
mkfifo /tmp/hpipe
#//Create a job that takes the input from the pipe
"$cocoaD" progressbar \
--indeterminate --title "Changing Passphrase" \
--text "Please wait..." < /tmp/hpipe &
#//Sends text through the pipe to be displayed
exec 3<> /tmp/hpipe
echo -n "Changing Passphrase for \""$volumeName" ("$diskSize" GB)\" ... Please Wait ..." >&3
#//Erase volume and apply new parition scheme
diskutil cs changeVolumePassphrase "$LVuuid" -oldpassphrase "$oldPass" -newpassphrase "$newPass"
#//Stop progress bar
exec 3>&-
#//Wait for background jobs to complete then remove the pipe
wait
rm -f /tmp/hpipe
encryptionLog
/usr/bin/osascript <<'APPLESCRIPT'
display dialog "The volume is now encrypted using the new passphrase you selected. A copy of the new passphrase has been uploaded to the JSS in the event you need to recover it." with title "Passphrase Change Completed" buttons {"Continue"} default button "Continue" with icon 1 giving up after 10
APPLESCRIPT
exit 0
}
#Function to erase a core storage volume
eraseCS() {
#//Create pipe
rm -f /tmp/hpipe
mkfifo /tmp/hpipe
#//Create a job that takes the input from the pipe
"$cocoaD" progressbar \
--indeterminate --title "Erasing Volume" \
--text "Please wait..." < /tmp/hpipe &
#//Sends text through the pipe to be displayed
exec 3<> /tmp/hpipe
echo -n "Erasing Volume: \""$volumeName" ("$diskSize" GB)\" ... Please Wait ..." >&3
#//Erase volume and apply new parition scheme
diskutil cs delete "$LVGuuid"
diskutil rename disk2s2 "$volumeName"
#//Stop progress bar
exec 3>&-
#//Wait for background jobs to complete then remove the pipe
wait
rm -f /tmp/hpipe
#Prompt to inform the user the volume has been been erased
/usr/bin/osascript <<'APPLESCRIPT'
display dialog "The volume has been successfully erased. Starting Encryption Process." with title "Erase Complete" buttons {"Ok"} default button "Ok" with icon 1 giving up after 10
APPLESCRIPT
}
#Function to erase a non core storage volume
eraseVolume() {
#//Create pipe
rm -f /tmp/hpipe
mkfifo /tmp/hpipe
#//Create a job that takes the input from the pipe
"$cocoaD" progressbar \
--indeterminate --title "Erasing Volume" \
--text "Please wait..." < /tmp/hpipe &
#//Sends text through the pipe to be displayed
exec 3<> /tmp/hpipe
echo -n "Erasing Volume: \""$volumeName" ("$diskSize" GB)\" ... Please Wait ..." >&3
#//Erase volume and apply new parition scheme
diskutil eraseDisk jhfs+ "$volumeName" GPT "$diskNumber"
#//Stop progress bar
exec 3>&-
#//Wait for background jobs to complete then remove the pipe
wait
rm -f /tmp/hpipe
#Prompt to infom the user of the status
/usr/bin/osascript <<'APPLESCRIPT'
display dialog "The volume has been successfully erased. Starting Encryption Process." with title "Erase Complete" buttons {"Ok"} default button "Ok" with icon 1 giving up after 10
APPLESCRIPT
#Starts the encryption function
startEncryption
}
#Function to capture the password for the volume and validate it after its entered
createPassphrase() {
/usr/bin/osascript <<'APPLESCRIPT'
--Verifies that the password for FileVault is more than 8 characters
set repeatPrompt to true
--Repeat statement to check for 8 characters and repeat if not found
repeat while (repeatPrompt = true)
set newPassword to display dialog "Please enter a passphrase to use for encryption:" default answer "" with title "Encryption Passphrase" buttons {"Use Passphrase"} default button 1 with icon 1 with text and hidden answer
set userPass to (text returned of result)
--if statement to check the input length
if length of (text returned of newPassword) is less than 8 then
display dialog "Please use a passphrase that is 8 characters or longer" buttons {"Re-Enter Passphrase"} default button "Re-Enter Passphrase" with icon 1
else if length of (text returned of newPassword) is greater than 7 then
set verifyPassword to display dialog "Please Re-Enter Your Passphrase:" default answer "" with title "Verify Encryption Passphrase" buttons {"Continue"} default button 1 with icon 1 with text and hidden answer
--if statement to verify that the password has been entered correctly and matches
if text returned of result is equal to userPass then
set repeatPrompt to false
display dialog "Your Passphrase Has Been Verified and Accepted." with title "Encryption Passphrase Validation Successful" buttons {"Continue"} default button "Continue" with icon 1 giving up after 5
userPass
else
display dialog "The passphrases you have entered do not match. Please enter matching passphrases." with title "Encryption Passphrase Validation Failed" buttons {"Re-Enter Passphrase"} default button "Re-Enter Passphrase" with icon stop
end if
end if
end repeat
APPLESCRIPT
}
#Function to start encryption
startEncryption() {
#Variable that calls the create passphrase function
userPassphrase=`createPassphrase`
#Variable to encode the passphrase with base64
pMask=`echo "$userPassphrase" | base64`
#//Create pipe
rm -f /tmp/hpipe
mkfifo /tmp/hpipe
#//Create a job that takes the input from the pipe
"$cocoaD" progressbar \
--indeterminate --title "Encrypting Volume" \
--text "Please wait..." < /tmp/hpipe &
#//Sends text through the pipe to be displayed
exec 3<> /tmp/hpipe
echo -n "Encrypting \""$volumeName" ("$diskSize" GB)\" ... This may take awhile ..." >&3
#//Apply new parition scheme
diskutil cs convert "$pickVolume" -passphrase "$userPassphrase"
#//Stop progress bar
exec 3>&-
#//Wait for background jobs to complete then remove the pipe
wait
rm -f /tmp/hpipe
#Starts function to log the passphrase and upload it to the JSS into the extension attribute
encryptionLog
#Starts the function to inform the user the encryption is finished
encryptionFinished
}
#Function to verify the next step
verifyStart() {
userVerify=`/usr/bin/osascript <<'APPLESCRIPT'
set askUser to display dialog "The encryption process is about to begin in 10 seconds. If you would like to quit before it begins, select \"Exit\" now." buttons {"Exit", "Continue"} default button "Exit" giving up after 10 with title "Starting Encryption Soon.."
if button returned of askUser is "Exit" then
set userStop to yes
userStop
end if
APPLESCRIPT`
echo "$userVerify"
if [[ "$userVerify" == "yes" ]];
then
echo "Quitting.."
exit 0
fi
}
#Function to verify the erase
verifyErase() {
userVerify=`/usr/bin/osascript <<'APPLESCRIPT'
set askUser to display dialog "The erase process is about to begin in 10 seconds. If you would like to quit before it begins, select \"Exit\" now." buttons {"Exit", "Continue"} default button "Exit" giving up after 10 with title "Starting Erase Soon.."
if button returned of askUser is "Exit" then
set userStop to yes
userStop
end if
APPLESCRIPT`
echo "$userVerify"
if [[ "$userVerify" == "yes" ]];
then
echo "Quitting.."
exit 0
fi
}
#Function to inform the user the encryption is complete
encryptionFinished() {
/usr/bin/osascript <<'APPLESCRIPT'
display dialog "The volume is now encrypted using the passphrase you selected. A copy of the passphrase has been uploaded to the JSS in the event you need to recover it." with title "Encryption Completed" buttons {"Continue"} default button "Continue" with icon 1 giving up after 10
APPLESCRIPT
exit 0
}
#Function to create and log the passphrase
encryptionLog() {
#Pulls the current user that is logged in
currentUser=`who | grep "console" | cut -d" " -f1`
#Pulls the current date
currentDate=`date`
#Creates the variable for the log
logItems=`echo "$currentDate $currentUser \"$volumeName\" $pMask"`
#Appends the variable set above to the log on the next available line
echo "$logItems" >> "$logPath"
#Hides the log file
chflags hidden "$logPath"
#Updates the inventory to the JSS
#Uncomment to upload to the JSS
#sudo jamf recon
}
#======== Volume Selection Section ========#
pickVolume=`/usr/bin/osascript <<'APPLESCRIPT'
--Sets the variable to loop until volume is verified by the user
set volumeVerified to false
repeat while volumeVerified is false
-- Returns the volumes that are currently mounted
-- If you want to exclude the startup volume, replace "VOLUMENAME" in the grep command
-- do shell script "ls /Volumes | grep -v \"VOLUMENAME\""
do shell script "ls /Volumes"
-- Creates a list from the ls command above
set listVolumes to the paragraphs of result
-- Creates a prompt for the user to select a volume from list created above
set chooseVolume to (choose from list listVolumes with prompt "Select the external drive to use:" OK button name "Select Volume" cancel button name "Exit" without empty selection allowed)
-- Quits if the user selects cancel
if chooseVolume is false then return
-- Sets the selected volume to the POSIX path
set selectedVolume to "/Volumes/" & chooseVolume & "/"
--Verifies the drive selected is correct
set verifyVolume to display dialog "You have selected:
/Volumes/" & chooseVolume & "
Is this correct?" with title "Verify Volume" buttons {"Continue", "Go Back"} with icon file 1
if button returned of verifyVolume is "Continue" then
set volumeVerified to true
end if
end repeat
selectedVolume
APPLESCRIPT`
#=========================================#
#//Verifies a volume has been selected before continuing. If a volume has been selected, it will run the function to fill the variables that may be used throughout the script
if [[ -z "$pickVolume" ]];
then
echo "No volume selected..exiting."
exit 0
else
volumeChecks
renameVolume
fi
if [[ -z "$newName" ]];
then
echo "Current Volume Name Being Used"
else
diskutil rename "$pickVolume" "$newName"
volumeName="$newName"
pickVolume="/Volumes/$volumeName"
fi
#//Encryption Check - If volume is already encrypted, it will run the function that includes the options only for encrypted volumes
if [[ "$encryptionCheck" == "Yes" ]];
then
encryptedVolume
fi
#//Location Check - Verifies the volume selected is an external drive and not an internal drive
if [[ "$deviceLocation" == "External" ]];
then
echo "$pickVolume is an external drive"
else
echo "$pickVolume is an internal drive and unable to be used"
exit 0
fi
#//Partition Check - Verifies the
if [[ "$paritionScheme" == "Apple_Partition_Scheme" ]];
then
echo "$partitionScheme is being used. The volume will need to be formatted using GUID in order to apply encryption"
verifyErase
eraseVolume
else
echo "The partition scheme $partitionScheme is valid and can be encrypted"
verifyStart
startEncryption
fi