From c7905c66386b229c1ac633fd4bae92e912cf76c1 Mon Sep 17 00:00:00 2001 From: Andrew Keesler Date: Tue, 16 Feb 2021 08:15:50 -0500 Subject: [PATCH] internal/concierge/impersonator: fail if impersonation headers set If someone has already set impersonation headers in their request, then we should fail loudly so the client knows that its existing impersonation headers will not work. Signed-off-by: Andrew Keesler --- .../concierge/impersonator/impersonator.go | 24 +++++++++++++++++++ .../impersonator/impersonator_test.go | 24 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/internal/concierge/impersonator/impersonator.go b/internal/concierge/impersonator/impersonator.go index 710df348..2bd01574 100644 --- a/internal/concierge/impersonator/impersonator.go +++ b/internal/concierge/impersonator/impersonator.go @@ -88,6 +88,12 @@ func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { "method", r.Method, ) + if err := ensureNoImpersonationHeaders(r); err != nil { + log.Error(err, "impersonation header already exists") + http.Error(w, "impersonation header already exists", http.StatusBadRequest) + return + } + tokenCredentialReq, err := extractToken(r, p.jsonDecoder) if err != nil { log.Error(err, "invalid token encoding") @@ -120,6 +126,24 @@ func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { p.proxy.ServeHTTP(w, newR) } +func ensureNoImpersonationHeaders(r *http.Request) error { + if _, ok := r.Header[transport.ImpersonateUserHeader]; ok { + return fmt.Errorf("%q header already exists", transport.ImpersonateUserHeader) + } + + if _, ok := r.Header[transport.ImpersonateGroupHeader]; ok { + return fmt.Errorf("%q header already exists", transport.ImpersonateGroupHeader) + } + + for header := range r.Header { + if strings.HasPrefix(header, transport.ImpersonateUserExtraHeaderPrefix) { + return fmt.Errorf("%q header already exists", transport.ImpersonateUserExtraHeaderPrefix) + } + } + + return nil +} + func getProxyHeaders(userInfo user.Info, requestHeaders http.Header) http.Header { newHeaders := http.Header{} newHeaders.Set("Impersonate-User", userInfo.GetName()) diff --git a/internal/concierge/impersonator/impersonator_test.go b/internal/concierge/impersonator/impersonator_test.go index 94a46f28..e993538c 100644 --- a/internal/concierge/impersonator/impersonator_test.go +++ b/internal/concierge/impersonator/impersonator_test.go @@ -127,6 +127,30 @@ func TestImpersonator(t *testing.T) { }, wantCreationErr: "could not get in-cluster transport: using a custom transport with TLS certificate options or the insecure flag is not allowed", }, + { + name: "Impersonate-User header already in request", + getKubeconfig: func() (*rest.Config, error) { return &testServerKubeconfig, nil }, + request: newRequest(map[string][]string{"Impersonate-User": {"some-user"}}), + wantHTTPBody: "impersonation header already exists\n", + wantHTTPStatus: http.StatusBadRequest, + wantLogs: []string{"\"error\"=\"\\\"Impersonate-User\\\" header already exists\" \"msg\"=\"impersonation header already exists\" \"method\"=\"GET\" \"url\"=\"http://pinniped.dev/blah\""}, + }, + { + name: "Impersonate-Group header already in request", + getKubeconfig: func() (*rest.Config, error) { return &testServerKubeconfig, nil }, + request: newRequest(map[string][]string{"Impersonate-Group": {"some-group"}}), + wantHTTPBody: "impersonation header already exists\n", + wantHTTPStatus: http.StatusBadRequest, + wantLogs: []string{"\"error\"=\"\\\"Impersonate-Group\\\" header already exists\" \"msg\"=\"impersonation header already exists\" \"method\"=\"GET\" \"url\"=\"http://pinniped.dev/blah\""}, + }, + { + name: "Impersonate-Extra header already in request", + getKubeconfig: func() (*rest.Config, error) { return &testServerKubeconfig, nil }, + request: newRequest(map[string][]string{"Impersonate-Extra-something": {"something"}}), + wantHTTPBody: "impersonation header already exists\n", + wantHTTPStatus: http.StatusBadRequest, + wantLogs: []string{"\"error\"=\"\\\"Impersonate-Extra-\\\" header already exists\" \"msg\"=\"impersonation header already exists\" \"method\"=\"GET\" \"url\"=\"http://pinniped.dev/blah\""}, + }, { name: "missing authorization header", getKubeconfig: func() (*rest.Config, error) { return &testServerKubeconfig, nil },