Epithet, Briefly 30 Nov 2023
Since Bob asked, I'm cleaning up a system to make using short-lived ssh certificates easy, simple, and secure.
The gist is to use a custom ssh-agent which, in turn, uses some modern authn service (OIDC, Keycloak, Okta, Google Sign-In, etc) to authenticate you. It then passes that auth token up to a CA which relies on a policy service to verify the auth token and respond with cert params (time, principals, extensions, whatever is needed). The CA uses the policy provided attributes to generate a short lived cert, which it gives back to the agent. Voila, you can access things for a couple minutes.
There is a real sequence diagram of what is going on in the repo.
CA
The CA is dirt simple and is the only thing that will ever see the CA private key. The same CA service should be usable by more or less anyone, maybe with some variety in terms of where the private key is stored, but that is it.
The CA receives an opaque auth token + pubkey from the agent and responds with a cert. The existing implementation uses a policy service to decide whether to issue the cert, and what attributes to give it.
The actual CA was kept as simple as possible, because it is a CA. You don't want to muck with it much.
Policy
The policy service consumes the opaque auth tokens from the CA and reponds with basic info, assuming the auth is valid:
{
"identity":"brianm@skife.org",
"principals":["oncall_fluffy", "oncall_wibble", "wheel"],
"expiration":"2m",
"extensions": {
"permit-pty":true,
"permit-port-forwarding":true
}
}
The policy server (single endpoint, takes a post with the context for the request) is nice as it can be dynamic and make use of risk models and various other signals to decide what to do: eg, "is it a deploy server asking for a key? Is there actually a deploy in progress matching the identity requesting the cert? Okay, give it a 5 minute cert" on the sophisticated side; simply checking an OIDC token for validity on the simpler side.
Agent
The ssh agent generates a new keypair on startup and never lets the private key leave memory. It has a small GRPC API over a domain socket for interfacing with authentication mechanisms, such as a helper to simply feed it tokens over stdin for simple cases. We popped a browser (or used a cli tool) to do the Okta dance.
Michael and I made this at a previous company. We spun up the CA in one lambda function, the policy server in another, and authed against Okta. I want it for my own stuff now and it doesn't look like anyone there is maintaining it anymore, so I have been bringing it back to life.