From 544a76d208306fc6606e8bbc1e06ba8781fc3305 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Wed, 15 Jan 2025 19:58:56 -0800 Subject: [PATCH 1/2] Honor SSH IdentitiesOnly setting --- frontend/types/gotypes.d.ts | 1 + pkg/remote/sshclient.go | 23 +++++++++++++++++------ pkg/wshrpc/wshrpctypes.go | 1 + 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index 876e63bd5e..a80b81b7f0 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -315,6 +315,7 @@ declare global { "ssh:hostname"?: string; "ssh:port"?: string; "ssh:identityfile"?: string[]; + "ssh:identitiesonly"?: boolean; "ssh:batchmode"?: boolean; "ssh:pubkeyauthentication"?: boolean; "ssh:passwordauthentication"?: boolean; diff --git a/pkg/remote/sshclient.go b/pkg/remote/sshclient.go index f135b19327..6243ab7faf 100644 --- a/pkg/remote/sshclient.go +++ b/pkg/remote/sshclient.go @@ -579,12 +579,14 @@ func createClientConfig(connCtx context.Context, sshKeywords *wshrpc.ConnKeyword var authSockSigners []ssh.Signer var agentClient agent.ExtendedAgent - conn, err := net.Dial("unix", utilfn.SafeDeref(sshKeywords.SshIdentityAgent)) - if err != nil { - log.Printf("Failed to open Identity Agent Socket: %v", err) - } else { - agentClient = agent.NewClient(conn) - authSockSigners, _ = agentClient.Signers() + if !utilfn.SafeDeref(sshKeywords.SshIdentitiesOnly) { + conn, err := net.Dial("unix", utilfn.SafeDeref(sshKeywords.SshIdentityAgent)) + if err != nil { + log.Printf("Failed to open Identity Agent Socket: %v", err) + } else { + agentClient = agent.NewClient(conn) + authSockSigners, _ = agentClient.Signers() + } } publicKeyCallback := ssh.PublicKeysCallback(createPublicKeyCallback(connCtx, sshKeywords, authSockSigners, agentClient, debugInfo)) @@ -830,6 +832,12 @@ func findSshConfigKeywords(hostPattern string) (connKeywords *wshrpc.ConnKeyword } sshKeywords.SshAddKeysToAgent = utilfn.Ptr(strings.ToLower(trimquotes.TryTrimQuotes(addKeysToAgentRaw)) == "yes") + identitiesOnly, err := WaveSshConfigUserSettings().GetStrict(hostPattern, "IdentitiesOnly") + if err != nil { + return nil, err + } + sshKeywords.SshIdentitiesOnly = utilfn.Ptr(strings.ToLower(trimquotes.TryTrimQuotes(identitiesOnly)) == "yes") + identityAgentRaw, err := WaveSshConfigUserSettings().GetStrict(hostPattern, "IdentityAgent") if err != nil { return nil, err @@ -933,6 +941,9 @@ func mergeKeywords(oldKeywords *wshrpc.ConnKeywords, newKeywords *wshrpc.ConnKey if newKeywords.SshIdentityAgent != nil { outKeywords.SshIdentityAgent = newKeywords.SshIdentityAgent } + if newKeywords.SshIdentitiesOnly != nil { + outKeywords.SshIdentitiesOnly = newKeywords.SshIdentitiesOnly + } if newKeywords.SshProxyJump != nil { outKeywords.SshProxyJump = newKeywords.SshProxyJump } diff --git a/pkg/wshrpc/wshrpctypes.go b/pkg/wshrpc/wshrpctypes.go index 28c69e20a0..cb0850eac5 100644 --- a/pkg/wshrpc/wshrpctypes.go +++ b/pkg/wshrpc/wshrpctypes.go @@ -489,6 +489,7 @@ type ConnKeywords struct { SshHostName *string `json:"ssh:hostname,omitempty"` SshPort *string `json:"ssh:port,omitempty"` SshIdentityFile []string `json:"ssh:identityfile,omitempty"` + SshIdentitiesOnly *bool `json:"ssh:identitiesonly,omitempty"` SshBatchMode *bool `json:"ssh:batchmode,omitempty"` SshPubkeyAuthentication *bool `json:"ssh:pubkeyauthentication,omitempty"` SshPasswordAuthentication *bool `json:"ssh:passwordauthentication,omitempty"` From c3d8a1530e04de63b41dcbd7006eaa06abe66659 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Wed, 15 Jan 2025 20:43:37 -0800 Subject: [PATCH 2/2] Add comment with reasoning --- pkg/remote/sshclient.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/remote/sshclient.go b/pkg/remote/sshclient.go index 6243ab7faf..fdebf2fd03 100644 --- a/pkg/remote/sshclient.go +++ b/pkg/remote/sshclient.go @@ -579,6 +579,9 @@ func createClientConfig(connCtx context.Context, sshKeywords *wshrpc.ConnKeyword var authSockSigners []ssh.Signer var agentClient agent.ExtendedAgent + + // IdentitiesOnly indicates that only the keys listed in IdentityFile should be used, even if there are matches in the SSH Agent, PKCS11Provider, or SecurityKeyProvider. See https://man.openbsd.org/ssh_config#IdentitiesOnly + // TODO: Update if we decide to support PKCS11Provider and SecurityKeyProvider if !utilfn.SafeDeref(sshKeywords.SshIdentitiesOnly) { conn, err := net.Dial("unix", utilfn.SafeDeref(sshKeywords.SshIdentityAgent)) if err != nil {