08 Issuing Certificates
This chapter explains how SSH Teams issues user SSH certificates from the CLI after device registration.
8.1 Prerequisites
| Requirement | Lab | Staging | Production |
|---|---|---|---|
Device registration completed (sshteam init) |
Required | Required | Required |
| At least one joined target server | Recommended | Required | Required |
| Matching issuance policy exists | Recommended | Required | Required |
Server trust file (TrustedUserCAKeys) in place |
Recommended | Required | Required |
| Default server selection verified | Optional | Recommended | Required |
8.2 Signing Endpoint Contract
graph LR
A[CLI command sign, issue, or agent] --> B[Resolve target host key fingerprint]
B --> C[Build request principal key type timezone]
C --> D[Send POST /api/v1/ssh/sign with DPoP token and proof]
D --> E[Validate token and DPoP proof]
E --> F[Evaluate policy server principal user time window]
F --> G{Policy match}
G -->|deny| H[Return error no certificate]
G -->|allow| I[Sign short-lived SSH certificate]
I --> J[Return certificate to CLI]
J --> K[CLI writes file or loads ssh-agent]
Certificate issuance requests are submitted by CLI commands to:
POST /api/v1/ssh/sign
The CLI request contains:
- Public key material (existing key for
sign, generated ephemeral key forissue/agent). principalderived from<user@host[:port]>.- Target server fingerprint resolved from the SSH host key.
- Optional timezone override (
--timezone) for policy evaluation. - Certificate type (
ED25519orRSA).
Authentication model:
- Access token is DPoP-bound.
- CLI sends
Authorization: DPoP <access-token>and a per-requestDPoPproof. - If access token is near expiry, CLI auto-refreshes with refresh token + DPoP.
Primary CLI entry points:
sshteam sign <user@host[:port]> -k <public-key-file>sshteam issue <user@host[:port]>sshteam agent <user@host[:port]>
Server selection notes:
- If
--serveris omitted, the configured default server is used. --serveracceptshttps://host[:port]orhost[:port](HTTPS assumed if scheme omitted).
8.3 Policy Resolution Logic
On each signing request, SSH Teams evaluates policy before issuing a certificate.
Inputs commonly used by policy matching:
- Target server fingerprint (resolved from the host key).
- Requested principal (UNIX username from connection target).
- Device/user identity associated with the access token.
- Current time window (evaluated in local timezone or
--timezoneoverride).
Operational behavior:
- If policy allows the request, server returns a signed certificate.
- If policy denies the request, server returns an error and no certificate is issued.
Practical implications:
- Changing server tags/fingerprint targeting or policy windows immediately impacts issuance.
- A certificate denial does not revoke the device; it indicates policy mismatch for that request.
8.4 Certificate Type Selection
SSH Teams supports ED25519 and RSA certificate issuance.
Use this rule of thumb:
- Choose
ED25519for most modern environments (smaller keys, faster operations). - Choose
RSAwhen legacy compatibility requires it.
8.4.1 sign command (existing key)
Use this when you already manage local SSH key files.
sshteam sign devops@app01.example.net -k ~/.ssh/id_ed25519.pub
Write certificate to file:
sshteam sign devops@app01.example.net -k ~/.ssh/id_rsa.pub --type RSA -o ~/.ssh/id_rsa-cert.pub
8.4.2 issue command (ephemeral keypair)
Use this for short-lived, per-connection key material.
sshteam issue devops@app01.example.net
RSA variant:
sshteam issue devops@app01.example.net --type RSA --bits 4096
issue returns the generated private-key path on stdout. The wrapper in Chapter 09 uses this flow automatically.
8.4.3 agent command (load into ssh-agent)
Use this when you want certificate-backed auth loaded directly into the local SSH agent.
sshteam agent devops@app01.example.net
ssh devops@app01.example.net
Notes:
- Requires a running
ssh-agent(SSH_AUTH_SOCKset). - Agent lifetime is constrained by certificate validity.
- For ED25519, do not supply
--bits.
8.5 Common Denial Reasons and Diagnostics
Common issuance failures and how to diagnose them:
- Policy mismatch (principal/server/time constraints): verify policy allows requested user, target host fingerprint, and current window.
- Device/token issues (
invalid_grant, expired/revoked session): runsshteam init <server>again and re-approve device. - DPoP proof problems (
invalid_dpop_proof): re-initialize device credentials to regenerate DPoP key material. - Host key resolution/connectivity issues: confirm SSH reachability to target host and correct
host[:port]in command. - TLS trust failure to SSH Teams API: use trusted certs in production; for lab/self-signed environments, use
--insecuretemporarily. - Multi-CA ambiguity: explicitly set server using
--serveror adjust default viasshteam init <server> --default.
Useful operator checks:
sshteam devices list
- Confirm active default server marker (
[default]). - Confirm token status is valid (or refresh available).
8.6 Certificate Issuance Verification Checklist
Use this checklist after rollout or policy changes:
- Device registration is complete and token is valid (
sshteam devices list). - Issue/sign command succeeds for at least one allowed user-host combination.
- Deny-path is validated with an intentionally disallowed combination.
- Certificate type expectations are met; ED25519 default path is validated.
- RSA path is validated if your environment requires it.
- Multi-CA behavior is verified; default server issuance works without
--server. - Explicit
--serverpath works for non-default CA. - End-to-end SSH login succeeds using issued certificate.
- Audit/log records show expected issuance and denial events.
If issuance fails during validation, use 12-troubleshooting-handbook.md#126-certificate-issuance-failures.
8.7 Pro Tip and Common Gotcha
Pro tip:
- Validate both an allowed and denied issuance path after every policy change so your access boundaries stay intentional.
Common gotcha:
- Operators often test
sshteam signonly, then assumeissueandagentbehave the same in all environments. Validate all command paths you plan to support.