Repository navigation
sshmgr 3.3.0: git remote modes, devbox VMs, knownhosts pin fix - #52
Merged
Merged
Conversation
A reachable port that is not SSH (a web server on 443, for one) made ssh-keyscan return nothing, and pin printed "pinned 0 host key(s)" and exited 0, which read as success and left the host untrusted. ScanChecked says why nothing came back, a missing ssh-keyscan included; pin reports each such host, still pins the rest, and exits non-zero. Scan keeps its old contract for its other callers.
defaults.git holds the remote mode, the default identity and an owner-to-profile map; a host's vm names the hypervisor and VM whose address is resolved at connect time. Both are omitted when unset, so existing manifests save unchanged. The JSON schema had drifted: category, key_store, op_vault, keys and onepassword_agent were valid in code and rejected by the schema. A test now compares every manifest type's JSON fields with the schema.
With defaults.git.profile set, plain git@github.com remotes resolve to that profile's GitHub key through a Host github.com block placed before Host *. A host with vm gets ProxyCommand "<sshmgr>" vm proxy <alias>, written by sshmgr itself (raw_options still may not hold one), preferring the PATH entry so a package upgrade does not strand the path. The path is quoted literally: ssh does not unescape, so Go's %q would double Windows backslashes. Both are pinned against ssh -G.
git use points each checkout's GitHub origin at profile SSH, plain SSH or HTTPS. The mode is the first argument, else --mode, else SSHMGR_GIT_MODE, else defaults.git.mode, else profile; the owner picks the profile through defaults.git.orgs, then defaults.git.profile, and several candidates are an error rather than a guess. A new URL must pass git ls-remote before origin is rewritten, non-GitHub origins are skipped, and --dry-run touches nothing. git status shows each checkout's mode and profile.
One interface over Parallels (prlctl), VMPal, VMware (vmrun), UTM (utmctl), Lima (limactl), OrbStack (orb) and Podman: list VMs, resolve a VM's current SSH endpoint, start it, and run a command in it where the CLI can. OrbStack and Podman run their own SSH and keys, so they are listed but never handed an address; VMware runs guest commands only with guest credentials, so its Exec says so. Tests use stand-in CLIs on PATH; the VMPal driver was also run against the installed vmpal.
vm add records a VM host (hypervisor and VM name; HostName is the alias, since ProxyCommand ignores it and an address would go stale) and renders its ProxyCommand. vm proxy, which ssh runs, resolves the VM's address on each connection, starts a stopped VM and waits for it, then relays stdio. vm list shows every hypervisor's VMs and which host uses each, and says when a hypervisor is not installed. vm docker-context creates or updates an ssh://<alias> Docker context. OrbStack and Podman are refused as hosts: they run their own SSH and keys.
A package upgrade can move the binary a rendered ProxyCommand names, and every connection to that VM then fails with a bare exec error. doctor reads the root and category configs, reports each sshmgr ProxyCommand whose binary is gone (a bare name resolves through PATH; foreign ProxyCommands are ignored), fails its verdict, and says to run sshmgr config render. stale_proxy is in the JSON, always an array.
vm add already refused them, but a hand-edited manifest could still give one a vm block, rendering a ProxyCommand for a machine whose SSH and keys the hypervisor owns. Validation and the schema now agree with the command.
New reference pages for git and vm, recipes for switching checkouts to profile SSH and for a VM devbox, the defaults.git and vm manifest fields, doctor's stale_proxy check, and the CHANGELOG. Also corrects the knownhosts page and feature catalog, which still described per-profile trust stores at 0644.
The binary-surface guard flagged git and docker. It could not see the hypervisor CLIs at all, because the drivers resolve them through lookup() and run them from a variable; it now reads lookup's literal arguments too, so prlctl, vmpal, vmrun, utmctl, limactl, orb and podman are pinned (proven by removing one: the test names it). vm add changes ~/.ssh and now confirms like every other mutating verb, with --yes.
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.
sshmgr 3.3.0 (unreleased; lands under
[Unreleased]): git remote modes, devbox VMs, and theknownhosts pinbug. One commit per concern.Git remote modes
sshmgr git status [PATH...], andsshmgr git use profile|ssh|https [PATH...]with--mode,--profile,--dry-runand--yes.--mode, thenSSHMGR_GIT_MODE, then manifestdefaults.git.mode, thenprofile.defaults.git.orgs, thendefaults.git.profile. Several candidates is an error, not a guess.git ls-remote(prompts off, SSH in batch mode) beforeoriginis rewritten. Non-GitHub origins are skipped.defaults.git.profileset, the renderer adds aHost github.comblock beforeHost *(ssh -Gpinned).Devboxes
src/internal/core/hypervisor: one interface over Parallels, VMPal, VMware, UTM, Lima, OrbStack and Podman.vm: {hypervisor, name}rendersProxyCommand "<sshmgr>" vm proxy <alias>.vm proxyresolves the address on each connection, starts a stopped VM, and relays stdio.vm list,vm add(confirms, with--yes) andvm docker-context.doctorfails on a ProxyCommand whose sshmgr binary has gone (stale_proxy);config renderrewrites it.Fixes
knownhosts pinreportedpinned 0and exited 0 for a host serving no SSH key. It now names each such host and exits non-zero.category,key_store,op_vault,keys,onepassword_agent). It now matches the code, and a test compares every type's JSON fields.knownhostsdocs and feature catalog described per-profile 0644 stores; there is one hashed 0600 store.Guards added or extended, each shown to fail first:
lookup()names (git, docker and seven hypervisor CLIs declared).goOnlyentries for every new verb and flag).Verified locally
go vetpass;go buildpasses for linux, windows and darwin;make e2epasses.TestVMProxyStartsAStoppedVMAndRelaysneeds a local listener, so it skipped here and runs in CI. The relay itself is also tested overnet.Pipe.vmpal; the other drivers are tested with stand-in CLIs.Docs:
docs/tools/git.md,docs/tools/vm.md, two recipes,configuration.md(defaults.git,vm),doctor.md, the README index and the CHANGELOG.