Skip to content

Added support of ssh_agent and passphrase #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ package vssh

import (
"fmt"
"io/ioutil"

"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"io/ioutil"
"net"
)

// GetConfigPEM returns SSH configuration that uses the given private key.
Expand All @@ -26,6 +27,37 @@ func GetConfigPEM(user, keyFile string) (*ssh.ClientConfig, error) {
return getConfig(user, ssh.PublicKeys(signer)), nil
}

// GetConfigPEMWithPassphrase returns SSH configuration that uses the given private key and passphrase.
func GetConfigPEMWithPassphrase(user, keyFile string, passphrase string) (*ssh.ClientConfig, error) {
key, err := ioutil.ReadFile(keyFile)
if err != nil {
return nil, fmt.Errorf("unable to read private key: %v", err)
}

signer, err := ssh.ParsePrivateKeyWithPassphrase(key, []byte(passphrase))
if err != nil {
return nil, fmt.Errorf("unable to parse private key: %v", err)
}

return getConfig(user, ssh.PublicKeys(signer)), nil
}

// GetConfigSSHAgent returns SSH configuration from SSH Agent.
// default socket can get from env: os.Getenv("SSH_AUTH_SOCK")
func GetConfigSSHAgent(user, socket string) (*ssh.ClientConfig, error) {
conn, err := net.Dial("unix", socket)
if err != nil {
return nil, fmt.Errorf("unable to connect to ssh agent: %v", err)
}
agentconn := agent.NewClient(conn)
signers, err := agentconn.Signers()
if err != nil {
return nil, fmt.Errorf("unable to get signers: %v", err)
}

return getConfig(user, ssh.PublicKeys(signers...)), nil
}

// GetConfigUserPass returns SSH configuration that uses the given
// username and password.
func GetConfigUserPass(user, password string) *ssh.ClientConfig {
Expand Down
21 changes: 20 additions & 1 deletion vssh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestForceReConn(t *testing.T) {
t.Error(err)
}

vs.ForceReConn("127.0.0.1:22")
_ = vs.ForceReConn("127.0.0.1:22")
if len(vs.actionQ) != 2 {
t.Fatal("expect to have two tasks but got", len(vs.actionQ))
}
Expand Down Expand Up @@ -140,3 +140,22 @@ func TestGetConfigPEM(t *testing.T) {
t.Error("expect error but nil")
}
}

func TestGetConfigPEMWithPassphrase(t *testing.T) {
_, err := GetConfigPEMWithPassphrase("vssh", "notexitfile", "pass1")
if err == nil {
t.Error("expect error but nil")
}

_, err = GetConfigPEMWithPassphrase("vssh", "vssh.go", "pass2")
if err == nil {
t.Error("expect error but nil")
}
}

func TestGetConfigSSHAgent(t *testing.T) {
_, err := GetConfigSSHAgent("root", "/path/to/socket/file")
if err == nil {
t.Error("expect error but nil")
}
}