Enable SSH using Yubikey stored secrets

October 27, 2021

Outdated web info on setting up a Mac to store SSH secrets

We recently stood up an internal cloud using CloudStack to support internal development projects. We run a baremetal ( VMs ) Kubernetes cluster on our CloudStack implementation. Now we have a lot of VMs we can SSH into so in the spirit of automating the mundane we invested some time in setting up our Yubikeys to hold SSH keys. This blog is a quick overview of the key steps involved. I would normally direct you to some great resource on the internet but even the blog linked from the main Yubikey site did not work for us. https://florin.myip.org/blog/easy-multifactor-authentication-ssh-using-yubikey-neo-tokens

These instructions should work for all modern versions of OSX including Catalina, Mohave and Monterey.

The key objective of Yubikey SSH login is:

  • Store keys on yubikey

  • login to your favourite server with ssh using ssh user-name@server-name and you get automagically logged in.

The main steps include:

  • install gpg and pinentry-mac

  • apply some configuration

  • plug in yubikey

  • run gpg commands to generate keys and back up keys to local storage

  • use ssh-copy-id to load public key onto server

Mac setup

You can try your own way but the following is what worked for us after trying other’s methods and we ended up reverting to reading the gpg docs for minimal required setup.

Key Assumptions

Install (MacGPG2 Suite) [https://gpgtools.org]using the installer rather than homebrew is recommended. This give a nice UI for managing keys. It also installs some binaries that we will also install the brew version of.

Install gpg and pinentry using brew

> brew install gpg pinentry-mac

# edit ~/.bash_profile
# GPG SSH_AGENT enable
GPG_TTY=$(tty)
export GPG_TTY
unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
    export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi

Edit ~/.gnupg/gpg-agent.conf

pinentry-program /usr/local/MacGPG2/libexec/pinentry- mac.app/Contents/MacOS/pinentry-mac
enable-ssh-support
write-env-file ~/gnupg/gpg-agent-info
use-standard-socket
default-cache-ttl 600
max-cache-ttl 7200
debug-level guru
log-file ~/.gnupg/pgp.log

[Optional] Edit ~/.gnupg/gpg-agent.conf

no-tty # prevents output to terminal NOTE this must be commented out while 
# setting up Card or gpg cannot output to terminal. We also found that no-tty
# is required to have some terminal pin entry work such as sudo. There may be
# a workaround but sudo does not throw a ui dialog for pin entry and notty blocks
# sudo pinentry.
no-emit-version # prevents output of version information of gpg and OS
auto-key-retrieve # Will attempt to retrieve your public key from a key server 

Setup Card

# Check you can connect to card
# best to have no-tty option commented out for setup
> gpg --card-status
gpg: error reading symlink '/proc/curproc/file': No such file or directory
Reader ...........: Yubico YubiKey OTP FIDO CCID
Application ID ...: D2760001240100000006163812190000
Application type .: OpenPGP
Version ..........: 0.0
Manufacturer .....: Yubico
...

Note if card is not found. touching the yubikey and running command again can help. Smartcards have feelings too ;)

> gpg --edit-card
Displays card info
enter admin
gpg/card> help # displays commands
passwd to setup yout card pins note that this is not the master pins but only for key storage and retrieval

> gpg -k 
# Displays keys on your computer
# Select last 16 chars of the key you want to add
# You can get the same information from the MacGPG2 UI
> gpg --key-edit 95BB13865E4B4B9A  
gpg: error reading symlink '/proc/curproc/file': No such file or directory
gpg (GnuPG) 2.3.3; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.
...

gpg> toggle # enagles key selection
keys will be displayed first key is key 0, second is key 1
gpg> key 1
You should now see a * next to the selected key. This * will not appear for the default key 0
gpg> keytocard
Really move the primary key? (y/N)
agree and your key is loaded
repeat for default key


# Copy public key to be able to send to server
> ssh-add -L > my-public-key.pub
# Copy public key to server
> ssh-copy-id -fi my-public-key.pub username@servername

Check ssh with -v option to view key usage and wish you good luck.

> ssh -v user@host 

Look out for outputs like the following:

debug1: Next authentication method: publickey
debug1: Offering public key: cardno:17 301 339 ECDSA SHA256:fA80h5...KLyf592+no agent
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug1: Offering public key: cardno:17 301 339 RSA SHA256:fA80h5...KLyf592+no agent
debug1: Server accepts key: cardno:17 301 339 RSA SHA256:ffA80h5...KLyf592+no agent
debug1: Authentication succeeded (publickey).

You should be able to login to your favourite server as you with something like:

> ssh servername
            _             
           (_)            
  ___ _ __  _  ___  _   _ 
 / _ \ '_ \| |/ _ \| | | |
|  __/ | | | | (_) | |_| |
 \___|_| |_| |\___/ \__, |
          _/ |       __/ |
          |__/       |___/