2017-06-01 44 views
0
通過Hashicorp庫簽名密鑰,認證

我已經簽署了使用Hashicorp跳馬我的公鑰,並在~/.ssh/id_rsa-cert.pub 保存生成的certificiate它工作得很好,我可以做ssh -i ~/.ssh/id_rsa-cert.pub [email protected],它讓我在SSH:無法使用轉到

當我嘗試在Go中實現時,我的問題就開始了。

這是我的代碼:

package main 

import (
"encoding/base64" 
"fmt" 
"golang.org/x/crypto/ssh" 
"golang.org/x/crypto/ssh/agent" 
"net" 
"os" 
) 

func main() { 
pubKey := "AAAAB3NzaC1yc2EAAAADAQABA..." 
signedKey := "AAAAHHNzaC1yc2EtY2VydC..." 
pubKeyBytes, err := base64.StdEncoding.DecodeString(pubKey) 
if err != nil { 
    panic(err) 
} 
pk, err := ssh.ParsePublicKey(pubKeyBytes) 
if err != nil { 
    panic(err) 
} 
fmt.Printf("%T\n", pk) 

signedKeyBytes, err := base64.StdEncoding.DecodeString(signedKey) 
if err != nil { 
    panic(err) 
} 
fmt.Printf("%T\n", pk) 
sk, err := ssh.ParsePublicKey(signedKeyBytes) 
if err != nil { 
    panic(err) 
} 
fmt.Printf("%T\n", sk) 

conn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")) 
if err != nil { 
    panic(err) 
} 
sshAgent := agent.NewClient(conn) 
signers, err := sshAgent.Signers() 
if err != nil { 
    panic(err) 
} 

c := &ssh.Certificate{ 
    Key:   pk, 
    SignatureKey: sk, 
} 

signer, err := ssh.NewCertSigner(c, signers[0]) 
if err != nil { 
    panic(err) 
} 

auths := []ssh.AuthMethod{ssh.PublicKeys(signer)} 
sshClient, err := ssh.Dial("tcp", "10.0.0.150:22", &ssh.ClientConfig{ 
    User: "user1", 
    /*The signed key is signed against user2's public key, and should allow him to log in. 
    It works via command line; [email protected]: ssh -i id_rsa-cert.pub [email protected]*/ 
    Auth:   auths, 
    HostKeyCallback: ssh.InsecureIgnoreHostKey(), 
}) 
fmt.Println(sshClient, err) /*This does not work*/ 

sshClient2, err := ssh.Dial("tcp", "10.0.0.150:22", &ssh.ClientConfig{ 
    User: "user2", 
    /*User2 is allowed to connect with his basic keypair 
    [email protected]: ssh [email protected]*/ 
    Auth: []ssh.AuthMethod{ 
     ssh.PublicKeysCallback(sshAgent.Signers), 
    }, 
    HostKeyCallback: ssh.InsecureIgnoreHostKey(), 
}) 
fmt.Println(sshClient2, err) /*This works fine*/ 
} 

的錯誤,我得到的是:從服務器

ssh: handshake failed: ssh: unable to authenticate, attempted methods [publickey none], 
no supported methods remain 

而且sshd的日誌問題:

sshd[7149]: error: Unknown certificate type 0 sshd[7149]: error: 
key_from_blob: can't parse cert data sshd[7149]: error: 
userauth_pubkey: cannot decode key: [email protected] 

我需要什麼在這裏做什麼來獲得這個工作?

+0

顯然使用了'ssh.InsecureIgnoreHostKey()',你當你的服務器要求使用ssh.InsecureIgnoreHostKey認證 –

+0

的一種或至少一種方法,我的印象是無視鍵()會接受任何主機密鑰?這是不正確的? –

+0

Alex:您是否找到了解決問題的方案?我仍然有同樣的問題,我很想有一個golang實現來授權簽名密鑰。 –

回答

0

我花了幾個小時弄清楚了這一點。

解決方案是使用您的私鑰和您的證書,並先簽署一個簽名者,然後簽署一個證書並將兩者結合起來。以下是按預期工作的工作代碼。

package main 

import (
    "bytes" 
    "golang.org/x/crypto/ssh" 
    "io/ioutil" 
    "log" 
) 

func main() { 
    authorizedKeysBytes, _ := ioutil.ReadFile("/home/wooh/.ssh/signed-cert.pub") 
    pcert, _, _, _, err := ssh.ParseAuthorizedKey(authorizedKeysBytes) 

    privkeyBytes, _ := ioutil.ReadFile("/home/wooh/.ssh/id_rsa") 
    upkey, err := ssh.ParseRawPrivateKey(privkeyBytes) 

    if err != nil { 
     log.Printf("Failed to load authorized_keys, err: %v", err) 
    } 

    usigner, err := ssh.NewSignerFromKey(upkey) 
    if err != nil { 
     log.Printf("Failed to create new signer, err: %v", err) 
    } 
    log.Printf("signer: %v", usigner) 

    ucertSigner, err := ssh.NewCertSigner(pcert.(*ssh.Certificate), usigner) 

    if err != nil { 
     log.Printf("Failed to create new signer, err: %v", err) 
    } 

    sshConfig := &ssh.ClientConfig{ 
     User:   "wooh", 
     Auth:   []ssh.AuthMethod{ssh.PublicKeys(ucertSigner)}, 
     HostKeyCallback: ssh.InsecureIgnoreHostKey(), 
    } 

    client, err := ssh.Dial("tcp", "127.0.0.1:22", sshConfig) 

    if err != nil { 
     log.Fatalf("Failed to dial, err: %v", err) 
    } 

    session, err := client.NewSession() 
    if err != nil { 
     log.Fatal("Failed to create session: ", err) 
    } 
    defer session.Close() 

    var b bytes.Buffer 
    session.Stdout = &b 
    if err := session.Run("/usr/bin/whoami"); err != nil { 
     log.Fatal("Failed to run: " + err.Error()) 
    } 
    log.Println(b.String()) 
}