2014-06-26 9 views
5

Próbuję połączyć się z serwerem amazon AWS linux za pomocą klucza [ssh] [1] pakietu języka programowania Go. Jednak dokumentacja pakietu jest nieco zagadkowa/myląca. Czy ktoś wie, jak połączyć się przez ssh za pomocą klucza, a przynajmniej jeśli jest to możliwe? Co denerwuje mnie to, że w [Dial] [3] Przykładem mówiPołącz się z serwerem za pomocą SSH i klucza/klucza z golang

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

Zasadniczo chcę naśladować ssh -i x.pem [email protected] zachowania i wykonać polecenie wewnątrz serwera (np whoami)

+1

panika oznacza, że ​​ignorujesz gdzieś błąd (lub ustawiasz odroczenie przed sprawdzeniem błędu). potrzebujemy jakiegoś kodu, żeby wiedzieć, co robisz. – JimB

+0

@JimB Dodałem kod. Myślę, że sprawdziłem wszystkie błędy. Odroczenie zamknięcia sesji zostało ustawione po sprawdzeniu błędu – hey

+1

twoja panika jest spowodowana tym, że wywołujesz 'odroczenie session.Close()' w miejscu gdzie sesja jest zerowa. 't.Error (err)' nie wraca wcześniej. – JimB

Odpowiedz

10

trzeba użyć ssh.PublicKeys włączyć listę ssh.Signers się z ssh.AuthMethod. Możesz użyć ssh.ParsePrivateKey, aby uzyskać Signer z bajtów pem, lub jeśli potrzebujesz użyć klucza prywatnego RSA, DSA lub ecdsa, możesz je przekazać ssh.NewSignerFromKey.

Oto przykład poprawionego rozwiązania z obsługą agenta (ponieważ użycie agenta jest zwykle kolejnym krokiem po zwykłym użyciu pliku klucza).

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

Nie jestem pewien, czy rozumiem kod. Jak przekazać plik klucza (np. Mykey.pem) lub kluczową treść? Podpis wydaje się być interfejsem. Mam klucze przechowywane w db – hey

+1

Dodałem notatkę o użyciu 'ParsePrivateKey', aby uzyskać sygnatariusza z bajtów pem. – JimB

+0

dlaczego potrzebuję "agenta"? wydaje się zadeklarowany, ale nie jest używany, ponieważ korzystam z '' signers, err: = ssh.ParsePrivateKey (cl.Key) '' – hey

6

Oto przykład uruchomić ls zdalnie za pomocą „zwykły plik klucza prywatnego”.

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) 
Powiązane problemy