func TestTLSConnection(t *testing.T) { srv, opts := RunServerWithConfig("./configs/tls.conf") defer srv.Shutdown() endpoint := fmt.Sprintf("%s:%d", opts.Host, opts.Port) nurl := fmt.Sprintf("tls://%s:%s@%s/", opts.Username, opts.Password, endpoint) nc, err := nats.Connect(nurl) if err == nil { t.Fatalf("Expected error trying to connect to secure server") } // Do simple SecureConnect nc, err = nats.Connect(fmt.Sprintf("tls://%s/", endpoint)) if err == nil { t.Fatalf("Expected error trying to connect to secure server with no auth") } // Now do more advanced checking, verifying servername and using rootCA. nc, err = nats.Connect(nurl, nats.RootCAs("./configs/certs/ca.pem")) if err != nil { t.Fatalf("Got an error on Connect with Secure Options: %+v\n", err) } defer nc.Close() subj := "foo-tls" sub, _ := nc.SubscribeSync(subj) nc.Publish(subj, []byte("We are Secure!")) nc.Flush() nmsgs, _ := sub.QueuedMsgs() if nmsgs != 1 { t.Fatalf("Expected to receive a message over the TLS connection") } }
func stressConnect(t *testing.T, wg *sync.WaitGroup, errCh chan error, url string, index int) { defer wg.Done() subName := fmt.Sprintf("foo.%d", index) for i := 0; i < 100; i++ { nc, err := nats.Connect(url, nats.RootCAs("./configs/certs/ca.pem")) if err != nil { errCh <- fmt.Errorf("Unable to create TLS connection: %v\n", err) return } defer nc.Close() sub, err := nc.SubscribeSync(subName) if err != nil { errCh <- fmt.Errorf("Unable to subscribe on '%s': %v\n", subName, err) return } if err := nc.Publish(subName, []byte("secure data")); err != nil { errCh <- fmt.Errorf("Unable to send on '%s': %v\n", subName, err) } if _, err := sub.NextMsg(2 * time.Second); err != nil { errCh <- fmt.Errorf("Unable to get next message: %v\n", err) } nc.Close() } errCh <- nil }
func TestServerTLSHintConnections(t *testing.T) { s, opts := RunServerWithConfig("./configs/tls.conf") defer s.Shutdown() endpoint := fmt.Sprintf("%s:%d", opts.Host, opts.Port) secureURL := fmt.Sprintf("tls://%s:%s@%s/", opts.Username, opts.Password, endpoint) nc, err := nats.Connect(secureURL, nats.RootCAs("./configs/certs/badca.pem")) if err == nil { t.Fatal("Expected an error from bad RootCA file") } nc, err = nats.Connect(secureURL, nats.RootCAs("./configs/certs/ca.pem")) if err != nil { t.Fatal("Failed to create secure (TLS) connection", err) } defer nc.Close() }
func TestTLSBadAuthError(t *testing.T) { srv, opts := RunServerWithConfig("./configs/tls.conf") defer srv.Shutdown() endpoint := fmt.Sprintf("%s:%d", opts.Host, opts.Port) nurl := fmt.Sprintf("tls://%s:%s@%s/", opts.Username, "NOT_THE_PASSWORD", endpoint) _, err := nats.Connect(nurl, nats.RootCAs("./configs/certs/ca.pem")) if err == nil { t.Fatalf("Expected error trying to connect to secure server") } if err.Error() != nats.ErrAuthorization.Error() { t.Fatalf("Excpected and auth violation, got %v\n", err) } }
func (cc *certConfig) certLoad() error { if !FileExists(cc.certPath) { return fmt.Errorf("certLoad: path '%s' does not exist", cc.certPath) } if !FileExists(cc.keyPath) { return fmt.Errorf("certLoad: path '%s' does not exist", cc.keyPath) } if !FileExists(cc.caPath) { return fmt.Errorf("certLoad: path '%s' does not exist", cc.caPath) } cert, err := tls.LoadX509KeyPair(cc.certPath, cc.keyPath) if err != nil { return fmt.Errorf("certLoad: error parsing X509 cert='%s'/key='%s', error was: '%v'", cc.certPath, cc.keyPath, err) } cc.cert = cert // nats.RootCA will do repeat this, but we detect failure earlier // this way and don't bother proceeding down the whole state sequence. pool := x509.NewCertPool() rootPEM, err := ioutil.ReadFile(cc.caPath) if err != nil || rootPEM == nil { err = fmt.Errorf("certLoad: error loading "+ "rootCA file '%s': %v", cc.caPath, err) return err } ok := pool.AppendCertsFromPEM([]byte(rootPEM)) if !ok { return fmt.Errorf("certLoad: failed to parse root certificate from %q", cc.caPath) } cc.rootCA = nats.RootCAs(cc.caPath) cc.tlsConfig = tls.Config{ Certificates: []tls.Certificate{cc.cert}, MinVersion: tls.VersionTLS12, } return nil }
func TestClientCertificate(t *testing.T) { s, opts := RunServerWithConfig("./configs/tlsverify.conf") defer s.Shutdown() endpoint := fmt.Sprintf("%s:%d", opts.Host, opts.Port) secureURL := fmt.Sprintf("nats://%s", endpoint) // Make sure this fails nc, err := nats.Connect(secureURL, nats.Secure()) if err == nil { nc.Close() t.Fatal("Sould have failed (TLS) connection without client certificate") } // Check parameters validity nc, err = nats.Connect(secureURL, nats.ClientCert("", "")) if err == nil { nc.Close() t.Fatal("Sould have failed due to invalid parameters") } // Should fail because wrong key nc, err = nats.Connect(secureURL, nats.ClientCert("./configs/certs/client-cert.pem", "./configs/certs/key.pem")) if err == nil { nc.Close() t.Fatal("Sould have failed due to invalid key") } // Should fail because no CA nc, err = nats.Connect(secureURL, nats.ClientCert("./configs/certs/client-cert.pem", "./configs/certs/client-key.pem")) if err == nil { nc.Close() t.Fatal("Sould have failed due to missing ca") } nc, err = nats.Connect(secureURL, nats.RootCAs("./configs/certs/ca.pem"), nats.ClientCert("./configs/certs/client-cert.pem", "./configs/certs/client-key.pem")) if err != nil { t.Fatalf("Failed to create (TLS) connection: %v", err) } defer nc.Close() omsg := []byte("Hello!") checkRecv := make(chan bool) received := 0 nc.Subscribe("foo", func(m *nats.Msg) { received += 1 if !bytes.Equal(m.Data, omsg) { t.Fatal("Message received does not match") } checkRecv <- true }) err = nc.Publish("foo", omsg) if err != nil { t.Fatalf("Failed to publish on secure (TLS) connection: %v", err) } nc.Flush() if err := Wait(checkRecv); err != nil { t.Fatal("Failed to receive message") } }
func TestTLSConnz(t *testing.T) { srv, opts := RunServerWithConfig("./configs/tls.conf") defer srv.Shutdown() rootCAFile := "./configs/certs/ca.pem" clientCertFile := "./configs/certs/client-cert.pem" clientKeyFile := "./configs/certs/client-key.pem" // Test with secure connection endpoint := fmt.Sprintf("%s:%d", opts.Host, opts.Port) nurl := fmt.Sprintf("tls://%s:%s@%s/", opts.Username, opts.Password, endpoint) nc, err := nats.Connect(nurl, nats.RootCAs(rootCAFile)) if err != nil { t.Fatalf("Got an error on Connect with Secure Options: %+v\n", err) } defer nc.Close() ch := make(chan struct{}) nc.Subscribe("foo", func(m *nats.Msg) { ch <- struct{}{} }) nc.Publish("foo", []byte("Hello")) // Wait for message <-ch url := fmt.Sprintf("https://localhost:%d/", opts.HTTPSPort) tlsConfig := &tls.Config{} caCert, err := ioutil.ReadFile(rootCAFile) if err != nil { t.Fatalf("Got error reading RootCA file: %s", err) } caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) tlsConfig.RootCAs = caCertPool cert, err := tls.LoadX509KeyPair(clientCertFile, clientKeyFile) if err != nil { t.Fatalf("Got error reading client certificates: %s", err) } tlsConfig.Certificates = []tls.Certificate{cert} transport := &http.Transport{TLSClientConfig: tlsConfig} httpClient := &http.Client{Transport: transport} resp, err := httpClient.Get(url + "connz") if err != nil { t.Fatalf("Expected no error: Got %v\n", err) } if resp.StatusCode != 200 { t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { t.Fatalf("Got an error reading the body: %v\n", err) } c := server.Connz{} if err := json.Unmarshal(body, &c); err != nil { t.Fatalf("Got an error unmarshalling the body: %v\n", err) } if c.NumConns != 1 { t.Fatalf("Expected 1 connections, got %d\n", c.NumConns) } if c.Conns == nil || len(c.Conns) != 1 { t.Fatalf("Expected 1 connections in array, got %d\n", len(c.Conns)) } // Test inside details of each connection ci := c.Conns[0] if ci.Cid == 0 { t.Fatalf("Expected non-zero cid, got %v\n", ci.Cid) } if ci.IP != "127.0.0.1" { t.Fatalf("Expected \"127.0.0.1\" for IP, got %v\n", ci.IP) } if ci.Port == 0 { t.Fatalf("Expected non-zero port, got %v\n", ci.Port) } if ci.NumSubs != 1 { t.Fatalf("Expected num_subs of 1, got %v\n", ci.NumSubs) } if len(ci.Subs) != 0 { t.Fatalf("Expected subs of 0, got %v\n", ci.Subs) } if ci.InMsgs != 1 { t.Fatalf("Expected InMsgs of 1, got %v\n", ci.InMsgs) } if ci.OutMsgs != 1 { t.Fatalf("Expected OutMsgs of 1, got %v\n", ci.OutMsgs) } if ci.InBytes != 5 { t.Fatalf("Expected InBytes of 1, got %v\n", ci.InBytes) } if ci.OutBytes != 5 { t.Fatalf("Expected OutBytes of 1, got %v\n", ci.OutBytes) } if ci.Start.IsZero() { t.Fatalf("Expected Start to be valid\n") } if ci.Uptime == "" { t.Fatalf("Expected Uptime to be valid\n") } if ci.LastActivity.IsZero() { t.Fatalf("Expected LastActivity to be valid\n") } if ci.LastActivity.UnixNano() < ci.Start.UnixNano() { t.Fatalf("Expected LastActivity [%v] to be > Start [%v]\n", ci.LastActivity, ci.Start) } if ci.Idle == "" { t.Fatalf("Expected Idle to be valid\n") } }