github.com/hashicorp/terraform-plugin-sdk@v1.17.2/helper/acctest/random.go (about) 1 package acctest 2 3 import ( 4 "bytes" 5 crand "crypto/rand" 6 "crypto/rsa" 7 "crypto/x509" 8 "crypto/x509/pkix" 9 "encoding/pem" 10 "fmt" 11 "math/big" 12 "math/rand" 13 "net" 14 "strings" 15 "time" 16 17 "golang.org/x/crypto/ssh" 18 19 "github.com/apparentlymart/go-cidr/cidr" 20 ) 21 22 func init() { 23 rand.Seed(time.Now().UTC().UnixNano()) 24 } 25 26 // Helpers for generating random tidbits for use in identifiers to prevent 27 // collisions in acceptance tests. 28 29 // RandInt generates a random integer 30 func RandInt() int { 31 return rand.New(rand.NewSource(time.Now().UnixNano())).Int() 32 } 33 34 // RandomWithPrefix is used to generate a unique name with a prefix, for 35 // randomizing names in acceptance tests 36 func RandomWithPrefix(name string) string { 37 return fmt.Sprintf("%s-%d", name, rand.New(rand.NewSource(time.Now().UnixNano())).Int()) 38 } 39 40 func RandIntRange(min int, max int) int { 41 source := rand.New(rand.NewSource(time.Now().UnixNano())) 42 rangeMax := max - min 43 44 return int(source.Int31n(int32(rangeMax))) 45 } 46 47 // RandString generates a random alphanumeric string of the length specified 48 func RandString(strlen int) string { 49 return RandStringFromCharSet(strlen, CharSetAlphaNum) 50 } 51 52 // RandStringFromCharSet generates a random string by selecting characters from 53 // the charset provided 54 func RandStringFromCharSet(strlen int, charSet string) string { 55 result := make([]byte, strlen) 56 for i := 0; i < strlen; i++ { 57 result[i] = charSet[rand.Intn(len(charSet))] 58 } 59 return string(result) 60 } 61 62 // RandSSHKeyPair generates a public and private SSH key pair. The public key is 63 // returned in OpenSSH format, and the private key is PEM encoded. 64 func RandSSHKeyPair(comment string) (string, string, error) { 65 privateKey, privateKeyPEM, err := genPrivateKey() 66 if err != nil { 67 return "", "", err 68 } 69 70 publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey) 71 if err != nil { 72 return "", "", err 73 } 74 keyMaterial := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(publicKey))) 75 return fmt.Sprintf("%s %s", keyMaterial, comment), privateKeyPEM, nil 76 } 77 78 // RandTLSCert generates a self-signed TLS certificate with a newly created 79 // private key, and returns both the cert and the private key PEM encoded. 80 func RandTLSCert(orgName string) (string, string, error) { 81 template := &x509.Certificate{ 82 SerialNumber: big.NewInt(int64(RandInt())), 83 Subject: pkix.Name{ 84 Organization: []string{orgName}, 85 }, 86 NotBefore: time.Now(), 87 NotAfter: time.Now().Add(24 * time.Hour), 88 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 89 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 90 BasicConstraintsValid: true, 91 } 92 93 privateKey, privateKeyPEM, err := genPrivateKey() 94 if err != nil { 95 return "", "", err 96 } 97 98 cert, err := x509.CreateCertificate(crand.Reader, template, template, &privateKey.PublicKey, privateKey) 99 if err != nil { 100 return "", "", err 101 } 102 103 certPEM, err := pemEncode(cert, "CERTIFICATE") 104 if err != nil { 105 return "", "", err 106 } 107 108 return certPEM, privateKeyPEM, nil 109 } 110 111 // RandIpAddress returns a random IP address in the specified CIDR block. 112 // The prefix length must be less than 31. 113 func RandIpAddress(s string) (string, error) { 114 _, network, err := net.ParseCIDR(s) 115 if err != nil { 116 return "", err 117 } 118 119 firstIp, lastIp := cidr.AddressRange(network) 120 first := &big.Int{} 121 first.SetBytes([]byte(firstIp)) 122 last := &big.Int{} 123 last.SetBytes([]byte(lastIp)) 124 r := &big.Int{} 125 r.Sub(last, first) 126 if len := r.BitLen(); len > 31 { 127 return "", fmt.Errorf("CIDR range is too large: %d", len) 128 } 129 130 max := int(r.Int64()) 131 if max == 0 { 132 // panic: invalid argument to Int31n 133 return firstIp.String(), nil 134 } 135 136 host, err := cidr.Host(network, RandIntRange(0, max)) 137 if err != nil { 138 return "", err 139 } 140 141 return host.String(), nil 142 } 143 144 func genPrivateKey() (*rsa.PrivateKey, string, error) { 145 privateKey, err := rsa.GenerateKey(crand.Reader, 1024) 146 if err != nil { 147 return nil, "", err 148 } 149 150 privateKeyPEM, err := pemEncode(x509.MarshalPKCS1PrivateKey(privateKey), "RSA PRIVATE KEY") 151 if err != nil { 152 return nil, "", err 153 } 154 155 return privateKey, privateKeyPEM, nil 156 } 157 158 func pemEncode(b []byte, block string) (string, error) { 159 var buf bytes.Buffer 160 pb := &pem.Block{Type: block, Bytes: b} 161 if err := pem.Encode(&buf, pb); err != nil { 162 return "", err 163 } 164 165 return buf.String(), nil 166 } 167 168 const ( 169 // CharSetAlphaNum is the alphanumeric character set for use with 170 // RandStringFromCharSet 171 CharSetAlphaNum = "abcdefghijklmnopqrstuvwxyz012346789" 172 173 // CharSetAlpha is the alphabetical character set for use with 174 // RandStringFromCharSet 175 CharSetAlpha = "abcdefghijklmnopqrstuvwxyz" 176 )