1package awstesting 2 3import ( 4 "io/ioutil" 5 "net" 6 "net/http" 7 "os" 8 "strings" 9 "time" 10) 11 12func availableLocalAddr(ip string) (string, error) { 13 l, err := net.Listen("tcp", ip+":0") 14 if err != nil { 15 return "", err 16 } 17 defer l.Close() 18 19 return l.Addr().String(), nil 20} 21 22// CreateTLSServer will create the TLS server on an open port using the 23// certificate and key. The address will be returned that the server is running on. 24func CreateTLSServer(cert, key string, mux *http.ServeMux) (string, error) { 25 addr, err := availableLocalAddr("127.0.0.1") 26 if err != nil { 27 return "", err 28 } 29 30 if mux == nil { 31 mux = http.NewServeMux() 32 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {}) 33 } 34 35 go func() { 36 if err := http.ListenAndServeTLS(addr, cert, key, mux); err != nil { 37 panic(err) 38 } 39 }() 40 41 for i := 0; i < 60; i++ { 42 if _, err := http.Get("https://" + addr); err != nil && !strings.Contains(err.Error(), "connection refused") { 43 break 44 } 45 46 time.Sleep(1 * time.Second) 47 } 48 49 return "https://" + addr, nil 50} 51 52// CreateTLSBundleFiles returns the temporary filenames for the certificate 53// key, and CA PEM content. These files should be deleted when no longer 54// needed. CleanupTLSBundleFiles can be used for this cleanup. 55func CreateTLSBundleFiles() (cert, key, ca string, err error) { 56 cert, err = createTmpFile(TLSBundleCert) 57 if err != nil { 58 return "", "", "", err 59 } 60 61 key, err = createTmpFile(TLSBundleKey) 62 if err != nil { 63 return "", "", "", err 64 } 65 66 ca, err = createTmpFile(TLSBundleCA) 67 if err != nil { 68 return "", "", "", err 69 } 70 71 return cert, key, ca, nil 72} 73 74// CleanupTLSBundleFiles takes variadic list of files to be deleted. 75func CleanupTLSBundleFiles(files ...string) error { 76 for _, file := range files { 77 if err := os.Remove(file); err != nil { 78 return err 79 } 80 } 81 82 return nil 83} 84 85func createTmpFile(b []byte) (string, error) { 86 bundleFile, err := ioutil.TempFile(os.TempDir(), "aws-sdk-go-session-test") 87 if err != nil { 88 return "", err 89 } 90 91 _, err = bundleFile.Write(b) 92 if err != nil { 93 return "", err 94 } 95 96 defer bundleFile.Close() 97 return bundleFile.Name(), nil 98} 99 100/* Cert generation steps 101# Create the CA key 102openssl genrsa -des3 -out ca.key 1024 103 104# Create the CA Cert 105openssl req -new -sha256 -x509 -days 3650 \ 106 -subj "/C=GO/ST=Gopher/O=Testing ROOT CA" \ 107 -key ca.key -out ca.crt 108 109# Create config 110cat > csr_details.txt <<-EOF 111 112[req] 113default_bits = 1024 114prompt = no 115default_md = sha256 116req_extensions = SAN 117distinguished_name = dn 118 119[ dn ] 120C=GO 121ST=Gopher 122O=Testing Certificate 123OU=Testing IP 124 125[SAN] 126subjectAltName = IP:127.0.0.1 127EOF 128 129# Create certificate signing request 130openssl req -new -sha256 -nodes -newkey rsa:1024 \ 131 -config <( cat csr_details.txt ) \ 132 -keyout ia.key -out ia.csr 133 134# Create a signed certificate 135openssl x509 -req -days 3650 \ 136 -CAcreateserial \ 137 -extfile <( cat csr_details.txt ) \ 138 -extensions SAN \ 139 -CA ca.crt -CAkey ca.key -in ia.csr -out ia.crt 140 141# Verify 142openssl req -noout -text -in ia.csr 143openssl x509 -noout -text -in ia.crt 144*/ 145var ( 146 // TLSBundleCA ca.crt 147 TLSBundleCA = []byte(`-----BEGIN CERTIFICATE----- 148MIICiTCCAfKgAwIBAgIJAJ5X1olt05XjMA0GCSqGSIb3DQEBCwUAMDgxCzAJBgNV 149BAYTAkdPMQ8wDQYDVQQIEwZHb3BoZXIxGDAWBgNVBAoTD1Rlc3RpbmcgUk9PVCBD 150QTAeFw0xNzAzMDkwMDAyMDZaFw0yNzAzMDcwMDAyMDZaMDgxCzAJBgNVBAYTAkdP 151MQ8wDQYDVQQIEwZHb3BoZXIxGDAWBgNVBAoTD1Rlc3RpbmcgUk9PVCBDQTCBnzAN 152BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw/8DN+t9XQR60jx42rsQ2WE2Dx85rb3n 153GQxnKZZLNddsT8rDyxJNP18aFalbRbFlyln5fxWxZIblu9Xkm/HRhOpbSimSqo1y 154uDx21NVZ1YsOvXpHby71jx3gPrrhSc/t/zikhi++6D/C6m1CiIGuiJ0GBiJxtrub 155UBMXT0QtI2ECAwEAAaOBmjCBlzAdBgNVHQ4EFgQU8XG3X/YHBA6T04kdEkq6+4GV 156YykwaAYDVR0jBGEwX4AU8XG3X/YHBA6T04kdEkq6+4GVYymhPKQ6MDgxCzAJBgNV 157BAYTAkdPMQ8wDQYDVQQIEwZHb3BoZXIxGDAWBgNVBAoTD1Rlc3RpbmcgUk9PVCBD 158QYIJAJ5X1olt05XjMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEAeILv 159z49+uxmPcfOZzonuOloRcpdvyjiXblYxbzz6ch8GsE7Q886FTZbvwbgLhzdwSVgG 160G8WHkodDUsymVepdqAamS3f8PdCUk8xIk9mop8LgaB9Ns0/TssxDvMr3sOD2Grb3 161xyWymTWMcj6uCiEBKtnUp4rPiefcvCRYZ17/hLE= 162-----END CERTIFICATE----- 163`) 164 165 // TLSBundleCert ai.crt 166 TLSBundleCert = []byte(`-----BEGIN CERTIFICATE----- 167MIICGjCCAYOgAwIBAgIJAIIu+NOoxxM0MA0GCSqGSIb3DQEBBQUAMDgxCzAJBgNV 168BAYTAkdPMQ8wDQYDVQQIEwZHb3BoZXIxGDAWBgNVBAoTD1Rlc3RpbmcgUk9PVCBD 169QTAeFw0xNzAzMDkwMDAzMTRaFw0yNzAzMDcwMDAzMTRaMFExCzAJBgNVBAYTAkdP 170MQ8wDQYDVQQIDAZHb3BoZXIxHDAaBgNVBAoME1Rlc3RpbmcgQ2VydGlmaWNhdGUx 171EzARBgNVBAsMClRlc3RpbmcgSVAwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB 172AN1hWHeioo/nASvbrjwCQzXCiWiEzGkw353NxsAB54/NqDL3LXNATtiSJu8kJBrm 173Ah12IFLtWLGXjGjjYlHbQWnOR6awveeXnQZukJyRWh7m/Qlt9Ho0CgZE1U+832ac 1745GWVldNxW1Lz4I+W9/ehzqe8I80RS6eLEKfUFXGiW+9RAgMBAAGjEzARMA8GA1Ud 175EQQIMAaHBH8AAAEwDQYJKoZIhvcNAQEFBQADgYEAdF4WQHfVdPCbgv9sxgJjcR1H 176Hgw9rZ47gO1IiIhzglnLXQ6QuemRiHeYFg4kjcYBk1DJguxzDTGnUwhUXOibAB+S 177zssmrkdYYvn9aUhjc3XK3tjAoDpsPpeBeTBamuUKDHoH/dNRXxerZ8vu6uPR3Pgs 1785v/KCV6IAEcvNyOXMPo= 179-----END CERTIFICATE----- 180`) 181 182 // TLSBundleKey ai.key 183 TLSBundleKey = []byte(`-----BEGIN RSA PRIVATE KEY----- 184MIICXAIBAAKBgQDdYVh3oqKP5wEr2648AkM1wolohMxpMN+dzcbAAeePzagy9y1z 185QE7YkibvJCQa5gIddiBS7Vixl4xo42JR20FpzkemsL3nl50GbpCckVoe5v0JbfR6 186NAoGRNVPvN9mnORllZXTcVtS8+CPlvf3oc6nvCPNEUunixCn1BVxolvvUQIDAQAB 187AoGBAMISrcirddGrlLZLLrKC1ULS2T0cdkqdQtwHYn4+7S5+/z42vMx1iumHLsSk 188rVY7X41OWkX4trFxhvEIrc/O48bo2zw78P7flTxHy14uxXnllU8cLThE29SlUU7j 189AVBNxJZMsXMlS/DowwD4CjFe+x4Pu9wZcReF2Z9ntzMpySABAkEA+iWoJCPE2JpS 190y78q3HYYgpNY3gF3JqQ0SI/zTNkb3YyEIUffEYq0Y9pK13HjKtdsSuX4osTIhQkS 191+UgRp6tCAQJBAOKPYTfQ2FX8ijgUpHZRuEAVaxASAS0UATiLgzXxLvOh/VC2at5x 192wjOX6sD65pPz/0D8Qj52Cq6Q1TQ+377SDVECQAIy0od+yPweXxvrUjUd1JlRMjbB 193TIrKZqs8mKbUQapw0bh5KTy+O1elU4MRPS3jNtBxtP25PQnuSnxmZcFTgAECQFzg 194DiiFcsn9FuRagfkHExMiNJuH5feGxeFaP9WzI144v9GAllrOI6Bm3JNzx2ZLlg4b 19520Qju8lIEj6yr6JYFaECQHM1VSojGRKpOl9Ox/R4yYSA9RV5Gyn00/aJNxVYyPD5 196i3acL2joQm2kLD/LO8paJ4+iQdRXCOMMIpjxSNjGQjQ= 197-----END RSA PRIVATE KEY----- 198`) 199) 200