Sudo with Solokey

Having sudo privileges enabled for your normal workstation user account is both a convenience and a security concern. The Pluggable Authentication Module for Linux (PAM) allows us to strengthen the requirements for using sudo, to include several authentication methods beyond just asking for a password. This chapter will install pam_u2f, which enables PAM authentication via FIDO2/U2F compatible hardware tokens like the Solokey. Each time sudo asks for authentication, it will prompt for a Solokey button press and a password to be entered.

CREDITS

Some of this guide was adapted from these other guides:

Thank you to the Fedora documentation team!

Open a root session as an anti-lockout measure

To prevent yourself from being locked out of your own system during the setup process, it is recommended to start a new terminal in a root session, and to keep it open. That way if you lock yourself out, you still have a way you can fix it.

[bash]: Run this on your workstation:
## Open root session and leave it alone in another window ....
sudo su

Consider adding a root password

If you use sudo a lot, you might not actually know the real root password of your system (or one might not even be set). As a backup, you may want to set a secure long random passphrase for the root user and keep it safe (you will rarely need it).

Warning

Reset the root password with a random string:

[bash]: Run this on your workstation:
(set -e
LENGTH=26
PASSWORD=$(tr -dc 'A-Za-z0-9!@#$%^&*()[]~+-_=?<>.,;:' < /dev/urandom | head -c ${LENGTH})
echo -e "\nSave this ${LENGTH} character long password somewhere safe:    ${PASSWORD}\n"
read -e -p "Do you want to reset the root password with this value (y/N)? " answer
(test "${answer,,}" == "y" || test "${answer,,}" == "yes") && \
    sudo sh -c "echo 'root:${PASSWORD}' | chpasswd && echo Done." || \
    echo "Cancelled."
)

Test that the root password works without using sudo:

[bash]: Run this on your workstation:
su

Register Solokeys

It is recommended that you register at least two solokeys: a primary key, and a backup key. That way, if you lose one of the keys, you can still use the other one.

Tip

Do the next steps as your normal workstation user account, which is the account that should already have sudo privileges.

Create a tempory file to capture solo key registrations:

[bash]: Set temporary environment variables
TMP_KEYS=$(mktemp)
  • Plug in the first solokey, then run:
[bash]: Run this on your workstation:
pamu2fcfg >> ${TMP_KEYS} && \
     echo >> ${TMP_KEYS}

It may ask you to enter the PIN of the solokey:

(stdout)
Enter PIN for /dev/hidraw1:
  • When the solokey lights up, press the button.

  • Unplug the first solokey and repeat the last command for the second solokey.

  • Unplug the second solokey and repeat for additional solokeys.

  • When you’ve written all the keys to ${TMP_KEYS}, reformat and install them into their final destination:

[bash]: Run this on your workstation:
echo "${USER}:$(cat ${TMP_KEYS} | \
    cut -d ":" -f 2 | tr '\n' ':')" | sed 's/:$//' | \
    sudo tee /etc/u2f_authorized_keys

Create custom PAM modules for U2F

You will create two new PAM modules: u2f-required and u2f-sufficient. They will both include these required settings:

  1. The authfile path to our authorized key list file.
  2. The cue literal to show the Please touch the device prompt message for each authentication. (If you omit this, it will print nothing, which can be confusing).

The only difference between the two PAM modules is that one is required, and the other is merely sufficient.

  • required means to enable 2FA: solokey + password required.
  • sufficient means to disable 2FA: solokey OR password is sufficient.
[bash]: Run this on your workstation:
cat << EOF | sudo tee /etc/pam.d/u2f-required
#%PAM-1.0
auth       required     pam_u2f.so authfile=/etc/u2f_authorized_keys cue
EOF
cat << EOF | sudo tee /etc/pam.d/u2f-sufficient
#%PAM-1.0
auth       sufficient     pam_u2f.so authfile=/etc/u2f_authorized_keys cue
EOF
Warning

The PAM modules you just created (/etc/pam.d/u2f-required and /etc/pam.d/u2f-sufficient) can be used for extending any of the other pam modules found in /etc/pam.d, by adding an appropriate include line at the right place. This can affect many more system authentication methods than just sudo, so be careful, but only sudo will be covered for now.

Configure PAM hook for sudo

As root, edit the file /etc/pam.d/sudo, and insert a new line directly after the #%PAM-1.0 header. A PAM module follows rules in top down order, as they are listed. Therefore your solokey rule needs to be the first authentication mechanism, and the existing password flow is the second authentication method.

Edit this file: /etc/pam.d/sudo
#%PAM-1.0
auth	  include      u2f-required
auth       include      system-auth
account    include      system-auth
password   include      system-auth
session    optional     pam_keyinit.so revoke
session    required     pam_limits.so
session    include      system-auth
Tip

Line 2 (auth include u2f-required) is the only line that was added to this file. Everything else in this file was here originally and is left intact.

Warning

If you change u2f-required to u2f-sufficient, then it will disable 2FA allowing solokey press OR user password as sufficient!

Test sudo

Tip

When testing sudo, always open a new terminal for each test. This is to avoid the auth caching mechanism (which is reset for new terminals).

[bash]: Run this on your workstation:
sudo su

The PAM system should now ask for you to touch your solokey (or press the button), and afterward prompt for your password.

(stdout)
Please touch the device.
[sudo] password for ryan: