2014-06-26 12 views
5

Sto provando a connettermi a un server Linux AWS di Amazon con una chiave utilizzando il pacchetto [ssh] [1] del linguaggio di programmazione Go. Tuttavia la documentazione del pacchetto è un po 'criptica/confusa. Qualcuno sa come connettersi tramite ssh usando una chiave o almeno se è possibile? Quello che mi preoccupa è che nel [Dial] [3] esempio diceConnessione a un server tramite SSH e un pem/chiave con golang

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

Io fondamentalmente voglio imitare lo ssh -i x.pem [email protected] comportamento ed eseguire un comando all'interno del server (ad esempio, whoami)

+1

un panico implica che stai ignorando un errore da qualche parte (o impostando un differimento prima di controllare un errore). abbiamo bisogno di un codice per sapere cosa stai facendo. – JimB

+0

@JimB Ho aggiunto del codice. Penso di aver controllato tutti gli errori. Il rinvio per chiudere la sessione è stato impostato dopo il controllo degli errori – hey

+1

il tuo panico è perché stai chiamando 'differire session.Close()' su dove la sessione è nullo. 't.Error (err)' non torna presto. – JimB

risposta

10

È necessario utilizzare ssh.PublicKeys per trasformare un elenco di ssh.Signers in un ssh.AuthMethod. È possibile utilizzare ssh.ParsePrivateKey per ottenere un Signer dai byte pem, oppure se è necessario utilizzare una chiave privata rsa, dsa o ecdsa, è possibile assegnarli a ssh.NewSignerFromKey.

Ecco un esempio un po 'dettagliato con il supporto dell'agente (poiché l'utilizzo di un agente è in genere il passaggio successivo dopo l'utilizzo di un file chiave).

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

Non sono sicuro di aver capito il codice. Come faccio a passare il file chiave (ad es. Mykey.pem) o il contenuto chiave? Il firmatario sembra essere un'interfaccia. Ho le chiavi memorizzate in un db – hey

+1

Ho aggiunto una nota sull'uso di 'ParsePrivateKey' per ottenere un firmatario dai byte pem. – JimB

+0

perché ho bisogno di '' agente''? sembra dichiarato ma non usato poiché uso '' signers, err: = ssh.ParsePrivateKey (cl.Key) '' – hey

6

Ecco un esempio di eseguire ls in remoto utilizzando la vostra "file della chiave privata pianura".

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) 
Problemi correlati