From 32d88a977d3e8e28935a5cd96aebe0fdeb47c26e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com> Date: Thu, 5 Aug 2021 17:42:08 +0200 Subject: [PATCH] Avoid unauthorized midlleware cross namespace reference Co-authored-by: Mathieu Lonjaret Co-authored-by: Romain --- .../with_middleware_cross_namespace.yml | 9 +++++++++ .../kubernetes/crd/kubernetes_http.go | 16 ++++++++++++--- .../kubernetes/crd/kubernetes_test.go | 20 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/pkg/provider/kubernetes/crd/fixtures/with_middleware_cross_namespace.yml b/pkg/provider/kubernetes/crd/fixtures/with_middleware_cross_namespace.yml index aaed4a1d8..25a2ac448 100644 --- a/pkg/provider/kubernetes/crd/fixtures/with_middleware_cross_namespace.yml +++ b/pkg/provider/kubernetes/crd/fixtures/with_middleware_cross_namespace.yml @@ -28,6 +28,15 @@ spec: port: 80 middlewares: - name: test-errorpage + - match: Host(`foo.com`) && PathPrefix(`/bur`) + kind: Rule + priority: 12 + services: + - name: whoami + namespace: default + port: 80 + middlewares: + - name: cross-ns-stripprefix@kubernetescrd --- apiVersion: traefik.containo.us/v1alpha1 diff --git a/pkg/provider/kubernetes/crd/kubernetes_http.go b/pkg/provider/kubernetes/crd/kubernetes_http.go index b179082e1..51471af28 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_http.go +++ b/pkg/provider/kubernetes/crd/kubernetes_http.go @@ -146,13 +146,23 @@ func (p *Provider) makeMiddlewareKeys(ctx context.Context, ingRouteNamespace str var mds []string for _, mi := range middlewares { - if strings.Contains(mi.Name, providerNamespaceSeparator) { + name := mi.Name + + if !p.AllowCrossNamespace && strings.HasSuffix(mi.Name, providerNamespaceSeparator+providerName) { + // Since we are not able to know if another namespace is in the name (namespace-name@kubernetescrd), + // if the provider namespace kubernetescrd is used, + // we don't allow this format to avoid cross namespace references. + return nil, fmt.Errorf("invalid reference to middleware %s: with crossnamespace disallowed, the namespace field needs to be explicitly specified", mi.Name) + } + + if strings.Contains(name, providerNamespaceSeparator) { if len(mi.Namespace) > 0 { log.FromContext(ctx). WithField(log.MiddlewareName, mi.Name). Warnf("namespace %q is ignored in cross-provider context", mi.Namespace) } - mds = append(mds, mi.Name) + + mds = append(mds, name) continue } @@ -165,7 +175,7 @@ func (p *Provider) makeMiddlewareKeys(ctx context.Context, ingRouteNamespace str ns = mi.Namespace } - mds = append(mds, makeID(ns, mi.Name)) + mds = append(mds, makeID(ns, name)) } return mds, nil diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go index 21b486feb..95fe6408f 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_test.go +++ b/pkg/provider/kubernetes/crd/kubernetes_test.go @@ -3986,6 +3986,13 @@ func TestCrossNamespace(t *testing.T) { Priority: 12, Middlewares: []string{"default-test-errorpage"}, }, + "default-test-crossnamespace-route-a1963878aac7331b7950": { + EntryPoints: []string{"foo"}, + Service: "default-test-crossnamespace-route-a1963878aac7331b7950", + Rule: "Host(`foo.com`) && PathPrefix(`/bur`)", + Priority: 12, + Middlewares: []string{"cross-ns-stripprefix@kubernetescrd"}, + }, }, Middlewares: map[string]*dynamic.Middleware{ "cross-ns-stripprefix": { @@ -4042,6 +4049,19 @@ func TestCrossNamespace(t *testing.T) { PassHostHeader: Bool(true), }, }, + "default-test-crossnamespace-route-a1963878aac7331b7950": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://10.10.0.1:80", + }, + { + URL: "http://10.10.0.2:80", + }, + }, + PassHostHeader: Bool(true), + }, + }, }, }, TLS: &dynamic.TLSConfiguration{},