/shavee

shavee is a Program to automatically decrypt and mount ZFS datasets using Yubikey HMAC as 2FA or any File on USB/SFTP/HTTPS drive with support for PAM to auto mount home directories.

Primary LanguageRustMIT LicenseMIT

shavee

rust workflow GitHub license GPG Crates.io

shavee is a simple program to decrypt and mount encrypted ZFS user home directories at login using Yubikey HMAC or a Simple USB drive as 2FA written in rust.

Supported methods

This program currently supports two methods for 2FA:

1. Yubikey

Yubikeys are secure authetication USB devices we can use for our Strong second factor.

Yubikey comes pre-programmed with a HMAC key on Slot 2 which can be used to derive our final encryption key along with our password.

Programmed HMAC secret in the Yubikey CANNOT be extracted once programmed in.

If you want to use Multiple keys on the same dataset (eg. backup keys) it is required for you to program SAME fresh HMAC secrets on all those keys.

Yubikey mode is set with the -y flag.

In this mode the program looks for a Yubikey on login and uses it's HMAC mode along with your password to derive the final encryption key.

Yubikey HMAC Slot can be set with the -s flag, defaults to SLOT 2

2. File/HTTP(S)/SFTP

In this mode the program looks for a file (can be any file) and use that along with your password to derive the final encryption.

File mode is set using the -f <path to file> option.

File can be a local file, a http(s) or a sftp location

Example HTTPS

shavee -f https://foo.org/secret.png

Exmaple SFTP

shavee -f sftp://user@foo.org/mnt/secretfile -P 4242

-P Option Sets port for both HTTP and SFTP.

Exmaple Local File

shavee -f /mnt/usb/secret.png

The idea with this method is to keep the file on a USB storage device or a Netork location you control and have it present during the login to derive the final encryption key.

You can use any pre existing file of your choice.

Or create one using

dd if=/dev/uranson of=./secretfile bs=4096 count=4096

Note: Since the file becomes part of your encryption key and its Security cannot be guaranteed as with Yubikey you are responsible for keeping it secure.

3. Password only

If no second factor is specified the program will use only password as a single factor.

Build and Install

  1. Install Rust
  2. Clone repo using
git clone https://github.com/ashuio/shavee.git 
  1. Build using
cargo build --release 
  1. Place the binary in your bin directory with
sudo cp target/release/shavee /usr/bin

Modes

  • pam : For use with the pam_exec.so module (Used with the -p flag)
  • create : Creates/Changes Key of a Dataset with the derived key (Used with the -c option)

Flags/Options

  • -y : Use Yubikey for 2FA
  • -f : Use any file as 2FA, takes filepath or a HTTP(S) location as an argument.
  • -p : Enable PAM mode (Lower case p )
  • -P : Set port for HTTP and SFTP requests (Upper case P )
  • -s : Set Yubikey HMAC Slot (Can be either 1 or 2)
  • -c : Create/Change key of ZFS dataset with the derived encryption key
  • -z : if present in conjunction with any of the above options, it will try to unlock and mount the given dataset with the derived key instead of printing it. Takes zfs dataset path as argument. ( Will automatically append username in PAM mode )

NOTE: The -y (Yubikey mode) flag and the -f <path to file> (File mode) option are interchangeable.

It is recommended to run the command to change keys again of your Datasets after version updates.

Configure ZFS Datasets

NOTE: If using with PAM your dataset password should be the SAME as your user account password for it to work automatically

NOTE: Remember to update your encryption key as well if you update your password.


You can change/update the key for existing ZFS datasets by running

shavee -c -z <zfs dataset path>

Example

shavee -y -c -z zroot/data/home/hunter

Here we use Yubikey as our second factor. (Can be omitted for password only auth)

Note: Encryption must already be enabled and the key loaded to change key of an exisiting dataset.

Create a new dataset

To create a new dataset with our derived encryption key simply run

sudo shavee -c -z <Desired dataset>

Example

sudo shavee -f /mnt/usb/secretfile -c -z zroot/data/home/hunter

Here we use a FILE for our second factor (Can be omitted for password auth only)

Use shavee to unlock and mount any zfs patition

Simply use the option -z to unlock any zfs dataset

Example

shavee -y -z zroot/data/home/hunter/secrets

Use in Scripts

You can also pipe the password directly into shavee to use with scripts

Example

echo "hunter2" | shavee -y -z zroot/data/home/hunter/secrets

Here "hunter2" will be treated as the password

Use a USB Drive instead of a Yubikey

You can use the -f option instead of the -y flag to substitute a Yubikey with any USB Drive.

Auto mount the USB so shavee can find the required keyfile on login

We can use udev for this, simply create and add the following to /etc/udev/rules.d/99-usb-automount.rules

ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_UUID}=="<UUID of partition>", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=yes --collect $devnode <Desired Mount point>"

Example

ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_UUID}=="ADB0-DA9C", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=yes --collect $devnode /media/usb"

Here we're mounting the first partition of the usb disk to /media/usb

You can get the UUID by running

udevadm info --query=all --name=<Target disk> | grep ID_FS_UUID=

Example

udevadm info --query=all --name=/dev/sdb1 | grep ID_FS_UUID=

Run udevadm control --reload-rules after to make sure new rules are loaded.

Use shavee with PAM to auto unlock homedir

This program uses the pam_exec.so module to execute during the login process.

simply add the following line to your desired pam login method file.

In our example we will be adding it to /etc/pam.d/sddm to handle graphical logins and /etc/pam.d/login to handle CLI logins.

Add the following line to you pam config file

auth    optional    pam_exec.so expose_authtok <full path to program> -p -y -z <base home dir>

Example

auth    optional    pam_exec.so expose_authtok /usr/bin/shavee -p -y -z zroot/data/home

Where zroot/data/home mounts to /home

Dual home directories in ZFS

Since ZFS mounts datasets OVER preexisting directories and we defined our module in PAM as optional we still get authenticated with JUST the pass even though our dataset is NOT decrypted (eg. Because Yubikey was not inserted).

We can use this to our advantage and essentially have TWO home directories.

First which would be your normal encrypted home directory which would be unlocked and mounted when your Yubikey is present at login.

Second would be the directory which would already be present and would be loaded on decryption failure i.e when no Yubikey is inserted during login.

Let me know if interested and maybe i can write up a more detailed guide.