1
0
Fork 0

Merge current v2.4 into master

This commit is contained in:
romain 2021-06-22 14:05:57 +02:00
commit ce2e02b690
119 changed files with 4628 additions and 4165 deletions

View file

@ -190,7 +190,7 @@
},
"rateLimit": {
"average": 42,
"period": 42,
"period": "42ns",
"burst": 42,
"sourceCriterion": {
"ipStrategy": {
@ -306,7 +306,7 @@
},
"retry": {
"attempts": 42,
"initialInterval": 42
"initialInterval": "42ns"
},
"contentType": {
"autoDetect": true
@ -352,9 +352,9 @@
],
"maxIdleConnsPerHost": 42,
"forwardingTimeouts": {
"dialTimeout": 42,
"responseHeaderTimeout": 42,
"idleConnTimeout": 42
"dialTimeout": "42ns",
"responseHeaderTimeout": "42ns",
"idleConnTimeout": "42ns"
}
}
}
@ -473,4 +473,4 @@
}
}
}
}
}

View file

@ -12,9 +12,9 @@
],
"maxIdleConnsPerHost": 111,
"forwardingTimeouts": {
"dialTimeout": 111000000000,
"responseHeaderTimeout": 111000000000,
"idleConnTimeout": 111000000000
"dialTimeout": "1m51s",
"responseHeaderTimeout": "1m51s",
"idleConnTimeout": "1m51s"
}
},
"entryPoints": {
@ -22,13 +22,13 @@
"address": "xxxx",
"transport": {
"lifeCycle": {
"requestAcceptGraceTimeout": 111000000000,
"graceTimeOut": 111000000000
"requestAcceptGraceTimeout": "1m51s",
"graceTimeOut": "1m51s"
},
"respondingTimeouts": {
"readTimeout": 111000000000,
"writeTimeout": 111000000000,
"idleTimeout": 111000000000
"readTimeout": "1m51s",
"writeTimeout": "1m51s",
"idleTimeout": "1m51s"
}
},
"proxyProtocol": {
@ -75,7 +75,7 @@
}
},
"providers": {
"providersThrottleDuration": 111000000000,
"providersThrottleDuration": "1m51s",
"docker": {
"constraints": "Label(\"foo\", \"bar\")",
"watch": true,
@ -92,8 +92,8 @@
"useBindPortIP": true,
"swarmMode": true,
"network": "MyNetwork",
"swarmModeRefreshSeconds": 42,
"httpClientTimeout": 42
"swarmModeRefreshSeconds": "42ns",
"httpClientTimeout": "42ns"
},
"file": {
"directory": "file Directory",
@ -116,10 +116,10 @@
"key": "xxxx",
"insecureSkipVerify": true
},
"dialerTimeout": 42,
"responseHeaderTimeout": 42,
"tlsHandshakeTimeout": 42,
"keepAlive": 42,
"dialerTimeout": "42ns",
"responseHeaderTimeout": "42ns",
"tlsHandshakeTimeout": "42ns",
"keepAlive": "42ns",
"forceTaskHostname": true,
"basic": {
"httpBasicAuthUser": "xxxx",
@ -142,7 +142,7 @@
"hostname": "xxxx",
"publishedService": "xxxx"
},
"throttleDuration": 111000000000
"throttleDuration": "1m51s"
},
"kubernetesCRD": {
"endpoint": "xxxx",
@ -154,7 +154,7 @@
],
"labelSelector": "myLabelSelector",
"ingressClass": "MyIngressClass",
"throttleDuration": 111000000000
"throttleDuration": "1m51s"
},
"kubernetesGateway": {
"endpoint": "xxxx",
@ -165,7 +165,7 @@
"b"
],
"labelSelector": "myLabelSelector",
"throttleDuration": 111000000000
"throttleDuration": "1m51s"
},
"rest": {
"insecure": true
@ -198,10 +198,10 @@
"username": "xxxx",
"password": "xxxx"
},
"endpointWaitTime": 42
"endpointWaitTime": "42ns"
},
"prefix": "MyPrefix",
"refreshInterval": 42,
"refreshInterval": "42ns",
"requireConsistent": true,
"stale": true,
"cache": true,
@ -272,8 +272,8 @@
},
"http": {
"endpoint": "xxxx",
"pollInterval": 42,
"pollTimeout": 42,
"pollInterval": "42ns",
"pollTimeout": "42ns",
"tls": {
"ca": "xxxx",
"caOptional": true,
@ -303,13 +303,13 @@
},
"datadog": {
"address": "xxxx",
"pushInterval": 42,
"pushInterval": "42ns",
"addEntryPointsLabels": true,
"addServicesLabels": true
},
"statsD": {
"address": "xxxx",
"pushInterval": 42,
"pushInterval": "42ns",
"addEntryPointsLabels": true,
"addServicesLabels": true,
"prefix": "MyPrefix"
@ -317,7 +317,7 @@
"influxDB": {
"address": "xxxx",
"protocol": "xxxx",
"pushInterval": 42,
"pushInterval": "42ns",
"database": "myDB",
"retentionPolicy": "12",
"username": "xxxx",
@ -345,7 +345,7 @@
"500"
],
"retryAttempts": true,
"minDuration": 42
"minDuration": "42ns"
},
"fields": {
"defaultMode": "drop",
@ -428,7 +428,7 @@
"keyType": "MyKeyType",
"dnsChallenge": {
"provider": "DNSProvider",
"delayBeforeCheck": 42,
"delayBeforeCheck": "42ns",
"resolvers": [
"xxxx",
"xxxx"

View file

@ -19,13 +19,13 @@
},
"transport": {
"lifeCycle": {
"graceTimeOut": 2,
"requestAcceptGraceTimeout": 1
"graceTimeOut": "2ns",
"requestAcceptGraceTimeout": "1ns"
},
"respondingTimeouts": {
"idleTimeout": 5,
"readTimeout": 3,
"writeTimeout": 4
"idleTimeout": "5ns",
"readTimeout": "3ns",
"writeTimeout": "4ns"
}
}
},
@ -49,14 +49,14 @@
},
"transport": {
"lifeCycle": {
"graceTimeOut": 20,
"requestAcceptGraceTimeout": 10
"graceTimeOut": "20ns",
"requestAcceptGraceTimeout": "10ns"
},
"respondingTimeouts": {
"idleTimeout": 50,
"readTimeout": 30,
"writeTimeout": 40
"idleTimeout": "50ns",
"readTimeout": "30ns",
"writeTimeout": "40ns"
}
}
}
]
]

View file

@ -246,7 +246,7 @@ type IPStrategy struct {
// Get an IP selection strategy.
// If nil return the RemoteAddr strategy
// else return a strategy base on the configuration using the X-Forwarded-For Header.
// else return a strategy based on the configuration using the X-Forwarded-For Header.
// Depth override the ExcludedIPs.
func (s *IPStrategy) Get() (ip.Strategy, error) {
if s == nil {
@ -264,7 +264,7 @@ func (s *IPStrategy) Get() (ip.Strategy, error) {
if err != nil {
return nil, err
}
return &ip.CheckerStrategy{
return &ip.PoolStrategy{
Checker: checker,
}, nil
}

View file

@ -15,14 +15,8 @@ func (c *Configuration) GetTCPRoutersByEntryPoints(ctx context.Context, entryPoi
for rtName, rt := range c.TCPRouters {
logger := log.FromContext(log.With(ctx, log.Str(log.RouterName, rtName)))
eps := rt.EntryPoints
if len(eps) == 0 {
logger.Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints)
eps = entryPoints
}
entryPointsCount := 0
for _, entryPointName := range eps {
for _, entryPointName := range rt.EntryPoints {
if !contains(entryPoints, entryPointName) {
rt.AddError(fmt.Errorf("entryPoint %q doesn't exist", entryPointName), false)
logger.WithField(log.EntryPointName, entryPointName).

View file

@ -43,14 +43,16 @@ func (s *DepthStrategy) GetIP(req *http.Request) string {
return strings.TrimSpace(xffs[len(xffs)-s.Depth])
}
// CheckerStrategy a strategy based on an IP Checker
// allows to check that addresses are in a trusted IPs.
type CheckerStrategy struct {
// PoolStrategy is a strategy based on an IP Checker.
// It allows to check whether addresses are in a given pool of IPs.
type PoolStrategy struct {
Checker *Checker
}
// GetIP return the selected IP.
func (s *CheckerStrategy) GetIP(req *http.Request) string {
// GetIP checks the list of Forwarded IPs (most recent first) against the
// Checker pool of IPs. It returns the first IP that is not in the pool, or the
// empty string otherwise.
func (s *PoolStrategy) GetIP(req *http.Request) string {
if s.Checker == nil {
return ""
}
@ -60,9 +62,13 @@ func (s *CheckerStrategy) GetIP(req *http.Request) string {
for i := len(xffs) - 1; i >= 0; i-- {
xffTrimmed := strings.TrimSpace(xffs[i])
if len(xffTrimmed) == 0 {
continue
}
if contain, _ := s.Checker.Contains(xffTrimmed); !contain {
return xffTrimmed
}
}
return ""
}

View file

@ -74,34 +74,35 @@ func TestDepthStrategy_GetIP(t *testing.T) {
}
}
func TestExcludedIPsStrategy_GetIP(t *testing.T) {
func TestTrustedIPsStrategy_GetIP(t *testing.T) {
testCases := []struct {
desc string
excludedIPs []string
trustedIPs []string
xForwardedFor string
expected string
useRemote bool
}{
{
desc: "Use excluded all IPs",
excludedIPs: []string{"10.0.0.4", "10.0.0.3", "10.0.0.2", "10.0.0.1"},
desc: "Trust all IPs",
trustedIPs: []string{"10.0.0.4", "10.0.0.3", "10.0.0.2", "10.0.0.1"},
xForwardedFor: "10.0.0.4,10.0.0.3,10.0.0.2,10.0.0.1",
expected: "",
},
{
desc: "Use excluded IPs",
excludedIPs: []string{"10.0.0.2", "10.0.0.1"},
desc: "Do not trust all IPs",
trustedIPs: []string{"10.0.0.2", "10.0.0.1"},
xForwardedFor: "10.0.0.4,10.0.0.3,10.0.0.2,10.0.0.1",
expected: "10.0.0.3",
},
{
desc: "Use excluded IPs CIDR",
excludedIPs: []string{"10.0.0.1/24"},
desc: "Do not trust all IPs with CIDR",
trustedIPs: []string{"10.0.0.1/24"},
xForwardedFor: "127.0.0.1,10.0.0.4,10.0.0.3,10.0.0.2,10.0.0.1",
expected: "127.0.0.1",
},
{
desc: "Use excluded all IPs CIDR",
excludedIPs: []string{"10.0.0.1/24"},
desc: "Trust all IPs with CIDR",
trustedIPs: []string{"10.0.0.1/24"},
xForwardedFor: "10.0.0.4,10.0.0.3,10.0.0.2,10.0.0.1",
expected: "",
},
@ -112,10 +113,10 @@ func TestExcludedIPsStrategy_GetIP(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
checker, err := NewChecker(test.excludedIPs)
checker, err := NewChecker(test.trustedIPs)
require.NoError(t, err)
strategy := CheckerStrategy{Checker: checker}
strategy := PoolStrategy{Checker: checker}
req := httptest.NewRequest(http.MethodGet, "http://127.0.0.1", nil)
req.Header.Set(xForwardedFor, test.xForwardedFor)
actual := strategy.GetIP(req)

View file

@ -56,7 +56,7 @@ func (n MockSpan) Tracer() opentracing.Tracer { retu
func (n MockSpan) LogEvent(event string) {}
func (n MockSpan) LogEventWithPayload(event string, payload interface{}) {}
func (n MockSpan) Log(data opentracing.LogData) {}
func (n MockSpan) Reset() {
func (n *MockSpan) Reset() {
n.Tags = make(map[string]interface{})
}

View file

@ -281,7 +281,7 @@ func unzipFile(f *zipa.File, dest string) error {
defer func() { _ = rc.Close() }()
pathParts := strings.SplitN(f.Name, string(os.PathSeparator), 2)
pathParts := strings.SplitN(f.Name, "/", 2)
p := filepath.Join(dest, pathParts[1])
if f.FileInfo().IsDir() {

View file

@ -473,9 +473,10 @@ func (p *Provider) resolveCertificate(ctx context.Context, domain types.Domain,
}
request := certificate.ObtainRequest{
Domains: domains,
Bundle: true,
MustStaple: oscpMustStaple,
Domains: domains,
Bundle: true,
MustStaple: oscpMustStaple,
PreferredChain: p.PreferredChain,
}
cert, err := client.Certificate.Obtain(request)

View file

@ -26,7 +26,7 @@ var _ provider.Provider = (*Provider)(nil)
// Provider holds configurations of the provider.
type Provider struct {
Directory string `description:"Load dynamic configuration from one or more .toml or .yml files in a directory." json:"directory,omitempty" toml:"directory,omitempty" yaml:"directory,omitempty" export:"true"`
Directory string `description:"Load dynamic configuration from one or more .yml or .toml files in a directory." json:"directory,omitempty" toml:"directory,omitempty" yaml:"directory,omitempty" export:"true"`
Watch bool `description:"Watch provider." json:"watch,omitempty" toml:"watch,omitempty" yaml:"watch,omitempty" export:"true"`
Filename string `description:"Load dynamic configuration from a file." json:"filename,omitempty" toml:"filename,omitempty" yaml:"filename,omitempty" export:"true"`
DebugLogGeneratedTemplate bool `description:"Enable debug logging of generated configuration template." json:"debugLogGeneratedTemplate,omitempty" toml:"debugLogGeneratedTemplate,omitempty" yaml:"debugLogGeneratedTemplate,omitempty" export:"true"`

View file

@ -0,0 +1,20 @@
kind: Endpoints
apiVersion: v1
metadata:
name: service1
namespace: testing
subsets:
- addresses:
- ip: 10.10.0.1
- ip: 10.10.0.2
ports:
- name: tchouk
port: 8089
- addresses:
- ip: 10.10.0.1
- ip: 10.10.0.2
- ip: 10.10.0.3
ports:
- name: carotte
port: 8090

View file

@ -0,0 +1,15 @@
kind: Ingress
apiVersion: networking.k8s.io/v1beta1
metadata:
name: ""
namespace: testing
spec:
rules:
- host: traefik.tchouk
http:
paths:
- path: /bar
backend:
serviceName: service1
servicePort: tchouk

View file

@ -0,0 +1,14 @@
kind: Service
apiVersion: v1
metadata:
name: service1
namespace: testing
spec:
ports:
- name: carotte
port: 8082
- name: tchouk
port: 80
clusterIP: 10.0.0.1

View file

@ -555,8 +555,8 @@ func loadService(client Client, namespace string, backend networkingv1.IngressBa
return nil, errors.New("endpoints not found")
}
var port int32
for _, subset := range endpoints.Subsets {
var port int32
for _, p := range subset.Ports {
if portName == p.Name {
port = p.Port

View file

@ -647,6 +647,36 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
},
},
},
{
desc: "Ingress with a named port matching subset of service pods",
expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{},
HTTP: &dynamic.HTTPConfiguration{
Middlewares: map[string]*dynamic.Middleware{},
Routers: map[string]*dynamic.Router{
"testing-traefik-tchouk-bar": {
Rule: "Host(`traefik.tchouk`) && PathPrefix(`/bar`)",
Service: "testing-service1-tchouk",
},
},
Services: map[string]*dynamic.Service{
"testing-service1-tchouk": {
LoadBalancer: &dynamic.ServersLoadBalancer{
PassHostHeader: Bool(true),
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:8089",
},
{
URL: "http://10.10.0.2:8089",
},
},
},
},
},
},
},
},
{
desc: "2 ingresses in different namespace with same service name",
expected: &dynamic.Configuration{

View file

@ -62,6 +62,12 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint
if configuration.TCP != nil {
for routerName, router := range configuration.TCP.Routers {
if len(router.EntryPoints) == 0 {
log.WithoutContext().
WithField(log.RouterName, routerName).
Debugf("No entryPoint defined for this TCP router, using the default one(s) instead: %+v", defaultEntryPoints)
router.EntryPoints = defaultEntryPoints
}
conf.TCP.Routers[provider.MakeQualifiedName(pvd, routerName)] = router
}
for middlewareName, middleware := range configuration.TCP.Middlewares {

View file

@ -449,6 +449,36 @@ func Test_mergeConfiguration_tlsStore(t *testing.T) {
}
}
func Test_mergeConfiguration_defaultTCPEntryPoint(t *testing.T) {
given := dynamic.Configurations{
"provider-1": &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{
"router-1": {},
},
Services: map[string]*dynamic.TCPService{
"service-1": {},
},
},
},
}
expected := &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{
"router-1@provider-1": {
EntryPoints: []string{"defaultEP"},
},
},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{
"service-1@provider-1": {},
},
}
actual := mergeConfiguration(given, []string{"defaultEP"})
assert.Equal(t, expected, actual.TCP)
}
func Test_applyModel(t *testing.T) {
testCases := []struct {
desc string

View file

@ -15,6 +15,8 @@ import (
"github.com/traefik/traefik/v2/pkg/types"
)
const defaultBufSize = 4096
// Router is a TCP router.
type Router struct {
routingTable map[string]Handler
@ -238,6 +240,11 @@ func clientHelloServerName(br *bufio.Reader) (string, bool, string, error) {
}
recLen := int(hdr[3])<<8 | int(hdr[4]) // ignoring version in hdr[1:3]
if recordHeaderLen+recLen > defaultBufSize {
br = bufio.NewReaderSize(br, recordHeaderLen+recLen)
}
helloBytes, err := br.Peek(recordHeaderLen + recLen)
if err != nil {
log.Errorf("Error while Hello: %s", err)