mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	Merge pull request #14889 from liggitt/honor-skip-validate
Auto commit by PR queue bot
This commit is contained in:
		@@ -332,6 +332,7 @@ type SimpleRESTStorage struct {
 | 
				
			|||||||
	// The id requested, and location to return for ResourceLocation
 | 
						// The id requested, and location to return for ResourceLocation
 | 
				
			||||||
	requestedResourceLocationID string
 | 
						requestedResourceLocationID string
 | 
				
			||||||
	resourceLocation            *url.URL
 | 
						resourceLocation            *url.URL
 | 
				
			||||||
 | 
						resourceLocationTransport   http.RoundTripper
 | 
				
			||||||
	expectedResourceNamespace   string
 | 
						expectedResourceNamespace   string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If non-nil, called inside the WorkFunc when answering update, delete, create.
 | 
						// If non-nil, called inside the WorkFunc when answering update, delete, create.
 | 
				
			||||||
@@ -477,7 +478,7 @@ func (storage *SimpleRESTStorage) ResourceLocation(ctx api.Context, id string) (
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// Make a copy so the internal URL never gets mutated
 | 
						// Make a copy so the internal URL never gets mutated
 | 
				
			||||||
	locationCopy := *storage.resourceLocation
 | 
						locationCopy := *storage.resourceLocation
 | 
				
			||||||
	return &locationCopy, nil, nil
 | 
						return &locationCopy, storage.resourceLocationTransport, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Implement Connecter
 | 
					// Implement Connecter
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -286,6 +286,11 @@ func dialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) {
 | 
				
			|||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Return if we were configured to skip validation
 | 
				
			||||||
 | 
							if tlsConfig != nil && tlsConfig.InsecureSkipVerify {
 | 
				
			||||||
 | 
								return tlsConn, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Verify
 | 
							// Verify
 | 
				
			||||||
		host, _, _ := net.SplitHostPort(dialAddr)
 | 
							host, _, _ := net.SplitHostPort(dialAddr)
 | 
				
			||||||
		if err := tlsConn.VerifyHostname(host); err != nil {
 | 
							if err := tlsConn.VerifyHostname(host); err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,8 @@ package apiserver
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"compress/gzip"
 | 
						"compress/gzip"
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"crypto/x509"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
@@ -125,43 +127,97 @@ func TestProxy(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestProxyUpgrade(t *testing.T) {
 | 
					func TestProxyUpgrade(t *testing.T) {
 | 
				
			||||||
	backendServer := httptest.NewServer(websocket.Handler(func(ws *websocket.Conn) {
 | 
					
 | 
				
			||||||
 | 
						localhostPool := x509.NewCertPool()
 | 
				
			||||||
 | 
						if !localhostPool.AppendCertsFromPEM(localhostCert) {
 | 
				
			||||||
 | 
							t.Errorf("error setting up localhostCert pool")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testcases := map[string]struct {
 | 
				
			||||||
 | 
							ServerFunc     func(http.Handler) *httptest.Server
 | 
				
			||||||
 | 
							ProxyTransport http.RoundTripper
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							"http": {
 | 
				
			||||||
 | 
								ServerFunc:     httptest.NewServer,
 | 
				
			||||||
 | 
								ProxyTransport: nil,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"https (invalid hostname + InsecureSkipVerify)": {
 | 
				
			||||||
 | 
								ServerFunc: func(h http.Handler) *httptest.Server {
 | 
				
			||||||
 | 
									cert, err := tls.X509KeyPair(exampleCert, exampleKey)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Errorf("https (invalid hostname): proxy_test: %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts := httptest.NewUnstartedServer(h)
 | 
				
			||||||
 | 
									ts.TLS = &tls.Config{
 | 
				
			||||||
 | 
										Certificates: []tls.Certificate{cert},
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts.StartTLS()
 | 
				
			||||||
 | 
									return ts
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								ProxyTransport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"https (valid hostname + RootCAs)": {
 | 
				
			||||||
 | 
								ServerFunc: func(h http.Handler) *httptest.Server {
 | 
				
			||||||
 | 
									cert, err := tls.X509KeyPair(localhostCert, localhostKey)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Errorf("https (valid hostname): proxy_test: %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts := httptest.NewUnstartedServer(h)
 | 
				
			||||||
 | 
									ts.TLS = &tls.Config{
 | 
				
			||||||
 | 
										Certificates: []tls.Certificate{cert},
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts.StartTLS()
 | 
				
			||||||
 | 
									return ts
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								ProxyTransport: &http.Transport{TLSClientConfig: &tls.Config{RootCAs: localhostPool}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for k, tc := range testcases {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							backendServer := tc.ServerFunc(websocket.Handler(func(ws *websocket.Conn) {
 | 
				
			||||||
 | 
								defer ws.Close()
 | 
				
			||||||
 | 
								body := make([]byte, 5)
 | 
				
			||||||
 | 
								ws.Read(body)
 | 
				
			||||||
 | 
								ws.Write([]byte("hello " + string(body)))
 | 
				
			||||||
 | 
							}))
 | 
				
			||||||
 | 
							defer backendServer.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							serverURL, _ := url.Parse(backendServer.URL)
 | 
				
			||||||
 | 
							simpleStorage := &SimpleRESTStorage{
 | 
				
			||||||
 | 
								errors:                    map[string]error{},
 | 
				
			||||||
 | 
								resourceLocation:          serverURL,
 | 
				
			||||||
 | 
								resourceLocationTransport: tc.ProxyTransport,
 | 
				
			||||||
 | 
								expectedResourceNamespace: "myns",
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							namespaceHandler := handleNamespaced(map[string]rest.Storage{"foo": simpleStorage})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							server := httptest.NewServer(namespaceHandler)
 | 
				
			||||||
 | 
							defer server.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ws, err := websocket.Dial("ws://"+server.Listener.Addr().String()+"/api/version2/proxy/namespaces/myns/foo/123", "", "http://127.0.0.1/")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Errorf("%s: websocket dial err: %s", k, err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		defer ws.Close()
 | 
							defer ws.Close()
 | 
				
			||||||
		body := make([]byte, 5)
 | 
					 | 
				
			||||||
		ws.Read(body)
 | 
					 | 
				
			||||||
		ws.Write([]byte("hello " + string(body)))
 | 
					 | 
				
			||||||
	}))
 | 
					 | 
				
			||||||
	defer backendServer.Close()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serverURL, _ := url.Parse(backendServer.URL)
 | 
							if _, err := ws.Write([]byte("world")); err != nil {
 | 
				
			||||||
	simpleStorage := &SimpleRESTStorage{
 | 
								t.Errorf("%s: write err: %s", k, err)
 | 
				
			||||||
		errors:                    map[string]error{},
 | 
								continue
 | 
				
			||||||
		resourceLocation:          serverURL,
 | 
							}
 | 
				
			||||||
		expectedResourceNamespace: "myns",
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespaceHandler := handleNamespaced(map[string]rest.Storage{"foo": simpleStorage})
 | 
							response := make([]byte, 20)
 | 
				
			||||||
 | 
							n, err := ws.Read(response)
 | 
				
			||||||
	server := httptest.NewServer(namespaceHandler)
 | 
							if err != nil {
 | 
				
			||||||
	defer server.Close()
 | 
								t.Errorf("%s: read err: %s", k, err)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
	ws, err := websocket.Dial("ws://"+server.Listener.Addr().String()+"/api/version2/proxy/namespaces/myns/foo/123", "", "http://127.0.0.1/")
 | 
							}
 | 
				
			||||||
	if err != nil {
 | 
							if e, a := "hello world", string(response[0:n]); e != a {
 | 
				
			||||||
		t.Fatalf("websocket dial err: %s", err)
 | 
								t.Errorf("%s: expected '%#v', got '%#v'", k, e, a)
 | 
				
			||||||
	}
 | 
								continue
 | 
				
			||||||
	defer ws.Close()
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if _, err := ws.Write([]byte("world")); err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("write err: %s", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	response := make([]byte, 20)
 | 
					 | 
				
			||||||
	n, err := ws.Read(response)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("read err: %s", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if e, a := "hello world", string(response[0:n]); e != a {
 | 
					 | 
				
			||||||
		t.Fatalf("expected '%#v', got '%#v'", e, a)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -225,3 +281,50 @@ func TestRedirectOnMissingTrailingSlash(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// exampleCert was generated from crypto/tls/generate_cert.go with the following command:
 | 
				
			||||||
 | 
					//    go run generate_cert.go  --rsa-bits 512 --host example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
 | 
				
			||||||
 | 
					var exampleCert = []byte(`-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIBcjCCAR6gAwIBAgIQBOUTYowZaENkZi0faI9DgTALBgkqhkiG9w0BAQswEjEQ
 | 
				
			||||||
 | 
					MA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2MDAw
 | 
				
			||||||
 | 
					MFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCZ
 | 
				
			||||||
 | 
					xfR3sgeHBraGFfF/24tTn4PRVAHOf2UOOxSQRs+aYjNqimFqf/SRIblQgeXdBJDR
 | 
				
			||||||
 | 
					gVK5F1Js2zwlehw0bHxRAgMBAAGjUDBOMA4GA1UdDwEB/wQEAwIApDATBgNVHSUE
 | 
				
			||||||
 | 
					DDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBYGA1UdEQQPMA2CC2V4YW1w
 | 
				
			||||||
 | 
					bGUuY29tMAsGCSqGSIb3DQEBCwNBAI/mfBB8dm33IpUl+acSyWfL6gX5Wc0FFyVj
 | 
				
			||||||
 | 
					dKeesE1XBuPX1My/rzU6Oy/YwX7LOL4FaeNUS6bbL4axSLPKYSs=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var exampleKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
 | 
				
			||||||
 | 
					MIIBOgIBAAJBAJnF9HeyB4cGtoYV8X/bi1Ofg9FUAc5/ZQ47FJBGz5piM2qKYWp/
 | 
				
			||||||
 | 
					9JEhuVCB5d0EkNGBUrkXUmzbPCV6HDRsfFECAwEAAQJBAJLH9yPuButniACTn5L5
 | 
				
			||||||
 | 
					IJQw1mWQt6zBw9eCo41YWkA0866EgjC53aPZaRjXMp0uNJGdIsys2V5rCOOLWN2C
 | 
				
			||||||
 | 
					ODECIQDICHsi8QQQ9wpuJy8X5l8MAfxHL+DIqI84wQTeVM91FQIhAMTME8A18/7h
 | 
				
			||||||
 | 
					1Ad6drdnxAkuC0tX6Sx0LDozrmen+HFNAiAlcEDrt0RVkIcpOrg7tuhPLQf0oudl
 | 
				
			||||||
 | 
					Zvb3Xlj069awSQIgcT15E/43w2+RASifzVNhQ2MCTr1sSA8lL+xzK+REmnUCIBhQ
 | 
				
			||||||
 | 
					j4139pf8Re1J50zBxS/JlQfgDQi9sO9pYeiHIxNs
 | 
				
			||||||
 | 
					-----END RSA PRIVATE KEY-----`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// localhostCert was generated from crypto/tls/generate_cert.go with the following command:
 | 
				
			||||||
 | 
					//     go run generate_cert.go  --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
 | 
				
			||||||
 | 
					var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
 | 
				
			||||||
 | 
					bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
 | 
				
			||||||
 | 
					bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
 | 
				
			||||||
 | 
					IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
 | 
				
			||||||
 | 
					AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
 | 
				
			||||||
 | 
					EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
 | 
				
			||||||
 | 
					AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
 | 
				
			||||||
 | 
					Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// localhostKey is the private key for localhostCert.
 | 
				
			||||||
 | 
					var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
 | 
				
			||||||
 | 
					MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
 | 
				
			||||||
 | 
					0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
 | 
				
			||||||
 | 
					NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
 | 
				
			||||||
 | 
					AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
 | 
				
			||||||
 | 
					MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
 | 
				
			||||||
 | 
					EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
 | 
				
			||||||
 | 
					1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
 | 
				
			||||||
 | 
					-----END RSA PRIVATE KEY-----`)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -240,6 +240,11 @@ func (h *UpgradeAwareProxyHandler) dialURL() (net.Conn, error) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Return if we were configured to skip validation
 | 
				
			||||||
 | 
							if tlsConfig != nil && tlsConfig.InsecureSkipVerify {
 | 
				
			||||||
 | 
								return tlsConn, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Verify
 | 
							// Verify
 | 
				
			||||||
		host, _, _ := net.SplitHostPort(dialAddr)
 | 
							host, _, _ := net.SplitHostPort(dialAddr)
 | 
				
			||||||
		if err := tlsConn.VerifyHostname(host); err != nil {
 | 
							if err := tlsConn.VerifyHostname(host); err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,8 @@ package rest
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"crypto/x509"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
@@ -259,38 +261,88 @@ func TestServeHTTP(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestProxyUpgrade(t *testing.T) {
 | 
					func TestProxyUpgrade(t *testing.T) {
 | 
				
			||||||
	backendServer := httptest.NewServer(websocket.Handler(func(ws *websocket.Conn) {
 | 
					
 | 
				
			||||||
 | 
						localhostPool := x509.NewCertPool()
 | 
				
			||||||
 | 
						if !localhostPool.AppendCertsFromPEM(localhostCert) {
 | 
				
			||||||
 | 
							t.Errorf("error setting up localhostCert pool")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testcases := map[string]struct {
 | 
				
			||||||
 | 
							ServerFunc     func(http.Handler) *httptest.Server
 | 
				
			||||||
 | 
							ProxyTransport http.RoundTripper
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							"http": {
 | 
				
			||||||
 | 
								ServerFunc:     httptest.NewServer,
 | 
				
			||||||
 | 
								ProxyTransport: nil,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"https (invalid hostname + InsecureSkipVerify)": {
 | 
				
			||||||
 | 
								ServerFunc: func(h http.Handler) *httptest.Server {
 | 
				
			||||||
 | 
									cert, err := tls.X509KeyPair(exampleCert, exampleKey)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Errorf("https (invalid hostname): proxy_test: %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts := httptest.NewUnstartedServer(h)
 | 
				
			||||||
 | 
									ts.TLS = &tls.Config{
 | 
				
			||||||
 | 
										Certificates: []tls.Certificate{cert},
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts.StartTLS()
 | 
				
			||||||
 | 
									return ts
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								ProxyTransport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"https (valid hostname + RootCAs)": {
 | 
				
			||||||
 | 
								ServerFunc: func(h http.Handler) *httptest.Server {
 | 
				
			||||||
 | 
									cert, err := tls.X509KeyPair(localhostCert, localhostKey)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Errorf("https (valid hostname): proxy_test: %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts := httptest.NewUnstartedServer(h)
 | 
				
			||||||
 | 
									ts.TLS = &tls.Config{
 | 
				
			||||||
 | 
										Certificates: []tls.Certificate{cert},
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts.StartTLS()
 | 
				
			||||||
 | 
									return ts
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								ProxyTransport: &http.Transport{TLSClientConfig: &tls.Config{RootCAs: localhostPool}},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for k, tc := range testcases {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							backendServer := tc.ServerFunc(websocket.Handler(func(ws *websocket.Conn) {
 | 
				
			||||||
 | 
								defer ws.Close()
 | 
				
			||||||
 | 
								body := make([]byte, 5)
 | 
				
			||||||
 | 
								ws.Read(body)
 | 
				
			||||||
 | 
								ws.Write([]byte("hello " + string(body)))
 | 
				
			||||||
 | 
							}))
 | 
				
			||||||
 | 
							defer backendServer.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							serverURL, _ := url.Parse(backendServer.URL)
 | 
				
			||||||
 | 
							proxyHandler := &UpgradeAwareProxyHandler{
 | 
				
			||||||
 | 
								Location:  serverURL,
 | 
				
			||||||
 | 
								Transport: tc.ProxyTransport,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							proxy := httptest.NewServer(proxyHandler)
 | 
				
			||||||
 | 
							defer proxy.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ws, err := websocket.Dial("ws://"+proxy.Listener.Addr().String()+"/some/path", "", "http://127.0.0.1/")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatalf("%s: websocket dial err: %s", k, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		defer ws.Close()
 | 
							defer ws.Close()
 | 
				
			||||||
		body := make([]byte, 5)
 | 
					 | 
				
			||||||
		ws.Read(body)
 | 
					 | 
				
			||||||
		ws.Write([]byte("hello " + string(body)))
 | 
					 | 
				
			||||||
	}))
 | 
					 | 
				
			||||||
	defer backendServer.Close()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serverURL, _ := url.Parse(backendServer.URL)
 | 
							if _, err := ws.Write([]byte("world")); err != nil {
 | 
				
			||||||
	proxyHandler := &UpgradeAwareProxyHandler{
 | 
								t.Fatalf("%s: write err: %s", k, err)
 | 
				
			||||||
		Location: serverURL,
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	proxy := httptest.NewServer(proxyHandler)
 | 
					 | 
				
			||||||
	defer proxy.Close()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ws, err := websocket.Dial("ws://"+proxy.Listener.Addr().String()+"/some/path", "", "http://127.0.0.1/")
 | 
							response := make([]byte, 20)
 | 
				
			||||||
	if err != nil {
 | 
							n, err := ws.Read(response)
 | 
				
			||||||
		t.Fatalf("websocket dial err: %s", err)
 | 
							if err != nil {
 | 
				
			||||||
	}
 | 
								t.Fatalf("%s: read err: %s", k, err)
 | 
				
			||||||
	defer ws.Close()
 | 
							}
 | 
				
			||||||
 | 
							if e, a := "hello world", string(response[0:n]); e != a {
 | 
				
			||||||
	if _, err := ws.Write([]byte("world")); err != nil {
 | 
								t.Fatalf("%s: expected '%#v', got '%#v'", k, e, a)
 | 
				
			||||||
		t.Fatalf("write err: %s", err)
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	response := make([]byte, 20)
 | 
					 | 
				
			||||||
	n, err := ws.Read(response)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatalf("read err: %s", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if e, a := "hello world", string(response[0:n]); e != a {
 | 
					 | 
				
			||||||
		t.Fatalf("expected '%#v', got '%#v'", e, a)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -349,3 +401,50 @@ func TestDefaultProxyTransport(t *testing.T) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// exampleCert was generated from crypto/tls/generate_cert.go with the following command:
 | 
				
			||||||
 | 
					//    go run generate_cert.go  --rsa-bits 512 --host example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
 | 
				
			||||||
 | 
					var exampleCert = []byte(`-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIBcjCCAR6gAwIBAgIQBOUTYowZaENkZi0faI9DgTALBgkqhkiG9w0BAQswEjEQ
 | 
				
			||||||
 | 
					MA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2MDAw
 | 
				
			||||||
 | 
					MFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCZ
 | 
				
			||||||
 | 
					xfR3sgeHBraGFfF/24tTn4PRVAHOf2UOOxSQRs+aYjNqimFqf/SRIblQgeXdBJDR
 | 
				
			||||||
 | 
					gVK5F1Js2zwlehw0bHxRAgMBAAGjUDBOMA4GA1UdDwEB/wQEAwIApDATBgNVHSUE
 | 
				
			||||||
 | 
					DDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBYGA1UdEQQPMA2CC2V4YW1w
 | 
				
			||||||
 | 
					bGUuY29tMAsGCSqGSIb3DQEBCwNBAI/mfBB8dm33IpUl+acSyWfL6gX5Wc0FFyVj
 | 
				
			||||||
 | 
					dKeesE1XBuPX1My/rzU6Oy/YwX7LOL4FaeNUS6bbL4axSLPKYSs=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var exampleKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
 | 
				
			||||||
 | 
					MIIBOgIBAAJBAJnF9HeyB4cGtoYV8X/bi1Ofg9FUAc5/ZQ47FJBGz5piM2qKYWp/
 | 
				
			||||||
 | 
					9JEhuVCB5d0EkNGBUrkXUmzbPCV6HDRsfFECAwEAAQJBAJLH9yPuButniACTn5L5
 | 
				
			||||||
 | 
					IJQw1mWQt6zBw9eCo41YWkA0866EgjC53aPZaRjXMp0uNJGdIsys2V5rCOOLWN2C
 | 
				
			||||||
 | 
					ODECIQDICHsi8QQQ9wpuJy8X5l8MAfxHL+DIqI84wQTeVM91FQIhAMTME8A18/7h
 | 
				
			||||||
 | 
					1Ad6drdnxAkuC0tX6Sx0LDozrmen+HFNAiAlcEDrt0RVkIcpOrg7tuhPLQf0oudl
 | 
				
			||||||
 | 
					Zvb3Xlj069awSQIgcT15E/43w2+RASifzVNhQ2MCTr1sSA8lL+xzK+REmnUCIBhQ
 | 
				
			||||||
 | 
					j4139pf8Re1J50zBxS/JlQfgDQi9sO9pYeiHIxNs
 | 
				
			||||||
 | 
					-----END RSA PRIVATE KEY-----`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// localhostCert was generated from crypto/tls/generate_cert.go with the following command:
 | 
				
			||||||
 | 
					//     go run generate_cert.go  --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
 | 
				
			||||||
 | 
					var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
 | 
				
			||||||
 | 
					bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
 | 
				
			||||||
 | 
					bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
 | 
				
			||||||
 | 
					IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
 | 
				
			||||||
 | 
					AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
 | 
				
			||||||
 | 
					EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
 | 
				
			||||||
 | 
					AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
 | 
				
			||||||
 | 
					Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// localhostKey is the private key for localhostCert.
 | 
				
			||||||
 | 
					var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
 | 
				
			||||||
 | 
					MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
 | 
				
			||||||
 | 
					0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
 | 
				
			||||||
 | 
					NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
 | 
				
			||||||
 | 
					AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
 | 
				
			||||||
 | 
					MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
 | 
				
			||||||
 | 
					EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
 | 
				
			||||||
 | 
					1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
 | 
				
			||||||
 | 
					-----END RSA PRIVATE KEY-----`)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,11 @@ func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) {
 | 
				
			|||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Return if we were configured to skip validation
 | 
				
			||||||
 | 
						if s.tlsConfig != nil && s.tlsConfig.InsecureSkipVerify {
 | 
				
			||||||
 | 
							return conn, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	host, _, err := net.SplitHostPort(dialAddr)
 | 
						host, _, err := net.SplitHostPort(dialAddr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,64 +17,97 @@ limitations under the License.
 | 
				
			|||||||
package spdy
 | 
					package spdy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"crypto/rand"
 | 
					 | 
				
			||||||
	"crypto/rsa"
 | 
					 | 
				
			||||||
	"crypto/tls"
 | 
						"crypto/tls"
 | 
				
			||||||
	"crypto/x509"
 | 
						"crypto/x509"
 | 
				
			||||||
	"crypto/x509/pkix"
 | 
					 | 
				
			||||||
	"encoding/pem"
 | 
					 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"math/big"
 | 
					 | 
				
			||||||
	"net"
 | 
					 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"net/http/httptest"
 | 
						"net/http/httptest"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/util/httpstream"
 | 
						"k8s.io/kubernetes/pkg/util/httpstream"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRoundTripAndNewConnection(t *testing.T) {
 | 
					func TestRoundTripAndNewConnection(t *testing.T) {
 | 
				
			||||||
	testCases := []struct {
 | 
					
 | 
				
			||||||
 | 
						localhostPool := x509.NewCertPool()
 | 
				
			||||||
 | 
						if !localhostPool.AppendCertsFromPEM(localhostCert) {
 | 
				
			||||||
 | 
							t.Errorf("error setting up localhostCert pool")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						testCases := map[string]struct {
 | 
				
			||||||
 | 
							serverFunc             func(http.Handler) *httptest.Server
 | 
				
			||||||
 | 
							clientTLS              *tls.Config
 | 
				
			||||||
		serverConnectionHeader string
 | 
							serverConnectionHeader string
 | 
				
			||||||
		serverUpgradeHeader    string
 | 
							serverUpgradeHeader    string
 | 
				
			||||||
		useTLS                 bool
 | 
					 | 
				
			||||||
		shouldError            bool
 | 
							shouldError            bool
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							"no headers": {
 | 
				
			||||||
 | 
								serverFunc:             httptest.NewServer,
 | 
				
			||||||
			serverConnectionHeader: "",
 | 
								serverConnectionHeader: "",
 | 
				
			||||||
			serverUpgradeHeader:    "",
 | 
								serverUpgradeHeader:    "",
 | 
				
			||||||
			shouldError:            true,
 | 
								shouldError:            true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							"no upgrade header": {
 | 
				
			||||||
 | 
								serverFunc:             httptest.NewServer,
 | 
				
			||||||
			serverConnectionHeader: "Upgrade",
 | 
								serverConnectionHeader: "Upgrade",
 | 
				
			||||||
			serverUpgradeHeader:    "",
 | 
								serverUpgradeHeader:    "",
 | 
				
			||||||
			shouldError:            true,
 | 
								shouldError:            true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							"no connection header": {
 | 
				
			||||||
 | 
								serverFunc:             httptest.NewServer,
 | 
				
			||||||
			serverConnectionHeader: "",
 | 
								serverConnectionHeader: "",
 | 
				
			||||||
			serverUpgradeHeader:    "SPDY/3.1",
 | 
								serverUpgradeHeader:    "SPDY/3.1",
 | 
				
			||||||
			shouldError:            true,
 | 
								shouldError:            true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							"http": {
 | 
				
			||||||
 | 
								serverFunc:             httptest.NewServer,
 | 
				
			||||||
			serverConnectionHeader: "Upgrade",
 | 
								serverConnectionHeader: "Upgrade",
 | 
				
			||||||
			serverUpgradeHeader:    "SPDY/3.1",
 | 
								serverUpgradeHeader:    "SPDY/3.1",
 | 
				
			||||||
			shouldError:            false,
 | 
								shouldError:            false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							"https (invalid hostname + InsecureSkipVerify)": {
 | 
				
			||||||
 | 
								serverFunc: func(h http.Handler) *httptest.Server {
 | 
				
			||||||
 | 
									cert, err := tls.X509KeyPair(exampleCert, exampleKey)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Errorf("https (invalid hostname): proxy_test: %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts := httptest.NewUnstartedServer(h)
 | 
				
			||||||
 | 
									ts.TLS = &tls.Config{
 | 
				
			||||||
 | 
										Certificates: []tls.Certificate{cert},
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts.StartTLS()
 | 
				
			||||||
 | 
									return ts
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								clientTLS:              &tls.Config{InsecureSkipVerify: true},
 | 
				
			||||||
 | 
								serverConnectionHeader: "Upgrade",
 | 
				
			||||||
 | 
								serverUpgradeHeader:    "SPDY/3.1",
 | 
				
			||||||
 | 
								shouldError:            false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"https (valid hostname + RootCAs)": {
 | 
				
			||||||
 | 
								serverFunc: func(h http.Handler) *httptest.Server {
 | 
				
			||||||
 | 
									cert, err := tls.X509KeyPair(localhostCert, localhostKey)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Errorf("https (valid hostname): proxy_test: %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts := httptest.NewUnstartedServer(h)
 | 
				
			||||||
 | 
									ts.TLS = &tls.Config{
 | 
				
			||||||
 | 
										Certificates: []tls.Certificate{cert},
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									ts.StartTLS()
 | 
				
			||||||
 | 
									return ts
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								clientTLS:              &tls.Config{RootCAs: localhostPool},
 | 
				
			||||||
			serverConnectionHeader: "Upgrade",
 | 
								serverConnectionHeader: "Upgrade",
 | 
				
			||||||
			serverUpgradeHeader:    "SPDY/3.1",
 | 
								serverUpgradeHeader:    "SPDY/3.1",
 | 
				
			||||||
			useTLS:                 true,
 | 
					 | 
				
			||||||
			shouldError:            false,
 | 
								shouldError:            false,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i, testCase := range testCases {
 | 
						for k, testCase := range testCases {
 | 
				
			||||||
		server := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
							server := testCase.serverFunc(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
			if testCase.shouldError {
 | 
								if testCase.shouldError {
 | 
				
			||||||
				if e, a := httpstream.HeaderUpgrade, req.Header.Get(httpstream.HeaderConnection); e != a {
 | 
									if e, a := httpstream.HeaderUpgrade, req.Header.Get(httpstream.HeaderConnection); e != a {
 | 
				
			||||||
					t.Fatalf("%d: Expected connection=upgrade header, got '%s", i, a)
 | 
										t.Fatalf("%s: Expected connection=upgrade header, got '%s", k, a)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				w.Header().Set(httpstream.HeaderConnection, testCase.serverConnectionHeader)
 | 
									w.Header().Set(httpstream.HeaderConnection, testCase.serverConnectionHeader)
 | 
				
			||||||
@@ -92,102 +125,32 @@ func TestRoundTripAndNewConnection(t *testing.T) {
 | 
				
			|||||||
				return nil
 | 
									return nil
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			if spdyConn == nil {
 | 
								if spdyConn == nil {
 | 
				
			||||||
				t.Fatalf("%d: unexpected nil spdyConn", i)
 | 
									t.Fatalf("%s: unexpected nil spdyConn", k)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			defer spdyConn.Close()
 | 
								defer spdyConn.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			stream := <-streamCh
 | 
								stream := <-streamCh
 | 
				
			||||||
			io.Copy(stream, stream)
 | 
								io.Copy(stream, stream)
 | 
				
			||||||
		}))
 | 
							}))
 | 
				
			||||||
 | 
					 | 
				
			||||||
		clientTLS := &tls.Config{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if testCase.useTLS {
 | 
					 | 
				
			||||||
			privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				t.Fatalf("%d: error generating keypair: %s", i, err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			notBefore := time.Now()
 | 
					 | 
				
			||||||
			notAfter := notBefore.Add(1 * time.Hour)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			template := x509.Certificate{
 | 
					 | 
				
			||||||
				SerialNumber: big.NewInt(1),
 | 
					 | 
				
			||||||
				Subject: pkix.Name{
 | 
					 | 
				
			||||||
					Organization: []string{"Localhost Co"},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				NotBefore:             notBefore,
 | 
					 | 
				
			||||||
				NotAfter:              notAfter,
 | 
					 | 
				
			||||||
				KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
 | 
					 | 
				
			||||||
				ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 | 
					 | 
				
			||||||
				BasicConstraintsValid: true,
 | 
					 | 
				
			||||||
				IsCA: true,
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			host := "127.0.0.1"
 | 
					 | 
				
			||||||
			if ip := net.ParseIP(host); ip != nil {
 | 
					 | 
				
			||||||
				template.IPAddresses = append(template.IPAddresses, ip)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			template.DNSNames = append(template.DNSNames, host)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				t.Fatalf("%d: error creating cert: %s", i, err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			cert, err := x509.ParseCertificate(derBytes)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				t.Fatalf("%d: error parsing cert: %s", i, err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			roots := x509.NewCertPool()
 | 
					 | 
				
			||||||
			roots.AddCert(cert)
 | 
					 | 
				
			||||||
			server.TLS = &tls.Config{
 | 
					 | 
				
			||||||
				RootCAs: roots,
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			clientTLS.RootCAs = roots
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			certBuf := bytes.Buffer{}
 | 
					 | 
				
			||||||
			err = pem.Encode(&certBuf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				t.Fatalf("%d: error encoding cert: %s", i, err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			keyBuf := bytes.Buffer{}
 | 
					 | 
				
			||||||
			err = pem.Encode(&keyBuf, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)})
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				t.Fatalf("%d: error encoding key: %s", i, err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			tlsCert, err := tls.X509KeyPair(certBuf.Bytes(), keyBuf.Bytes())
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				t.Fatalf("%d: error calling tls.X509KeyPair: %s", i, err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			server.TLS.Certificates = []tls.Certificate{tlsCert}
 | 
					 | 
				
			||||||
			clientTLS.Certificates = []tls.Certificate{tlsCert}
 | 
					 | 
				
			||||||
			server.StartTLS()
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			server.Start()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		defer server.Close()
 | 
							defer server.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		req, err := http.NewRequest("GET", server.URL, nil)
 | 
							req, err := http.NewRequest("GET", server.URL, nil)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			t.Fatalf("%d: Error creating request: %s", i, err)
 | 
								t.Fatalf("%s: Error creating request: %s", k, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		spdyTransport := NewRoundTripper(clientTLS)
 | 
							spdyTransport := NewRoundTripper(testCase.clientTLS)
 | 
				
			||||||
		client := &http.Client{Transport: spdyTransport}
 | 
							client := &http.Client{Transport: spdyTransport}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		resp, err := client.Do(req)
 | 
							resp, err := client.Do(req)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			t.Fatalf("%d: unexpected error from client.Do: %s", i, err)
 | 
								t.Fatalf("%s: unexpected error from client.Do: %s", k, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		conn, err := spdyTransport.NewConnection(resp)
 | 
							conn, err := spdyTransport.NewConnection(resp)
 | 
				
			||||||
		haveErr := err != nil
 | 
							haveErr := err != nil
 | 
				
			||||||
		if e, a := testCase.shouldError, haveErr; e != a {
 | 
							if e, a := testCase.shouldError, haveErr; e != a {
 | 
				
			||||||
			t.Fatalf("%d: shouldError=%t, got %t: %v", i, e, a, err)
 | 
								t.Fatalf("%s: shouldError=%t, got %t: %v", k, e, a, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if testCase.shouldError {
 | 
							if testCase.shouldError {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
@@ -195,32 +158,79 @@ func TestRoundTripAndNewConnection(t *testing.T) {
 | 
				
			|||||||
		defer conn.Close()
 | 
							defer conn.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if resp.StatusCode != http.StatusSwitchingProtocols {
 | 
							if resp.StatusCode != http.StatusSwitchingProtocols {
 | 
				
			||||||
			t.Fatalf("%d: expected http 101 switching protocols, got %d", i, resp.StatusCode)
 | 
								t.Fatalf("%s: expected http 101 switching protocols, got %d", k, resp.StatusCode)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		stream, err := conn.CreateStream(http.Header{})
 | 
							stream, err := conn.CreateStream(http.Header{})
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			t.Fatalf("%d: error creating client stream: %s", i, err)
 | 
								t.Fatalf("%s: error creating client stream: %s", k, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		n, err := stream.Write([]byte("hello"))
 | 
							n, err := stream.Write([]byte("hello"))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			t.Fatalf("%d: error writing to stream: %s", i, err)
 | 
								t.Fatalf("%s: error writing to stream: %s", k, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if n != 5 {
 | 
							if n != 5 {
 | 
				
			||||||
			t.Fatalf("%d: Expected to write 5 bytes, but actually wrote %d", i, n)
 | 
								t.Fatalf("%s: Expected to write 5 bytes, but actually wrote %d", k, n)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		b := make([]byte, 5)
 | 
							b := make([]byte, 5)
 | 
				
			||||||
		n, err = stream.Read(b)
 | 
							n, err = stream.Read(b)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			t.Fatalf("%d: error reading from stream: %s", i, err)
 | 
								t.Fatalf("%s: error reading from stream: %s", k, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if n != 5 {
 | 
							if n != 5 {
 | 
				
			||||||
			t.Fatalf("%d: Expected to read 5 bytes, but actually read %d", i, n)
 | 
								t.Fatalf("%s: Expected to read 5 bytes, but actually read %d", k, n)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if e, a := "hello", string(b[0:n]); e != a {
 | 
							if e, a := "hello", string(b[0:n]); e != a {
 | 
				
			||||||
			t.Fatalf("%d: expected '%s', got '%s'", i, e, a)
 | 
								t.Fatalf("%s: expected '%s', got '%s'", k, e, a)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// exampleCert was generated from crypto/tls/generate_cert.go with the following command:
 | 
				
			||||||
 | 
					//    go run generate_cert.go  --rsa-bits 512 --host example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
 | 
				
			||||||
 | 
					var exampleCert = []byte(`-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIBcjCCAR6gAwIBAgIQBOUTYowZaENkZi0faI9DgTALBgkqhkiG9w0BAQswEjEQ
 | 
				
			||||||
 | 
					MA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2MDAw
 | 
				
			||||||
 | 
					MFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCZ
 | 
				
			||||||
 | 
					xfR3sgeHBraGFfF/24tTn4PRVAHOf2UOOxSQRs+aYjNqimFqf/SRIblQgeXdBJDR
 | 
				
			||||||
 | 
					gVK5F1Js2zwlehw0bHxRAgMBAAGjUDBOMA4GA1UdDwEB/wQEAwIApDATBgNVHSUE
 | 
				
			||||||
 | 
					DDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBYGA1UdEQQPMA2CC2V4YW1w
 | 
				
			||||||
 | 
					bGUuY29tMAsGCSqGSIb3DQEBCwNBAI/mfBB8dm33IpUl+acSyWfL6gX5Wc0FFyVj
 | 
				
			||||||
 | 
					dKeesE1XBuPX1My/rzU6Oy/YwX7LOL4FaeNUS6bbL4axSLPKYSs=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var exampleKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
 | 
				
			||||||
 | 
					MIIBOgIBAAJBAJnF9HeyB4cGtoYV8X/bi1Ofg9FUAc5/ZQ47FJBGz5piM2qKYWp/
 | 
				
			||||||
 | 
					9JEhuVCB5d0EkNGBUrkXUmzbPCV6HDRsfFECAwEAAQJBAJLH9yPuButniACTn5L5
 | 
				
			||||||
 | 
					IJQw1mWQt6zBw9eCo41YWkA0866EgjC53aPZaRjXMp0uNJGdIsys2V5rCOOLWN2C
 | 
				
			||||||
 | 
					ODECIQDICHsi8QQQ9wpuJy8X5l8MAfxHL+DIqI84wQTeVM91FQIhAMTME8A18/7h
 | 
				
			||||||
 | 
					1Ad6drdnxAkuC0tX6Sx0LDozrmen+HFNAiAlcEDrt0RVkIcpOrg7tuhPLQf0oudl
 | 
				
			||||||
 | 
					Zvb3Xlj069awSQIgcT15E/43w2+RASifzVNhQ2MCTr1sSA8lL+xzK+REmnUCIBhQ
 | 
				
			||||||
 | 
					j4139pf8Re1J50zBxS/JlQfgDQi9sO9pYeiHIxNs
 | 
				
			||||||
 | 
					-----END RSA PRIVATE KEY-----`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// localhostCert was generated from crypto/tls/generate_cert.go with the following command:
 | 
				
			||||||
 | 
					//     go run generate_cert.go  --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
 | 
				
			||||||
 | 
					var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
 | 
				
			||||||
 | 
					bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
 | 
				
			||||||
 | 
					bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
 | 
				
			||||||
 | 
					IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
 | 
				
			||||||
 | 
					AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
 | 
				
			||||||
 | 
					EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
 | 
				
			||||||
 | 
					AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
 | 
				
			||||||
 | 
					Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// localhostKey is the private key for localhostCert.
 | 
				
			||||||
 | 
					var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
 | 
				
			||||||
 | 
					MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
 | 
				
			||||||
 | 
					0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
 | 
				
			||||||
 | 
					NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
 | 
				
			||||||
 | 
					AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
 | 
				
			||||||
 | 
					MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
 | 
				
			||||||
 | 
					EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
 | 
				
			||||||
 | 
					1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
 | 
				
			||||||
 | 
					-----END RSA PRIVATE KEY-----`)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user