Tool providing a simple SSH CA
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-29 18:39:23 +01:00
assets assets: crop avatar to its symbol for small sizes 2026-10-29 18:39:23 +01:00
bin fix: non-RSA CA keys, exit codes, index principals; add t/init-sign.t 2026-10-29 15:44:38 +01:00
t fix: non-RSA CA keys, exit codes, index principals; add t/init-sign.t 2026-10-29 15:44:38 +01:00
.editorconfig Add .editorconfig 2021-06-28 11:39:28 +02:00
.gitignore Update version in Makefile.PL 2022-04-09 11:37:05 +02:00
.perltidyrc tidy: reformat using perltidy 2022-04-09 11:27:53 +02:00
LICENSE add: LICENSE (close #7) 2026-10-29 15:15:38 +01:00
Makefile.PL Update version in Makefile.PL 2022-04-09 11:37:05 +02:00
README.md chg: README Operating section, fix key paths, check ca.pub (closes #8) 2026-10-29 15:16:58 +01:00

SSH with certificates

This tool helps creating/managing SSH certificates.

Background

Accessing SSH servers needs authentication. This can be done using password authentication or using key based authentication. Password authentication is considered as bad; from the security point of view key based authentication is the preferred way.)

But:

  • Keys are not bound to user identities.
  • Keys do not expire.
  • Keys need management on the remote systems (authorized_keys file)
  • …

Using SSH certificates solves several of these issues.

If you create a SSH CA (just a key pair) and distribute the public key of this CA as a "cert-authority" to the remote systems, all public keys, that are signed by this authority are able to access the remote systems.

(If you see similarities to X509: there are some. But SSH certificates are not X509 certificates.)

Initialization

Create the keypair for your CA (and some directory structure):

ssh-ca init [--no-git] <name-of-the-CA>

This creates a new directory structure:

<name-of-the-CA>
   +--- ca.pub        <--- public CA key
   +--- private/ca    <--- private CA key (never commit it)
   +--- tmp/
   +--- issued/
   +--- requests/
   +--- .gitignore    (ignores private/)

The key type is ssh-keygen's default; ssh-keygen asks for a passphrase.

The public key (ca.pub) you should install on the remote systems as a cert-authority:

# .ssh/authorized_keys
cert-authority ssh-…

or, server wide, via TrustedUserCAKeys in sshd_config.

Git integration

Unless --no-git is given, init makes <name-of-the-CA> a Git repository (with private/ ignored) and commits the initial state. Later sign runs add and commit index.txt and the issued files automatically, as long as <name-of-the-CA>/.git exists.

Operating

Requests

A user sends you the public key (id_*.pub). Optionally store it as

<CA>/requests/<IDENTITY>[/<PRINCIPALS>]/id_*.pub

Signing

ssh-ca sign -i <IDENTITY> [-n <principal>[,<principal>…]] \
    [-v <validity>] [-O <option>[,<option>…]] [--push] <CA> [KEY.pub…]
  • -i is mandatory; it becomes the certificate's key ID.
  • -n sets the principals (the remote accounts); they are sorted.
  • -v is the validity (default +30d, see ssh-keygen(1)).
  • Without KEY.pub arguments all requests/<IDENTITY>[/<PRINCIPALS>]/id_* are signed.
  • --push runs git push after the commit.

Results:

<CA>/issued/<IDENTITY>[/<PRINCIPALS>]/<timestamp>/<serial>/id_*.pub
                                                          id_*-cert.pub
<CA>/issued/<IDENTITY>[/<PRINCIPALS>]/latest -> <timestamp>
<CA>/index.txt     (V<TAB>serial<TAB>from<TAB>to<TAB>id<TAB>principals)

Give the user the *-cert.pub file; it belongs next to the private key (~/.ssh/id_xxx-cert.pub) and is picked up by ssh automatically.

Revocation

Not supported by ssh-ca. Use short validity periods, or maintain a KRL manually (ssh-keygen -k, RevokedKeys in sshd_config).