In this post, I will cover the usages of a Yubikey for:

  • Protect local sudo command,
  • Protect local gnome login screen,
  • Protect local tty screen,
  • Protect remote ssh connections.

PROTECTING LOCAL SUDO

sudo apt update && sudo apt upgrade -y
sudo apt install libpam-u2f -y
mkdir -p ~/.config/Yubico
pamu2fcfg > ~/.config/Yubico/u2f_keys
sudo nano /etc/pam.d/sudo

Add the line in bold after the mentioned line:

@include common-auth
auth required pam_u2f.so

It is complete. Try to use the sudo command with and without the Yubikey connected.

The Yubikey will flash asking to touch its button to allow the command to go through.


PROTECTING LOCAL GNOME LOGIN

sudo nano /etc/pam.d/gdm-password

Add the line in bold after the mentioned line:

@include common-auth
auth required pam_u2f.so

PROTECTING LOCAL TTY SCREEN

sudo nano /etc/pam.d/login

Add the line in bold after the mentioned line:

@include common-auth
auth required pam_u2f.so

PROTECTING REMOTE SSH

sudo apt update && sudo apt upgrade -y
sudo add-apt-repository ppa:yubico/stable
sudo apt install libpam-yubico -y
sudo nano /etc/ssh/yubikeys

Add one line for each user followed by the first 12 characters of its own Yubikey:

usera:f8v6d6f687d6
userb:df98b67d7b68:adf1n98b7kf5
userc:edf8n98b7nf6

Create API credentials at the Yubikey website. Go to https://upgrade.yubico.com/getapikey.

Edit the PAM configuration file for the SSH server:

sudo nano /etc/pam.d/sshd

Add the following line at the top of the document replacing the ID and KEY from the API:

auth required pam_yubico.so id=ID key=KEY mode=client debug authfile=/etc/ssh/yubikeys

The most popular keyboard-interactive options are:

  • required (OTP and Password have to be met),
  • sufficient (OTP or Password have to be met).

Then edit the file:

sudo nano /etc/ssh/sshd_config

And make sure both of the following configurations are enabled:

ChallengeResponseAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive

It requires both methods to be met:

  • publickey (SSH-Key),
  • and keyboard-interactive (what comes out of the PAM).

To allow one specific user to connections only with ssh-key append:

Match User userd
    AuthenticationMethods publickey

Restart the service:

sudo systemctl restart ssh

PROTECTING REMOTE SUDO

sudo nano /etc/pam.d/sudo

Add the following line at the top of the document replacing the ID and KEY from the API:

auth required pam_yubico.so id=ID key=KEY mode=client authfile=/etc/ssh/yubikeys

PROTECTING REMOTE RASPBERRY PI’s SSH

Following the same steps to protect the SSH you may realize that the repo below does not exist for RPi:

sudo add-apt-repository ppa:yubico/stable

But do not let it stop you. It will work the same way.


USING ANSIBLE WITH 2FA

There are many workaround solutions that simply create bypass conditions for the Ansible, such as allowing root from a certain address or network:

Match Address 10.1.1.0/24,192.168.111.222
  PermitRootLogin yes

Or to suppress the 2FA for a specific user that only Ansible uses:

Match User ansible_user
  AuthenticationMethods publickey

But the best way for making the 2FA prompt to the Ansible that will enter the OTP is inserting the following configuration to the /etc/ansible/ansible.cfg:

[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=publickey,keyboard-interactive

Note: Ansible executes the requests to many servers in parallel (to improve performance) for each module execution, so consider serializing the execution giving it an order to follow to prevent overlapping of the OTP prompts (if more than one server requires OTP).

  serial: 1
  order: inventory

The order can be: inventory, reverse_inventory, sorted, reverse_sorted, or shuffle