Skip to content

Commit

Permalink
BCDA-509: Tests for servicemux.go (#77)
Browse files Browse the repository at this point in the history
* Starting servicemux tests

* More servicemux tests

* Consolidate serveHTTP() and serveHTTPS()

* serveHTTPS() test and consolidating localhost cert

* Fix data race, remove duplicate testing

* Create functions for repeated env var retrieval/reset
  • Loading branch information
em1 authored Nov 21, 2018
1 parent 3360a9d commit 195cd44
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 30 deletions.
2 changes: 1 addition & 1 deletion bcda/client/bluebutton_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (s *BBTestSuite) SetupTest() {
os.Setenv("BB_SERVER_LOCATION", s.ts.URL)
os.Setenv("BB_CLIENT_CERT_FILE", "../../shared_files/bb-dev-test-cert.pem")
os.Setenv("BB_CLIENT_KEY_FILE", "../../shared_files/bb-dev-test-key.pem")
os.Setenv("BB_CLIENT_CA_FILE", "../../shared_files/test-server-cert.pem")
os.Setenv("BB_CLIENT_CA_FILE", "../../shared_files/localhost.crt")

if bbClient, err := client.NewBlueButtonClient(); err != nil {
s.Fail("Failed to create Blue Button client", err)
Expand Down
41 changes: 13 additions & 28 deletions bcda/servicemux/servicemux.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ func URLPrefixMatcher(prefix string) cmux.Matcher {
}

type ServiceMux struct {
Addr string
Listener net.Listener
Servers []map[*http.Server]string
Addr string
Listener net.Listener
Servers []map[*http.Server]string
TLSConfig tls.Config
}

func New(addr string) *ServiceMux {
Expand Down Expand Up @@ -108,7 +109,7 @@ func (sm *ServiceMux) serveHTTPS(tlsCertPath, tlsKeyPath string) {
log.Panic(err)
}

config := &tls.Config{
sm.TLSConfig = tls.Config{
Certificates: []tls.Certificate{certificate},
Rand: rand.Reader,
PreferServerCipherSuites: true,
Expand All @@ -118,31 +119,9 @@ func (sm *ServiceMux) serveHTTPS(tlsCertPath, tlsKeyPath string) {
},
}

sm.Listener = tls.NewListener(sm.Listener, config)
sm.Listener = tls.NewListener(sm.Listener, &sm.TLSConfig)

m := cmux.New(sm.Listener)

for _, server := range sm.Servers {
for srv, path := range server {
var match net.Listener

if path == "" {
match = m.Match(cmux.Any())
} else {
match = m.Match(URLPrefixMatcher(path))
}

srv.TLSConfig = config

//nolint
go srv.Serve(match)
}
}

err = m.Serve()
if err != nil {
panic(err)
}
sm.serveHTTP()
}

func (sm *ServiceMux) serveHTTP() {
Expand All @@ -158,6 +137,8 @@ func (sm *ServiceMux) serveHTTP() {
match = m.Match(URLPrefixMatcher(path))
}

srv.TLSConfig = &sm.TLSConfig

//nolint
go srv.Serve(match)
}
Expand All @@ -169,6 +150,10 @@ func (sm *ServiceMux) serveHTTP() {
}
}

func (sm *ServiceMux) Close() {
sm.Listener.Close()
}

func IsHTTPS(r *http.Request) bool {
srvCtxKey := r.Context().Value(http.ServerContextKey)
if srvCtxKey == nil {
Expand Down
237 changes: 237 additions & 0 deletions bcda/servicemux/servicemux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package servicemux

import (
"crypto/tls"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
"os"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)

type ServiceMuxTestSuite struct {
suite.Suite
}

func (s *ServiceMuxTestSuite) TestNew() {
sm := New("127.0.0.1:0")
go func() {
defer sm.Close()
}()

assert.NotNil(s.T(), sm)
assert.Equal(s.T(), "127.0.0.1:0", sm.Addr)
assert.NotNil(s.T(), sm.Listener)
assert.IsType(s.T(), tcpKeepAliveListener{}, sm.Listener)
assert.Empty(s.T(), sm.Servers)
}

func (s *ServiceMuxTestSuite) TestAddServer() {
sm := New("127.0.0.1:0")
go func() {
defer sm.Close()
}()

srv := &http.Server{}
go func() {
defer srv.Close()
}()
sm.AddServer(srv, "test")

assert.Len(s.T(), sm.Servers, 1)
for k, v := range sm.Servers[0] {
assert.Equal(s.T(), srv, k)
assert.Equal(s.T(), "test", v)
}
}

func (s *ServiceMuxTestSuite) TestServe_NoCert() {
origTLSCert, origTLSKey, origHTTPOnly := getOrigVars()

defer resetOrigVars(origTLSCert, origTLSKey, origHTTPOnly)

os.Setenv("BCDA_TLS_CERT", "")
os.Setenv("BCDA_TLS_KEY", "test.key")
os.Setenv("HTTP_ONLY", "")

sm := &ServiceMux{}
assert.Panics(s.T(), sm.Serve)
}

func (s *ServiceMuxTestSuite) TestServe_NoKey() {
origTLSCert, origTLSKey, origHTTPOnly := getOrigVars()

defer resetOrigVars(origTLSCert, origTLSKey, origHTTPOnly)

os.Setenv("BCDA_TLS_CERT", "test.crt")
os.Setenv("BCDA_TLS_KEY", "")
os.Setenv("HTTP_ONLY", "")

sm := &ServiceMux{}
assert.Panics(s.T(), sm.Serve)
}

var testHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
_, err := w.Write([]byte("Test"))
if err != nil {
log.Fatal(err)
}
}

func (s *ServiceMuxTestSuite) TestServe_serveHTTPS() {
srv := &http.Server{
Handler: testHandler,
}

sm := New("127.0.0.1:0")
sm.AddServer(srv, "/test")

go func() {
defer sm.Close()

origTLSCert, origTLSKey, origHTTPOnly := getOrigVars()

defer resetOrigVars(origTLSCert, origTLSKey, origHTTPOnly)

os.Setenv("BCDA_TLS_CERT", "../../shared_files/localhost.crt")
os.Setenv("BCDA_TLS_KEY", "../../shared_files/localhost.key")
os.Setenv("HTTP_ONLY", "false")

sm.Serve()
}()

// Allow certificate signed by unknown authority
http.DefaultClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}

resp, err := http.Get("https://" + sm.Listener.Addr().String() + "/test")
if err != nil {
s.T().Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
s.T().Fatal(err)
}

assert.Equal(s.T(), "Test", string(body))
}

func (s *ServiceMuxTestSuite) TestServe_serveHTTPS_badKeypair() {
srv := &http.Server{
Handler: testHandler,
}

sm := New("127.0.0.1:0")
sm.AddServer(srv, "/test")

defer sm.Close()

origTLSCert, origTLSKey, origHTTPOnly := getOrigVars()

defer resetOrigVars(origTLSCert, origTLSKey, origHTTPOnly)

os.Setenv("BCDA_TLS_CERT", "foo.crt")
os.Setenv("BCDA_TLS_KEY", "foo.key")
os.Setenv("HTTP_ONLY", "false")

assert.Panics(s.T(), sm.Serve)
}

func (s *ServiceMuxTestSuite) TestServe_serveHTTP() {
srv := http.Server{
Handler: testHandler,
}

sm := New("127.0.0.1:0")
sm.AddServer(&srv, "/test")

go func() {
origTLSCert, origTLSKey, origHTTPOnly := getOrigVars()

defer func() {
sm.Close()
resetOrigVars(origTLSCert, origTLSKey, origHTTPOnly)
}()

os.Setenv("BCDA_TLS_CERT", "")
os.Setenv("BCDA_TLS_KEY", "")
os.Setenv("HTTP_ONLY", "true")

sm.Serve()
}()

resp, err := http.Get("http://" + sm.Listener.Addr().String() + "/test")
if err != nil {
s.T().Fatal(err)
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
s.T().Fatal(err)
}

assert.Equal(s.T(), "Test", string(b))
}

func (s *ServiceMuxTestSuite) TestServe_serveHTTP_emptyPath() {
srv := http.Server{
Handler: testHandler,
}

sm := New("127.0.0.1:0")
sm.AddServer(&srv, "")

go func() {
origTLSCert, origTLSKey, origHTTPOnly := getOrigVars()

defer func() {
sm.Close()
resetOrigVars(origTLSCert, origTLSKey, origHTTPOnly)
}()

os.Setenv("BCDA_TLS_CERT", "")
os.Setenv("BCDA_TLS_KEY", "")
os.Setenv("HTTP_ONLY", "true")

sm.Serve()
}()

resp, err := http.Get("http://" + sm.Listener.Addr().String() + "/foo")
if err != nil {
s.T().Fatal(err)
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
s.T().Fatal(err)
}

assert.Equal(s.T(), "Test", string(b))
}

func (s *ServiceMuxTestSuite) TestIsHTTPS_false() {
req := httptest.NewRequest("GET", "/", nil)
assert.False(s.T(), IsHTTPS(req))
}

func TestServiceMuxTestSuite(t *testing.T) {
suite.Run(t, new(ServiceMuxTestSuite))
}

func getOrigVars() (origTLSCert, origTLSKey, origHTTPOnly string) {
return os.Getenv("BCDA_TLS_CERT"), os.Getenv("BCDA_TLS_KEY"), os.Getenv("HTTP_ONLY")
}

func resetOrigVars(origTLSCert, origTLSKey, origHTTPOnly string) {
os.Setenv("BCDA_TLS_CERT", origTLSCert)
os.Setenv("BCDA_TLS_KEY", origTLSKey)
os.Setenv("HTTP_ONLY", origHTTPOnly)
}
2 changes: 1 addition & 1 deletion bcdaworker/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (s *MainTestSuite) SetupTest() {
os.Setenv("FHIR_PAYLOAD_DIR", "data/test")
os.Setenv("BB_CLIENT_CERT_FILE", "../shared_files/bb-dev-test-cert.pem")
os.Setenv("BB_CLIENT_KEY_FILE", "../shared_files/bb-dev-test-key.pem")
os.Setenv("BB_CLIENT_CA_FILE", "../shared_files/test-server-cert.pem")
os.Setenv("BB_CLIENT_CA_FILE", "../shared_files/localhost.crt")
models.InitializeGormModels()
}

Expand Down
File renamed without changes.
15 changes: 15 additions & 0 deletions shared_files/localhost.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
-----END RSA PRIVATE KEY-----

0 comments on commit 195cd44

Please sign in to comment.