DEV Community

Erik Huelsmann
Erik Huelsmann

Posted on • Updated on

Server access with SSH certificates - deep dive

There are a growing number of articles around which explain about the setup and use of SSH certificates, like the Wikibooks Certificate-based Authentication cookbook.

This article goes into detail where the others stop: Most articles describe how the principal in the certificate (-n argument to ssh-keygen when signing the user's key) needs to be set to the name of the user on the target host. There are however many more options that can be used on the server as well as in the certificate to manage access.

Advanced principals

By default, OpenSSH requires the name of the user logging in to be among the principals in the certificate. That is, if certificate based authentication is used, 'bob' needs to be in the list of principals to be able to:

$ ssh bob@server01.example.com
Enter fullscreen mode Exit fullscreen mode

Next to this default, servers have 3 mechanisms for setting up more advanced authentication setups using principals.

AuthorizedPrincipalsFile

Using this directive, a global or per-user list of principals can be configured for access to the server. That is to say that if the server is configured with an authorized_principals file:

# /etc/ssh/sshd_config

# for a global configuration:
AuthorizedPrincipalsFile /etc/ssh/authorized_principals

# for per-user configuration, relative to $HOME:
AuthorizedPrincipalsFile .ssh/authorized_principals
Enter fullscreen mode Exit fullscreen mode

which contains

access-any-user
Enter fullscreen mode Exit fullscreen mode

Then, if bob has a certificate named any_bob with the access-any-user principal, he can authenticate to the server as any user:

bob@client$ ssh -o CertificateFile=any_bob-cert.pub -i any_bob sshd@server01.example.com
This account is currently not available.
Enter fullscreen mode Exit fullscreen mode

The response This account is currently not available. indicates the authentication was successful and the nologin shell was executed.

Remark: Using the AuthorizedPrincipalsFile directive disables the default behaviour to accept certificates listing the target username among the principals.

Per-principal command restriction

The authorized principals file supports the same options as the authorized keys file does. Assuming server01 has a user named wacky with a regular login shell, if we change /etc/ssh/authorized_principals to contain:

command="/usr/bin/date" access-any-user
Enter fullscreen mode Exit fullscreen mode

Then:

bob@client$ ssh -o CertificateFile=any_bob-cert.pub -i any_bob wacky@server01.example.com
Sat Mar 30 15:29:44 CET 2024
Enter fullscreen mode Exit fullscreen mode

The source from which is being connected can be restricted using this method using the from= option. See for more options the documentation of the authorized_keys file.

Certificate based restrictions

Certificates can come with their own restrictions, independent of the restrictions specified by the server. The ones to highlight here are force-command and source-address. In case a force-command restriction in the certificate conflicts with the command restriction in the authorized principals file (i.e. they are not the same string), the mechanism is considered a mismatch (and the next mechanism - e.g. password based - is tried).

Certificate identity (-I) and sequence numbers (-z)

Although most sources hostnames for host certificates and <user>@<host> for user certificates, these can be any string value. They serve two purposes:

  1. To identify the certificate that was presented during authentication, in the system logs (syslog or journalctl); and
  2. To identify the certificate in the Key Revocation List (KRL)

Many articles don't specify a sequence number, but specifying one is definitely desirable to be able to revoke specific certificates.

Dynamic authorization of principals

The configuration option AuthorizedPrincipalsCommand is a global setting which may be used to configure dynamic authorized principal list generation using an external command:

AuthorizedPrincipalsCommand /usr/local/bin/dynamic-principals "%u %s"
AuthorizedPrincipalsCommandUser dedicateduser
Enter fullscreen mode Exit fullscreen mode

The sshd_config man page lists the supported tokens. Each returned line on standard output must conform to the same requirements as the lines from a static authorized principals file.

Prerequisites

To authenticate servers to clients:

  • A host certificate authority (CA) key pair
  • A host CA's public key deployed to clients; configured using the @cert-authority known_hosts-marker either through

    • global configuration (/etc/ssh/ssh_known_hosts)
    • user specific configuration (~/.ssh/authorized_keys)

    In case of a user-specified CA in authorized_keys, a principals list needs to be specified with the principals= option.

To authenticate clients to servers:

  • A client CA key pair
  • A client CA's public key deployed to servers; configured through /etc/ssh/sshd_config using the TrustedUserCAKeys configuration directive

Note: neither the client CA nor the host CA require a certificate of their own.

Conclusion

Although by default the target user name must be among the principals in the certificate, this is not a hard requirement: principals can be listed statically or dynamically on the server resulting in a successful authentication when a non-empty intersection between the server and certificate principals exists. This allows for a setup where principals define roles rather than login accounts.

Using the concepts presented in this article (especially the - certificate-based - command restriction) in combination with command restrictions in e.g. sudo opens opportunities for fine-grained control over user and admin access.

Top comments (0)