github.com/bhameyie/otto@v0.2.1-0.20160406174117-16052efa52ec/helper/sshagent/sshagent.go (about) 1 // Helpers for interacting with the local SSH Agent 2 package sshagent 3 4 import ( 5 "fmt" 6 "net" 7 "os" 8 "os/exec" 9 "reflect" 10 11 execHelper "github.com/hashicorp/otto/helper/exec" 12 "github.com/hashicorp/otto/ui" 13 14 "golang.org/x/crypto/ssh" 15 "golang.org/x/crypto/ssh/agent" 16 ) 17 18 // HasKey determines if a given public key (provided as a string with the 19 // contents of a public key file), is loaded into the local SSH Agent. 20 func HasKey(publicKey string) (bool, error) { 21 pk, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey)) 22 if err != nil { 23 return false, fmt.Errorf("Error parsing provided public key: %s", err) 24 } 25 26 agentKeys, err := ListKeys() 27 if err != nil { 28 return false, err 29 } 30 31 for _, agentKey := range agentKeys { 32 if reflect.DeepEqual(agentKey.Marshal(), pk.Marshal()) { 33 return true, nil 34 } 35 } 36 return false, nil 37 } 38 39 // ListKeys connects to the local SSH Agent and lists all the public keys 40 // loaded into it. It returns user friendly error message when it has trouble. 41 func ListKeys() ([]*agent.Key, error) { 42 sshAuthSock := os.Getenv("SSH_AUTH_SOCK") 43 if sshAuthSock == "" { 44 return nil, fmt.Errorf( 45 "The SSH_AUTH_SOCK environment variable is not set, which normally\n" + 46 "means that no SSH Agent is running.") 47 } 48 49 conn, err := net.Dial("unix", sshAuthSock) 50 if err != nil { 51 return nil, fmt.Errorf( 52 "Error connecting to agent: %s\n\n"+ 53 "The agent address is detected using the SSH_AUTH_SOCK environment\n"+ 54 "variable. Please verify this variable is correct and the SSH agent\n"+ 55 "is properly set up.", 56 err) 57 } 58 defer conn.Close() 59 60 agent := agent.NewClient(conn) 61 loadedKeys, err := agent.List() 62 if err != nil { 63 return nil, fmt.Errorf("Error listing keys: %s", err) 64 } 65 return loadedKeys, err 66 } 67 68 // Add takes the path of a private key and runs ssh-add locally to add it to 69 // the agent. It needs a Ui to be able to interact with the user for the 70 // password prompt. 71 func Add(ui ui.Ui, privateKeyPath string) error { 72 cmd := exec.Command("ssh-add", privateKeyPath) 73 return execHelper.Run(ui, cmd) 74 }