Skip to content

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 for issue/agent).
  • principal derived from <user@host[:port]>.
  • Target server fingerprint resolved from the SSH host key.
  • Optional timezone override (--timezone) for policy evaluation.
  • Certificate type (ED25519 or RSA).

Authentication model:

  • Access token is DPoP-bound.
  • CLI sends Authorization: DPoP <access-token> and a per-request DPoP proof.
  • 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 --server is omitted, the configured default server is used.
  • --server accepts https://host[:port] or host[: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 --timezone override).

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 ED25519 for most modern environments (smaller keys, faster operations).
  • Choose RSA when 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_SOCK set).
  • 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): run sshteam 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 --insecure temporarily.
  • Multi-CA ambiguity: explicitly set server using --server or adjust default via sshteam 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:

  1. Device registration is complete and token is valid (sshteam devices list).
  2. Issue/sign command succeeds for at least one allowed user-host combination.
  3. Deny-path is validated with an intentionally disallowed combination.
  4. Certificate type expectations are met; ED25519 default path is validated.
  5. RSA path is validated if your environment requires it.
  6. Multi-CA behavior is verified; default server issuance works without --server.
  7. Explicit --server path works for non-default CA.
  8. End-to-end SSH login succeeds using issued certificate.
  9. 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 sign only, then assume issue and agent behave the same in all environments. Validate all command paths you plan to support.