Skip to content

Instantly share code, notes, and snippets.

@joostd
Last active March 1, 2025 23:07
Show Gist options
  • Save joostd/3b42fe8daaf14cac65bdea2fb3046665 to your computer and use it in GitHub Desktop.
Save joostd/3b42fe8daaf14cac65bdea2fb3046665 to your computer and use it in GitHub Desktop.
Demo for using a FIDO security key and ssh-agent to provide a form of SSH single sign-on (SSO), but require the security key to be inserted when signing in.
FROM ubuntu:22.04
ARG user
RUN apt-get update && apt-get install -y openssh-server
RUN mkdir /var/run/sshd
EXPOSE 22
RUN useradd -ms /bin/bash "$user"
COPY id_userca.pub /etc/ssh/user_ca.pub
RUN echo "TrustedUserCAKeys /etc/ssh/user_ca.pub" >> /etc/ssh/sshd_config
CMD ["/usr/sbin/sshd", "-D"]
# demo: simulate "SSO" by using a security key as posession factor only, and as password that can be handled by ssh-agent as knowledge factor
USER=myuser
all: server_up ssh server_dn realclean
usage:
@echo usage:
@echo make issue - generate an SSH certificate
@echo make clean - remove all generated SSH files
@echo make ssh - sign in to the server
@echo " ssh -i ./mykey ${USER}@localhost"
# generate the CA key pair
id_userca id_userca.pub:
ssh-keygen -t ed25519 -f id_userca -N "" -C [email protected]
# issue a certificate to your security key
issue: mykey-cert.pub
# Generate an SSH key on a security key
mykey mykey.pub:
ssh-keygen -t ed25519-sk -f ./mykey -N "password" -O no-touch-required -C ${USER}@example.org
# have the CA sign your pubkey into a SSH certificate
mykey-cert.pub: id_userca mykey.pub
ssh-keygen -s ./id_userca -I ${USER}@example.org -V +52w -n ${USER},${USER}@example.org -O no-touch-required mykey.pub
server_up: id_userca mykey.pub
docker build --build-arg user=${USER} -t ssh-server .
docker run -d -p 22:22 --name ssh_demo ssh-server
server_dn:
docker stop ssh_demo
docker rm ssh_demo
docker rmi ssh-server
ssh-keygen -R 'localhost'
ssh: mykey mykey-cert.pub
ssh-add mykey
ssh -i ./mykey -o StrictHostKeyChecking=accept-new ${USER}@localhost whoami
ssh-add -D
clean:
-rm mykey{,.pub,-cert.pub}
caclean:
-rm id_userca id_userca.pub
realclean: clean caclean

ssh-cert-sk-notouch

Demo for using a FIDO security key, SSH certificate, and ssh-agent to provide a form of SSH single sign-on (SSO), but require the security key to be inserted when signing in.

It uses the security key as a posession factor only. Note that when using hardware-backed SSH keys (i.e.of type ecdsa-sk or ed25519-sk), the private key file does not contain the private key itself but a reference (a "key handle") to the actual private key which is stored on the security key.

SSH certificates are used so that the authorization to sign in without touch is stored as a certificate extension.

Lastly, ssh-agent is used to obtain 'single sign-on", as the private key file is protected with a passphrase. This is normally superfluous when using security keys when the security key requires a PIN, but in this case the security key is configured without any touch or PIN requirements (neither UP nor UV in FIDO terms).

The effect is that a user only needs to supply the passphrase once when adding the key to the agent, but can subsequently sign in on any server that trusts the certificate issuer as long as the security key is inserted.

This can be useful when running automation scripts that repeatedly sign in on a server that makes user interaction impracticle, for instance when using ansible to deploy a server.

SSO can be disabled either by removing the key from the agent (ssh-agent -D) or by removing the security key, in which case the agent can no longer access the security key:

sign_and_send_pubkey: signing failed for ED25519-SK "./mykey" from agent: agent refused operation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment