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.
This commit is contained in:
James Nugent 2017-03-20 15:42:34 -05:00 committed by Paul Stack
parent db132b312d
commit 9476fc4418
1 changed files with 32 additions and 0 deletions

View File

@ -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())