1
0
Fork 0

Define TLS options on the Router configuration

Co-authored-by: juliens <julien@containo.us>
This commit is contained in:
Jean-Baptiste Doumenjou 2019-06-17 18:14:08 +02:00 committed by Traefiker Bot
parent d306c8fd50
commit 85ce16b34f
24 changed files with 958 additions and 148 deletions

View file

@ -22,7 +22,9 @@ type Router struct {
}
// RouterTLSConfig holds the TLS configuration for a router
type RouterTLSConfig struct{}
type RouterTLSConfig struct {
Options string `json:"options,omitempty" toml:"options,omitzero"`
}
// TCPRouter holds the router configuration.
type TCPRouter struct {
@ -34,7 +36,8 @@ type TCPRouter struct {
// RouterTCPTLSConfig holds the TLS configuration for a router
type RouterTCPTLSConfig struct {
Passthrough bool `json:"passthrough" toml:"passthrough,omitzero"`
Passthrough bool `json:"passthrough" toml:"passthrough,omitzero"`
Options string `json:"options,omitempty" toml:"options,omitzero"`
}
// LoadBalancerService holds the LoadBalancerService configuration.

View file

@ -162,9 +162,11 @@ func TestDecodeConfiguration(t *testing.T) {
"traefik.tcp.routers.Router0.entrypoints": "foobar, fiibar",
"traefik.tcp.routers.Router0.service": "foobar",
"traefik.tcp.routers.Router0.tls.passthrough": "false",
"traefik.tcp.routers.Router0.tls.options": "foo",
"traefik.tcp.routers.Router1.rule": "foobar",
"traefik.tcp.routers.Router1.entrypoints": "foobar, fiibar",
"traefik.tcp.routers.Router1.service": "foobar",
"traefik.tcp.routers.Router1.tls.options": "foo",
"traefik.tcp.routers.Router1.tls.passthrough": "false",
"traefik.tcp.services.Service0.loadbalancer.server.Port": "42",
"traefik.tcp.services.Service1.loadbalancer.server.Port": "42",
@ -185,6 +187,7 @@ func TestDecodeConfiguration(t *testing.T) {
Rule: "foobar",
TLS: &config.RouterTCPTLSConfig{
Passthrough: false,
Options: "foo",
},
},
"Router1": {
@ -196,6 +199,7 @@ func TestDecodeConfiguration(t *testing.T) {
Rule: "foobar",
TLS: &config.RouterTCPTLSConfig{
Passthrough: false,
Options: "foo",
},
},
},
@ -580,6 +584,7 @@ func TestEncodeConfiguration(t *testing.T) {
Rule: "foobar",
TLS: &config.RouterTCPTLSConfig{
Passthrough: false,
Options: "foo",
},
},
"Router1": {
@ -591,6 +596,7 @@ func TestEncodeConfiguration(t *testing.T) {
Rule: "foobar",
TLS: &config.RouterTCPTLSConfig{
Passthrough: false,
Options: "foo",
},
},
},
@ -1110,10 +1116,12 @@ func TestEncodeConfiguration(t *testing.T) {
"traefik.TCP.Routers.Router0.EntryPoints": "foobar, fiibar",
"traefik.TCP.Routers.Router0.Service": "foobar",
"traefik.TCP.Routers.Router0.TLS.Passthrough": "false",
"traefik.TCP.Routers.Router0.TLS.Options": "foo",
"traefik.TCP.Routers.Router1.Rule": "foobar",
"traefik.TCP.Routers.Router1.EntryPoints": "foobar, fiibar",
"traefik.TCP.Routers.Router1.Service": "foobar",
"traefik.TCP.Routers.Router1.TLS.Passthrough": "false",
"traefik.TCP.Routers.Router1.TLS.Options": "foo",
"traefik.TCP.Services.Service0.LoadBalancer.server.Port": "42",
"traefik.TCP.Services.Service1.LoadBalancer.server.Port": "42",
}

View file

@ -1,6 +1,7 @@
package config
import (
"context"
"sort"
"strings"
"sync"
@ -128,6 +129,74 @@ func (r *RuntimeConfiguration) PopulateUsedBy() {
}
}
func contains(entryPoints []string, entryPointName string) bool {
for _, name := range entryPoints {
if name == entryPointName {
return true
}
}
return false
}
// GetRoutersByEntrypoints returns all the http routers by entrypoints name and routers name
func (r *RuntimeConfiguration) GetRoutersByEntrypoints(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*RouterInfo {
entryPointsRouters := make(map[string]map[string]*RouterInfo)
for rtName, rt := range r.Routers {
if (tls && rt.TLS == nil) || (!tls && rt.TLS != nil) {
continue
}
eps := rt.EntryPoints
if len(eps) == 0 {
eps = entryPoints
}
for _, entryPointName := range eps {
if !contains(entryPoints, entryPointName) {
log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))).
Errorf("entryPoint %q doesn't exist", entryPointName)
continue
}
if _, ok := entryPointsRouters[entryPointName]; !ok {
entryPointsRouters[entryPointName] = make(map[string]*RouterInfo)
}
entryPointsRouters[entryPointName][rtName] = rt
}
}
return entryPointsRouters
}
// GetTCPRoutersByEntrypoints returns all the tcp routers by entrypoints name and routers name
func (r *RuntimeConfiguration) GetTCPRoutersByEntrypoints(ctx context.Context, entryPoints []string) map[string]map[string]*TCPRouterInfo {
entryPointsRouters := make(map[string]map[string]*TCPRouterInfo)
for rtName, rt := range r.TCPRouters {
eps := rt.EntryPoints
if len(eps) == 0 {
eps = entryPoints
}
for _, entryPointName := range eps {
if !contains(entryPoints, entryPointName) {
log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))).
Errorf("entryPoint %q doesn't exist", entryPointName)
continue
}
if _, ok := entryPointsRouters[entryPointName]; !ok {
entryPointsRouters[entryPointName] = make(map[string]*TCPRouterInfo)
}
entryPointsRouters[entryPointName][rtName] = rt
}
}
return entryPointsRouters
}
// RouterInfo holds information about a currently running HTTP router
type RouterInfo struct {
*Router // dynamic configuration

View file

@ -1,6 +1,7 @@
package config_test
import (
"context"
"testing"
"github.com/containous/traefik/pkg/config"
@ -688,3 +689,399 @@ func TestPopulateUsedby(t *testing.T) {
}
}
func TestGetTCPRoutersByEntrypoints(t *testing.T) {
testCases := []struct {
desc string
conf config.Configuration
entryPoints []string
expected map[string]map[string]*config.TCPRouterInfo
}{
{
desc: "Empty Configuration without entrypoint",
conf: config.Configuration{},
entryPoints: []string{""},
expected: map[string]map[string]*config.TCPRouterInfo{},
},
{
desc: "Empty Configuration with unknown entrypoints",
conf: config.Configuration{},
entryPoints: []string{"foo"},
expected: map[string]map[string]*config.TCPRouterInfo{},
},
{
desc: "Valid configuration with an unknown entrypoint",
conf: config.Configuration{
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "Host(`bar.foo`)",
},
},
},
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "HostSNI(`bar.foo`)",
},
},
},
},
entryPoints: []string{"foo"},
expected: map[string]map[string]*config.TCPRouterInfo{},
},
{
desc: "Valid configuration with a known entrypoint",
conf: config.Configuration{
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "Host(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "Host(`foo.bar`)",
},
"foobar": {
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "Host(`bar.foobar`)",
},
},
},
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "HostSNI(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "HostSNI(`foo.bar`)",
},
"foobar": {
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "HostSNI(`bar.foobar`)",
},
},
},
},
entryPoints: []string{"web"},
expected: map[string]map[string]*config.TCPRouterInfo{
"web": {
"foo": {
TCPRouter: &config.TCPRouter{
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "HostSNI(`bar.foo`)",
},
},
"foobar": {
TCPRouter: &config.TCPRouter{
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "HostSNI(`bar.foobar`)",
},
},
},
},
},
{
desc: "Valid configuration with multiple known entrypoints",
conf: config.Configuration{
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "Host(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "Host(`foo.bar`)",
},
"foobar": {
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "Host(`bar.foobar`)",
},
},
},
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "HostSNI(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "HostSNI(`foo.bar`)",
},
"foobar": {
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "HostSNI(`bar.foobar`)",
},
},
},
},
entryPoints: []string{"web", "webs"},
expected: map[string]map[string]*config.TCPRouterInfo{
"web": {
"foo": {
TCPRouter: &config.TCPRouter{
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "HostSNI(`bar.foo`)",
},
},
"foobar": {
TCPRouter: &config.TCPRouter{
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "HostSNI(`bar.foobar`)",
},
},
},
"webs": {
"bar": {
TCPRouter: &config.TCPRouter{
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "HostSNI(`foo.bar`)",
},
},
"foobar": {
TCPRouter: &config.TCPRouter{
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "HostSNI(`bar.foobar`)",
},
},
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
runtimeConfig := config.NewRuntimeConfig(test.conf)
actual := runtimeConfig.GetTCPRoutersByEntrypoints(context.Background(), test.entryPoints)
assert.Equal(t, test.expected, actual)
})
}
}
func TestGetRoutersByEntrypoints(t *testing.T) {
testCases := []struct {
desc string
conf config.Configuration
entryPoints []string
expected map[string]map[string]*config.RouterInfo
}{
{
desc: "Empty Configuration without entrypoint",
conf: config.Configuration{},
entryPoints: []string{""},
expected: map[string]map[string]*config.RouterInfo{},
},
{
desc: "Empty Configuration with unknown entrypoints",
conf: config.Configuration{},
entryPoints: []string{"foo"},
expected: map[string]map[string]*config.RouterInfo{},
},
{
desc: "Valid configuration with an unknown entrypoint",
conf: config.Configuration{
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "Host(`bar.foo`)",
},
},
},
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "HostSNI(`bar.foo`)",
},
},
},
},
entryPoints: []string{"foo"},
expected: map[string]map[string]*config.RouterInfo{},
},
{
desc: "Valid configuration with a known entrypoint",
conf: config.Configuration{
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "Host(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "Host(`foo.bar`)",
},
"foobar": {
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "Host(`bar.foobar`)",
},
},
},
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "HostSNI(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "HostSNI(`foo.bar`)",
},
"foobar": {
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "HostSNI(`bar.foobar`)",
},
},
},
},
entryPoints: []string{"web"},
expected: map[string]map[string]*config.RouterInfo{
"web": {
"foo": {
Router: &config.Router{
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "Host(`bar.foo`)",
},
},
"foobar": {
Router: &config.Router{
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "Host(`bar.foobar`)",
},
},
},
},
},
{
desc: "Valid configuration with multiple known entrypoints",
conf: config.Configuration{
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "Host(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "Host(`foo.bar`)",
},
"foobar": {
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "Host(`bar.foobar`)",
},
},
},
TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{
"foo": {
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "HostSNI(`bar.foo`)",
},
"bar": {
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "HostSNI(`foo.bar`)",
},
"foobar": {
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "HostSNI(`bar.foobar`)",
},
},
},
},
entryPoints: []string{"web", "webs"},
expected: map[string]map[string]*config.RouterInfo{
"web": {
"foo": {
Router: &config.Router{
EntryPoints: []string{"web"},
Service: "myprovider.foo-service",
Rule: "Host(`bar.foo`)",
},
},
"foobar": {
Router: &config.Router{
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "Host(`bar.foobar`)",
},
},
},
"webs": {
"bar": {
Router: &config.Router{
EntryPoints: []string{"webs"},
Service: "myprovider.bar-service",
Rule: "Host(`foo.bar`)",
},
},
"foobar": {
Router: &config.Router{
EntryPoints: []string{"web", "webs"},
Service: "myprovider.foobar-service",
Rule: "Host(`bar.foobar`)",
},
},
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
runtimeConfig := config.NewRuntimeConfig(test.conf)
actual := runtimeConfig.GetRoutersByEntrypoints(context.Background(), test.entryPoints, false)
assert.Equal(t, test.expected, actual)
})
}
}