HOWTO
YUBIKEY
NOTES ON USING LOCAL SUDO WITH YUBIKEY

Published: 20221225

Tested on: Ubuntu 20.04.5 LTS

In this article the words "YubiKey" (a product name from the company Yubico) and "U2F key" are used interchangeably. A YubiKey can have one or several authentication "methods" (or applications) and one of these are U2F. For all intents and purposes of this article, you can think: "a YubiKey is a U2F key".

-

Before anything else, the user you're about to configure should already have sudo privileges.

Install the U2F PAM module

$ sudo apt install libpam-u2f

Associate your YubiKey (U2F key) with your local user account

First make sure your YubiKey is inserted into your computer.
Then we configure your inserted YubiKey (U2F key):

$ mkdir -p ~/.config/Yubico
$ pamu2fcfg > ~/.config/Yubico/u2f_keys

Your YubiKey should now be flashing, which means that you need to touch the metal (gold colored) part of the physical key.

Add another (backup) YubiKey

This can also be done later, but it is good practise to always add two keys whenever you're setting up YubiKeys.

Make sure that only your backup key is inserted.
Configure it by appending the u2f_keys file (Note the -n flag and the double >>).

$ pamu2fcfg -n >> ~/.config/Yubico/u2f_keys

Your YubiKey should now be flashing, which means that you need to touch the metal (gold colored) part of the physical key.

Securing the secrets

It can be wise to move the file (u2f_keys) from your account and into /etc and make sure only root can read it.

$ sudo mkdir -p /etc/yubico
$ sudo mv ~/.config/Yubico/u2f_keys /etc/yubico/
$ sudo chown root.root /etc/yubico/u2f_keys
$ sudo chmod 0600 /etc/yubico/u2f_keys

If you want to add severeal sudo users (with U2F keys) to your machine, make sure that each user's "u2f_keys"-line is appended to /etc/yubico/u2f_keys

Also make sure that each user's "u2f_keys"-line is on a separate line. pamu2fcfg doesn't add newline, so you may have to do that manually when you edit /etc/yubico/u2f_keys

Configure the PAM module for sudo to use U2F

Before you alter any PAM configurations, make sure you have at least one terminal logged in as root. This is because it is easy to make mistakes when you're messing with PAM, and making a mistake means that you will lock yourself out of root privileges of your own machine.

Let's configure PAM!

Open up the PAM configuration for sudo:

$ sudo vi /etc/pam.d/sudo

The file will look something like this:

#%PAM-1.0
session    required   pam_env.so readenv=1 user_readenv=0
session    required   pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0
@include common-auth
@include common-account
@include common-session-noninteractive

The line that matters is "@include common-auth" and I have two options for you to consider:

Option 1 - Configure so that "it is enough" to only authenticate with your YubiKey.

The configuration will look like this:

#%PAM-1.0
session    required   pam_env.so readenv=1 user_readenv=0
session    required   pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0
auth       sufficient pam_u2f.so authfile=/etc/yubico/u2f_keys
@include common-auth
@include common-account
@include common-session-noninteractive

The placement of the line is important. It being before "@include common-auth" means that it will first try to authenticate any sudo calls via the U2F PAM module. The word "sufficient" means that when a successful authentication is made, PAM will not require anything else. This is the setup you're looking for if you want to authenticate yourself with "the touch of a button" instead of having to type your user password each time you call on sudo.

Option 2 - Configure so that both password and U2F are required.

Then configuration will look like this:

#%PAM-1.0
session    required   pam_env.so readenv=1 user_readenv=0
session    required   pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0
@include common-auth
auth       required   pam_u2f.so authfile=/etc/yubico/u2f_keys
@include common-account
@include common-session-noninteractive

Again the placement matters. First sudo will ask for the user password because "@include common-auth" comes first. The word "required" means that after a successful password authentication is made, PAM will also require a successful authentication with U2F (YubiKey being present and button being pressed). The result is that sudo his now setup with MFA.

Testing your setup

Testing - Option 1

Open up a new terminal.
Type a simple sudo command:

$ sudo id

Your YubiKey should now be blinking with a green light... Press the button..

$ sudo id
uid=0(root) gid=0(root) groups=0(root)
$ 

Success!

If you don't press the button, it will timeout and ask for your password instead.

If your YubiKey isn't inserted, it will immediately go to the next step, which is asking for your password instead.

Testing - Option 2

Open up a terminal.
Type a simple sudo command:

$ sudo id

sudo will first ask you for your password:

$ sudo id
[sudo] password for user1:

After you've typed your password the YubiKey will be blinking with a green light.
Press the button and...

$ sudo id
[sudo] password for user1:
uid=0(root) gid=0(root) groups=0(root)
$

Success!

But how about on my server?

It is only natural to now be thinking of how to set this up for a server.

But remember: Not only does the machine with the U2F configuration need to have a local YubiKey, it also needs someone to press it. This means that the application of using sudo with a YubiKey isn't really automation friendly. It can be made easy, but it can't run unsupervised - which is the point.

There are however tricks where you can let a local U2F authentication forward over SSH to mean something on a remote server. More on this in my other article: Passwordless Remote Server Administration with SSH, sudo and YubiKey