Skip to content

Commit

Permalink
Added url validation to webserver.hostname config
Browse files Browse the repository at this point in the history
* Added url.Parse() validation to the webserver.hostname.
* Use stricter formatting strings in config package.
  • Loading branch information
ARolek committed Jul 19, 2024
1 parent a58cd89 commit ad3511b
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 24 deletions.
12 changes: 12 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"
"time"
Expand Down Expand Up @@ -332,6 +333,17 @@ func (c *Config) Validate() error {
}
}

// if HostName is set, validate it
if string(c.Webserver.HostName) != "" {
_, err := url.Parse(string(c.Webserver.HostName))
if err != nil {
return ErrInvalidHostName{
HostName: string(c.Webserver.HostName),
Err: err,
}
}
}

return nil
}

Expand Down
30 changes: 19 additions & 11 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func TestParse(t *testing.T) {
hostname = "cdn.tegola.io"
port = ":8080"
cors_allowed_origin = "tegola.io"
proxy_protocol = "https"
proxy_protocol = "https"
[webserver.headers]
Access-Control-Allow-Origin = "*"
Expand Down Expand Up @@ -484,7 +484,7 @@ func TestParse(t *testing.T) {
[webserver]
hostname = "${ENV_TEST_HOST_1}.${ENV_TEST_HOST_2}.${ENV_TEST_HOST_3}"
port = "${ENV_TEST_WEBSERVER_PORT}"
proxy_protocol = ""
proxy_protocol = ""
[webserver.headers]
Cache-Control = "${ENV_TEST_WEBSERVER_HEADER_STRING}"
Expand Down Expand Up @@ -783,7 +783,7 @@ func TestValidate(t *testing.T) {

err := tc.config.Validate()
if !errors.Is(err, tc.expectedErr) {
t.Errorf("expected err: %v got %v", tc.expectedErr, err)
t.Errorf("expected err: %s got %s", tc.expectedErr, err)
return
}
}
Expand Down Expand Up @@ -1358,7 +1358,7 @@ func TestValidate(t *testing.T) {
},
},
},
"12 mvt_provider comingle; flip": {
"13 mvt_provider comingle; flip": {
expectedErr: config.ErrMVTDifferentProviders{
Original: "stdprovider1",
Current: "provider1",
Expand Down Expand Up @@ -1390,7 +1390,7 @@ func TestValidate(t *testing.T) {
},
},
},
"13 reserved token name": {
"14 reserved token name": {
config: config.Config{
Maps: []provider.Map{
{
Expand All @@ -1414,7 +1414,7 @@ func TestValidate(t *testing.T) {
},
},
},
"13 duplicate parameter name": {
"15 duplicate parameter name": {
config: config.Config{
Maps: []provider.Map{
{
Expand Down Expand Up @@ -1443,7 +1443,7 @@ func TestValidate(t *testing.T) {
},
},
},
"13 duplicate token name": {
"16 duplicate token name": {
config: config.Config{
Maps: []provider.Map{
{
Expand Down Expand Up @@ -1472,7 +1472,7 @@ func TestValidate(t *testing.T) {
},
},
},
"13 parameter unknown type": {
"17 parameter unknown type": {
config: config.Config{
Maps: []provider.Map{
{
Expand All @@ -1496,7 +1496,7 @@ func TestValidate(t *testing.T) {
},
},
},
"13 parameter two defaults": {
"18 parameter two defaults": {
config: config.Config{
Maps: []provider.Map{
{
Expand Down Expand Up @@ -1524,7 +1524,7 @@ func TestValidate(t *testing.T) {
},
},
},
"13 parameter invalid default": {
"19 parameter invalid default": {
config: config.Config{
Maps: []provider.Map{
{
Expand All @@ -1551,7 +1551,7 @@ func TestValidate(t *testing.T) {
},
},
},
"13 invalid token name": {
"20 invalid token name": {
config: config.Config{
Maps: []provider.Map{
{
Expand All @@ -1575,6 +1575,14 @@ func TestValidate(t *testing.T) {
},
},
},
"21 invalid webserver hostname": {
config: config.Config{
Webserver: config.Webserver{
HostName: ":\\malformed.host",
},
},
expectedErr: config.ErrInvalidHostName{},
},
}

for name, tc := range tests {
Expand Down
45 changes: 34 additions & 11 deletions config/errors.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config

import (
"errors"
"fmt"
"strings"

Expand All @@ -12,7 +13,7 @@ type ErrMapNotFound struct {
}

func (e ErrMapNotFound) Error() string {
return fmt.Sprintf("config: map (%v) not found", e.MapName)
return fmt.Sprintf("config: map (%s) not found", e.MapName)
}

type ErrParamTokenReserved struct {
Expand Down Expand Up @@ -104,7 +105,7 @@ type ErrInvalidProviderLayerName struct {
}

func (e ErrInvalidProviderLayerName) Error() string {
return fmt.Sprintf("config: invalid provider layer name (%v)", e.ProviderLayerName)
return fmt.Sprintf("config: invalid provider layer name (%s)", e.ProviderLayerName)
}

type ErrOverlappingLayerZooms struct {
Expand All @@ -113,7 +114,7 @@ type ErrOverlappingLayerZooms struct {
}

func (e ErrOverlappingLayerZooms) Error() string {
return fmt.Sprintf("config: overlapping zooms for layer (%v) and layer (%v)", e.ProviderLayer1, e.ProviderLayer2)
return fmt.Sprintf("config: overlapping zooms for layer (%s) and layer (%s)", e.ProviderLayer1, e.ProviderLayer2)
}

type ErrInvalidLayerZoom struct {
Expand All @@ -129,7 +130,7 @@ func (e ErrInvalidLayerZoom) Error() string {
n, d = "MinZoom", "below"
}
return fmt.Sprintf(
"config: for provider layer %v %v(%v) is %v allowed level of %v",
"config: for provider layer %s %s(%d) is %s allowed level of %d",
e.ProviderLayer, n, e.Zoom, d, e.ZoomLimit,
)
}
Expand All @@ -155,7 +156,7 @@ type ErrMixedProviders struct {
}

func (e ErrMixedProviders) Error() string {
return fmt.Sprintf("config: can not mix MVT providers with normal providers for map %v", e.Map)
return fmt.Sprintf("config: can not mix MVT providers with normal providers for map %s", e.Map)
}

// ErrMissingEnvVar represents an environmental variable the system was unable to find in the environment
Expand All @@ -164,21 +165,43 @@ type ErrMissingEnvVar struct {
}

func (e ErrMissingEnvVar) Error() string {
return fmt.Sprintf("config: config file is referencing an environment variable that is not set (%v)", e.EnvVar)
return fmt.Sprintf("config: config file is referencing an environment variable that is not set (%s)", e.EnvVar)
}

type ErrInvalidHeader struct {
Header string
}

func (e ErrInvalidHeader) Error() string {
return fmt.Sprintf("config: header (%v) blacklisted", e.Header)
return fmt.Sprintf("config: header (%s) blacklisted", e.Header)
}

type ErrInvalidURIPrefix string

func (e ErrInvalidURIPrefix) Error() string {
return fmt.Sprintf("config: invalid uri_prefix (%v). uri_prefix must start with a forward slash '/' ", string(e))
return fmt.Sprintf("config: invalid uri_prefix (%s). uri_prefix must start with a forward slash '/' ", string(e))
}

type ErrInvalidHostName struct {
HostName string
Err error
}

func (e ErrInvalidHostName) Error() string {
return fmt.Sprintf("config: invalid hostname (%s) - %s", string(e.HostName), e.Err)
}

func (e ErrInvalidHostName) Unwrap() error {
return e.Err
}

func (e ErrInvalidHostName) Is(target error) bool {

if _, ok := target.(ErrInvalidHostName); ok {
return true
}

return errors.Is(e.Err, target)
}

// ErrUnknownProviderType is returned when the config contains a provider type that has not been registered
Expand Down Expand Up @@ -207,7 +230,7 @@ type ErrProviderNameRequired struct {
}

func (e ErrProviderNameRequired) Error() string {
return fmt.Sprintf("config: name field required for provider at position %v", e.Pos)
return fmt.Sprintf("config: name field required for provider at position %d", e.Pos)
}

// ErrProviderNameDuplicate is returned when the name of a provider is duplicated in the provider list
Expand All @@ -216,7 +239,7 @@ type ErrProviderNameDuplicate struct {
}

func (e ErrProviderNameDuplicate) Error() string {
return fmt.Sprintf("config: name for provider at position %v is a duplicate", e.Pos)
return fmt.Sprintf("config: name for provider at position %d is a duplicate", e.Pos)
}

// ErrProviderTypeRequired is returned when the type of a provider is missing from the provider list
Expand All @@ -225,5 +248,5 @@ type ErrProviderTypeRequired struct {
}

func (e ErrProviderTypeRequired) Error() string {
return fmt.Sprintf("config: type field required for provider at position %v", e.Pos)
return fmt.Sprintf("config: type field required for provider at position %d", e.Pos)
}
4 changes: 2 additions & 2 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func setHeaders(w http.ResponseWriter) {
// add our default CORS headers
for name, val := range DefaultCORSHeaders {
if val == "" {
log.Warnf("default CORS header (%v) has no value", name)
log.Warnf("default CORS header (%s) has no value", name)
}

w.Header().Set(name, val)
Expand All @@ -211,7 +211,7 @@ func setHeaders(w http.ResponseWriter) {
// set user defined headers
for name, val := range Headers {
if val == "" {
log.Warnf("header (%v) has no value", name)
log.Warnf("header (%s) has no value", name)
}

w.Header().Set(name, val)
Expand Down

0 comments on commit ad3511b

Please sign in to comment.