I want to develop some scripts for things like Chrx, Chromebrew, MrChromebox scripts etc and I don't want to register a new SSH key to my account every time I need to powerwash or use recovery on one of my Chromebooks because I messed it up. I already use my Yubikey for GPG/FIDO/U2F/SSH on all the other systems I develop on, and I only needed the SSH portion to work for this particular use case. I also didn't want to deal with using Crouton or Crostini since that requires additional downloads and more configuration and complexity.
Since the Crosh userland doesn't have scdaemon or pcscd for talking to the smart card, I had to come up with another way to access the Yubikey and make the SSH key available. I ended up trying a few different things to make it work, but overall the solution ended up being brilliantly straightforward. Originally I tried using Chromebrew to install one of the smartcard access/manager packages, but the dependency chain ended up pulling in Gnome keyring and a bunch of other crazy things that I didn't need at all. I ended up breaking Chromebrew a few different ways trying to uninstall all those packages without just nuking /usr/local/
since I had some other stuff installed there from dev_install
and my other scripts.
I had run across some instructions in the ChromiumOS (ChromeOS) source code that I ended up being able to utilize to make this super easy and still very secure.
TL;DR to expound on later
# Open a Crosh shell via Ctrl+Alt+T or Crosh window app then typing `shell`
# Create host keys (only needs to be done once).
sudo su - # or sudo -i
## TODO: make this a HEREDOC fed to sudo
mkdir -p /mnt/stateful_partition/etc/ssh;
ssh-keygen -f /mnt/stateful_partition/etc/ssh/ssh_host_rsa_key -N '' -t rsa;
ssh-keygen -f /mnt/stateful_partition/etc/ssh/ssh_host_ed25519_key -N '' -t ed25519;
# We don't need to do the iptables portion if we are only accessing via localhost
# Open firewall and start sshd (must be done on every boot).
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Only necessary if don't have your SSH public key handy or added to Github
# You need to start the daemon temporarily in foreground mode so that you can get your Yubikey's public key
# /usr/sbin/sshd -D
# Open Secure Shell
# Create a connection for chronos@localhost
# Add --ssh-agent=gsc for the Relay Options and -A for SSH Arguments
# Attempt the connection, you may get prompted to allow the Smart Card Connector/Secure Shell to talk
# You may get prompted to trust the host, you can do so
# Then you will get a password prompt because it doesn't know our key yet
# press Ctrl+Shift+J to view the ssh-rsa or ssh-ecdsa key
# copy the key starting with ssh- to the last character of ==
# Back in the Crosh shell
# Ctrl+C to kill sshd
exit # leave root shell
mkdir -p ~/.ssh/
### I learned recently that if you use an SSH public key with Github you can fetch it at github.com/<yourusername>.keys
# GITHUB_USERNAME=YourUserNameHere
curl -L github.com/${GITHUB_USERNAME}.keys | tee -a ~/.ssh/authorized_keys
# TRUSTED_SSH_KEY='<paste your ssh-rsa key here>'
# echo "$TRUSTED_SSH_KEY" >> ~/.ssh/authorized_keys
# Note we removed the -D so it will run in the background
sudo /usr/sbin/sshd -oAuthorizedKeysFile=/home/chronos/user/.ssh/authorized_keys
### If you use are accessing the system "remotely" ie from another host entirely you need the iptables rule, then
### use your SSH client as normal
### On ChromeOS
# Back in Secure Shell
# Hit enter on the password prompt (it should fail/stop prompting because we killed the sshd it was talking to)
## Otherwise if you accidentally ran sshd without -D keep
## pressing Enter each time you are prompted for the password until it fails
## run `sudo kill $(pgrep sshd)` and then run the sshd line above again
# When it gives you the option to reconnect, accept the offer by pressing R
# You should get prompted for the PIN for your GPG/SSH key from the Yubikey
# If you enter your key correctly you will be prompted to cache the PIN
# Choose yes and you won't be prompted for your PIN each time the SSH key is used
# Choose no and you will get prompted, this is a GREAT thing for remote shared systems
With Chromebrew the chmod shouldn't be necessary, but the iptables still is to access from another host.
PERSISTED_PATH=/usr/local
sudo chown -R $USER $PERSISTED_PATH
mkdir ${PERSISTED_PATH}/custom_ssh
ssh-keygen -f ${PERSISTED_PATH}/custom_ssh/ssh_host_rsa_key -N '' -t rsa
ssh-keygen -f ${PERSISTED_PATH}/custom_ssh/ssh_host_dsa_key -N '' -t dsa
cat << EOF > ${PERSISTED_PATH}/custom_ssh/sshd_config
Port 2222
HostKey ${PERSISTED_PATH}/custom_ssh/ssh_host_rsa_key
HostKey ${PERSISTED_PATH}/custom_ssh/ssh_host_dsa_key
PidFile ${PERSISTED_PATH}/custom_ssh/sshd.pid
EOF
/usr/sbin/sshd -f ${PERSISTED_PATH}/custom_ssh/sshd_config
sudo iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
mkdir -p ~/.ssh/
### I learned recently that if you use an SSH public key with Github you can fetch it at github.com/<yourusername>.keys
# GITHUB_USERNAME=YourUserNameHere
curl -L github.com/${GITHUB_USERNAME}.keys | tee -a ~/.ssh/authorized_keys
Google Groups (hterm)
Test USB forwarding the GPG portion of Yubikey into Termina/Linux apps and then use the GPG as SSH agent to log into Dev shell via SSH from the Linux containers, if it doesn't require the firewall rule this would essentially allow you to setup a remote access to the Linux apps and then possibly with agent/key forwarding, access the underlying ChromeOS shell for development purposes completely remotely WITHOUT opening a firewall port to the entire network, so if you had Tailscale inside Linux apps you could grant access to someone remote via the access method and give them pretty low level access.