github.com/Tyktechnologies/tyk@v2.9.5+incompatible/gateway/cert_go1.10_test.go (about)

     1  // +build go1.10
     2  
     3  package gateway
     4  
     5  import (
     6  	"crypto/tls"
     7  	"crypto/x509"
     8  	"crypto/x509/pkix"
     9  	"encoding/pem"
    10  	"errors"
    11  	"fmt"
    12  
    13  	//	"net"
    14  	"net/http"
    15  	"net/http/httptest"
    16  	"strings"
    17  	"testing"
    18  
    19  	"github.com/TykTechnologies/tyk/certs"
    20  	"github.com/TykTechnologies/tyk/config"
    21  	"github.com/TykTechnologies/tyk/test"
    22  )
    23  
    24  func uploadCertPublicKey(serverCert tls.Certificate) (string, error) {
    25  	x509Cert, _ := x509.ParseCertificate(serverCert.Certificate[0])
    26  	pubDer, _ := x509.MarshalPKIXPublicKey(x509Cert.PublicKey)
    27  	pubPem := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: pubDer})
    28  	pubID, _ := CertificateManager.Add(pubPem, "")
    29  
    30  	if pubID != certs.HexSHA256(pubDer) {
    31  		errStr := fmt.Sprintf("certmanager returned wrong pub key fingerprint: %s %s", certs.HexSHA256(pubDer), pubID)
    32  		return "", errors.New(errStr)
    33  	}
    34  
    35  	return pubID, nil
    36  }
    37  
    38  func TestPublicKeyPinning(t *testing.T) {
    39  	_, _, _, serverCert := genServerCertificate()
    40  	pubID, err := uploadCertPublicKey(serverCert)
    41  	if err != nil {
    42  		t.Error(err)
    43  	}
    44  	defer CertificateManager.Delete(pubID, "")
    45  
    46  	upstream := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    47  	}))
    48  	upstream.TLS = &tls.Config{
    49  		InsecureSkipVerify: true,
    50  		Certificates:       []tls.Certificate{serverCert},
    51  	}
    52  
    53  	upstream.StartTLS()
    54  	defer upstream.Close()
    55  
    56  	t.Run("Pub key match", func(t *testing.T) {
    57  		globalConf := config.Global()
    58  		// For host using pinning, it should ignore standard verification in all cases, e.g setting variable below does nothing
    59  		globalConf.ProxySSLInsecureSkipVerify = false
    60  		config.SetGlobal(globalConf)
    61  		defer ResetTestConfig()
    62  
    63  		ts := StartTest()
    64  		defer ts.Close()
    65  
    66  		BuildAndLoadAPI(func(spec *APISpec) {
    67  			spec.Proxy.ListenPath = "/"
    68  			spec.PinnedPublicKeys = map[string]string{"127.0.0.1": pubID}
    69  			spec.Proxy.TargetURL = upstream.URL
    70  		})
    71  
    72  		ts.Run(t, test.TestCase{Code: 200})
    73  	})
    74  
    75  	t.Run("Pub key not match", func(t *testing.T) {
    76  		ts := StartTest()
    77  		defer ts.Close()
    78  
    79  		BuildAndLoadAPI(func(spec *APISpec) {
    80  			spec.Proxy.ListenPath = "/"
    81  			spec.PinnedPublicKeys = map[string]string{"127.0.0.1": "wrong"}
    82  			spec.Proxy.TargetURL = upstream.URL
    83  		})
    84  
    85  		ts.Run(t, test.TestCase{Code: 500})
    86  	})
    87  
    88  	t.Run("Global setting", func(t *testing.T) {
    89  		globalConf := config.Global()
    90  		globalConf.Security.PinnedPublicKeys = map[string]string{"127.0.0.1": "wrong"}
    91  		config.SetGlobal(globalConf)
    92  		defer ResetTestConfig()
    93  
    94  		ts := StartTest()
    95  		defer ts.Close()
    96  
    97  		BuildAndLoadAPI(func(spec *APISpec) {
    98  			spec.Proxy.ListenPath = "/"
    99  			spec.Proxy.TargetURL = upstream.URL
   100  		})
   101  
   102  		ts.Run(t, test.TestCase{Code: 500})
   103  	})
   104  
   105  	t.Run("Though proxy", func(t *testing.T) {
   106  		_, _, _, proxyCert := genServerCertificate()
   107  		proxy := initProxy("https", &tls.Config{
   108  			Certificates: []tls.Certificate{proxyCert},
   109  		})
   110  
   111  		globalConf := config.Global()
   112  		globalConf.ProxySSLInsecureSkipVerify = true
   113  		config.SetGlobal(globalConf)
   114  		defer ResetTestConfig()
   115  
   116  		defer proxy.Stop()
   117  
   118  		ts := StartTest()
   119  		defer ts.Close()
   120  
   121  		BuildAndLoadAPI(func(spec *APISpec) {
   122  			spec.Proxy.ListenPath = "/"
   123  			spec.Proxy.TargetURL = upstream.URL
   124  			spec.Proxy.Transport.ProxyURL = proxy.URL
   125  			spec.PinnedPublicKeys = map[string]string{"*": "wrong"}
   126  		})
   127  
   128  		ts.Run(t, test.TestCase{Code: 500})
   129  	})
   130  
   131  	t.Run("Enable Common Name check", func(t *testing.T) {
   132  		// start upstream server
   133  		_, _, _, serverCert := genCertificate(&x509.Certificate{
   134  			EmailAddresses: []string{"test@test.com"},
   135  			Subject:        pkix.Name{CommonName: "localhost"},
   136  		})
   137  		serverPubID, err := uploadCertPublicKey(serverCert)
   138  		if err != nil {
   139  			t.Error(err)
   140  		}
   141  		defer CertificateManager.Delete(serverPubID, "")
   142  
   143  		upstream := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   144  		}))
   145  		upstream.TLS = &tls.Config{
   146  			InsecureSkipVerify: true,
   147  			Certificates:       []tls.Certificate{serverCert},
   148  		}
   149  
   150  		upstream.StartTLS()
   151  		defer upstream.Close()
   152  
   153  		// start proxy
   154  		_, _, _, proxyCert := genCertificate(&x509.Certificate{
   155  			Subject: pkix.Name{CommonName: "local1.host"},
   156  		})
   157  		proxyPubID, err := uploadCertPublicKey(proxyCert)
   158  		if err != nil {
   159  			t.Error(err)
   160  		}
   161  		defer CertificateManager.Delete(proxyPubID, "")
   162  
   163  		proxy := initProxy("http", &tls.Config{
   164  			Certificates: []tls.Certificate{proxyCert},
   165  		})
   166  		defer proxy.Stop()
   167  
   168  		globalConf := config.Global()
   169  		globalConf.SSLForceCommonNameCheck = true
   170  		globalConf.ProxySSLInsecureSkipVerify = true
   171  		config.SetGlobal(globalConf)
   172  		defer ResetTestConfig()
   173  
   174  		ts := StartTest()
   175  		defer ts.Close()
   176  
   177  		pubKeys := fmt.Sprintf("%s,%s", serverPubID, proxyPubID)
   178  		upstream.URL = strings.Replace(upstream.URL, "127.0.0.1", "localhost", 1)
   179  		proxy.URL = strings.Replace(proxy.URL, "127.0.0.1", "local1.host", 1)
   180  
   181  		BuildAndLoadAPI([]func(spec *APISpec){func(spec *APISpec) {
   182  			spec.Proxy.ListenPath = "/valid"
   183  			spec.Proxy.TargetURL = upstream.URL
   184  			spec.Proxy.Transport.ProxyURL = proxy.URL
   185  			spec.PinnedPublicKeys = map[string]string{"*": pubKeys}
   186  		},
   187  			func(spec *APISpec) {
   188  				spec.Proxy.ListenPath = "/invalid"
   189  				spec.Proxy.TargetURL = upstream.URL
   190  				spec.Proxy.Transport.ProxyURL = proxy.URL
   191  				spec.PinnedPublicKeys = map[string]string{"*": "wrong"}
   192  			}}...)
   193  
   194  		ts.Run(t, []test.TestCase{
   195  			{Code: 200, Path: "/valid"},
   196  			{Code: 500, Path: "/invalid"},
   197  		}...)
   198  	})
   199  }
   200  
   201  func TestProxyTransport(t *testing.T) {
   202  	upstream := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   203  		w.Write([]byte("test"))
   204  	}))
   205  	defer upstream.Close()
   206  
   207  	defer ResetTestConfig()
   208  
   209  	ts := StartTest()
   210  	defer ts.Close()
   211  
   212  	//matching ciphers
   213  	t.Run("Global: Cipher match", func(t *testing.T) {
   214  		globalConf := config.Global()
   215  		globalConf.ProxySSLInsecureSkipVerify = true
   216  		// force creating new transport on each reque
   217  		globalConf.MaxConnTime = -1
   218  
   219  		globalConf.ProxySSLCipherSuites = []string{"TLS_RSA_WITH_AES_128_CBC_SHA"}
   220  		config.SetGlobal(globalConf)
   221  		BuildAndLoadAPI(func(spec *APISpec) {
   222  			spec.Proxy.ListenPath = "/"
   223  			spec.Proxy.TargetURL = upstream.URL
   224  		})
   225  		ts.Run(t, test.TestCase{Path: "/", Code: 200})
   226  	})
   227  
   228  	t.Run("Global: Cipher not match", func(t *testing.T) {
   229  		globalConf := config.Global()
   230  		globalConf.ProxySSLInsecureSkipVerify = true
   231  		// force creating new transport on each reque
   232  		globalConf.MaxConnTime = -1
   233  
   234  		globalConf.ProxySSLCipherSuites = []string{"TLS_RSA_WITH_RC4_128_SHA"}
   235  		config.SetGlobal(globalConf)
   236  		BuildAndLoadAPI(func(spec *APISpec) {
   237  			spec.Proxy.ListenPath = "/"
   238  			spec.Proxy.TargetURL = upstream.URL
   239  		})
   240  		ts.Run(t, test.TestCase{Path: "/", Code: 500})
   241  	})
   242  
   243  	t.Run("API: Cipher override", func(t *testing.T) {
   244  		globalConf := config.Global()
   245  		globalConf.ProxySSLInsecureSkipVerify = true
   246  		// force creating new transport on each reque
   247  		globalConf.MaxConnTime = -1
   248  
   249  		globalConf.ProxySSLCipherSuites = []string{"TLS_RSA_WITH_RC4_128_SHA"}
   250  		config.SetGlobal(globalConf)
   251  		BuildAndLoadAPI(func(spec *APISpec) {
   252  			spec.Proxy.ListenPath = "/"
   253  			spec.Proxy.TargetURL = upstream.URL
   254  			spec.Proxy.Transport.SSLCipherSuites = []string{"TLS_RSA_WITH_AES_128_CBC_SHA"}
   255  		})
   256  
   257  		ts.Run(t, test.TestCase{Path: "/", Code: 200})
   258  	})
   259  
   260  	t.Run("API: MinTLS not match", func(t *testing.T) {
   261  		globalConf := config.Global()
   262  		globalConf.ProxySSLInsecureSkipVerify = true
   263  		// force creating new transport on each reque
   264  		globalConf.MaxConnTime = -1
   265  
   266  		globalConf.ProxySSLMinVersion = 772
   267  		config.SetGlobal(globalConf)
   268  		BuildAndLoadAPI(func(spec *APISpec) {
   269  			spec.Proxy.ListenPath = "/"
   270  			spec.Proxy.TargetURL = upstream.URL
   271  			spec.Proxy.Transport.SSLCipherSuites = []string{"TLS_RSA_WITH_AES_128_CBC_SHA"}
   272  		})
   273  
   274  		ts.Run(t, test.TestCase{Path: "/", Code: 500})
   275  	})
   276  
   277  	t.Run("API: Invalid proxy", func(t *testing.T) {
   278  		globalConf := config.Global()
   279  		globalConf.ProxySSLInsecureSkipVerify = true
   280  		// force creating new transport on each reque
   281  		globalConf.MaxConnTime = -1
   282  
   283  		globalConf.ProxySSLMinVersion = 771
   284  		config.SetGlobal(globalConf)
   285  		BuildAndLoadAPI(func(spec *APISpec) {
   286  			spec.Proxy.ListenPath = "/"
   287  			spec.Proxy.TargetURL = upstream.URL
   288  			spec.Proxy.Transport.SSLCipherSuites = []string{"TLS_RSA_WITH_AES_128_CBC_SHA"}
   289  			// Invalid proxy
   290  			spec.Proxy.Transport.ProxyURL = upstream.URL
   291  		})
   292  
   293  		ts.Run(t, test.TestCase{Path: "/", Code: 500})
   294  	})
   295  
   296  	t.Run("API: Valid proxy", func(t *testing.T) {
   297  		globalConf := config.Global()
   298  		globalConf.ProxySSLInsecureSkipVerify = true
   299  		// force creating new transport on each reque
   300  		globalConf.MaxConnTime = -1
   301  
   302  		globalConf.ProxySSLMinVersion = 771
   303  		config.SetGlobal(globalConf)
   304  
   305  		_, _, _, proxyCert := genServerCertificate()
   306  		proxy := initProxy("https", &tls.Config{
   307  			Certificates: []tls.Certificate{proxyCert},
   308  		})
   309  		defer proxy.Stop()
   310  
   311  		BuildAndLoadAPI(func(spec *APISpec) {
   312  			spec.Proxy.ListenPath = "/"
   313  			spec.Proxy.Transport.SSLCipherSuites = []string{"TLS_RSA_WITH_AES_128_CBC_SHA"}
   314  			spec.Proxy.Transport.ProxyURL = proxy.URL
   315  		})
   316  
   317  		client := GetTLSClient(nil, nil)
   318  		client.Transport = &http.Transport{
   319  			TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
   320  		}
   321  		ts.Run(t, test.TestCase{Path: "/", Code: 200, Client: client})
   322  	})
   323  }