Configuring Hosts for SSH on Smallstep Certificate Manager

This documentation is for Smallstep Certificate Manager only. It does not apply to Smallstep SSH.

This guide assumes that you have already set up a Certificate Manager Authority that has been converted to issue SSH Certificates. If this hasn’t already been done, contact Smallstep with this request.


The following information is step-by-step instructions on how to configure a host device to be accessible via SSH by a dedicated user utilizing SSH on CM for certificate generation. This information could be used to piece together a script that would configure each host appropriately if desired.

Host Configuration

Create an Administrative User

To avoid managing individual users on all of your hosts, create an “admin” user on the host that can be used for administrative tasks when SSHing to a device.


Assuming that your box is running CentOS (commands will differ slightly otherwise), create an admin user for your host and set a secure password. Password will not be required to SSH to the user, but it will be required to escalate to the user while in the device.

sudo adduser admin

echo "admin:$admin_pw" | sudo chpasswd

Add this user to your /etc/sudoers and then configure its permissions as desired.

sudo usermod -aG wheel admin

Bootstrap to the SSH Authority

There are some files the host device will need in order to accept certificates from your SSH CA. Some will need to be configured by hand or as part of your provisioning script, and others can be configured using calls to the CA.

Commands for this section will require the host device to have step installed.


Use the step CLI to bootstrap your host device to your SSH CA. This will set up your STEPPATH and download some configuration files that will allow the device to make further connections to your authority. Run this bootstrap command as the POSIX user responsible for using the step CLI. This will set up the STEPPATH in that user’s home directory, whether this be the root or admin user. If desired, you may also run subsequent bootstraps as different users, but at least one user must have admin rights in order to move and renew the host certificate and key.

step ca bootstrap ${CA_Fingerprint} ${CA_URL}

Now, you should have your Root CA Certificate stored at $(step path)/certs/root_ca.crt. Your sshd_config will need to point to the location of this file: you may leave it here or copy it to a separate location for that purpose.

You will also need to provide your host with the credentials to use a provisioner on your authority.

  • If using a JWK provisioner, the JWK encrypted key password or the JWK private key will need to be stored on the host.
  • If using an X5C provisioner, you will need to import an X5C authorization certificate and key onto the host.

Use this secret to have your authority sign the Host SSH key that will be used to accept connections to your device.

# Provision an SSH certificate, without assigning it a password.
# If you forget --no-password --insecure, sshd will fail to run.
# --sign will have the CA sign the existing key.

# This will create a couple of files under the specified path
# with names beginning with ssh_host_ecdsa_key.

# If you would like to add additional principals to the certificate,
# you can also pass the `--principal=` flag to the command multiple times.
# We recommend adding all private IPs and the hostnames as principals to
# this certificate.

# If using a JWK encrypted key password:
step ssh certificate ${device_host_name} /etc/ssh/ssh_host_ecdsa_key \\
--host --no-password --insecure --force \\
--provisioner-password-file=/path/to/password/file \\
--provisioner ${provisioner_name}

# If using an X5C provisioner
step ssh certificate ${device_host_name} /etc/ssh/ssh_host_ecdsa_key \\
--host --no-password --insecure --force \\
--provisioner ${provisioner_name} \\
--x5c-cert=/path/to/x5c/cert --x5c-key=/path/to/x5c/key 

Now you have an SSH certificate and key for your host. It will be important to note the lifetime of this certificate, so you can appropriately renew it later on.


⚠️ Warning: As SSH on CM doesn’t monitor host devices (they don’t “enroll” like they would in SSH Professional), it is highly recommended to set up monitoring on the lifetime of your host certificates and make sure that they are renewing as expected.


You will also need to create a file that will allow your device to trust the SSH User CA. Store the User CA Public Key (to be provided by Smallstep) with your other configuration files.

# Save the CA's public user SSH key
# Device will trust any SSH key signed by the corresponding user private key
echo "ecdsa-sha2-nistp256 ${ca_user_pub_key} \\
> $(step path)/certs/ssh_user_key.pub

Configure sshd_config Settings

If you only want users with access to your certificate authority to have SSH access to your host, make sure to disable other means of authentication in your sshd_config. Additionally, you will point the configuration at the files that were just created such that the SSH Daemon will trust the correct certificates.

# If you want to allow root login, change to 'yes'
# If so, you'll also need to set up a provisioner to allow users to SSH as root
PermitRootLogin no

# Only accept PubkeyAuthentication
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
HostbasedAuthentication no
IgnoreUserKnownHosts yes

# SSH CA Configuration
# The path to the CA public key for authenticating user certificates
# Assumes step ca bootstrap was run as root, UPDATE IF NOT THE CASE!
TrustedUserCAKeys /root/.step/certs/ssh_user_key.pub 

# Path to the private key and certificate
HostKey /etc/ssh/ssh_host_ecdsa_key
HostCertificate /etc/ssh/ssh_host_ecdsa_key-cert.pub

# The rest...
# Update other settings as desired ...
......

Finally, restart sshd to allow these changes to take effect:

sudo systemctl restart sshd.service

Validation

You can validate that your host configuration is set up properly when you SSH to it by passing in verbose flags. The command ssh -vv ... should ultimately return something that looks like the following:

debug1: Server host certificate: [ecdsa-sha2-nistp256-cert-v01@openssh.com](<mailto:ecdsa-sha2-nistp256-cert-v01@openssh.com>) SHA256:el0B60OaOad5HsHUBertodk2dUNnegU9xJe8M, serial 8070123455661379 ID "[ec2-xx-xx-xx-xx.compute-1.amazonaws.com](<http://ec2-18-204-221-163.compute-1.amazonaws.com/>)" CA ecdsa-sha2-nistp256 SHA256:sqfZG6AOPUvcheFUIZDX+DEesnyfdfEWEdpcxUzY+0 valid from 2022-02-01T06:15:35 to 2022-03-03T06:16:35

Certificate Renewal

The SSH Host Certificate will need to be renewed at some point before its expiration date. This time period is defined either as the default used on the provisioner or the amount of time passed to the CA when provisioning the certificate. We recommend renewing your host cert on the day that it reaches two-thirds of it lifetime.


We suggest is setting up a systemd service that runs the renewal command on a defined schedule. This is at the user’s discretion, but the renewal command itself will look something like:

step ssh renew \\
/etc/ssh/ssh_host_ecdsa_key-cert.pub /etc/ssh/ssh_host_ecdsa_key \\
--force

If you would like to check on the remaining lifetime of an SSH certificate, you can use the needs-renewal step command to do so. This command can be used to check if the certificate has reached a certain percentage of its lifetime or if it will expire within a given period.


Accessing Devices as a User

Users will need to update their SSH configuration to trust the SSH Host CA. They may do so by adding the SSH Host CA Public Key (supplied by Smallstep) to their ssh_known_hosts file.

sudo echo "@cert-authority *.company.com ${ca_host_pub_key}" \\
> /etc/ssh/ssh_known_hosts

This entry assumes that all host devices will have an FQDN of .company.com. If this is not the case, you can simply replace "*.company.com" with "*" in the above line.


From there, provisioner admins may request an SSH Certificate from the authority (you can also “bake” default principals into provisioner templates for non-admin users):

step ssh certificate ${user_email} id_ecdsa --principal "admin" \\
--no-password --insecure --force

The provisioner in use will likely be an OIDC provisioner, so users may be managed by your IdP. The identity of ${user_email} above assumes this to be the case and will pass user information to the IdP to allow for authentication.


Then, use this certificate to SSH to your Host Device:

ssh admin@${device_host_name} -i ./id_ecdsa-cert.pub

It is an absolute requirement that ${device_host_name} matches the host name listed as the identity on the device’s SSH Host Certificate. If it doesn’t, your SSH command will fail.

If it is not possible to issue the device a valid FQDN, you may instead use the Private IP or hostname of the device on its Host SSH Certificate.*


You can also use step ssh login with the --principal flag added if preferred over generating a certificate that’s stored to disk.