2014-06-26 58 views
5

我正嘗試使用Go編程語言的[ssh] [1]軟件包連接到亞馬遜AWS Linux服務器。然而,包文檔有點神祕/混亂。有誰知道如何通過ssh使用密鑰連接,或者至少如果可能的話?讓我困擾的是,在[撥號] [3]例如它說使用SSH連接到服務器並使用golang與pem/key

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

我基本上要模仿的ssh -i x.pem [email protected]行爲和服務器內執行一個命令(如whoami

+1

恐慌意味着你忽略了某處的錯誤(或者在檢查錯誤之前設置延遲)。我們需要一些代碼來知道你在做什麼。 – JimB

+0

@JimB我添加了一些代碼。我想我已經檢查了所有的錯誤。關閉會話的延遲是在錯誤檢查後設置的 – hey

+1

你的恐慌是因爲你調用'defer session.Close()'在哪裏會話是零。 't.Error(err)'不會提早回來。 – JimB

回答

10

您需要使用ssh.PublicKeysssh.Signers的列表變成ssh.AuthMethod。您可以使用ssh.ParsePrivateKey從pem字節中獲得Signer,或者如果您需要使用rsa,dsa或ecdsa私鑰,則可以將它們授予ssh.NewSignerFromKey

下面的例子充實了Agent支持(因爲使用代理通常是簡單地使用密鑰文件之後的下一步)。

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

我不確定我瞭解代碼。我如何傳遞密鑰文件(例如mykey.pem)或密鑰內容?簽名者似乎是一個界面。我把密鑰存儲在db – hey

+1

我添加了一條關於使用'ParsePrivateKey'從pem字節獲取簽名者的註釋。 – JimB

+0

我爲什麼需要''代理人'?它似乎聲明,但沒有使用,因爲我使用''簽署者,錯誤:= ssh.ParsePrivateKey(cl.Key)'' – hey

6

這是遠程使用您的「純私人密鑰文件」運行LS一個例子。

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)