Feat/ssh certs - #452
Draft
patelspratik wants to merge 9 commits into
Draft
Conversation
Foundation for certificate-based SSH auth. Generates fresh ed25519
keypairs per renewal, caches the (private key, certificate) pair on
disk for the certificate's validity window, and writes atomically
(0600 private key). Files live under ~/.brev/ssh-certs/<envID>{,-cert.pub}
so a single IdentityFile directive loads both key and cert (OpenSSH
-cert.pub convention).
Independent of the IssueEnvironmentSSHCertificate RPC so the rest of
the feature can build and test before the generated connect client is
published. Includes EnvironmentCertEligible() mirroring dev-plane's
label constants (sshprovider=certauth).
resolveWorkspaceSSH already fetches the user's SSHAccess (carrying port_id + linux_user) and the environment labels from the Environment connect API during refresh, but discarded port_id after resolving the network port. Retain port_id and the sshprovider=certauth label on the workspace so the SSH config generator can emit a per-environment certificate-fetch entry. Fields stay zero-valued for environments that fall back to static-key auth.
Headless, non-interactive mode invoked by the ssh config's Match exec hook. Reuses the existing platform credential (no login prompt), checks the on-disk cert cache, mints a fresh ephemeral ed25519 keypair + short-lived certificate via a CertIssuer, and atomically writes them to the --out-key path (+ -cert.pub). On any failure it writes nothing and returns non-zero so ssh drops the Match IdentityFile and falls back to the static brev.pem. CertIssuer is an interface; today a stub returns ErrCertIssuanceUnavailable (the real connect-RPC issuer drops in once the buf module publishes IssueEnvironmentSSHCertificate). Flags are hidden since this is an implementation detail of the ssh config, not a user-facing mode.
For each cert-eligible workspace (sshprovider=certauth label + port_id), the SSH config generator now prepends a Match host <alias> exec block before the existing Host block. The Match block runs 'brev shell --cert-only' to mint a short-lived cert and carries the cert IdentityFile; the Host block keeps the static brev.pem IdentityFile. OpenSSH accumulates IdentityFile across Match and Host blocks when the exec succeeds (cert tried first, static as fallback), and drops the Match block's IdentityFile when the exec fails (mint error, CA down, or the not-yet-wired issuer stub), so ssh falls back to the static key. Verified empirically against the ssh binary. Ineligible workspaces (no certauth label, or missing port_id) and the WSL config (Windows paths/binary, deferred) get no Match block and keep the static key only.
Cut ~260 lines while preserving behavior and coverage: - Delete the Store type in pkg/sshcert (dead code: production uses the free functions HasValidCertAt/WriteFiles with explicit paths, since --cert-only receives --out-key). Removed its methods and tests. - Delete fakeIssuer from certonly_test.go (unused; tests use certIssuerFunc). - Replace makeCertMatchEntry's text/template with a direct Sprintf: the template was a constant string and the error branches guarded against impossible parse failures of that constant. - Drop validateCertOnly's 'flags set without --cert-only' branch: the flags are hidden and only set by the generated config, so the inverse scenario can't occur in practice. - Consolidate TestEnvironmentCertEligible and TestSafeFilename into table-driven form; merge redundant assertions. - Trim verbose per-function comments that restated the package doc.
Replace the placeholder stubCertIssuer with rpcCertIssuer, which calls dev-plane's EnvironmentService.IssueEnvironmentSSHCertificate via the authenticated connect client (register.NewEnvironmentServiceClient). The store satisfies externalnode.TokenProvider via GetAccessToken, so the existing platform credential is reused with no new login. CertIssuer remains an interface so runCertOnly stays unit-testable; add tests for rpcCertIssuer verifying request field mapping and error propagation. Remove the now-unused stub + ErrCertIssuanceUnavailable.
patelspratik
force-pushed
the
feat/ssh-certs
branch
from
August 20, 2026 23:58
3d5b905 to
e719698
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.