SSH connections are left dangling after use (#668)

This commit is contained in:
Frederik Ring
2025-11-09 17:28:31 +01:00
committed by GitHub
parent 95bf34280d
commit 9cb2ae1893
2 changed files with 22 additions and 11 deletions

View File

@@ -177,10 +177,20 @@ func (s *script) init() error {
IdentityPassphrase: s.c.SSHIdentityPassphrase, IdentityPassphrase: s.c.SSHIdentityPassphrase,
RemotePath: s.c.SSHRemotePath, RemotePath: s.c.SSHRemotePath,
} }
sshBackend, err := ssh.NewStorageBackend(sshConfig, logFunc)
sshBackend, closeSSHConnection, err := ssh.NewStorageBackend(sshConfig, logFunc)
s.registerHook(hookLevelPlumbing, func(err error) error {
if err := closeSSHConnection(); err != nil {
return errwrap.Wrap(err, "failed to close ssh connection")
}
return nil
})
if err != nil { if err != nil {
return errwrap.Wrap(err, "error creating ssh storage backend") return errwrap.Wrap(err, "error creating ssh storage backend")
} }
s.storages = append(s.storages, sshBackend) s.storages = append(s.storages, sshBackend)
} }

View File

@@ -36,8 +36,10 @@ type Config struct {
RemotePath string RemotePath string
} }
var noop = func() error { return nil }
// NewStorageBackend creates and initializes a new SSH storage backend. // NewStorageBackend creates and initializes a new SSH storage backend.
func NewStorageBackend(opts Config, logFunc storage.Log) (storage.Backend, error) { func NewStorageBackend(opts Config, logFunc storage.Log) (storage.Backend, func() error, error) {
var authMethods []ssh.AuthMethod var authMethods []ssh.AuthMethod
if opts.Password != "" { if opts.Password != "" {
@@ -47,20 +49,20 @@ func NewStorageBackend(opts Config, logFunc storage.Log) (storage.Backend, error
if _, err := os.Stat(opts.IdentityFile); err == nil { if _, err := os.Stat(opts.IdentityFile); err == nil {
key, err := os.ReadFile(opts.IdentityFile) key, err := os.ReadFile(opts.IdentityFile)
if err != nil { if err != nil {
return nil, errwrap.Wrap(nil, "error reading the private key") return nil, noop, errwrap.Wrap(nil, "error reading the private key")
} }
var signer ssh.Signer var signer ssh.Signer
if opts.IdentityPassphrase != "" { if opts.IdentityPassphrase != "" {
signer, err = ssh.ParsePrivateKeyWithPassphrase(key, []byte(opts.IdentityPassphrase)) signer, err = ssh.ParsePrivateKeyWithPassphrase(key, []byte(opts.IdentityPassphrase))
if err != nil { if err != nil {
return nil, errwrap.Wrap(nil, "error parsing the encrypted private key") return nil, noop, errwrap.Wrap(nil, "error parsing the encrypted private key")
} }
authMethods = append(authMethods, ssh.PublicKeys(signer)) authMethods = append(authMethods, ssh.PublicKeys(signer))
} else { } else {
signer, err = ssh.ParsePrivateKey(key) signer, err = ssh.ParsePrivateKey(key)
if err != nil { if err != nil {
return nil, errwrap.Wrap(nil, "error parsing the private key") return nil, noop, errwrap.Wrap(nil, "error parsing the private key")
} }
authMethods = append(authMethods, ssh.PublicKeys(signer)) authMethods = append(authMethods, ssh.PublicKeys(signer))
} }
@@ -72,13 +74,12 @@ func NewStorageBackend(opts Config, logFunc storage.Log) (storage.Backend, error
HostKeyCallback: ssh.InsecureIgnoreHostKey(), HostKeyCallback: ssh.InsecureIgnoreHostKey(),
} }
sshClient, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", opts.HostName, opts.Port), sshClientConfig) sshClient, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", opts.HostName, opts.Port), sshClientConfig)
if err != nil || sshClient == nil {
if err != nil { return nil, noop, errwrap.Wrap(err, "error creating ssh client")
return nil, errwrap.Wrap(err, "error creating ssh client")
} }
_, _, err = sshClient.SendRequest("keepalive", false, nil) _, _, err = sshClient.SendRequest("keepalive", false, nil)
if err != nil { if err != nil {
return nil, err return nil, sshClient.Close, err
} }
sftpClient, err := sftp.NewClient(sshClient, sftpClient, err := sftp.NewClient(sshClient,
@@ -87,7 +88,7 @@ func NewStorageBackend(opts Config, logFunc storage.Log) (storage.Backend, error
sftp.MaxConcurrentRequestsPerFile(64), sftp.MaxConcurrentRequestsPerFile(64),
) )
if err != nil { if err != nil {
return nil, errwrap.Wrap(err, "error creating sftp client") return nil, sshClient.Close, errwrap.Wrap(err, "error creating sftp client")
} }
return &sshStorage{ return &sshStorage{
@@ -98,7 +99,7 @@ func NewStorageBackend(opts Config, logFunc storage.Log) (storage.Backend, error
client: sshClient, client: sshClient,
sftpClient: sftpClient, sftpClient: sftpClient,
hostName: opts.HostName, hostName: opts.HostName,
}, nil }, sshClient.Close, nil
} }
// Name returns the name of the storage backend // Name returns the name of the storage backend