impersonator: disallow clients from setting the X-Forwarded-For header

Signed-off-by: Monis Khan <mok@vmware.com>
This commit is contained in:
Monis Khan 2021-03-19 15:35:06 -04:00
parent c03fe2d1fe
commit f519f0cb09
No known key found for this signature in database
GPG Key ID: 52C90ADA01B269B8
2 changed files with 41 additions and 0 deletions

View File

@ -19,6 +19,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/httpstream" "k8s.io/apimachinery/pkg/util/httpstream"
utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
@ -315,6 +316,12 @@ func newImpersonationReverseProxyFunc(restConfig *rest.Config) (func(*genericapi
"isUpgradeRequest", isUpgradeRequest, "isUpgradeRequest", isUpgradeRequest,
) )
// do not allow the client to cause log confusion by spoofing this header
if len(r.Header.Values("X-Forwarded-For")) > 0 {
r = utilnet.CloneRequest(r)
r.Header.Del("X-Forwarded-For")
}
reverseProxy := httputil.NewSingleHostReverseProxy(serverURL) reverseProxy := httputil.NewSingleHostReverseProxy(serverURL)
reverseProxy.Transport = rt reverseProxy.Transport = rt
reverseProxy.FlushInterval = 200 * time.Millisecond // the "watch" verb will not work without this line reverseProxy.FlushInterval = 200 * time.Millisecond // the "watch" verb will not work without this line

View File

@ -118,6 +118,40 @@ func TestImpersonator(t *testing.T) {
"Upgrade": {"spdy/3.1"}, "Upgrade": {"spdy/3.1"},
}, },
}, },
{
name: "happy path ignores forwarded header",
clientCert: newClientCert(t, ca, "test-username2", []string{"test-group3", "test-group4"}),
kubeAPIServerClientBearerTokenFile: "required-to-be-set",
clientMutateHeaders: func(header http.Header) {
header.Add("X-Forwarded-For", "example.com")
},
wantKubeAPIServerRequestHeaders: http.Header{
"Impersonate-User": {"test-username2"},
"Impersonate-Group": {"test-group3", "test-group4", "system:authenticated"},
"Authorization": {"Bearer some-service-account-token"},
"User-Agent": {"test-agent"},
"Accept": {"application/vnd.kubernetes.protobuf,application/json"},
"Accept-Encoding": {"gzip"},
"X-Forwarded-For": {"127.0.0.1"},
},
},
{
name: "happy path ignores forwarded header canonicalization",
clientCert: newClientCert(t, ca, "test-username2", []string{"test-group3", "test-group4"}),
kubeAPIServerClientBearerTokenFile: "required-to-be-set",
clientMutateHeaders: func(header http.Header) {
header.Add("x-FORWARDED-for", "example.com")
},
wantKubeAPIServerRequestHeaders: http.Header{
"Impersonate-User": {"test-username2"},
"Impersonate-Group": {"test-group3", "test-group4", "system:authenticated"},
"Authorization": {"Bearer some-service-account-token"},
"User-Agent": {"test-agent"},
"Accept": {"application/vnd.kubernetes.protobuf,application/json"},
"Accept-Encoding": {"gzip"},
"X-Forwarded-For": {"127.0.0.1"},
},
},
{ {
name: "user is authenticated but the kube API request returns an error", name: "user is authenticated but the kube API request returns an error",
kubeAPIServerStatusCode: http.StatusNotFound, kubeAPIServerStatusCode: http.StatusNotFound,