mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-02 12:17:39 -06:00
a036ea0ec8
Re-seeding the PRNG every time only serves to make the output an obfuscated timestamp. On windows with a low clock resolution, this manifests itself by outputting the same value on calls within the minimum time delta of the clock.
141 lines
3.7 KiB
Go
141 lines
3.7 KiB
Go
package acctest
|
|
|
|
import (
|
|
"bytes"
|
|
crand "crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"math/big"
|
|
"math/rand"
|
|
"strings"
|
|
"time"
|
|
|
|
"golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
func init() {
|
|
rand.Seed(time.Now().UTC().UnixNano())
|
|
}
|
|
|
|
// Helpers for generating random tidbits for use in identifiers to prevent
|
|
// collisions in acceptance tests.
|
|
|
|
// RandInt generates a random integer
|
|
func RandInt() int {
|
|
return rand.New(rand.NewSource(time.Now().UnixNano())).Int()
|
|
}
|
|
|
|
// RandomWithPrefix is used to generate a unique name with a prefix, for
|
|
// randomizing names in acceptance tests
|
|
func RandomWithPrefix(name string) string {
|
|
return fmt.Sprintf("%s-%d", name, rand.New(rand.NewSource(time.Now().UnixNano())).Int())
|
|
}
|
|
|
|
func RandIntRange(min int, max int) int {
|
|
source := rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
rangeMax := max - min
|
|
|
|
return int(source.Int31n(int32(rangeMax)))
|
|
}
|
|
|
|
// 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 {
|
|
result := make([]byte, strlen)
|
|
for i := 0; i < strlen; i++ {
|
|
result[i] = charSet[rand.Intn(len(charSet))]
|
|
}
|
|
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, privateKeyPEM, err := genPrivateKey()
|
|
if 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), 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()
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
cert, err := x509.CreateCertificate(crand.Reader, template, template, &privateKey.PublicKey, privateKey)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
certPEM, err := pemEncode(cert, "CERTIFICATE")
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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"
|
|
)
|