From 6906a022ca49bf5c52b3cba7bb83536e15e9afff Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Mon, 20 Sep 2021 12:54:05 +0200 Subject: [PATCH] Add cross namespace verification in Kubernetes CRD --- .../tcp/with_tls_options_cross_namespace.yml | 30 ++ .../crd/fixtures/with_cross_namespace.yml | 2 +- .../crd/fixtures/with_servers_transport.yml | 3 - ...with_servers_transport_cross_namespace.yml | 29 ++ .../with_tls_options_cross_namespace.yml | 31 ++ .../kubernetes/crd/kubernetes_http.go | 19 +- pkg/provider/kubernetes/crd/kubernetes_tcp.go | 44 +- .../kubernetes/crd/kubernetes_test.go | 389 +++++++++++++----- 8 files changed, 418 insertions(+), 129 deletions(-) create mode 100644 pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_cross_namespace.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/with_servers_transport_cross_namespace.yml create mode 100644 pkg/provider/kubernetes/crd/fixtures/with_tls_options_cross_namespace.yml diff --git a/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_cross_namespace.yml new file mode 100644 index 000000000..13958f95d --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/tcp/with_tls_options_cross_namespace.yml @@ -0,0 +1,30 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRouteTCP +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: HostSNI(`foo.com`) + services: + - name: whoamitcp + port: 8000 + + tls: + options: + name: tls-options-cn + namespace: cross-ns + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: TLSOption +metadata: + name: tls-options-cn + namespace: cross-ns + +spec: + minVersion: VersionTLS12 diff --git a/pkg/provider/kubernetes/crd/fixtures/with_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_cross_namespace.yml index 5054eb819..543c5696c 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_cross_namespace.yml @@ -33,7 +33,7 @@ spec: - name: whoami-svc namespace: cross-ns port: 80 - serversTransport: test + serversTransport: foo-test@kubernetescrd --- apiVersion: traefik.containo.us/v1alpha1 diff --git a/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml index c7c58219d..994941f06 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml @@ -142,7 +142,4 @@ spec: - name: whoamitls port: 443 serversTransport: default-test - - name: whoami3 - port: 8443 - serversTransport: foo-test@kubernetescrd diff --git a/pkg/provider/kubernetes/crd/fixtures/with_servers_transport_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport_cross_namespace.yml new file mode 100644 index 000000000..7b9ab8891 --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport_cross_namespace.yml @@ -0,0 +1,29 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: Host(`foo.com`) && PathPrefix(`/bar`) + kind: Rule + priority: 12 + services: + - name: whoami + port: 80 + serversTransport: cross-ns-st-cross-ns@kubernetescrd + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: ServersTransport +metadata: + name: st-cross-ns + namespace: cross-ns + +spec: + disableHTTP2: true + diff --git a/pkg/provider/kubernetes/crd/fixtures/with_tls_options_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_tls_options_cross_namespace.yml new file mode 100644 index 000000000..57228278b --- /dev/null +++ b/pkg/provider/kubernetes/crd/fixtures/with_tls_options_cross_namespace.yml @@ -0,0 +1,31 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: test.route + namespace: default + +spec: + entryPoints: + - foo + + routes: + - match: Host(`foo.com`) && PathPrefix(`/bar`) + kind: Rule + priority: 12 + services: + - name: whoami + port: 80 + tls: + options: + name: tls-options-cn + namespace: cross-ns + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: TLSOption +metadata: + name: tls-options-cn + namespace: cross-ns + +spec: + minVersion: VersionTLS12 diff --git a/pkg/provider/kubernetes/crd/kubernetes_http.go b/pkg/provider/kubernetes/crd/kubernetes_http.go index eee924546..b78d14c31 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_http.go +++ b/pkg/provider/kubernetes/crd/kubernetes_http.go @@ -104,7 +104,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli } } - conf.Routers[normalized] = &dynamic.Router{ + r := &dynamic.Router{ Middlewares: mds, Priority: route.Priority, EntryPoints: ingressRoute.Spec.EntryPoints, @@ -113,7 +113,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli } if ingressRoute.Spec.TLS != nil { - tlsConf := &dynamic.RouterTLSConfig{ + r.TLS = &dynamic.RouterTLSConfig{ CertResolver: ingressRoute.Spec.TLS.CertResolver, Domains: ingressRoute.Spec.TLS.Domains, } @@ -129,14 +129,21 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli tlsOptionsName = makeID(ns, tlsOptionsName) } else if len(ns) > 0 { logger. - WithField("TLSoptions", ingressRoute.Spec.TLS.Options.Name). - Warnf("namespace %q is ignored in cross-provider context", ns) + WithField("TLSOption", ingressRoute.Spec.TLS.Options.Name). + Warnf("Namespace %q is ignored in cross-provider context", ns) } - tlsConf.Options = tlsOptionsName + if !isNamespaceAllowed(p.AllowCrossNamespace, ingressRoute.Namespace, ns) { + logger.Errorf("TLSOption %s/%s is not in the IngressRoute namespace %s", + ns, ingressRoute.Spec.TLS.Options.Name, ingressRoute.Namespace) + continue + } + + r.TLS.Options = tlsOptionsName } - conf.Routers[normalized].TLS = tlsConf } + + conf.Routers[normalized] = r } } diff --git a/pkg/provider/kubernetes/crd/kubernetes_tcp.go b/pkg/provider/kubernetes/crd/kubernetes_tcp.go index 181baa7d5..187020a2d 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_tcp.go +++ b/pkg/provider/kubernetes/crd/kubernetes_tcp.go @@ -93,7 +93,7 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client conf.Services[serviceName].Weighted.Services = append(conf.Services[serviceName].Weighted.Services, srv) } - conf.Routers[serviceName] = &dynamic.TCPRouter{ + r := &dynamic.TCPRouter{ EntryPoints: ingressRouteTCP.Spec.EntryPoints, Middlewares: mds, Rule: route.Match, @@ -101,32 +101,38 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client } if ingressRouteTCP.Spec.TLS != nil { - conf.Routers[serviceName].TLS = &dynamic.RouterTCPTLSConfig{ + r.TLS = &dynamic.RouterTCPTLSConfig{ Passthrough: ingressRouteTCP.Spec.TLS.Passthrough, CertResolver: ingressRouteTCP.Spec.TLS.CertResolver, Domains: ingressRouteTCP.Spec.TLS.Domains, } - if ingressRouteTCP.Spec.TLS.Options == nil || len(ingressRouteTCP.Spec.TLS.Options.Name) == 0 { - continue - } - - tlsOptionsName := ingressRouteTCP.Spec.TLS.Options.Name - // Is a Kubernetes CRD reference (i.e. not a cross-provider reference) - ns := ingressRouteTCP.Spec.TLS.Options.Namespace - if !strings.Contains(tlsOptionsName, "@") { - if len(ns) == 0 { - ns = ingressRouteTCP.Namespace + if ingressRouteTCP.Spec.TLS.Options != nil && len(ingressRouteTCP.Spec.TLS.Options.Name) > 0 { + tlsOptionsName := ingressRouteTCP.Spec.TLS.Options.Name + // Is a Kubernetes CRD reference (i.e. not a cross-provider reference) + ns := ingressRouteTCP.Spec.TLS.Options.Namespace + if !strings.Contains(tlsOptionsName, providerNamespaceSeparator) { + if len(ns) == 0 { + ns = ingressRouteTCP.Namespace + } + tlsOptionsName = makeID(ns, tlsOptionsName) + } else if len(ns) > 0 { + logger. + WithField("TLSOption", ingressRouteTCP.Spec.TLS.Options.Name). + Warnf("Namespace %q is ignored in cross-provider context", ns) } - tlsOptionsName = makeID(ns, tlsOptionsName) - } else if len(ns) > 0 { - logger. - WithField("TLSoptions", ingressRouteTCP.Spec.TLS.Options.Name). - Warnf("namespace %q is ignored in cross-provider context", ns) - } - conf.Routers[serviceName].TLS.Options = tlsOptionsName + if !isNamespaceAllowed(p.AllowCrossNamespace, ingressRouteTCP.Namespace, ns) { + logger.Errorf("TLSOption %s/%s is not in the IngressRouteTCP namespace %s", + ns, ingressRouteTCP.Spec.TLS.Options.Name, ingressRouteTCP.Namespace) + continue + } + + r.TLS.Options = tlsOptionsName + } } + + conf.Routers[serviceName] = r } } diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go index 3a4678d35..dafa56653 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_test.go +++ b/pkg/provider/kubernetes/crd/kubernetes_test.go @@ -2732,8 +2732,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, { - desc: "TLS with tls options and specific namespace", - paths: []string{"services.yml", "with_tls_options_and_specific_namespace.yml"}, + desc: "TLS with tls options and specific namespace", + paths: []string{"services.yml", "with_tls_options_and_specific_namespace.yml"}, + AllowCrossNamespace: true, expected: &dynamic.Configuration{ UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -2926,8 +2927,9 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, { - desc: "TLS with unknown tls options namespace", - paths: []string{"services.yml", "with_unknown_tls_options_namespace.yml"}, + desc: "TLS with unknown tls options namespace", + paths: []string{"services.yml", "with_unknown_tls_options_namespace.yml"}, + AllowCrossNamespace: true, expected: &dynamic.Configuration{ UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -3485,9 +3487,8 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, { - desc: "ServersTransport", - AllowCrossNamespace: true, - paths: []string{"services.yml", "with_servers_transport.yml"}, + desc: "ServersTransport", + paths: []string{"services.yml", "with_servers_transport.yml"}, expected: &dynamic.Configuration{ UDP: &dynamic.UDPConfiguration{ Routers: map[string]*dynamic.UDPRouter{}, @@ -3546,20 +3547,6 @@ func TestLoadIngressRoutes(t *testing.T) { ServersTransport: "default-test", }, }, - "default-whoami3-8443": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "http://10.10.0.7:8443", - }, - { - URL: "http://10.10.0.8:8443", - }, - }, - PassHostHeader: Bool(true), - ServersTransport: "foo-test@kubernetescrd", - }, - }, "default-whoamitls-443": { LoadBalancer: &dynamic.ServersLoadBalancer{ Servers: []dynamic.Server{ @@ -3585,10 +3572,6 @@ func TestLoadIngressRoutes(t *testing.T) { Name: "default-whoamitls-443", Weight: Int(1), }, - { - Name: "default-whoami3-8443", - Weight: Int(1), - }, }, }, }, @@ -3597,80 +3580,6 @@ func TestLoadIngressRoutes(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, - { - desc: "ServersTransport without crossnamespace", - paths: []string{"services.yml", "with_servers_transport.yml"}, - expected: &dynamic.Configuration{ - UDP: &dynamic.UDPConfiguration{ - Routers: map[string]*dynamic.UDPRouter{}, - Services: map[string]*dynamic.UDPService{}, - }, - TCP: &dynamic.TCPConfiguration{ - Routers: map[string]*dynamic.TCPRouter{}, - Middlewares: map[string]*dynamic.TCPMiddleware{}, - Services: map[string]*dynamic.TCPService{}, - }, - HTTP: &dynamic.HTTPConfiguration{ - ServersTransports: map[string]*dynamic.ServersTransport{ - "foo-test": { - ServerName: "test", - InsecureSkipVerify: true, - RootCAs: []tls.FileOrContent{"TESTROOTCAS0", "TESTROOTCAS1", "TESTROOTCAS2", "TESTROOTCAS3", "TESTROOTCAS5", "TESTALLCERTS"}, - Certificates: tls.Certificates{ - {CertFile: "TESTCERT1", KeyFile: "TESTKEY1"}, - {CertFile: "TESTCERT2", KeyFile: "TESTKEY2"}, - {CertFile: "TESTCERT3", KeyFile: "TESTKEY3"}, - }, - MaxIdleConnsPerHost: 42, - ForwardingTimeouts: &dynamic.ForwardingTimeouts{ - DialTimeout: types.Duration(42 * time.Second), - ResponseHeaderTimeout: types.Duration(42 * time.Second), - IdleConnTimeout: types.Duration(42 * time.Millisecond), - }, - DisableHTTP2: true, - PeerCertURI: "foo://bar", - }, - "default-test": { - ServerName: "test", - ForwardingTimeouts: &dynamic.ForwardingTimeouts{ - DialTimeout: types.Duration(30 * time.Second), - IdleConnTimeout: types.Duration(90 * time.Second), - }, - }, - }, - Routers: map[string]*dynamic.Router{}, - Middlewares: map[string]*dynamic.Middleware{}, - Services: map[string]*dynamic.Service{ - "default-external-svc-with-https-443": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "https://external.domain:443", - }, - }, - PassHostHeader: Bool(true), - ServersTransport: "default-test", - }, - }, - "default-whoamitls-443": { - LoadBalancer: &dynamic.ServersLoadBalancer{ - Servers: []dynamic.Server{ - { - URL: "https://10.10.0.5:8443", - }, - { - URL: "https://10.10.0.6:8443", - }, - }, - PassHostHeader: Bool(true), - ServersTransport: "default-default-test", - }, - }, - }, - }, - TLS: &dynamic.TLSConfiguration{}, - }, - }, } for _, test := range testCases { @@ -4669,7 +4578,7 @@ func TestCrossNamespace(t *testing.T) { }, }, PassHostHeader: Bool(true), - ServersTransport: "cross-ns-test", + ServersTransport: "foo-test@kubernetescrd", }, }, "cross-ns-whoami-svc-80": { @@ -4816,6 +4725,189 @@ func TestCrossNamespace(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "HTTP ServersTransport cross namespace allowed", + paths: []string{"services.yml", "with_servers_transport_cross_namespace.yml"}, + allowCrossNamespace: true, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "default-test-route-6b204d94623b3df4370c": { + EntryPoints: []string{"foo"}, + Service: "default-test-route-6b204d94623b3df4370c", + Rule: "Host(`foo.com`) && PathPrefix(`/bar`)", + Priority: 12, + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "default-test-route-6b204d94623b3df4370c": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:80", + }, + { + URL: "http://10.10.0.2:80", + }, + }, + PassHostHeader: Bool(true), + ServersTransport: "cross-ns-st-cross-ns@kubernetescrd", + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{ + "cross-ns-st-cross-ns": { + ForwardingTimeouts: &dynamic.ForwardingTimeouts{ + DialTimeout: 30000000000, + ResponseHeaderTimeout: 0, + IdleConnTimeout: 90000000000, + }, + DisableHTTP2: true, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "HTTP ServersTransport cross namespace disallowed", + paths: []string{"services.yml", "with_servers_transport_cross_namespace.yml"}, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{ + "cross-ns-st-cross-ns": { + ForwardingTimeouts: &dynamic.ForwardingTimeouts{ + DialTimeout: 30000000000, + ResponseHeaderTimeout: 0, + IdleConnTimeout: 90000000000, + }, + DisableHTTP2: true, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{}, + }, + }, + { + desc: "HTTP TLSOption cross namespace allowed", + paths: []string{"services.yml", "with_tls_options_cross_namespace.yml"}, + allowCrossNamespace: true, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "default-test-route-6b204d94623b3df4370c": { + EntryPoints: []string{"foo"}, + Service: "default-test-route-6b204d94623b3df4370c", + Rule: "Host(`foo.com`) && PathPrefix(`/bar`)", + Priority: 12, + TLS: &dynamic.RouterTLSConfig{ + Options: "cross-ns-tls-options-cn", + }, + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "default-test-route-6b204d94623b3df4370c": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:80", + }, + { + URL: "http://10.10.0.2:80", + }, + }, + PassHostHeader: Bool(true), + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{ + Options: map[string]tls.Options{ + "cross-ns-tls-options-cn": { + MinVersion: "VersionTLS12", + ALPNProtocols: []string{"h2", "http/1.1", "acme-tls/1"}, + }, + }, + }, + }, + }, + { + desc: "HTTP TLSOption cross namespace disallowed", + paths: []string{"services.yml", "with_tls_options_cross_namespace.yml"}, + allowCrossNamespace: false, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "default-test-route-6b204d94623b3df4370c": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:80", + }, + { + URL: "http://10.10.0.2:80", + }, + }, + PassHostHeader: Bool(true), + }, + }, + }, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TLS: &dynamic.TLSConfiguration{ + Options: map[string]tls.Options{ + "cross-ns-tls-options-cn": { + MinVersion: "VersionTLS12", + ALPNProtocols: []string{"h2", "http/1.1", "acme-tls/1"}, + }, + }, + }, + }, + }, { desc: "TCP middleware cross namespace disallowed", paths: []string{"tcp/services.yml", "tcp/with_middleware_with_cross_namespace.yml"}, @@ -5012,6 +5104,101 @@ func TestCrossNamespace(t *testing.T) { TLS: &dynamic.TLSConfiguration{}, }, }, + { + desc: "TCP TLSOption cross namespace allowed", + paths: []string{"tcp/services.yml", "tcp/with_tls_options_cross_namespace.yml"}, + allowCrossNamespace: true, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{ + "default-test.route-fdd3e9338e47a45efefc": { + EntryPoints: []string{"foo"}, + Service: "default-test.route-fdd3e9338e47a45efefc", + Rule: "HostSNI(`foo.com`)", + TLS: &dynamic.RouterTCPTLSConfig{ + Options: "cross-ns-tls-options-cn", + }, + }, + }, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-test.route-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + }, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{ + Options: map[string]tls.Options{ + "cross-ns-tls-options-cn": { + MinVersion: "VersionTLS12", + ALPNProtocols: []string{"h2", "http/1.1", "acme-tls/1"}, + }, + }, + }, + }, + }, + { + desc: "TCP TLSOption cross namespace disallowed", + paths: []string{"tcp/services.yml", "tcp/with_tls_options_cross_namespace.yml"}, + allowCrossNamespace: false, + expected: &dynamic.Configuration{ + UDP: &dynamic.UDPConfiguration{ + Routers: map[string]*dynamic.UDPRouter{}, + Services: map[string]*dynamic.UDPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{}, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{}, + ServersTransports: map[string]*dynamic.ServersTransport{}, + }, + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Middlewares: map[string]*dynamic.TCPMiddleware{}, + Services: map[string]*dynamic.TCPService{ + "default-test.route-fdd3e9338e47a45efefc": { + LoadBalancer: &dynamic.TCPServersLoadBalancer{ + Servers: []dynamic.TCPServer{ + { + Address: "10.10.0.1:8000", + }, + { + Address: "10.10.0.2:8000", + }, + }, + }, + }, + }, + }, + TLS: &dynamic.TLSConfiguration{ + Options: map[string]tls.Options{ + "cross-ns-tls-options-cn": { + MinVersion: "VersionTLS12", + ALPNProtocols: []string{"h2", "http/1.1", "acme-tls/1"}, + }, + }, + }, + }, + }, { desc: "UDP cross namespace allowed", paths: []string{"udp/services.yml", "udp/with_cross_namespace.yml"}, @@ -5118,6 +5305,8 @@ func TestCrossNamespace(t *testing.T) { crdObjects = append(crdObjects, o) case *v1alpha1.TLSStore: crdObjects = append(crdObjects, o) + case *v1alpha1.ServersTransport: + crdObjects = append(crdObjects, o) default: } }