I was only able to test this with APFS but I assume it is very similar.
Step Zero: Get the Disk ID for your drive
mount | egrep '^/'
Mine looks like this:
/dev/disk1s5s1 on / (apfs, sealed, local, read-only, journaled)
/dev/disk1s4 on /System/Volumes/VM (apfs, local, noexec, journaled, noatime, nobrowse)
/dev/disk1s2 on /System/Volumes/Preboot (apfs, local, journaled, nobrowse)
/dev/disk1s6 on /System/Volumes/Update (apfs, local, journaled, nobrowse)
/dev/disk1s1 on /System/Volumes/Data (apfs, local, journaled, nobrowse)
/dev/disk1s3 on /Volumes/Recovery (apfs, local, journaled, nobrowse)
/dev/disk1s5 on /Volumes/SSD 1 (apfs, sealed, local, journaled, nobrowse)
/dev/disk8s1 on /Volumes/Dual-USB (apfs, local, nodev, nosuid, journaled, noowners)
Note the /dev/disk8s1
for Dual-USB
that will come in handy later.
Step One: Come up with a unique name to be stored in keychain
This can be anything you want, but it must not match anything else in your keychain.
I chose
KEYCHAIN_NAME='Dual-USB'
because I was working with a USB thumb drive that has both USB-A and USB-C, hence “dual”.
Step Two: Create a password
This can anything you like, but since we’re using it with a shell script, I recommend not using these characters:
'
"
!
?
just to be safe.
Save your password in 1Password (because safety) and then assign it to the variable PW_ADD
like so:
PW_ADD='WHEITHWJ$H@#iu2y359y24h'
Step Three: Add password to keychain
security add-generic-password \
-a "$KEYCHAIN_NAME" \
-s "$KEYCHAIN_NAME" \
-w "$PW_ADD"
You can put that all on one line if you remove the \
at the end of each line.
Step Four: Check Keychain Access.app
Make sure the password is in there as you’d expect.
Step Five: Retrieve the password from keychain into a variable
PW=$(security find-generic-password \
-a "$KEYCHAIN_NAME" \
-s "$KEYCHAIN_NAME" \
-g 2>&1 \
| awk -F'"' '/^password/{print $2}')
Step Six: use the $PW
variable with diskutil
diskutil apfs unlockVolume /dev/disk8s1 -passphrase "$PW"
Now, there are several things to note here:
-
/dev/disk8s1
is specific to my system and probably won’t be the same for yours. You should have yours from Step Zero. My concern is that this device ID might not be consistent across reboots, etc depending on other drives that might get attached/detached.
-
this is an APFS-specific command. I guess the HFS version is diskutil coreStorage unlockVolume
?
-
I did not need a diskutil mount
command. If you do, I’ll need to know more about that.
Assuming that the device ID does stay the same, I should be able to script this like so:
#!/usr/bin/env zsh -f
PATH="/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin"
# where should it be mounted when it's mounted
MNTPNT='/Volumes/Dual-USB'
if [[ -d "$MNTPNT" ]]
then
echo "$NAME: '$MNTPNT' is already mounted." >>/dev/stderr
exit 0
fi
## This can be whatever you like as long as it is unique
## And the same as what you used when adding the password TO keychain
KEYCHAIN_NAME='Dual-USB'
PW=$(security find-generic-password -a "$KEYCHAIN_NAME" -s "$KEYCHAIN_NAME" -g 2>&1 | awk -F'"' '/^password/{print $2}')
## Change this for HFS if necessary
diskutil apfs unlockVolume /dev/disk8s1 -passphrase "$PW"
if [[ -d "$MNTPNT" ]]
then
echo "$NAME: '$MNTPNT' mounted successfully."
exit 0
else
echo "$NAME: '$MNTPNT' failed to mount" >>/dev/stderr
exit 1
fi
exit 0
#EOF
So… that’s a start. Let’s try that and go from there. Also, how are you unmounting the drive? Are you doing it from Finder or Terminal?
My hunch is that we’ll have to find a way to use diskutil list
to get the device ID dynamically, but we’ll cross that bridge when we come to it.