CentOS/RHEL 10 Yubikey Access via SSH
Intro
I recently set up an external graphics card paired with a micro PC for local
Ollama
experimentation. It’s been a while since I set up a new CentOS system and I
wanted to be able to easily move my Yubikey between systems. I hit a snag in
that the standard udev rules are (understandably) designed to only provide
access to the user logged in at the console and I wanted to use my Yubikey via
SSH.
Issues
The official Yubico documentation points to a very old set of documentation that is designed only for authenticating with a Yubikey. This is useful, but I want to be able to use mine to hold my GPG keys.
To get started with the CLI tooling, I snagged ykpers and ykclient from
EPEL and
attempted to make sure that things were working by running ykinfo -v.
Unfortunately, I was hit with a USB error: Access denied (insufficient
permissions) error. I checked that the hardware was properly recognized by
running sudo ykinfo -v and there were no issues.
Troubleshooting
Being from the 1900’s, I went down the traditional route of troubleshooting by
checking logs and trying different methods. There wasn’t much in the logs that
was suspicious so I attempted to log in via gdm and all was well.
I dropped the error into my favorite search engine and found many old articles
regarding udev rules that were mostly focused on old Debian-based systems.
(Granted, this isn’t a common use case)
I finally sighed and dropped the issue into Gemini using the following prompt:
Why am I seeing
USB error: Access denied (insufficient permissions)when attempting to access my Yubikey usingykinfowhen logged in via SSH and how do I fix it? I’m using CentOS 10 and want any solutions to respect good security practice while still allowing remote access.
Resolution
The answer provided by Gemini was generally correct and I wanted to make sure that more up to date information was in my online memory somewhere.
The default rules at /lib/udev/rules.d/69-yubikey.rules are:
ACTION!="add|change", GOTO="yubico_end"
# Udev rules for letting the console user access the Yubikey USB
# device node, needed for challenge/response to work correctly.
# Yubico Yubikey II
ATTRS{idVendor}=="1050",
ATTRS{idProduct}=="0010|0110|0111|0114|0116|0401|0403|0405|0407|0410", \
ENV{ID_SECURITY_TOKEN}="1"
LABEL="yubico_end"
The issue that we’re running into is the ID_SECURITY_TOKEN which is set when
logging in via gdm instead of allowing access to a group.
To ensure that we keep everything working properly for both gdm and remote
access, we’ll set up a local yubikey-access group and extend the original
file.
Unfortunately, we can’t easily extend udev rules, so we’ll need to create a
new one.
The updated file should be placed in /etc/udev/rules.d/69-yubikey.rules with
the following content:
ACTION!="add|change", GOTO="yubico_end"
# Udev rules for letting the console user access the Yubikey USB
# device node, needed for challenge/response to work correctly.
# Yubico Yubikey II
ATTRS{idVendor}=="1050",
ATTRS{idProduct}=="0010|0110|0111|0114|0116|0401|0403|0405|0407|0410", \
OWNER="root", \
GROUP="yubikey-access", \
MODE="0660" \
ENV{ID_SECURITY_TOKEN}="1"
LABEL="yubico_end"
After you save the file, you need to trigger the new rules:
sudo udevadm control --reload-rules
sudo udevadm trigger
Now add the yubikey-access group and add whatever users you like to the group:
sudo groupadd yubikey-access -U user1,user2,user3
You may need to either log back in or use
newgrp yubikey-accessto ensure that the new group is active for any user that is logged in.
Drawbacks
The biggest drawback to this approach is that the idProduct field won’t be
updated alongside updates to the source file. This could be remedied using
DNF post transaction actions
(but I’m not bothering for the moment).