Yubikey: Difference between revisions

From NixOS Wiki
imported>Darthdeus
add note on using gpgconf instead of hardcoding SSH_AUTH_SOCK path
 
(30 intermediate revisions by 22 users not shown)
Line 1: Line 1:
This article describes how [https://yubico.com Yubico]'s [[Wikipedia:YubiKey|YubiKey]] works and how you can use it.
This article describes how you can integrate [https://yubico.com Yubico]'s [[Wikipedia:YubiKey|YubiKey]] with NixOS.


To access the yubikey as user add the following udev rules to your configuration.nix:
== GPG and SSH  ==
 
Based on [https://github.com/drduh/YubiKey-Guide a guide] by [https://github.com/drduh @drduh]:


<syntaxHighlight lang=nix>
<syntaxHighlight lang=nix>
services.udev.packages = [ pkgs.yubikey-personalization ];
services.udev.packages = [ pkgs.yubikey-personalization ];
 
programs.gnupg.agent = {
  enable = true;
  enableSSHSupport = true;
};
</syntaxHighlight>
</syntaxHighlight>


As the yubikey-personalization tool does [https://github.com/Yubico/yubikey-personalization/issues/57 not support all yubico products] you might want to add the libu2f-host udev rules to your configuration.nix:
== Logging-in ==
<syntaxHighlight lang=nix>
 
services.udev.packages = [ pkgs.libu2f-host ];
To use your yubikey as a user login or for sudo access you'll have to install a PAM (Pluggable Authentication Module) for your yubikey.
 
=== pam_u2f ===
 
The <code>pam_u2f</code> module implements the U2F (universal second factor) protocol. The protocol was initially developed by Yubico, Google and NXP and is nowadays hosted as an open-standard by the FIDO Alliance. All current and most legacy Yubikeys support the U2F protocol making this the preferred way to use Yubikeys for user login.
 
Use this page to check whether your Yubikey supports '''FIDO U2F''' before starting: https://www.yubico.com/products/identifying-your-yubikey/
 
1. Connect your Yubikey
 
2. Create an authorization mapping file for your user. The authorization mapping file is like <code>~/.ssh/known_hosts</code> but for Yubikeys.
 
# <code>nix-shell -p pam_u2f</code>
# <code>mkdir -p ~/.config/Yubico</code>
# <code>pamu2fcfg > ~/.config/Yubico/u2f_keys</code>
# add another yubikey (optional): <code>pamu2fcfg -n >> ~/.config/Yubico/u2f_keys</code>
 
 
3. Verify that <code>~/.config/Yubico/u2f_keys</code> contains one line in the following style:
 
<syntaxHighlight>
<username>:<KeyHandle1>,<UserKey1>,<CoseType1>,<Options1>:<KeyHandle2>,<UserKey2>,<CoseType2>,<Options2>:...
</syntaxHighlight>
</syntaxHighlight>


To use the smart card mode (CCID) of Yubikey, you will also need the PCSC-Lite daemon:
4. Enable the u2f PAM module for login and sudo requests


<syntaxHighlight lang=nix>
<syntaxHighlight lang=nix>
services.pcscd.enable = true;
security.pam.services = {
  login.u2fAuth = true;
  sudo.u2fAuth = true;
};
</syntaxHighlight>
</syntaxHighlight>


In order to manage OTP keys you can install the <code>yubioath-desktop</code> package in your profile.
PAM U2F Docs: https://developers.yubico.com/pam-u2f/
This application will also both the udev rules as well as pcscd enabled.
 
 
5. Verify PAM configuration
 
See chapter ''Test PAM configuration'' an the end of this page.
 
=== yubico-pam ===
 
The <code>yubico-pam</code> module uses a OTP (one time password) challenge response to authenticate users.


Based on [https://github.com/drduh/YubiKey-Guide a guide] by [https://github.com/drduh @drduh], the following should be sufficient for a yubikey usable for ssh:
Use this page to check whether your Yubikey supports '''Yubico OTP''' before starting: https://www.yubico.com/products/identifying-your-yubikey/


<syntaxHighlight lang=nix>
You can enable challenge-response logins with the following commands:
services.pcscd.enable = true;
services.udev.packages = [ pkgs.yubikey-personalization ];


'''1.)'''
run: <code>nix-shell --command 'ykinfo -s' -p yubikey-personalization</code>
to get the serial code and enter it into <code>yubico.id = [ "12345678" ];</code>


environment.shellInit = ''
{{warning|1=Ignoring step 1 is considered insecure, any user could just plugin a yubikey and gain root access!}}
  export GPG_TTY="$(tty)"
  gpg-connect-agent /bye
  export SSH_AUTH_SOCK="/run/user/$UID/gnupg/S.gpg-agent.ssh"
'';


programs = {
'''2.)'''<syntaxHighlight lang=nix>
  ssh.startAgent = false;
security.pam.yubico = {
  gnupg.agent = {
  enable = true;
    enable = true;
  debug = true;
    enableSSHSupport = true;
  mode = "challenge-response";
  };
  id = [ "12345678" ];
};
};
</syntaxHighlight>
</syntaxHighlight>


Alternatively, <code>SSH_AUTH_SOCK</code> can be set more generally as
You'll also need to program the Yubikey for challenge-response on slot 2 and setup the current user for logon:
 
# <code>nix-shell -p yubico-pam -p yubikey-manager</code>
# <code>ykman otp chalresp --touch --generate 2</code>
# <code>ykpamcfg -2 -v</code>
 
 
To automatically login, without having to touch the key, omit the <code>--touch</code> option.


<syntaxHighlight lang=bash>
Having that, you should be able to use your Yubikey to login and for sudo. You can also set <code>security.pam.yubico.control</code> to "required" in order to have multi-factor authentication.
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
 
See also: https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html.
 
== Smartcard mode ==
 
To use the smart card mode (CCID) of Yubikey, you will need the PCSC-Lite daemon:
 
<syntaxHighlight lang=nix>
services.pcscd.enable = true;
</syntaxHighlight>
</syntaxHighlight>


if the right version of <code>gpgconf</code> is available <ref>https://github.com/drduh/YubiKey-Guide#replace-agents</ref>. Note that this might not work on all systems.
Please note that the PCSC-Lite daemon [https://ludovicrousseau.blogspot.com/2019/06/gnupg-and-pcsc-conflicts.html sometimes conflicts] with gpg-agent. This can be solved by putting the line <code>disable-ccid</code> into <code>~/.gnupg/scdaemon.conf</code>. There is also a [https://nix-community.github.io/home-manager/options.xhtml#opt-programs.gpg.scdaemonSettings Home Manager Option] for that.
 
== OTP ==
 
In order to manage OTP keys, you should install the <code>yubioath-flutter</code> package in your profile.
This application will also require both the udev rules as well as pcscd enabled.


== Offline key generation ==
== Key generation ==


It is best practice to create the keys on a system without network connection to avoid leakages.
It is best practice to create the keys on a system without network connection to avoid leakages.
This [https://github.com/drduh/YubiKey-Guide guide] explains in depth the steps needed for that.
This [https://github.com/drduh/YubiKey-Guide guide] explains in depth the steps needed for that.
There is also a [https://github.com/Mic92/dotfiles/blob/6a48eee2c772bd1f52f22fca5f531770958c738f/nixos/images/yubikey-image.nix nix expression] that creates a nixos live image with all necessary dependencies pre-installed.
There is also a [https://github.com/Mic92/dotfiles/blob/ed0ac1af816a7ebb7c5d4f040b77fa88e3ec1c79/nixos/images/yubikey-image.nix nix expression] that creates a nixos live image with all necessary dependencies pre-installed.
The image can be created with the [https://github.com/nix-community/nixos-generators nixos-generator tool]
The image can be created with the [https://github.com/nix-community/nixos-generators nixos-generator tool]
and depending on the image copied onto a usb stick or executed directly using <code>kexec</code>
and depending on the image copied onto a usb stick or executed directly using <code>kexec</code>


== Multiple Keys ==
== Multiple keys ==


If you want to use GPG with multiple keys, containing the same subkeys, you have to do this routine when swapping the key
If you want to use GPG with multiple keys, containing the same subkeys, you have to do this routine when swapping the key
Line 68: Line 124:
# <code>gpg --card-status</code> (optional, to see if key is visibile)
# <code>gpg --card-status</code> (optional, to see if key is visibile)


== References ==
== Test PAM configuration ==
 
Test user and/or sudo authentication.
Replace <code><username></code> by your users account name.
 
# <code>nix-shell -p pamtester</code>
# <code>pamtester login <username> authenticate</code>
# <code>pamtester sudo <username> authenticate</code>
 
 
If the result is <code>pamtester: successfully authenticated</code> then everything should work as expected.
 
== Locking the screen when a Yubikey is unplugged ==
 
This can be achieved with a <code>udev</code> rule, which can be added to your <code>configuration.nix</code>
 
<syntaxHighlight lang=nix>
services.udev.extraRules = ''
      ACTION=="remove",\
      ENV{ID_BUS}=="usb",\
      ENV{ID_MODEL_ID}=="0407",\
      ENV{ID_VENDOR_ID}=="1050",\
      ENV{ID_VENDOR}=="Yubico",\
      RUN+="${pkgs.systemd}/bin/loginctl lock-sessions"
  '';
</syntaxHighlight>
 
This will lock all sessions if any Yubikey matching the rule is unplugged.
 
If this does not work with your Yubikey take a look at the output of this command when you plug-in/unplug your Yubikey
<code>udevadm monitor --udev --environment</code> and adjust the rule accordingly. This rule should work with most Yubikey 5 series models
 
== Links ==
 
* [https://rzetterberg.github.io/yubikey-gpg-nixos.html GPG-keys for SSH authentication on NixOS]
* [[Yubikey_based_Full_Disk_Encryption_(FDE)_on_NixOS]]
 
[[Category:Cookbook]]
[[Category:Security]]
[[Category:Hardware]]

Latest revision as of 00:32, 7 October 2024

This article describes how you can integrate Yubico's YubiKey with NixOS.

GPG and SSH

Based on a guide by @drduh:

services.udev.packages = [ pkgs.yubikey-personalization ];

programs.gnupg.agent = {
  enable = true;
  enableSSHSupport = true;
};

Logging-in

To use your yubikey as a user login or for sudo access you'll have to install a PAM (Pluggable Authentication Module) for your yubikey.

pam_u2f

The pam_u2f module implements the U2F (universal second factor) protocol. The protocol was initially developed by Yubico, Google and NXP and is nowadays hosted as an open-standard by the FIDO Alliance. All current and most legacy Yubikeys support the U2F protocol making this the preferred way to use Yubikeys for user login.

Use this page to check whether your Yubikey supports FIDO U2F before starting: https://www.yubico.com/products/identifying-your-yubikey/

1. Connect your Yubikey

2. Create an authorization mapping file for your user. The authorization mapping file is like ~/.ssh/known_hosts but for Yubikeys.

  1. nix-shell -p pam_u2f
  2. mkdir -p ~/.config/Yubico
  3. pamu2fcfg > ~/.config/Yubico/u2f_keys
  4. add another yubikey (optional): pamu2fcfg -n >> ~/.config/Yubico/u2f_keys


3. Verify that ~/.config/Yubico/u2f_keys contains one line in the following style:

<username>:<KeyHandle1>,<UserKey1>,<CoseType1>,<Options1>:<KeyHandle2>,<UserKey2>,<CoseType2>,<Options2>:...

4. Enable the u2f PAM module for login and sudo requests

security.pam.services = {
  login.u2fAuth = true;
  sudo.u2fAuth = true;
};

PAM U2F Docs: https://developers.yubico.com/pam-u2f/


5. Verify PAM configuration

See chapter Test PAM configuration an the end of this page.

yubico-pam

The yubico-pam module uses a OTP (one time password) challenge response to authenticate users.

Use this page to check whether your Yubikey supports Yubico OTP before starting: https://www.yubico.com/products/identifying-your-yubikey/

You can enable challenge-response logins with the following commands:

1.) run: nix-shell --command 'ykinfo -s' -p yubikey-personalization to get the serial code and enter it into yubico.id = [ "12345678" ];

Warning: Ignoring step 1 is considered insecure, any user could just plugin a yubikey and gain root access!

2.)

security.pam.yubico = {
   enable = true;
   debug = true;
   mode = "challenge-response";
   id = [ "12345678" ];
};

You'll also need to program the Yubikey for challenge-response on slot 2 and setup the current user for logon:

  1. nix-shell -p yubico-pam -p yubikey-manager
  2. ykman otp chalresp --touch --generate 2
  3. ykpamcfg -2 -v


To automatically login, without having to touch the key, omit the --touch option.

Having that, you should be able to use your Yubikey to login and for sudo. You can also set security.pam.yubico.control to "required" in order to have multi-factor authentication.

See also: https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html.

Smartcard mode

To use the smart card mode (CCID) of Yubikey, you will need the PCSC-Lite daemon:

services.pcscd.enable = true;

Please note that the PCSC-Lite daemon sometimes conflicts with gpg-agent. This can be solved by putting the line disable-ccid into ~/.gnupg/scdaemon.conf. There is also a Home Manager Option for that.

OTP

In order to manage OTP keys, you should install the yubioath-flutter package in your profile. This application will also require both the udev rules as well as pcscd enabled.

Key generation

It is best practice to create the keys on a system without network connection to avoid leakages. This guide explains in depth the steps needed for that. There is also a nix expression that creates a nixos live image with all necessary dependencies pre-installed. The image can be created with the nixos-generator tool and depending on the image copied onto a usb stick or executed directly using kexec

Multiple keys

If you want to use GPG with multiple keys, containing the same subkeys, you have to do this routine when swapping the key

  1. killall gpg-agent
  2. rm -r ~/.gnupg/private-keys-v1.d/
  3. Plug in the new YubiKey
  4. gpg --card-status (optional, to see if key is visibile)

Test PAM configuration

Test user and/or sudo authentication. Replace <username> by your users account name.

  1. nix-shell -p pamtester
  2. pamtester login <username> authenticate
  3. pamtester sudo <username> authenticate


If the result is pamtester: successfully authenticated then everything should work as expected.

Locking the screen when a Yubikey is unplugged

This can be achieved with a udev rule, which can be added to your configuration.nix

services.udev.extraRules = ''
      ACTION=="remove",\
       ENV{ID_BUS}=="usb",\
       ENV{ID_MODEL_ID}=="0407",\
       ENV{ID_VENDOR_ID}=="1050",\
       ENV{ID_VENDOR}=="Yubico",\
       RUN+="${pkgs.systemd}/bin/loginctl lock-sessions"
  '';

This will lock all sessions if any Yubikey matching the rule is unplugged.

If this does not work with your Yubikey take a look at the output of this command when you plug-in/unplug your Yubikey udevadm monitor --udev --environment and adjust the rule accordingly. This rule should work with most Yubikey 5 series models

Links