2016-01-04 22:21:38 +01:00
|
|
|
package acctest
|
|
|
|
|
|
|
|
import (
|
2017-03-20 21:42:34 +01:00
|
|
|
"bytes"
|
|
|
|
crand "crypto/rand"
|
|
|
|
"crypto/rsa"
|
|
|
|
"crypto/x509"
|
2017-05-16 12:40:33 +02:00
|
|
|
"crypto/x509/pkix"
|
2017-03-20 21:42:34 +01:00
|
|
|
"encoding/pem"
|
|
|
|
"fmt"
|
2017-05-16 12:40:33 +02:00
|
|
|
"math/big"
|
2016-01-04 22:21:38 +01:00
|
|
|
"math/rand"
|
2017-03-20 21:42:34 +01:00
|
|
|
"strings"
|
2016-01-04 22:21:38 +01:00
|
|
|
"time"
|
2017-03-20 21:42:34 +01:00
|
|
|
|
|
|
|
"golang.org/x/crypto/ssh"
|
2016-01-04 22:21:38 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// Helpers for generating random tidbits for use in identifiers to prevent
|
|
|
|
// collisions in acceptance tests.
|
|
|
|
|
2016-01-05 16:06:32 +01:00
|
|
|
// RandInt generates a random integer
|
|
|
|
func RandInt() int {
|
|
|
|
reseed()
|
|
|
|
return rand.New(rand.NewSource(time.Now().UnixNano())).Int()
|
|
|
|
}
|
|
|
|
|
2017-04-12 21:19:38 +02:00
|
|
|
// RandomWithPrefix is used to generate a unique name with a prefix, for
|
|
|
|
// randomizing names in acceptance tests
|
|
|
|
func RandomWithPrefix(name string) string {
|
|
|
|
reseed()
|
|
|
|
return fmt.Sprintf("%s-%d", name, rand.New(rand.NewSource(time.Now().UnixNano())).Int())
|
|
|
|
}
|
|
|
|
|
2017-03-22 23:53:49 +01:00
|
|
|
func RandIntRange(min int, max int) int {
|
|
|
|
reseed()
|
|
|
|
source := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
|
|
rangeMax := max - min
|
|
|
|
|
|
|
|
return int(source.Int31n(int32(rangeMax)))
|
|
|
|
}
|
|
|
|
|
2016-01-04 22:21:38 +01:00
|
|
|
// RandString generates a random alphanumeric string of the length specified
|
|
|
|
func RandString(strlen int) string {
|
|
|
|
return RandStringFromCharSet(strlen, CharSetAlphaNum)
|
|
|
|
}
|
|
|
|
|
|
|
|
// RandStringFromCharSet generates a random string by selecting characters from
|
|
|
|
// the charset provided
|
|
|
|
func RandStringFromCharSet(strlen int, charSet string) string {
|
2016-01-05 16:06:32 +01:00
|
|
|
reseed()
|
2016-01-04 22:21:38 +01:00
|
|
|
result := make([]byte, strlen)
|
|
|
|
for i := 0; i < strlen; i++ {
|
|
|
|
result[i] = charSet[rand.Intn(len(charSet))]
|
|
|
|
}
|
|
|
|
return string(result)
|
|
|
|
}
|
|
|
|
|
2017-03-20 21:42:34 +01:00
|
|
|
// 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) {
|
2017-05-16 12:40:33 +02:00
|
|
|
privateKey, privateKeyPEM, err := genPrivateKey()
|
|
|
|
|
|
|
|
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), privateKeyPEM, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// RandTLSCert generates a self-signed TLS certificate with a newly created
|
|
|
|
// private key, and returns both the cert and the private key PEM encoded.
|
|
|
|
func RandTLSCert(orgName string) (string, string, error) {
|
|
|
|
template := &x509.Certificate{
|
|
|
|
SerialNumber: big.NewInt(int64(RandInt())),
|
|
|
|
Subject: pkix.Name{
|
|
|
|
Organization: []string{orgName},
|
|
|
|
},
|
|
|
|
NotBefore: time.Now(),
|
|
|
|
NotAfter: time.Now().Add(24 * time.Hour),
|
|
|
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
|
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
|
|
|
BasicConstraintsValid: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
privateKey, privateKeyPEM, err := genPrivateKey()
|
2017-03-20 21:42:34 +01:00
|
|
|
if err != nil {
|
|
|
|
return "", "", err
|
|
|
|
}
|
|
|
|
|
2017-05-16 12:40:33 +02:00
|
|
|
cert, err := x509.CreateCertificate(crand.Reader, template, template, &privateKey.PublicKey, privateKey)
|
|
|
|
if err != nil {
|
2017-03-20 21:42:34 +01:00
|
|
|
return "", "", err
|
|
|
|
}
|
|
|
|
|
2017-05-16 12:40:33 +02:00
|
|
|
certPEM, err := pemEncode(cert, "CERTIFICATE")
|
2017-03-20 21:42:34 +01:00
|
|
|
if err != nil {
|
|
|
|
return "", "", err
|
|
|
|
}
|
2017-05-16 12:40:33 +02:00
|
|
|
|
|
|
|
return certPEM, privateKeyPEM, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func genPrivateKey() (*rsa.PrivateKey, string, error) {
|
|
|
|
privateKey, err := rsa.GenerateKey(crand.Reader, 1024)
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
privateKeyPEM, err := pemEncode(x509.MarshalPKCS1PrivateKey(privateKey), "RSA PRIVATE KEY")
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return privateKey, privateKeyPEM, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func pemEncode(b []byte, block string) (string, error) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
pb := &pem.Block{Type: block, Bytes: b}
|
|
|
|
if err := pem.Encode(&buf, pb); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return buf.String(), nil
|
2017-03-20 21:42:34 +01:00
|
|
|
}
|
|
|
|
|
2016-01-05 16:06:32 +01:00
|
|
|
// Seeds random with current timestamp
|
|
|
|
func reseed() {
|
|
|
|
rand.Seed(time.Now().UTC().UnixNano())
|
|
|
|
}
|
|
|
|
|
2016-01-04 22:21:38 +01:00
|
|
|
const (
|
|
|
|
// CharSetAlphaNum is the alphanumeric character set for use with
|
|
|
|
// RandStringFromCharSet
|
|
|
|
CharSetAlphaNum = "abcdefghijklmnopqrstuvwxyz012346789"
|
|
|
|
|
|
|
|
// CharSetAlpha is the alphabetical character set for use with
|
|
|
|
// RandStringFromCharSet
|
|
|
|
CharSetAlpha = "abcdefghijklmnopqrstuvwxyz"
|
|
|
|
)
|