diff --git a/.golangci.yml b/.golangci.yml index 7dd5763bea..02749c267d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -323,6 +323,11 @@ linters: text: 'SA1019: cfg.(SSLRedirect|SSLTemporaryRedirect|SSLHost|SSLForceHost|FeaturePolicy) is deprecated' - path: (.+)\.go$ text: 'SA1019: c.Providers.(ConsulCatalog|Consul|Nomad).Namespace is deprecated' + - path: pkg/middlewares/auth/basic_auth_test.go + text: 'SA1008: keys in http.Header are canonicalized, "x-user" is not canonical; fix the constant or use http.CanonicalHeaderKey' + - path: pkg/middlewares/auth/digest_auth_test.go + text: 'SA1008: keys in http.Header are canonicalized, "x-user" is not canonical; fix the constant or use http.CanonicalHeaderKey' + paths: - pkg/provider/kubernetes/crd/generated/ diff --git a/pkg/middlewares/auth/basic_auth.go b/pkg/middlewares/auth/basic_auth.go index 944900ef1f..2dce9775c0 100644 --- a/pkg/middlewares/auth/basic_auth.go +++ b/pkg/middlewares/auth/basic_auth.go @@ -100,6 +100,8 @@ func (b *basicAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { req.URL.User = url.User(user) if b.headerField != "" { + // TODO Deprecated we should add the header with canonical key. + req.Header.Del(b.headerField) req.Header[b.headerField] = []string{user} } diff --git a/pkg/middlewares/auth/basic_auth_test.go b/pkg/middlewares/auth/basic_auth_test.go index f3f98df73b..e70aa38d8a 100644 --- a/pkg/middlewares/auth/basic_auth_test.go +++ b/pkg/middlewares/auth/basic_auth_test.go @@ -103,6 +103,30 @@ func TestBasicAuthUserHeader(t *testing.T) { assert.Equal(t, "traefik\n", string(body)) } +func TestBasicAuthUserHeaderCanonical(t *testing.T) { + var nextCalled bool + next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + nextCalled = true + assert.Empty(t, req.Header.Get("X-User")) + assert.Equal(t, []string{"test"}, req.Header["x-user"]) + }) + auth := dynamic.BasicAuth{ + Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"}, + HeaderField: "x-user", + } + m, err := NewBasic(t.Context(), next, auth, "test") + require.NoError(t, err) + + req := httptest.NewRequest(http.MethodGet, "http://localhost/", nil) + req.SetBasicAuth("test", "test") + req.Header.Set("X-User", "admin") + rw := httptest.NewRecorder() + m.ServeHTTP(rw, req) + + assert.Equal(t, http.StatusOK, rw.Result().StatusCode) + assert.True(t, nextCalled) +} + func TestBasicAuthHeaderRemoved(t *testing.T) { next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Empty(t, r.Header.Get(authorizationHeader)) diff --git a/pkg/middlewares/auth/digest_auth.go b/pkg/middlewares/auth/digest_auth.go index 454a972951..7ff7633ca4 100644 --- a/pkg/middlewares/auth/digest_auth.go +++ b/pkg/middlewares/auth/digest_auth.go @@ -98,6 +98,8 @@ func (d *digestAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } if d.headerField != "" { + // TODO Deprecated we should add the header with canonical key. + req.Header.Del(d.headerField) req.Header[d.headerField] = []string{username} } diff --git a/pkg/middlewares/auth/digest_auth_test.go b/pkg/middlewares/auth/digest_auth_test.go index 8987fe0998..ae922f305c 100644 --- a/pkg/middlewares/auth/digest_auth_test.go +++ b/pkg/middlewares/auth/digest_auth_test.go @@ -151,3 +151,30 @@ func TestDigestAuthUsersFromFile(t *testing.T) { }) } } + +func TestDigestAuthUserHeaderCanonical(t *testing.T) { + var nextCalled bool + next := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + nextCalled = true + assert.Empty(t, req.Header.Get("X-User")) + assert.Equal(t, []string{"test"}, req.Header["x-user"]) + }) + auth := dynamic.DigestAuth{ + Users: []string{"test:traefik:a2688e031edb4be6a3797f3882655c05"}, + HeaderField: "x-user", + } + m, err := NewDigest(t.Context(), next, auth, "test") + require.NoError(t, err) + + srv := httptest.NewServer(m) + t.Cleanup(srv.Close) + + req := testhelpers.MustNewRequest(http.MethodGet, srv.URL, nil) + req.Header.Set("X-User", "admin") + digestReq := newDigestRequest("test", "test", http.DefaultClient) + res, err := digestReq.Do(req) + require.NoError(t, err) + + assert.Equal(t, http.StatusOK, res.StatusCode) + assert.True(t, nextCalled) +}