Zssh - SSH Identity Management Through OpenZiti

Hi @dmuensterer

You've got really good timing! This is exactly the problem we've been working on.
We just open-sourced ziti-ssh (https://github.com/netfoundry/ziti-ssh), which implements Approach A & a bit more.

How it works

Four binaries:

  • ziti-ssh-ca — a CA service that runs as a ziti service (not a new controller endpoint). Authorized identities connect to it, send their SSH public key, and get back a short-lived signed certificate. It uses the controller's own intermediate CA private key, so there's a single trust root for both ziti identity certificates and SSH certificates. sshd needs one line: TrustedUserCAKeys /etc/ssh/ziti_ca.pub.
  • ziti-ssh-host — enrolls the identity & runs on the host, writes that TrustedUserCAKeys line, and proxies Ziti connections to local sshd. Port 22 stays firewalled externally.
  • ziti-ssh & ziti-scp — client tools that fetch a cert from the CA (cached, auto-refreshed before expiry) and opens an SSH or file copy session over ziti.

Why a separate service rather than a controller endpoint

We deliberately avoided modifying the controller(for now). Running as a standalone ziti service means no upstream PRs required — you deploy it alongside your existing network. The CA service is itself protected by ziti service policies, so only identities authorized to dial ssh-ca can request certificates. A native controller endpoint could be in the future and something we'd be open to exploring if this is widely adopted.

Revocation

A revoked identity can't dial ssh-ca, so it can't get new certificates. More importantly, it also can't dial the SSH service itself — so even an already-issued certificate is useless without network access to the target host. The certificate TTL (default 8h, configurable) bounds any residual risk in edge cases, but in practice revocation is effective immediately at the ziti layer.

Shared vs per-identity mode

Two modes.

  • Shared: all users authenticate as one Linux account (e.g. ziggy) — simple, no user provisioning, obviously less secure, but also less complex to implement.
  • Per-identity: the CA derives a Linux username from the ziti identity name and uses it as the certificate principal. ziti-ssh-host creates ephemeral Linux users on connect and applies per-identity groups and sudoers rules from a ziti-ssh-host.v1 config attached to the ziti service, so permission scope is tied to the service boundary.

Happy to answer questions. The project is new and contributions are welcome.