crosshackle is a way of transparently signing ssh private keys which is especially useful when the signed keys have a limited life and you want to prompt for resigning only when needed. It differs from the earlier faythe framework in utilising the openssh configuration file to manage the process rather than wrapping ssh in transparent but rather convoluted ways.
At its core, it consists of a single platform-dependant script to check and, if necessary, re-sign the certificate. Currently, we have a posix shell script for linux, Mac (or Windows) and powershell primarily for Windows but this also works on linux or Mac if required. This is the coupled with standard OpenSSH configuration snippet.
OpenSSH configuration file changes
To describe how it works, it is simplest to start with the changes to OpenSSHs configuration, usually in ${HOME}/.ssh/config
. In order to keep things tidy, it is recommended to add the following to this file.
Match Host *.essex.ac.uk Include ~/.ssh/ch_config
This will match any host in the target domain (essex.ac.uk) and include the contents of the crosshacke file which needs to contain the following:-
# crosshackle include file for domain essex.ac.uk # we only get here if host matching *.essex.ac.uk # check if we need a new cert Match Host !sshca.*,!sshenrol.*,* !exec "%d/.ssh/signkey %d/.ssh/id_ed25519_essex.ac.uk bret@sshca.essex.ac.uk" # if exit code was 1, create some fake settings to blow this # connection out of the water GlobalKnownHostsFile /dev/null UserKnownHostsFile /dev/null StrictHostKeyChecking yes ConnectTimeout 1 # check if we need to route through the gateway Match Host !sshgw.*,!sshca.*,!sshenrol.*,* !exec "ssh-keyscan -T 1 %h >%d/.ssh/junk 2>&1" ProxyJump bret@sshgw.essex.ac.uk # otherwise, use the defaults - if you need to override these # do this in the main config before this include file is called Host * User bret IdentityFile ~/.ssh/id_ed25519_essex.ac.uk ForwardAgent yes
Assuming that the client attempts to connect to host foo.essex.ac.uk (using an implicit or explicit username), OpenSSH (be that ssh, scp sftp etc) will run through each of the active configuration stanzas. These do the following:-
Lines 5 -11
This match block only applies to hosts not matching either the CA signing server or enrolment server. For those hosts that end up matching, the signing script specified is run. This checks whether the signed key associated with the private key file given as its first argument is still valid - e.g. still in date. If it isn’t, it’ll the signing script can use the second argument (username@sshca.<domain>) to resign the key.
Note that if this returns a non-zero code, meaning it failed, the following 4 settings are applied. These will cause the subsequent connection with the unsigned key to fail in a graceful way.Lines 14-15
This match block runs a script that attempts to retreive the hostkey from the server you want to connect to. If that fails, it sets the ProxyJump setting to force the connection to go via the named gateway.Lines 20 - end-of-file
This match block provides any default settings you wish to apply to hosts in the given domain.
Note that if you wish to provide per-host defaults that conflict with the domain wide settings, it would be better to do this in the main configuration file before the Match Host *.essex.ac.uk section.
Certificate signing script
The crosshackle configuration has an exec command to sign the users key. This requires two parameters:
ssh private file location (%d/.ssh/Id_essex.ac.uk)
The certificate you have previously registered with your SSH CA for signing.ssh destination to sign key
The signing script will need to run an ssh command to sign your key - this provides the destination to connect to.
The script itself need to
Check the supplied private key exists.
If there is a signed version of the private key (<key>-cert.pub), then check the validity date and if expired, reissue.
If there is no signed version of the private key, reissue.
Note that the SSH CA will probably prompt for password and MFA, but that dependant on how the SSH CA is configured.