2017-06-01 15 views
0
unterzeichnet authentifizieren

Ich habe meinen öffentlichen Schlüssel Hashicorp Vault unterzeichnet, und rettete die erzeugte certificiate in ~/.ssh/id_rsa-cert.pub Es funktioniert ganz gut, ich kann ssh -i ~/.ssh/id_rsa-cert.pub [email protected] tun, und es lässt mich inSSH: Kann nicht mit Schlüssel von Hashicorp Vault mit Go

.

Meine Probleme beginnen, wenn ich versuche, dies in Go zu implementieren.

Dies ist mein Code:

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*/ 
} 

Die Fehler, die ich bekommen sind:

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

Und die sshd Protokolle vom Server in Frage:

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] 

Was brauche ich um hier zu arbeiten?

+0

offensichtlich Sie verwenden 'ssh.InsecureIgnoreHostKey()', Sie ignorieren einen Schlüssel, wenn der Server erfordert einen oder zumindest eine Art der Authentifizierung –

+0

ich hatte den Eindruck, dass ssh.InsecureIgnoreHostKey mit() würde jeden Host-Schlüssel akzeptieren? Ist das nicht korrekt? –

+0

Alex: Haben Sie schon eine Lösung für Ihr Problem gefunden? Ich habe immer noch das gleiche Problem und ich würde gerne eine Golang-Implementierung für die Autorisierung signierter Schlüssel haben. –

Antwort

0

Ich verbrachte ein paar Stunden, um dies herauszufinden.

Die Lösung ist, Ihren privaten Schlüssel und Ihr Zertifikat zu verwenden und zuerst einen Unterzeichner, dann einen Certsigner zu erstellen und die beiden zu kombinieren. Unten ist der Arbeitscode, der wie erwartet funktioniert.

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