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
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
which contains
access-any-user
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.
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
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
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:
- To identify the certificate that was presented during authentication, in the system logs (syslog or journalctl); and
- 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
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. - global configuration (
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 theTrustedUserCAKeys
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)