From fcb4fed7a170b989f14fa07eed5c11edd36f0f47 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 fbc4428d7987..1a6fc8d19984 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())