Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connect to a server using SSH and a pem / key with golang

Tags:

ssh

go

I'm trying to connect to an amazon AWS linux server with a key using the [ssh][1] package of Go programming language. However the package documentation is a bit cryptic/confusing. Does anyone know how to connect through ssh using a key or at least if it's possible ? What bothers me is that in the [Dial][3] example it says

// An SSH client is represented with a ClientConn. Currently only
// the "password" authentication method is supported.

I basically want to mimic the ssh -i x.pem [email protected] behavior and execute a command inside the server ( e.g. whoami )

like image 476
hey Avatar asked Jun 26 '14 18:06

hey


2 Answers

You need to use ssh.PublicKeys to turn a list of ssh.Signers into an ssh.AuthMethod. You can use ssh.ParsePrivateKey to get a Signer from the pem bytes, or if you need to use an rsa, dsa or ecdsa private key, you can give those to ssh.NewSignerFromKey.

Here's an example fleshed out a bit with Agent support too (since using an agent is usually the next step after simply using a key file).

sock, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
if err != nil {
    log.Fatal(err)
}

agent := agent.NewClient(sock)

signers, err := agent.Signers()
if err != nil {
    log.Fatal(err)
}

// or get the signer from your private key file directly
// signer, err := ssh.ParsePrivateKey(pemBytes)
// if err != nil {
//     log.Fatal(err)
// }

auths := []ssh.AuthMethod{ssh.PublicKeys(signers...)}

cfg := &ssh.ClientConfig{
    User: "username",
    Auth: auths,
}
cfg.SetDefaults()

client, err := ssh.Dial("tcp", "aws-hostname:22", cfg)
if err != nil {
    log.Fatal(err)
}

session, err = client.NewSession()
if err != nil {
    log.Fatal(err)
}

log.Println("we have a session!")

...
like image 69
JimB Avatar answered Nov 10 '22 08:11

JimB


Here is an example to run ls remotely using your "plain private key file".

    pemBytes, err := ioutil.ReadFile("/location/to/YOUR.pem")
    if err != nil {
        log.Fatal(err)
    }
    signer, err := ssh.ParsePrivateKey(pemBytes)
    if err != nil {
        log.Fatalf("parse key failed:%v", err)
    }
    config := &ssh.ClientConfig{
        User: "ubuntu",
        Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }
    conn, err := ssh.Dial("tcp", "yourhost.com:22", config)
    if err != nil {
        log.Fatalf("dial failed:%v", err)
    }
    defer conn.Close()
    session, err := conn.NewSession()
    if err != nil {
        log.Fatalf("session failed:%v", err)
    }
    defer session.Close()
    var stdoutBuf bytes.Buffer
    session.Stdout = &stdoutBuf
    err = session.Run("ls -l")
    if err != nil {
        log.Fatalf("Run failed:%v", err)
    }
    log.Printf(">%s", stdoutBuf)
like image 14
emicklei Avatar answered Nov 10 '22 09:11

emicklei