mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
fix: allow ssh-agent to work in prod
This runs a separate shell script to get the correct environment variable instead of relying on one that comes from the environment waveterm was launched from. It also corrects the number of retries to adjust for the number of signers provided by the ssh-agent.
This commit is contained in:
parent
cd871a0c6c
commit
a3de9768f2
@ -1314,14 +1314,15 @@ func (wsh *WaveshellProc) RunInstall(autoInstall bool) {
|
||||
wsh.WriteToPtyBuffer("*error: cannot install on a local remote\n")
|
||||
return
|
||||
}
|
||||
_, err = shellapi.MakeShellApi(packet.ShellType_bash)
|
||||
sapi, err := shellapi.MakeShellApi(wsh.GetShellType())
|
||||
if err != nil {
|
||||
wsh.WriteToPtyBuffer("*error: %v\n", err)
|
||||
return
|
||||
}
|
||||
if wsh.Client == nil {
|
||||
remoteDisplayName := fmt.Sprintf("%s [%s]", remoteCopy.RemoteAlias, remoteCopy.RemoteCanonicalName)
|
||||
client, err := ConnectToClient(makeClientCtx, remoteCopy.SSHOpts, remoteDisplayName)
|
||||
sshAuthSock, _ := exec.CommandContext(makeClientCtx, sapi.GetLocalShellPath(), "-c", "echo \"${SSH_AUTH_SOCK}\"").CombinedOutput()
|
||||
client, err := ConnectToClient(makeClientCtx, remoteCopy.SSHOpts, remoteDisplayName, strings.TrimSpace(string(sshAuthSock)))
|
||||
if err != nil {
|
||||
statusErr := fmt.Errorf("ssh cannot connect to client: %w", err)
|
||||
wsh.setInstallErrorStatus(statusErr)
|
||||
@ -1614,7 +1615,8 @@ func (wsh *WaveshellProc) createWaveshellSession(clientCtx context.Context, remo
|
||||
wsSession = shexec.CmdWrap{Cmd: ecmd}
|
||||
} else if wsh.Client == nil {
|
||||
remoteDisplayName := fmt.Sprintf("%s [%s]", remoteCopy.RemoteAlias, remoteCopy.RemoteCanonicalName)
|
||||
client, err := ConnectToClient(clientCtx, remoteCopy.SSHOpts, remoteDisplayName)
|
||||
sshAuthSock, _ := exec.CommandContext(clientCtx, sapi.GetLocalShellPath(), "-c", "echo \"${SSH_AUTH_SOCK}\"").CombinedOutput()
|
||||
client, err := ConnectToClient(clientCtx, remoteCopy.SSHOpts, remoteDisplayName, strings.TrimSpace(string(sshAuthSock)))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ssh cannot connect to client: %w", err)
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ func createDummySigner() ([]ssh.Signer, error) {
|
||||
// they were successes. An error in this function prevents any other
|
||||
// keys from being attempted. But if there's an error because of a dummy
|
||||
// file, the library can still try again with a new key.
|
||||
func createPublicKeyCallback(connCtx context.Context, sshKeywords *SshKeywords, passphrase string) func() ([]ssh.Signer, error) {
|
||||
func createPublicKeyCallback(connCtx context.Context, sshKeywords *SshKeywords, passphrase string, authSockSignersExt []ssh.Signer) func() ([]ssh.Signer, error) {
|
||||
var identityFiles []string
|
||||
existingKeys := make(map[string][]byte)
|
||||
|
||||
@ -84,15 +84,8 @@ func createPublicKeyCallback(connCtx context.Context, sshKeywords *SshKeywords,
|
||||
// require pointer to modify list in closure
|
||||
identityFilesPtr := &identityFiles
|
||||
|
||||
sshAuthSock := os.Getenv("SSH_AUTH_SOCK")
|
||||
conn, err := net.Dial("unix", sshAuthSock)
|
||||
var authSockSigners []ssh.Signer
|
||||
if err != nil {
|
||||
log.Printf("Failed to open SSH_AUTH_SOCK: %v", err)
|
||||
} else {
|
||||
agentClient := agent.NewClient(conn)
|
||||
authSockSigners, _ = agentClient.Signers()
|
||||
}
|
||||
authSockSigners = append(authSockSigners, authSockSignersExt...)
|
||||
authSockSignersPtr := &authSockSigners
|
||||
|
||||
return func() ([]ssh.Signer, error) {
|
||||
@ -546,7 +539,7 @@ func DialContext(ctx context.Context, network string, addr string, config *ssh.C
|
||||
return ssh.NewClient(c, chans, reqs), nil
|
||||
}
|
||||
|
||||
func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDisplayName string) (*ssh.Client, error) {
|
||||
func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDisplayName string, sshAuthSock string) (*ssh.Client, error) {
|
||||
sshConfigKeywords, err := findSshConfigKeywords(opts.SSHHost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -557,7 +550,16 @@ func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDispla
|
||||
return nil, err
|
||||
}
|
||||
|
||||
publicKeyCallback := ssh.PublicKeysCallback(createPublicKeyCallback(connCtx, sshKeywords, opts.SSHPassword))
|
||||
conn, err := net.Dial("unix", sshAuthSock)
|
||||
var authSockSigners []ssh.Signer
|
||||
if err != nil {
|
||||
log.Printf("Failed to open SSH_AUTH_SOCK: %v", err)
|
||||
} else {
|
||||
agentClient := agent.NewClient(conn)
|
||||
authSockSigners, _ = agentClient.Signers()
|
||||
}
|
||||
|
||||
publicKeyCallback := ssh.PublicKeysCallback(createPublicKeyCallback(connCtx, sshKeywords, opts.SSHPassword, authSockSigners))
|
||||
keyboardInteractive := ssh.KeyboardInteractive(createCombinedKbdInteractiveChallenge(connCtx, opts.SSHPassword, remoteDisplayName))
|
||||
passwordCallback := ssh.PasswordCallback(createCombinedPasswordCallbackPrompt(connCtx, opts.SSHPassword, remoteDisplayName))
|
||||
|
||||
@ -572,7 +574,7 @@ func ConnectToClient(connCtx context.Context, opts *sstore.SSHOpts, remoteDispla
|
||||
|
||||
// exclude gssapi-with-mic and hostbased until implemented
|
||||
authMethodMap := map[string]ssh.AuthMethod{
|
||||
"publickey": ssh.RetryableAuthMethod(publicKeyCallback, len(sshKeywords.IdentityFile)),
|
||||
"publickey": ssh.RetryableAuthMethod(publicKeyCallback, len(sshKeywords.IdentityFile)+len(authSockSigners)),
|
||||
"keyboard-interactive": ssh.RetryableAuthMethod(keyboardInteractive, attemptsAllowed),
|
||||
"password": ssh.RetryableAuthMethod(passwordCallback, attemptsAllowed),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user