diff --git a/Makefile b/Makefile index becdf39..c1b9024 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ endif BINARY=keymaster # These are the values we want to pass for Version and BuildTime -VERSION?=1.15.4 +VERSION?=1.15.5 DEFAULT_HOST?= VERSION_FLAVOUR?= EXTRA_LDFLAGS?= diff --git a/cmd/keymaster/main.go b/cmd/keymaster/main.go index 8ed8620..4cf3673 100644 --- a/cmd/keymaster/main.go +++ b/cmd/keymaster/main.go @@ -299,19 +299,19 @@ func insertSSHCertIntoAgentORWriteToFilesystem(certText []byte, return nil } logger.Debugf(1, "Non fatal, failed to insert into agent without expiration") - encodedSigner, err := x509.MarshalPKCS8PrivateKey(signer) + encodedSigner, err := ssh.MarshalPrivateKey(signer, "") if err != nil { return err } err = ioutil.WriteFile( privateKeyPath, - pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: encodedSigner}), + pem.EncodeToMemory(encodedSigner), 0600) if err != nil { return err } // now we need to write the certificate - sshCertPath := privateKeyPath + ".pub" + sshCertPath := privateKeyPath + "-cert.pub" return ioutil.WriteFile(sshCertPath, certText, 0644) } diff --git a/cmd/keymaster/main_test.go b/cmd/keymaster/main_test.go index 81b1b90..535de72 100644 --- a/cmd/keymaster/main_test.go +++ b/cmd/keymaster/main_test.go @@ -6,12 +6,12 @@ import ( "crypto/rand" "crypto/tls" "crypto/x509" - "encoding/base64" "encoding/json" "fmt" "io/ioutil" "net/http" "os" + "os/exec" "path/filepath" "runtime" "testing" @@ -20,6 +20,7 @@ import ( "golang.org/x/crypto/ssh" "github.com/Cloud-Foundations/golib/pkg/log/testlogger" + "github.com/Cloud-Foundations/keymaster/lib/certgen" "github.com/Cloud-Foundations/keymaster/lib/client/config" "github.com/Cloud-Foundations/keymaster/lib/client/twofa/u2f" "github.com/Cloud-Foundations/keymaster/lib/client/util" @@ -202,41 +203,29 @@ func TestMost(t *testing.T) { } -func goCertToFileString(c ssh.Certificate, username string) (string, error) { - certBytes := c.Marshal() - encoded := base64.StdEncoding.EncodeToString(certBytes) - fileComment := "/tmp/" + username + "-" + c.SignatureKey.Type() + "-cert.pub" - return c.Type() + " " + encoded + " " + fileComment, nil -} - func TestInsertSSHCertIntoAgentORWriteToFilesystem(t *testing.T) { //step 1: generate publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } + sshPublic, err := ssh.NewPublicKey(publicKey) if err != nil { t.Fatal(err) } - cert := ssh.Certificate{ - Key: sshPublic, - ValidPrincipals: []string{"username"}, - ValidAfter: uint64(time.Now().Unix()) - 10, - ValidBefore: uint64(time.Now().Unix()) + 10, - } + sshPublicBytes := ssh.MarshalAuthorizedKey(sshPublic) + sshSigner, err := ssh.NewSignerFromKey(privateKey) if err != nil { t.Fatal(err) } - err = cert.SignCert(rand.Reader, sshSigner) - if err != nil { - t.Fatal(err) - } - certString, err := goCertToFileString(cert, "username") - if err != nil { - t.Fatal(err) - } + seconds := 10 + certDuration := time.Duration(seconds) * time.Second + extensions := make(map[string]string) + + certString, _, err := certgen.GenSSHCertFileString("username", string(sshPublicBytes), sshSigner, "km.example.com", certDuration, extensions) + // This test needs a running agent... and remote windows // builders do NOT have this... thus we need to abort this test // until we have a way to NOT timeout on missing agent in @@ -273,9 +262,23 @@ func TestInsertSSHCertIntoAgentORWriteToFilesystem(t *testing.T) { if err != nil { t.Fatal(err) } - os.Remove(privateKeyPath) - // TODO: on linux/macos create agent + unix socket and pass that + defer os.Remove(privateKeyPath) + //t.Logf("certString='%s'", certString) + + // TODO: on linux/macos create agent + unix socket and pass that + if oldSSHSock != "" && runtime.GOOS == "darwin" { + //reset the socket + err = os.Setenv("SSH_AUTH_SOCK", oldSSHSock) + if err != nil { + t.Fatal(err) + } + cmd := exec.Command("ssh-add", "-t", "30", privateKeyPath) + err := cmd.Run() + if err != nil { + t.Fatalf("Command finished with error: %v", err) + } + } } func TestMainSimple(t *testing.T) {