ssh certificates part 1
All of my infrastructure SSH access is handled with SSH certificates for more than a year now. As I am asked every now and then how it works, I will describe how it works in multiple blog posts.
This part will revolve around Client certificates.
What is it good for?
With general public key usage one can identify a user by his public key. These get
put into an ~/authorized_keys
file and if a user presents the correct key, they
are let onto the system.
This approach works well, but it is a bit tricky to find out, which key was actually
used. Restricting the user based on his key on any machine also requires to manage
the authorized_keys with options.
Now SSH certificates on the client side grant the possibility to sign a public key and remove the requirement for an authorized keys file. The options can be set directly in the certificate and are active on every server this certificate is used with. As the certificate can also hold an identification string it is easier to see from the logs, which key for what purpose connected. The only thing to make this work is to set every server to trust the signee and no authorized keys file has to be managed anymore.
generating the CA
First we need a SSH key for the purpose of a CA. This should not be the same key as your normal key in a production environment. The key is generated any other key with ssh-keygen
ssh-keygen -t ed25519 -C CA -f ca.key
You can choose any key type you want, it works with all types and any type can
sign any type.
The -C
flag adds a comment to the key.
Now we can sign a public key.
signing a user key
First we sign a user public key foouser.pub
.
ssh-keygen \
-s ca.key \
-I 'foouser' \
-n foouser \
foouser.pub
Now what do all these options mean?
-s
defines the signing key-I
is an identification for the certificate. This also shows up in the auth.log on the server.-n
the principal, which in this case means the username this key will be allowed to login with.
To restrict the IP address for the public key, one can use the following line
-O source-address="127.0.0.1,192.168.42.1"
Any option from ssh-keygen(1)
requires its own -O options, for example:
-O clear -O no-pty -O force-command="/opt/foo/bin/do_stufff"
A good source for further options is the ssh-keygen man page.
After the command was executed, a file foouser-cert.pub shows up. The content can be inspected using ssh-keygen again:
ssh-keygen -L -f foouser-cert.pub
To get the authentication working with this key, two steps have to be taken. First is to put the generated certificated in the same directory like the private key, so that the ssh agent will sent the certificate. Second is to put the CA onto the server, so that it will trust all created certificates.
This is done with the following option in the sshd_config
TrustedUserCAKeys /etc/ssh/ssh_user_certs
where the content of the file _/etc/ssh/ssh_usercerts is the ca public key. It is possible to put multiple CAs into that file.
Now one can connect to the server using the newly created key
ssh -vvv -I foouser <yourserver>
Which should print a line like
debug1: Server accepts key: pkalg ssh-ed25519-cert-v01@openssh.com blen 364
debug1: Offering ED25519-CERT public key: /home/foouser/.ssh/id_ed25519
debug3: sign_and_send_pubkey: ED25519-CERT SHA256:YYv18lDTPtT2g5vLylVQZiXQvknQNskCv1aCNaSZbmg
These three lines state for my session, that the server accepts certificates and that my certificate was sent.
With this, the first step to using SSH certificates is done. In the next post I will show how to use SSH certificates for the server side.