Add TrustForwardHeader options.

This commit is contained in:
Ludovic Fernandez 2017-10-16 12:46:03 +02:00 committed by Traefiker
parent 9598f646f5
commit aa308b7a3a
10 changed files with 265 additions and 40 deletions

View file

@ -229,7 +229,10 @@ func run(globalConfiguration *configuration.GlobalConfiguration) {
http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment
if len(globalConfiguration.EntryPoints) == 0 { if len(globalConfiguration.EntryPoints) == 0 {
globalConfiguration.EntryPoints = map[string]*configuration.EntryPoint{"http": {Address: ":80"}} globalConfiguration.EntryPoints = map[string]*configuration.EntryPoint{"http": {
Address: ":80",
ForwardedHeaders: &configuration.ForwardedHeaders{Insecure: true},
}}
globalConfiguration.DefaultEntryPoints = []string{"http"} globalConfiguration.DefaultEntryPoints = []string{"http"}
} }
@ -259,6 +262,14 @@ func run(globalConfiguration *configuration.GlobalConfiguration) {
globalConfiguration.LogLevel = "DEBUG" globalConfiguration.LogLevel = "DEBUG"
} }
// ForwardedHeaders must be remove in the next breaking version
for entryPointName := range globalConfiguration.EntryPoints {
entryPoint := globalConfiguration.EntryPoints[entryPointName]
if entryPoint.ForwardedHeaders == nil {
entryPoint.ForwardedHeaders = &configuration.ForwardedHeaders{Insecure: true}
}
}
// logging // logging
level, err := logrus.ParseLevel(strings.ToLower(globalConfiguration.LogLevel)) level, err := logrus.ParseLevel(strings.ToLower(globalConfiguration.LogLevel))
if err != nil { if err != nil {

View file

@ -10,6 +10,7 @@ import (
"github.com/containous/flaeg" "github.com/containous/flaeg"
"github.com/containous/traefik/acme" "github.com/containous/traefik/acme"
"github.com/containous/traefik/log"
"github.com/containous/traefik/provider/boltdb" "github.com/containous/traefik/provider/boltdb"
"github.com/containous/traefik/provider/consul" "github.com/containous/traefik/provider/consul"
"github.com/containous/traefik/provider/docker" "github.com/containous/traefik/provider/docker"
@ -229,11 +230,31 @@ func (ep *EntryPoints) Set(value string) error {
compress := toBool(result, "compress") compress := toBool(result, "compress")
var proxyProtocol *ProxyProtocol var proxyProtocol *ProxyProtocol
if len(result["proxyprotocol_trustedips"]) > 0 { ppTrustedIPs := result["proxyprotocol_trustedips"]
trustedIPs := strings.Split(result["proxyprotocol_trustedips"], ",") if len(result["proxyprotocol_insecure"]) > 0 || len(ppTrustedIPs) > 0 {
proxyProtocol = &ProxyProtocol{ proxyProtocol = &ProxyProtocol{
TrustedIPs: trustedIPs, Insecure: toBool(result, "proxyprotocol_insecure"),
} }
if len(ppTrustedIPs) > 0 {
proxyProtocol.TrustedIPs = strings.Split(ppTrustedIPs, ",")
}
}
// TODO must be changed to false by default in the next breaking version.
forwardedHeaders := &ForwardedHeaders{Insecure: true}
if _, ok := result["forwardedheaders_insecure"]; ok {
forwardedHeaders.Insecure = toBool(result, "forwardedheaders_insecure")
}
fhTrustedIPs := result["forwardedheaders_trustedips"]
if len(fhTrustedIPs) > 0 {
// TODO must be removed in the next breaking version.
forwardedHeaders.Insecure = toBool(result, "forwardedheaders_insecure")
forwardedHeaders.TrustedIPs = strings.Split(fhTrustedIPs, ",")
}
if proxyProtocol != nil && proxyProtocol.Insecure {
log.Warn("ProxyProtocol.Insecure:true is dangerous. Please use 'ProxyProtocol.TrustedIPs:IPs' and remove 'ProxyProtocol.Insecure:true'")
} }
(*ep)[result["name"]] = &EntryPoint{ (*ep)[result["name"]] = &EntryPoint{
@ -243,6 +264,7 @@ func (ep *EntryPoints) Set(value string) error {
Compress: compress, Compress: compress,
WhitelistSourceRange: whiteListSourceRange, WhitelistSourceRange: whiteListSourceRange,
ProxyProtocol: proxyProtocol, ProxyProtocol: proxyProtocol,
ForwardedHeaders: forwardedHeaders,
} }
return nil return nil
@ -302,6 +324,7 @@ type EntryPoint struct {
WhitelistSourceRange []string WhitelistSourceRange []string
Compress bool `export:"true"` Compress bool `export:"true"`
ProxyProtocol *ProxyProtocol `export:"true"` ProxyProtocol *ProxyProtocol `export:"true"`
ForwardedHeaders *ForwardedHeaders `export:"true"`
} }
// Redirect configures a redirection of an entry point to another, or to an URL // Redirect configures a redirection of an entry point to another, or to an URL
@ -453,5 +476,12 @@ type ForwardingTimeouts struct {
// ProxyProtocol contains Proxy-Protocol configuration // ProxyProtocol contains Proxy-Protocol configuration
type ProxyProtocol struct { type ProxyProtocol struct {
Insecure bool
TrustedIPs []string
}
// ForwardedHeaders Trust client forwarding headers
type ForwardedHeaders struct {
Insecure bool
TrustedIPs []string TrustedIPs []string
} }

View file

@ -1,7 +1,6 @@
package configuration package configuration
import ( import (
"fmt"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -16,7 +15,7 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
}{ }{
{ {
name: "all parameters", name: "all parameters",
value: "Name:foo TLS:goo TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:WhiteListSourceRange ProxyProtocol.TrustedIPs:192.168.0.1 Address::8000", value: "Name:foo TLS:goo TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:WhiteListSourceRange ProxyProtocol.TrustedIPs:192.168.0.1 ProxyProtocol.Insecure:false Address::8000",
expectedResult: map[string]string{ expectedResult: map[string]string{
"name": "foo", "name": "foo",
"address": ":8000", "address": ":8000",
@ -28,6 +27,7 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
"redirect_replacement": "RedirectReplacement", "redirect_replacement": "RedirectReplacement",
"whitelistsourcerange": "WhiteListSourceRange", "whitelistsourcerange": "WhiteListSourceRange",
"proxyprotocol_trustedips": "192.168.0.1", "proxyprotocol_trustedips": "192.168.0.1",
"proxyprotocol_insecure": "false",
"compress": "true", "compress": "true",
}, },
}, },
@ -57,10 +57,6 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
conf := parseEntryPointsConfiguration(test.value) conf := parseEntryPointsConfiguration(test.value)
for key, value := range conf {
fmt.Println(key, value)
}
assert.Len(t, conf, len(test.expectedResult)) assert.Len(t, conf, len(test.expectedResult))
assert.Equal(t, test.expectedResult, conf) assert.Equal(t, test.expectedResult, conf)
}) })
@ -131,7 +127,7 @@ func TestEntryPoints_Set(t *testing.T) {
}{ }{
{ {
name: "all parameters camelcase", name: "all parameters camelcase",
expression: "Name:foo Address::8000 TLS:goo,gii TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:Range ProxyProtocol.TrustedIPs:192.168.0.1", expression: "Name:foo Address::8000 TLS:goo,gii TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:Range ProxyProtocol.TrustedIPs:192.168.0.1 ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24",
expectedEntryPointName: "foo", expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{ expectedEntryPoint: &EntryPoint{
Address: ":8000", Address: ":8000",
@ -144,6 +140,9 @@ func TestEntryPoints_Set(t *testing.T) {
ProxyProtocol: &ProxyProtocol{ ProxyProtocol: &ProxyProtocol{
TrustedIPs: []string{"192.168.0.1"}, TrustedIPs: []string{"192.168.0.1"},
}, },
ForwardedHeaders: &ForwardedHeaders{
TrustedIPs: []string{"10.0.0.3/24", "20.0.0.3/24"},
},
WhitelistSourceRange: []string{"Range"}, WhitelistSourceRange: []string{"Range"},
TLS: &TLS{ TLS: &TLS{
ClientCAFiles: []string{"car"}, ClientCAFiles: []string{"car"},
@ -158,7 +157,7 @@ func TestEntryPoints_Set(t *testing.T) {
}, },
{ {
name: "all parameters lowercase", name: "all parameters lowercase",
expression: "name:foo address::8000 tls:goo,gii tls ca:car redirect.entryPoint:RedirectEntryPoint redirect.regex:RedirectRegex redirect.replacement:RedirectReplacement compress:true whiteListSourceRange:Range proxyProtocol.TrustedIPs:192.168.0.1", expression: "name:foo address::8000 tls:goo,gii tls ca:car redirect.entryPoint:RedirectEntryPoint redirect.regex:RedirectRegex redirect.replacement:RedirectReplacement compress:true whiteListSourceRange:Range proxyProtocol.trustedIPs:192.168.0.1 forwardedHeaders.trustedIPs:10.0.0.3/24,20.0.0.3/24",
expectedEntryPointName: "foo", expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{ expectedEntryPoint: &EntryPoint{
Address: ":8000", Address: ":8000",
@ -171,6 +170,9 @@ func TestEntryPoints_Set(t *testing.T) {
ProxyProtocol: &ProxyProtocol{ ProxyProtocol: &ProxyProtocol{
TrustedIPs: []string{"192.168.0.1"}, TrustedIPs: []string{"192.168.0.1"},
}, },
ForwardedHeaders: &ForwardedHeaders{
TrustedIPs: []string{"10.0.0.3/24", "20.0.0.3/24"},
},
WhitelistSourceRange: []string{"Range"}, WhitelistSourceRange: []string{"Range"},
TLS: &TLS{ TLS: &TLS{
ClientCAFiles: []string{"car"}, ClientCAFiles: []string{"car"},
@ -183,6 +185,76 @@ func TestEntryPoints_Set(t *testing.T) {
}, },
}, },
}, },
{
name: "default",
expression: "Name:foo",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
WhitelistSourceRange: []string{},
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
},
},
{
name: "ForwardedHeaders insecure true",
expression: "Name:foo ForwardedHeaders.Insecure:true",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
WhitelistSourceRange: []string{},
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
},
},
{
name: "ForwardedHeaders insecure false",
expression: "Name:foo ForwardedHeaders.Insecure:false",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
WhitelistSourceRange: []string{},
ForwardedHeaders: &ForwardedHeaders{Insecure: false},
},
},
{
name: "ForwardedHeaders TrustedIPs",
expression: "Name:foo ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
WhitelistSourceRange: []string{},
ForwardedHeaders: &ForwardedHeaders{
TrustedIPs: []string{"10.0.0.3/24", "20.0.0.3/24"},
},
},
},
{
name: "ProxyProtocol insecure true",
expression: "Name:foo ProxyProtocol.Insecure:true",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
WhitelistSourceRange: []string{},
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
ProxyProtocol: &ProxyProtocol{Insecure: true},
},
},
{
name: "ProxyProtocol insecure false",
expression: "Name:foo ProxyProtocol.Insecure:false",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
WhitelistSourceRange: []string{},
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
ProxyProtocol: &ProxyProtocol{},
},
},
{
name: "ProxyProtocol TrustedIPs",
expression: "Name:foo ProxyProtocol.TrustedIPs:10.0.0.3/24,20.0.0.3/24",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
WhitelistSourceRange: []string{},
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
ProxyProtocol: &ProxyProtocol{
TrustedIPs: []string{"10.0.0.3/24", "20.0.0.3/24"},
},
},
},
{ {
name: "compress on", name: "compress on",
expression: "Name:foo Compress:on", expression: "Name:foo Compress:on",
@ -190,6 +262,7 @@ func TestEntryPoints_Set(t *testing.T) {
expectedEntryPoint: &EntryPoint{ expectedEntryPoint: &EntryPoint{
Compress: true, Compress: true,
WhitelistSourceRange: []string{}, WhitelistSourceRange: []string{},
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
}, },
}, },
{ {
@ -199,6 +272,7 @@ func TestEntryPoints_Set(t *testing.T) {
expectedEntryPoint: &EntryPoint{ expectedEntryPoint: &EntryPoint{
Compress: true, Compress: true,
WhitelistSourceRange: []string{}, WhitelistSourceRange: []string{},
ForwardedHeaders: &ForwardedHeaders{Insecure: true},
}, },
}, },
} }

View file

@ -191,7 +191,7 @@ To enable IP whitelisting at the entrypoint level.
## ProxyProtocol ## ProxyProtocol
To enable [ProxyProtocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) support. To enable [ProxyProtocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) support.
Only IPs in `trustedIPs` will lead to remote client address replacement: you should declare your load-balancer IP or CIDR range here (in testing environment, you can trust everyone using `0.0.0.0/0`). Only IPs in `trustedIPs` will lead to remote client address replacement: you should declare your load-balancer IP or CIDR range here (in testing environment, you can trust everyone using `insecure = true`).
!!! danger !!! danger
When queuing Træfik behind another load-balancer, be sure to carefully configure Proxy Protocol on both sides. When queuing Træfik behind another load-balancer, be sure to carefully configure Proxy Protocol on both sides.
@ -201,6 +201,39 @@ Only IPs in `trustedIPs` will lead to remote client address replacement: you sho
[entryPoints] [entryPoints]
[entryPoints.http] [entryPoints.http]
address = ":80" address = ":80"
# Enable ProxyProtocol
[entryPoints.http.proxyProtocol] [entryPoints.http.proxyProtocol]
# List of trusted IPs
#
# Required
# Default: []
#
trustedIPs = ["127.0.0.1/32", "192.168.1.7"]
# Insecure mode FOR TESTING ENVIRONNEMENT ONLY
#
# Optional
# Default: false
#
# insecure = true
```
## Forwarded Header
Only IPs in `trustedIPs` will be authorize to trust the client forwarded headers (`X-Forwarded-*`).
```toml
[entryPoints]
[entryPoints.http]
address = ":80"
# Enable Forwarded Headers
[entryPoints.http.forwardedHeaders]
# List of trusted IPs
#
# Required
# Default: []
#
trustedIPs = ["127.0.0.1/32", "192.168.1.7"] trustedIPs = ["127.0.0.1/32", "192.168.1.7"]
``` ```

View file

@ -26,7 +26,7 @@ func NewIPWhitelister(whitelistStrings []string) (*IPWhiteLister, error) {
whiteLister := IPWhiteLister{} whiteLister := IPWhiteLister{}
ip, err := whitelist.NewIP(whitelistStrings) ip, err := whitelist.NewIP(whitelistStrings, false)
if err != nil { if err != nil {
return nil, fmt.Errorf("parsing CIDR whitelist %s: %v", whitelistStrings, err) return nil, fmt.Errorf("parsing CIDR whitelist %s: %v", whitelistStrings, err)
} }

51
server/header_rewriter.go Normal file
View file

@ -0,0 +1,51 @@
package server
import (
"net"
"net/http"
"os"
"github.com/containous/traefik/whitelist"
"github.com/vulcand/oxy/forward"
)
// NewHeaderRewriter Create a header rewriter
func NewHeaderRewriter(trustedIPs []string, insecure bool) (forward.ReqRewriter, error) {
IPs, err := whitelist.NewIP(trustedIPs, insecure)
if err != nil {
return nil, err
}
h, err := os.Hostname()
if err != nil {
h = "localhost"
}
return &headerRewriter{
secureRewriter: &forward.HeaderRewriter{TrustForwardHeader: true, Hostname: h},
insecureRewriter: &forward.HeaderRewriter{TrustForwardHeader: false, Hostname: h},
ips: IPs,
insecure: insecure,
}, nil
}
type headerRewriter struct {
secureRewriter forward.ReqRewriter
insecureRewriter forward.ReqRewriter
insecure bool
ips *whitelist.IP
}
func (h *headerRewriter) Rewrite(req *http.Request) {
clientIP, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
h.secureRewriter.Rewrite(req)
}
authorized, _, err := h.ips.Contains(clientIP)
if h.insecure || authorized {
h.secureRewriter.Rewrite(req)
} else {
h.insecureRewriter.Rewrite(req)
}
}

View file

@ -655,7 +655,7 @@ func (server *Server) prepareServer(entryPointName string, entryPoint *configura
} }
if entryPoint.ProxyProtocol != nil { if entryPoint.ProxyProtocol != nil {
IPs, err := whitelist.NewIP(entryPoint.ProxyProtocol.TrustedIPs) IPs, err := whitelist.NewIP(entryPoint.ProxyProtocol.TrustedIPs, entryPoint.ProxyProtocol.Insecure)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("Error creating whitelist: %s", err) return nil, nil, fmt.Errorf("Error creating whitelist: %s", err)
} }
@ -806,11 +806,19 @@ func (server *Server) loadConfig(configurations types.Configurations, globalConf
continue frontend continue frontend
} }
rewriter, err := NewHeaderRewriter(entryPoint.ForwardedHeaders.TrustedIPs, entryPoint.ForwardedHeaders.Insecure)
if err != nil {
log.Errorf("Error creating rewriter for frontend %s: %v", frontendName, err)
log.Errorf("Skipping frontend %s...", frontendName)
continue frontend
}
fwd, err := forward.New( fwd, err := forward.New(
forward.Logger(oxyLogger), forward.Logger(oxyLogger),
forward.PassHostHeader(frontend.PassHostHeader), forward.PassHostHeader(frontend.PassHostHeader),
forward.RoundTripper(roundTripper), forward.RoundTripper(roundTripper),
forward.ErrorHandler(errorHandler), forward.ErrorHandler(errorHandler),
forward.Rewriter(rewriter),
) )
if err != nil { if err != nil {

View file

@ -96,7 +96,10 @@ func TestPrepareServerTimeouts(t *testing.T) {
t.Parallel() t.Parallel()
entryPointName := "http" entryPointName := "http"
entryPoint := &configuration.EntryPoint{Address: "localhost:0"} entryPoint := &configuration.EntryPoint{
Address: "localhost:0",
ForwardedHeaders: &configuration.ForwardedHeaders{Insecure: true},
}
router := middlewares.NewHandlerSwitcher(mux.NewRouter()) router := middlewares.NewHandlerSwitcher(mux.NewRouter())
srv := NewServer(test.globalConfig) srv := NewServer(test.globalConfig)
@ -210,7 +213,9 @@ func TestServerLoadConfigHealthCheckOptions(t *testing.T) {
t.Run(fmt.Sprintf("%s/hc=%t", lbMethod, healthCheck != nil), func(t *testing.T) { t.Run(fmt.Sprintf("%s/hc=%t", lbMethod, healthCheck != nil), func(t *testing.T) {
globalConfig := configuration.GlobalConfiguration{ globalConfig := configuration.GlobalConfiguration{
EntryPoints: configuration.EntryPoints{ EntryPoints: configuration.EntryPoints{
"http": &configuration.EntryPoint{}, "http": &configuration.EntryPoint{
ForwardedHeaders: &configuration.ForwardedHeaders{Insecure: true},
},
}, },
HealthCheck: &configuration.HealthCheckConfig{Interval: flaeg.Duration(5 * time.Second)}, HealthCheck: &configuration.HealthCheckConfig{Interval: flaeg.Duration(5 * time.Second)},
} }
@ -383,7 +388,7 @@ func TestNewServerWithWhitelistSourceRange(t *testing.T) {
func TestServerLoadConfigEmptyBasicAuth(t *testing.T) { func TestServerLoadConfigEmptyBasicAuth(t *testing.T) {
globalConfig := configuration.GlobalConfiguration{ globalConfig := configuration.GlobalConfiguration{
EntryPoints: configuration.EntryPoints{ EntryPoints: configuration.EntryPoints{
"http": &configuration.EntryPoint{}, "http": &configuration.EntryPoint{ForwardedHeaders: &configuration.ForwardedHeaders{Insecure: true}},
}, },
} }
@ -492,7 +497,7 @@ func TestConfigureBackends(t *testing.T) {
} }
} }
func TestServerEntrypointWhitelistConfig(t *testing.T) { func TestServerEntryPointWhitelistConfig(t *testing.T) {
tests := []struct { tests := []struct {
desc string desc string
entrypoint *configuration.EntryPoint entrypoint *configuration.EntryPoint
@ -502,6 +507,7 @@ func TestServerEntrypointWhitelistConfig(t *testing.T) {
desc: "no whitelist middleware if no config on entrypoint", desc: "no whitelist middleware if no config on entrypoint",
entrypoint: &configuration.EntryPoint{ entrypoint: &configuration.EntryPoint{
Address: ":0", Address: ":0",
ForwardedHeaders: &configuration.ForwardedHeaders{Insecure: true},
}, },
wantMiddleware: false, wantMiddleware: false,
}, },
@ -512,6 +518,7 @@ func TestServerEntrypointWhitelistConfig(t *testing.T) {
WhitelistSourceRange: []string{ WhitelistSourceRange: []string{
"127.0.0.1/32", "127.0.0.1/32",
}, },
ForwardedHeaders: &configuration.ForwardedHeaders{Insecure: true},
}, },
wantMiddleware: true, wantMiddleware: true,
}, },
@ -633,7 +640,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
globalConfig := configuration.GlobalConfiguration{ globalConfig := configuration.GlobalConfiguration{
EntryPoints: configuration.EntryPoints{ EntryPoints: configuration.EntryPoints{
"http": &configuration.EntryPoint{}, "http": &configuration.EntryPoint{ForwardedHeaders: &configuration.ForwardedHeaders{Insecure: true}},
}, },
} }
dynamicConfigs := types.Configurations{"config": test.dynamicConfig(testServer.URL)} dynamicConfigs := types.Configurations{"config": test.dynamicConfig(testServer.URL)}

View file

@ -11,16 +11,18 @@ import (
type IP struct { type IP struct {
whiteListsIPs []*net.IP whiteListsIPs []*net.IP
whiteListsNet []*net.IPNet whiteListsNet []*net.IPNet
insecure bool
} }
// NewIP builds a new IP given a list of CIDR-Strings to whitelist // NewIP builds a new IP given a list of CIDR-Strings to whitelist
func NewIP(whitelistStrings []string) (*IP, error) { func NewIP(whitelistStrings []string, insecure bool) (*IP, error) {
if len(whitelistStrings) == 0 { if len(whitelistStrings) == 0 && !insecure {
return nil, errors.New("no whiteListsNet provided") return nil, errors.New("no whiteListsNet provided")
} }
ip := IP{} ip := IP{}
if !insecure {
for _, whitelistString := range whitelistStrings { for _, whitelistString := range whitelistStrings {
ipAddr := net.ParseIP(whitelistString) ipAddr := net.ParseIP(whitelistString)
if ipAddr != nil { if ipAddr != nil {
@ -33,12 +35,17 @@ func NewIP(whitelistStrings []string) (*IP, error) {
ip.whiteListsNet = append(ip.whiteListsNet, whitelist) ip.whiteListsNet = append(ip.whiteListsNet, whitelist)
} }
} }
}
return &ip, nil return &ip, nil
} }
// Contains checks if provided address is in the white list // Contains checks if provided address is in the white list
func (ip *IP) Contains(addr string) (bool, net.IP, error) { func (ip *IP) Contains(addr string) (bool, net.IP, error) {
if ip.insecure {
return true, nil, nil
}
ipAddr, err := ipFromRemoteAddr(addr) ipAddr, err := ipFromRemoteAddr(addr)
if err != nil { if err != nil {
return false, nil, fmt.Errorf("unable to parse address: %s: %s", addr, err) return false, nil, fmt.Errorf("unable to parse address: %s: %s", addr, err)
@ -50,6 +57,10 @@ func (ip *IP) Contains(addr string) (bool, net.IP, error) {
// ContainsIP checks if provided address is in the white list // ContainsIP checks if provided address is in the white list
func (ip *IP) ContainsIP(addr net.IP) (bool, error) { func (ip *IP) ContainsIP(addr net.IP) (bool, error) {
if ip.insecure {
return true, nil
}
for _, whiteListIP := range ip.whiteListsIPs { for _, whiteListIP := range ip.whiteListsIPs {
if whiteListIP.Equal(addr) { if whiteListIP.Equal(addr) {
return true, nil return true, nil

View file

@ -75,7 +75,7 @@ func TestNew(t *testing.T) {
test := test test := test
t.Run(test.desc, func(t *testing.T) { t.Run(test.desc, func(t *testing.T) {
t.Parallel() t.Parallel()
whitelister, err := NewIP(test.whitelistStrings) whitelister, err := NewIP(test.whitelistStrings, false)
if test.errMessage != "" { if test.errMessage != "" {
require.EqualError(t, err, test.errMessage) require.EqualError(t, err, test.errMessage)
} else { } else {
@ -275,7 +275,7 @@ func TestIsAllowed(t *testing.T) {
test := test test := test
t.Run(test.desc, func(t *testing.T) { t.Run(test.desc, func(t *testing.T) {
t.Parallel() t.Parallel()
whiteLister, err := NewIP(test.whitelistStrings) whiteLister, err := NewIP(test.whitelistStrings, false)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, whiteLister) require.NotNil(t, whiteLister)
@ -306,7 +306,7 @@ func TestBrokenIPs(t *testing.T) {
"\\&$§&/(", "\\&$§&/(",
} }
whiteLister, err := NewIP([]string{"1.2.3.4/24"}) whiteLister, err := NewIP([]string{"1.2.3.4/24"}, false)
require.NoError(t, err) require.NoError(t, err)
for _, testIP := range brokenIPs { for _, testIP := range brokenIPs {