A small SSH certificate authority that issues short-lived OpenSSH user certificates to OIDC-authenticated callers — primarily GitHub Actions.
Instead of storing a long-term SSH private key in GitHub Secrets, a workflow
generates an ephemeral key pair on every run, proves its identity with the
GitHub OIDC token, and receives a certificate valid for a few minutes.
Servers trust only the CA public key; there are no authorized_keys to
distribute, rotate, or clean up after a leak.
GitHub Actions
│ GitHub OIDC JWT + ephemeral public key
▼
oidc-ssh-ca POST /sign
│ verify JWT → match policy.yaml → sign in memory
▼
short-lived OpenSSH user certificate
│ ssh / ansible / rsync / scp
▼
target servers (trust only the CA public key)
This is not a replacement for Vault, OpenBao, or Teleport. It is a small, single-binary tool that replaces long-lived SSH keys in GitHub Actions with short-lived, OIDC-issued certificates.
The value is not just fewer keys. For a team that deploys to production from
GitHub Actions, it makes a workflow's identity the unit of SSH authorization:
what each run may do is decided by verified OIDC claims against a reviewable
policy.yaml, every issued certificate is logged for audit, and key rotation
collapses onto the single CA key. See
Why teams adopt oidc-ssh-ca
for the operational case.
Workflow-scoped SSH permissions
oidc-ssh-ca can issue SSH certificates with a forced command based on GitHub Actions OIDC claims.
This means a workflow does not need general-purpose SSH access.
For example:
deploy-prod.ymlcan only run/usr/local/bin/deploy-prodrestart-worker.ymlcan only run/usr/local/bin/restart-workercollect-logs.ymlcan only run/usr/local/bin/collect-logs
Even if a certificate is leaked, it cannot be reused as a general SSH shell. It is short-lived and restricted to the command encoded in the certificate.
Building from source
oidc-ssh-ca is a single static Go binary with no cgo and no runtime
dependencies; building it needs only the Go toolchain (1.22 or newer):
go build -o oidc-ssh-ca ./cmd/oidc-ssh-ca # build the binary go test ./... # run the tests
Or install it straight onto your PATH:
go install github.com/atsuoishimoto/oidc-ssh-ca/cmd/oidc-ssh-ca@latest
A multi-stage Dockerfile builds a distroless image (docker build -t oidc-ssh-ca .). See the
build guide
for cross-compilation, version stamping, and the container build.
Documentation
The full documentation is at oidc-ssh-ca.readthedocs.io — start with the Quickstart.
- Quickstart — CA key, policy, server, sshd, and the GitHub Actions workflow, end to end
- Choosing a deployment — Cloud Run (recommended), Docker Compose + Caddy, AWS Lambda via CLI or Terraform, and systemd
- Reference — policy format, the /sign API, commands, and operations (audit log, reload, emergency stop, key rotation)
- Testing — running the test suite, including the local end-to-end tests with a mock OIDC provider
The sources are in docs/; to build locally:
pip install -r docs/requirements.txt
make -C docs html # docs/_build/html/index.htmlStatus
MVP plus native Lambda support. GitHub Actions OIDC (RS256) is the
supported identity source; only ssh-ed25519 keys are accepted for both
the CA and client keys. An Ansible role for target servers is included
(ansible/). AWS IAM identity matching and Terraform modules
are planned — see .memo/memo.md for the full design document.




























