2014-06-26 6 views
5

Ich versuche, eine Verbindung zu einem Amazon AWS Linux-Server mit einem Schlüssel mit dem [ssh] [1] -Paket der Go-Programmiersprache. Die Paketdokumentation ist jedoch ein wenig kryptisch/verwirrend. Weiß jemand, wie man sich über ssh mit einem Schlüssel verbindet oder zumindest, wenn es möglich ist? Was mich stört, ist, dass in der [Dial] [3] Beispiel sagt, esVerbinden mit einem Server mit SSH und einem PEM/Schlüssel mit Golang

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

Ich möchte im Grunde die ssh imitieren -i x.pem [email protected] Verhalten und einen Befehl innerhalb des Servers ausführen (zB whoami)

+1

Eine Panik bedeutet, dass Sie irgendwo einen Fehler ignorieren (oder einen Fehler setzen, bevor Sie einen Fehler überprüfen). Wir brauchen Code, um zu wissen, was Sie tun. – JimB

+0

@JimB Ich habe etwas Code hinzugefügt. Ich denke, ich habe alle Fehler überprüft. Die Verzögerung, um die Sitzung zu beenden, wurde nach der Fehlerüberprüfung eingestellt – hey

+1

Ihre Panik ist, weil Sie rufen 'defer session.Close()' auf, wo Sitzung ist Null. 't.Error (err)' kommt nicht früh zurück. – JimB

Antwort

10

Sie müssen ssh.PublicKeys verwenden, um eine Liste von ssh.Signers in eine ssh.AuthMethod zu verwandeln. Sie können ssh.ParsePrivateKey verwenden, um eine Signer aus den PEM-Bytes zu erhalten, oder wenn Sie einen privaten Schlüssel RSA, Dsa oder Ecdsa verwenden müssen, können Sie diese ssh.NewSignerFromKey geben.

Hier ist ein Beispiel, das ein wenig mit Agent-Unterstützung ausgefeilt ist (da die Verwendung eines Agenten normalerweise der nächste Schritt ist, nachdem einfach eine Schlüsseldatei verwendet wurde).

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!") 

... 
+0

Ich bin mir nicht sicher, ob ich den Code verstehe. Wie übermittle ich die Schlüsseldatei (z. B. mykey.pem) oder den Schlüsselinhalt? Signer scheint eine Schnittstelle zu sein. Ich habe die Schlüssel in einem db gespeichert – hey

+1

Ich habe eine Notiz über die Verwendung von 'ParsePrivateKey' hinzugefügt, um einen Unterzeichner aus den PEM-Bytes zu erhalten. – JimB

+0

warum brauche ich '' agent''? es scheint erklärt, aber nicht verwendet, da ich '' signers, err: = ssh.ParsePrivateKey (cl.Key) '' – hey

6

Hier ist ein Beispiel ls remote über Ihre "plain private Schlüsseldatei" laufen.

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)}, 
    } 
    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) 
Verwandte Themen