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  }