Ability to use "X-Forwarded-For" as a source of IP for white list.

This commit is contained in:
Ludovic Fernandez 2018-03-23 17:40:04 +01:00 committed by Traefiker Bot
parent 4802484729
commit d2766b1b4f
50 changed files with 1496 additions and 599 deletions

View file

@ -40,18 +40,18 @@ func (p *Provider) buildConfigurationV2(containersInspected []dockerData) *types
"getLoadBalancer": getLoadBalancer,
// Frontend functions
"getBackendName": getBackendName,
"getPriority": getFuncIntLabel(label.TraefikFrontendPriority, label.DefaultFrontendPriorityInt),
"getPassHostHeader": getFuncBoolLabel(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeaderBool),
"getPassTLSCert": getFuncBoolLabel(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert),
"getEntryPoints": getFuncSliceStringLabel(label.TraefikFrontendEntryPoints),
"getBasicAuth": getFuncSliceStringLabel(label.TraefikFrontendAuthBasic),
"getWhitelistSourceRange": getFuncSliceStringLabel(label.TraefikFrontendWhitelistSourceRange),
"getFrontendRule": p.getFrontendRule,
"getRedirect": getRedirect,
"getErrorPages": getErrorPages,
"getRateLimit": getRateLimit,
"getHeaders": getHeaders,
"getBackendName": getBackendName,
"getPriority": getFuncIntLabel(label.TraefikFrontendPriority, label.DefaultFrontendPriorityInt),
"getPassHostHeader": getFuncBoolLabel(label.TraefikFrontendPassHostHeader, label.DefaultPassHostHeaderBool),
"getPassTLSCert": getFuncBoolLabel(label.TraefikFrontendPassTLSCert, label.DefaultPassTLSCert),
"getEntryPoints": getFuncSliceStringLabel(label.TraefikFrontendEntryPoints),
"getBasicAuth": getFuncSliceStringLabel(label.TraefikFrontendAuthBasic),
"getFrontendRule": p.getFrontendRule,
"getRedirect": getRedirect,
"getErrorPages": getErrorPages,
"getRateLimit": getRateLimit,
"getHeaders": getHeaders,
"getWhiteList": getWhiteList,
}
// filter containers
@ -276,6 +276,31 @@ func getBackendName(container dockerData) string {
return getDefaultBackendName(container)
}
func getWhiteList(labels map[string]string) *types.WhiteList {
if label.Has(labels, label.TraefikFrontendWhitelistSourceRange) {
log.Warnf("Deprecated configuration found: %s. Please use %s.", label.TraefikFrontendWhitelistSourceRange, label.TraefikFrontendWhiteListSourceRange)
}
ranges := label.GetSliceStringValue(labels, label.TraefikFrontendWhiteListSourceRange)
if len(ranges) > 0 {
return &types.WhiteList{
SourceRange: ranges,
UseXForwardedFor: label.GetBoolValue(labels, label.TraefikFrontendWhiteListUseXForwardedFor, false),
}
}
// TODO: Deprecated
values := label.GetSliceStringValue(labels, label.TraefikFrontendWhitelistSourceRange)
if len(values) > 0 {
return &types.WhiteList{
SourceRange: values,
UseXForwardedFor: false,
}
}
return nil
}
func getRedirect(labels map[string]string) *types.Redirect {
permanent := label.GetBoolValue(labels, label.TraefikFrontendRedirectPermanent, false)

View file

@ -113,17 +113,18 @@ func TestDockerBuildConfiguration(t *testing.T) {
label.TraefikBackendBufferingMemRequestBodyBytes: "2097152",
label.TraefikBackendBufferingRetryExpression: "IsNetworkError() && Attempts() <= 2",
label.TraefikFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
label.TraefikFrontendEntryPoints: "http,https",
label.TraefikFrontendPassHostHeader: "true",
label.TraefikFrontendPassTLSCert: "true",
label.TraefikFrontendPriority: "666",
label.TraefikFrontendRedirectEntryPoint: "https",
label.TraefikFrontendRedirectRegex: "nope",
label.TraefikFrontendRedirectReplacement: "nope",
label.TraefikFrontendRedirectPermanent: "true",
label.TraefikFrontendRule: "Host:traefik.io",
label.TraefikFrontendWhitelistSourceRange: "10.10.10.10",
label.TraefikFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
label.TraefikFrontendEntryPoints: "http,https",
label.TraefikFrontendPassHostHeader: "true",
label.TraefikFrontendPassTLSCert: "true",
label.TraefikFrontendPriority: "666",
label.TraefikFrontendRedirectEntryPoint: "https",
label.TraefikFrontendRedirectRegex: "nope",
label.TraefikFrontendRedirectReplacement: "nope",
label.TraefikFrontendRedirectPermanent: "true",
label.TraefikFrontendRule: "Host:traefik.io",
label.TraefikFrontendWhiteListSourceRange: "10.10.10.10",
label.TraefikFrontendWhiteListUseXForwardedFor: "true",
label.TraefikFrontendRequestHeaders: "Access-Control-Allow-Methods:POST,GET,OPTIONS || Content-type: application/json; charset=utf-8",
label.TraefikFrontendResponseHeaders: "Access-Control-Allow-Methods:POST,GET,OPTIONS || Content-type: application/json; charset=utf-8",
@ -187,8 +188,9 @@ func TestDockerBuildConfiguration(t *testing.T) {
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
},
WhitelistSourceRange: []string{
"10.10.10.10",
WhiteList: &types.WhiteList{
SourceRange: []string{"10.10.10.10"},
UseXForwardedFor: true,
},
Headers: &types.Headers{
CustomRequestHeaders: map[string]string{
@ -692,17 +694,17 @@ func TestDockerGetSliceStringLabel(t *testing.T) {
{
desc: "whitelist-label with empty string",
labels: map[string]string{
label.TraefikFrontendWhitelistSourceRange: "",
label.TraefikFrontendWhiteListSourceRange: "",
},
labelName: label.TraefikFrontendWhitelistSourceRange,
labelName: label.TraefikFrontendWhiteListSourceRange,
expected: nil,
},
{
desc: "whitelist-label with IPv4 mask",
labels: map[string]string{
label.TraefikFrontendWhitelistSourceRange: "1.2.3.4/16",
label.TraefikFrontendWhiteListSourceRange: "1.2.3.4/16",
},
labelName: label.TraefikFrontendWhitelistSourceRange,
labelName: label.TraefikFrontendWhiteListSourceRange,
expected: []string{
"1.2.3.4/16",
},
@ -710,9 +712,9 @@ func TestDockerGetSliceStringLabel(t *testing.T) {
{
desc: "whitelist-label with IPv6 mask",
labels: map[string]string{
label.TraefikFrontendWhitelistSourceRange: "fe80::/16",
label.TraefikFrontendWhiteListSourceRange: "fe80::/16",
},
labelName: label.TraefikFrontendWhitelistSourceRange,
labelName: label.TraefikFrontendWhiteListSourceRange,
expected: []string{
"fe80::/16",
},
@ -720,9 +722,9 @@ func TestDockerGetSliceStringLabel(t *testing.T) {
{
desc: "whitelist-label with multiple masks",
labels: map[string]string{
label.TraefikFrontendWhitelistSourceRange: "1.1.1.1/24, 1234:abcd::42/32",
label.TraefikFrontendWhiteListSourceRange: "1.1.1.1/24, 1234:abcd::42/32",
},
labelName: label.TraefikFrontendWhitelistSourceRange,
labelName: label.TraefikFrontendWhiteListSourceRange,
expected: []string{
"1.1.1.1/24",
"1234:abcd::42/32",
@ -1025,3 +1027,85 @@ func TestDockerGetPort(t *testing.T) {
})
}
}
func TestWhiteList(t *testing.T) {
testCases := []struct {
desc string
labels map[string]string
expected *types.WhiteList
}{
{
desc: "should return nil when no white list labels",
labels: map[string]string{},
expected: nil,
},
{
desc: "should return a struct when deprecated label",
labels: map[string]string{
label.TraefikFrontendWhitelistSourceRange: "10.10.10.10",
},
expected: &types.WhiteList{
SourceRange: []string{
"10.10.10.10",
},
UseXForwardedFor: false,
},
},
{
desc: "should return a struct when only range",
labels: map[string]string{
label.TraefikFrontendWhiteListSourceRange: "10.10.10.10",
},
expected: &types.WhiteList{
SourceRange: []string{
"10.10.10.10",
},
UseXForwardedFor: false,
},
},
{
desc: "should return a struct when range and UseXForwardedFor",
labels: map[string]string{
label.TraefikFrontendWhiteListSourceRange: "10.10.10.10",
label.TraefikFrontendWhiteListUseXForwardedFor: "true",
},
expected: &types.WhiteList{
SourceRange: []string{
"10.10.10.10",
},
UseXForwardedFor: true,
},
},
{
desc: "should return a struct when mix deprecated label and new labels",
labels: map[string]string{
label.TraefikFrontendWhitelistSourceRange: "20.20.20.20",
label.TraefikFrontendWhiteListSourceRange: "10.10.10.10",
label.TraefikFrontendWhiteListUseXForwardedFor: "true",
},
expected: &types.WhiteList{
SourceRange: []string{
"10.10.10.10",
},
UseXForwardedFor: true,
},
},
{
desc: "should return nil when only UseXForwardedFor",
labels: map[string]string{
label.TraefikFrontendWhiteListUseXForwardedFor: "true",
},
expected: nil,
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
actual := getWhiteList(test.labels)
assert.Equal(t, test.expected, actual)
})
}
}

View file

@ -122,16 +122,17 @@ func TestSwarmBuildConfiguration(t *testing.T) {
label.TraefikBackendBufferingMemRequestBodyBytes: "2097152",
label.TraefikBackendBufferingRetryExpression: "IsNetworkError() && Attempts() <= 2",
label.TraefikFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
label.TraefikFrontendEntryPoints: "http,https",
label.TraefikFrontendPassHostHeader: "true",
label.TraefikFrontendPassTLSCert: "true",
label.TraefikFrontendPriority: "666",
label.TraefikFrontendRedirectEntryPoint: "https",
label.TraefikFrontendRedirectRegex: "nope",
label.TraefikFrontendRedirectReplacement: "nope",
label.TraefikFrontendRule: "Host:traefik.io",
label.TraefikFrontendWhitelistSourceRange: "10.10.10.10",
label.TraefikFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
label.TraefikFrontendEntryPoints: "http,https",
label.TraefikFrontendPassHostHeader: "true",
label.TraefikFrontendPassTLSCert: "true",
label.TraefikFrontendPriority: "666",
label.TraefikFrontendRedirectEntryPoint: "https",
label.TraefikFrontendRedirectRegex: "nope",
label.TraefikFrontendRedirectReplacement: "nope",
label.TraefikFrontendRule: "Host:traefik.io",
label.TraefikFrontendWhiteListSourceRange: "10.10.10.10",
label.TraefikFrontendWhiteListUseXForwardedFor: "true",
label.TraefikFrontendRequestHeaders: "Access-Control-Allow-Methods:POST,GET,OPTIONS || Content-type: application/json; charset=utf-8",
label.TraefikFrontendResponseHeaders: "Access-Control-Allow-Methods:POST,GET,OPTIONS || Content-type: application/json; charset=utf-8",
@ -193,8 +194,9 @@ func TestSwarmBuildConfiguration(t *testing.T) {
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
},
WhitelistSourceRange: []string{
"10.10.10.10",
WhiteList: &types.WhiteList{
SourceRange: []string{"10.10.10.10"},
UseXForwardedFor: true,
},
Headers: &types.Headers{
CustomRequestHeaders: map[string]string{

View file

@ -76,16 +76,17 @@ func TestSegmentBuildConfiguration(t *testing.T) {
label.Prefix + "sauternes." + label.SuffixProtocol: "https",
label.Prefix + "sauternes." + label.SuffixWeight: "12",
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
label.Prefix + "sauternes." + label.SuffixFrontendEntryPoints: "http,https",
label.Prefix + "sauternes." + label.SuffixFrontendPassHostHeader: "true",
label.Prefix + "sauternes." + label.SuffixFrontendPassTLSCert: "true",
label.Prefix + "sauternes." + label.SuffixFrontendPriority: "666",
label.Prefix + "sauternes." + label.SuffixFrontendRedirectEntryPoint: "https",
label.Prefix + "sauternes." + label.SuffixFrontendRedirectRegex: "nope",
label.Prefix + "sauternes." + label.SuffixFrontendRedirectReplacement: "nope",
label.Prefix + "sauternes." + label.SuffixFrontendRedirectPermanent: "true",
label.Prefix + "sauternes." + label.SuffixFrontendWhitelistSourceRange: "10.10.10.10",
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
label.Prefix + "sauternes." + label.SuffixFrontendEntryPoints: "http,https",
label.Prefix + "sauternes." + label.SuffixFrontendPassHostHeader: "true",
label.Prefix + "sauternes." + label.SuffixFrontendPassTLSCert: "true",
label.Prefix + "sauternes." + label.SuffixFrontendPriority: "666",
label.Prefix + "sauternes." + label.SuffixFrontendRedirectEntryPoint: "https",
label.Prefix + "sauternes." + label.SuffixFrontendRedirectRegex: "nope",
label.Prefix + "sauternes." + label.SuffixFrontendRedirectReplacement: "nope",
label.Prefix + "sauternes." + label.SuffixFrontendRedirectPermanent: "true",
label.Prefix + "sauternes." + label.SuffixFrontendWhiteListSourceRange: "10.10.10.10",
label.Prefix + "sauternes." + label.SuffixFrontendWhiteListUseXForwardedFor: "true",
label.Prefix + "sauternes." + label.SuffixFrontendRequestHeaders: "Access-Control-Allow-Methods:POST,GET,OPTIONS || Content-type: application/json; charset=utf-8",
label.Prefix + "sauternes." + label.SuffixFrontendResponseHeaders: "Access-Control-Allow-Methods:POST,GET,OPTIONS || Content-type: application/json; charset=utf-8",
@ -144,8 +145,9 @@ func TestSegmentBuildConfiguration(t *testing.T) {
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
},
WhitelistSourceRange: []string{
"10.10.10.10",
WhiteList: &types.WhiteList{
SourceRange: []string{"10.10.10.10"},
UseXForwardedFor: true,
},
Headers: &types.Headers{
CustomRequestHeaders: map[string]string{

View file

@ -103,7 +103,7 @@ func (p *Provider) buildConfigurationV1(containersInspected []dockerData) *types
"getServiceWeight": getFuncServiceStringLabelV1(label.SuffixWeight, label.DefaultWeight),
// Services - Frontend functions
"getServiceEntryPoints": getFuncServiceSliceStringLabelV1(label.SuffixFrontendEntryPoints),
"getServiceWhitelistSourceRange": getFuncServiceSliceStringLabelV1(label.SuffixFrontendWhitelistSourceRange),
"getServiceWhitelistSourceRange": getFuncServiceSliceStringLabelV1(label.SuffixFrontendWhiteListSourceRange),
"getServiceBasicAuth": getFuncServiceSliceStringLabelV1(label.SuffixFrontendAuthBasic),
"getServiceFrontendRule": p.getServiceFrontendRuleV1,
"getServicePassHostHeader": getFuncServiceBoolLabelV1(label.SuffixFrontendPassHostHeader, label.DefaultPassHostHeaderBool),