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