+++
title = "ssh certificates part 2"
date = "2015-07-28T21:20:49+00:00"
author = "Gibheer"
draft = false
+++

This is the second part of the SSH certificate series, server side SSH
certificates. You can find the first one [here](/118).

This post shows, what use server side certificates can be and how they can be
created.

What use have server side certificates?
---------------------------------------

SSH certificates on the host side are used to extend the ssh host keys. These
can be used to better identify a running system, as multiple names can be
provided in the certificate. This avoids the message of a wrong host key in a
shared IP system, as all IPs and names can be provided.

SSH certificates can also help to identify freshly deployed systems in that the
system gets certified directly after the deployment by a _build ca_.

signing a host key
------------------

For this step, we need a CA key. How that can be generated was mentioned
in the [first part](/118).
We also need the host public key to sign. This can be either copied from /etc/ssh/ from
the server or it can be fetch using _ssh-keyscan_.

    ssh-keyscan foo.example.org

It can also take a parameter for a specific type

    ssh-keyscan -t ed25519 foo.example.org

This is needed for some older versions of openssh, where ed25519 public keys
were not fetched by default with _ssh-keyscan_.

The output returned looks like the following:

    zero-knowledge.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPIP0JSsdP2pjtcYNcmqyPg6nLbMOjDbRf0YR/M2pu2N

The second and third field need to be put into a file, so that it can be used
to generate the certificate.

A complete command would then look like this:

    ssh-keyscan foo.example.org | awk '/ssh|ecdsa/ { print $2,$3 }' > host.pub

With the resulting file, we can now proceed to create the certificate.

    ssh-keygen \
      -s ca.key \
      -V '+52w1d' \
      -I 'foohost' \
      -h \
      -n foo.example.org,bar.example.org \
      host.pub

The meaning of the options is:

* `-s` the key to use for signing (the ca)
* `-V` interval the certificate is valid
* `-I` the identity of the certificate (a name for the certificate)
* `-h` flag to create a host certificate
* `-n` all names the host is allowed to use (This list can also contain IPs)

The last option is the public key file to certify.

This results in a file host-cert.pub, which contains the certificate. It can be
viewed like the SSH client certificate, with _ssh-keygen_.

    ssh-keygen -L -f host-cert.pub

This file now has to be placed in the same directory like the public key on that
host, with the same `-cert.pub` ending.

The last step on the server is to adjust the _sshd_config_, so that it includes
the certificate. For that, add the following line for the fitting host key, for
example:

    HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub

With a reload, it should load the certificate and make it available for
authentication.

Now the only thing left to do is to tell the client, that it should trust the
CA to identify systems. For that, the public key of the CA has to be added
to the file `~/.ssh/known_hosts` in the following format

    @cert-authority * <content of ca.pub>

The _*_ marks a filter, so different CAs can be trusted depending on the domain.

With this, you are able to connect to your server only using the certificate
provided by the server. When connecting with debugging on, you should get output
like the following:

    $ ssh -v foo.example.com
    ...
    debug1: Server host key: ssh-ed25519-cert-v01@openssh.com SHA256:+JfUty0G4i3zkWdPiFzbHZS/64S7C+NbOpPAKJwjyUs
    debug1: Host 'foo.example.com' is known and matches the ED25519-CERT host certificate.
    debug1: Found CA key in /home/foo/.ssh/known_hosts:1
    ...

With the first part and now the second part done, you can already lock up your
infrastructure pretty fine. In the next part, I will show some stuff I use
to keep my infrastructure easily managable.
