From 9476fc44187f9e99568e34bce35411c101dc1e04 Mon Sep 17 00:00:00 2001 From: James Nugent Date: Mon, 20 Mar 2017 15:42:34 -0500 Subject: [PATCH] helper/acctest: Add NewSSHKeyPair function (#12894) Many cloud services prevent duplicate key pairs with different names. Among them are Digital Ocean, Joyent Triton and Packet. Consequently, if tests leave dangling resources it is not enough to simply randomise the name, the entire key material must be regenerated. This commit adds a helper method that returns a new randomly generated key pair, where the public key material is formatted in OpenSSH "authorized keys" format, and the private key material is PEM encoded. --- helper/acctest/random.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/helper/acctest/random.go b/helper/acctest/random.go index fbc4428d7..1a6fc8d19 100644 --- a/helper/acctest/random.go +++ b/helper/acctest/random.go @@ -1,8 +1,18 @@ package acctest import ( + "bufio" + "bytes" + crand "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" "math/rand" + "strings" "time" + + "golang.org/x/crypto/ssh" ) // Helpers for generating random tidbits for use in identifiers to prevent @@ -30,6 +40,28 @@ func RandStringFromCharSet(strlen int, charSet string) string { return string(result) } +// RandSSHKeyPair generates a public and private SSH key pair. The public key is +// returned in OpenSSH format, and the private key is PEM encoded. +func RandSSHKeyPair(comment string) (string, string, error) { + privateKey, err := rsa.GenerateKey(crand.Reader, 1024) + if err != nil { + return "", "", err + } + + var privateKeyBuffer bytes.Buffer + privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} + if err := pem.Encode(bufio.NewWriter(&privateKeyBuffer), privateKeyPEM); err != nil { + return "", "", err + } + + publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey) + if err != nil { + return "", "", err + } + keyMaterial := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(publicKey))) + return fmt.Sprintf("%s %s", keyMaterial, comment), privateKeyBuffer.String(), nil +} + // Seeds random with current timestamp func reseed() { rand.Seed(time.Now().UTC().UnixNano())