Skip to content

Commit

Permalink
Added listen path validation
Browse files Browse the repository at this point in the history
  • Loading branch information
vgarvardt authored Oct 5, 2017
1 parent 99c59bb commit 9329ba1
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 24 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Unreleased

- TODO
## Added

- Added Proxy Listen Path validation to prevent `chi` from panicking in case of invalid listen path

# 3.3.0

Expand Down
3 changes: 1 addition & 2 deletions cmd/janus/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"os"
"path/filepath"

mgo "gopkg.in/mgo.v2"

"github.com/hellofresh/janus/pkg/config"
tracerfactory "github.com/hellofresh/janus/pkg/opentracing"
"github.com/hellofresh/janus/pkg/store"
Expand All @@ -15,6 +13,7 @@ import (
"github.com/hellofresh/stats-go/hooks"
"github.com/opentracing/opentracing-go"
log "github.com/sirupsen/logrus"
"gopkg.in/mgo.v2"
)

var (
Expand Down
2 changes: 0 additions & 2 deletions cmd/janus/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"net/http"

"github.com/hellofresh/janus/pkg/api"
"github.com/hellofresh/janus/pkg/errors"
"github.com/hellofresh/janus/pkg/middleware"
"github.com/hellofresh/janus/pkg/notifier"
Expand Down Expand Up @@ -35,7 +34,6 @@ import (
)

var (
repo api.Repository
server *http.Server
)

Expand Down
2 changes: 1 addition & 1 deletion pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Plugin struct {
type Definition struct {
Name string `bson:"name" json:"name" valid:"required"`
Active bool `bson:"active" json:"active"`
Proxy *proxy.Definition `bson:"proxy" json:"proxy"`
Proxy *proxy.Definition `bson:"proxy" json:"proxy" valid:"required"`
Plugins []Plugin `bson:"plugins" json:"plugins"`
HealthCheck HealthCheck `bson:"health_check" json:"health_check"`
}
Expand Down
7 changes: 5 additions & 2 deletions pkg/api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/hellofresh/janus/pkg/api"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestNewInstanceOfDefinition(t *testing.T) {
Expand All @@ -17,9 +18,11 @@ func TestNewInstanceOfDefinition(t *testing.T) {
func TestSuccessfulValidation(t *testing.T) {
instance := api.NewDefinition()
instance.Name = "Test"
isValid, err := instance.Validate()
instance.Proxy.ListenPath = "/"
instance.Proxy.UpstreamURL = "http://example.com"

assert.NoError(t, err)
isValid, err := instance.Validate()
require.NoError(t, err)
assert.True(t, isValid)
}

Expand Down
19 changes: 13 additions & 6 deletions pkg/api/file_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/hellofresh/janus/pkg/proxy"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func newRepo(t *testing.T) *FileSystemRepository {
Expand Down Expand Up @@ -42,17 +43,23 @@ func TestNewFileSystemRepository(t *testing.T) {
assertFindByFindByListenPath(t, fsRepo)
assertExists(t, fsRepo)

defToAdd := &Definition{Name: "foo-bar", Proxy: &proxy.Definition{ListenPath: "/foo/bar/*"}}
defToAdd := &Definition{
Name: "foo-bar",
Proxy: &proxy.Definition{
ListenPath: "/foo/bar/*",
UpstreamURL: "http://example.com/foo/bar/",
},
}
err = fsRepo.Add(defToAdd)
assert.NoError(t, err)
require.NoError(t, err)

def, err := fsRepo.FindByName(defToAdd.Name)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, defToAdd.Name, def.Name)
assert.Equal(t, defToAdd.Proxy.ListenPath, def.Proxy.ListenPath)

def, err = fsRepo.FindByListenPath(defToAdd.Proxy.ListenPath)
assert.NoError(t, err)
require.NoError(t, err)
assert.Equal(t, defToAdd.Name, def.Name)
assert.Equal(t, defToAdd.Proxy.ListenPath, def.Proxy.ListenPath)

Expand All @@ -68,7 +75,7 @@ func TestNewFileSystemRepository(t *testing.T) {
assert.Equal(t, ErrAPIListenPathExists, err)

err = fsRepo.Remove(defToAdd.Name)
assert.NoError(t, err)
require.NoError(t, err)

err = fsRepo.Remove(defToAdd.Name)
assert.Equal(t, ErrAPIDefinitionNotFound, err)
Expand All @@ -80,8 +87,8 @@ func TestNewFileSystemRepository(t *testing.T) {
assert.Equal(t, ErrAPIDefinitionNotFound, err)

exists, err = fsRepo.Exists(defToAdd)
require.NoError(t, err)
assert.False(t, exists)
assert.NoError(t, err)
}

func assertFindByName(t *testing.T, fsRepo *FileSystemRepository) {
Expand Down
15 changes: 14 additions & 1 deletion pkg/proxy/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package proxy

import (
"encoding/json"
"strings"

"github.com/asaskevich/govalidator"
"github.com/hellofresh/janus/pkg/router"
Expand All @@ -10,7 +11,7 @@ import (
// Definition defines proxy rules for a route
type Definition struct {
PreserveHost bool `bson:"preserve_host" json:"preserve_host" mapstructure:"preserve_host"`
ListenPath string `bson:"listen_path" json:"listen_path" mapstructure:"listen_path" valid:"required"`
ListenPath string `bson:"listen_path" json:"listen_path" mapstructure:"listen_path" valid:"required,urlpath"`
UpstreamURL string `bson:"upstream_url" json:"upstream_url" mapstructure:"upstream_url" valid:"url,required"`
InsecureSkipVerify bool `bson:"insecure_skip_verify" json:"insecure_skip_verify" mapstructure:"insecure_skip_verify"`
StripPath bool `bson:"strip_path" json:"strip_path" mapstructure:"strip_path"`
Expand Down Expand Up @@ -81,3 +82,15 @@ func JSONUnmarshalRoute(rawRoute []byte) (*Route, error) {
}
return NewRoute(proxyRoute.Proxy), nil
}

func init() {
// initializes custom validators
govalidator.CustomTypeTagMap.Set("urlpath", func(i interface{}, o interface{}) bool {
s, ok := i.(string)
if !ok {
return false
}

return strings.Index(s, "/") == 0
})
}
23 changes: 14 additions & 9 deletions pkg/proxy/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,16 @@ func (p *Register) doRegister(listenPath string, handler http.HandlerFunc, metho
"listen_path": listenPath,
}).Debug("Registering a route")

for _, method := range methods {
if strings.ToUpper(method) == methodAll {
p.Router.Any(listenPath, handler, handlers...)
} else {
p.Router.Handle(strings.ToUpper(method), listenPath, handler, handlers...)
if strings.Index(listenPath, "/") != 0 {
log.WithField("listen_path", listenPath).
Error("Route listen path must begin with '/'.Skipping invalid route.")
} else {
for _, method := range methods {
if strings.ToUpper(method) == methodAll {
p.Router.Any(listenPath, handler, handlers...)
} else {
p.Router.Handle(strings.ToUpper(method), listenPath, handler, handlers...)
}
}
}
}
Expand All @@ -134,13 +139,13 @@ func singleJoiningSlash(a, b string) string {
a = cleanSlashes(a)
b = cleanSlashes(b)

aslash := strings.HasSuffix(a, "/")
bslash := strings.HasPrefix(b, "/")
aSlash := strings.HasSuffix(a, "/")
bSlash := strings.HasPrefix(b, "/")

switch {
case aslash && bslash:
case aSlash && bSlash:
return a + b[1:]
case !aslash && !bslash:
case !aSlash && !bSlash:
if len(b) > 0 {
return a + "/" + b
}
Expand Down

0 comments on commit 9329ba1

Please sign in to comment.