From 62b063b74b5eb1b7e72ebac7b5348593249f732b Mon Sep 17 00:00:00 2001 From: Monis Khan Date: Tue, 1 Aug 2023 18:37:34 -0400 Subject: [PATCH] wsstream: use a single approach to detect connection upgrade Signed-off-by: Monis Khan --- .../pkg/util/httpstream/wsstream/conn.go | 11 +++-------- .../request/websocket/protocol_test.go | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/staging/src/k8s.io/apimachinery/pkg/util/httpstream/wsstream/conn.go b/staging/src/k8s.io/apimachinery/pkg/util/httpstream/wsstream/conn.go index 09f54a49c74..55501ba3f7a 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/httpstream/wsstream/conn.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/httpstream/wsstream/conn.go @@ -21,14 +21,14 @@ import ( "fmt" "io" "net/http" - "regexp" "strings" "time" "golang.org/x/net/websocket" - "k8s.io/klog/v2" + "k8s.io/apimachinery/pkg/util/httpstream" "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/klog/v2" ) // The Websocket subprotocol "channel.k8s.io" prepends each binary message with a byte indicating @@ -77,18 +77,13 @@ const ( ReadWriteChannel ) -var ( - // connectionUpgradeRegex matches any Connection header value that includes upgrade - connectionUpgradeRegex = regexp.MustCompile("(^|.*,\\s*)upgrade($|\\s*,)") -) - // IsWebSocketRequest returns true if the incoming request contains connection upgrade headers // for WebSockets. func IsWebSocketRequest(req *http.Request) bool { if !strings.EqualFold(req.Header.Get("Upgrade"), "websocket") { return false } - return connectionUpgradeRegex.MatchString(strings.ToLower(req.Header.Get("Connection"))) + return httpstream.IsUpgradeRequest(req) } // IgnoreReceives reads from a WebSocket until it is closed, then returns. If timeout is set, the diff --git a/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol_test.go b/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol_test.go index 9428d8ec81c..cc3d0671b7c 100644 --- a/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol_test.go +++ b/staging/src/k8s.io/apiserver/pkg/authentication/request/websocket/protocol_test.go @@ -46,6 +46,25 @@ func TestAuthenticateRequest(t *testing.T) { } } +func TestAuthenticateRequestMultipleConnectionHeaders(t *testing.T) { + auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { + if token != "token" { + t.Errorf("unexpected token: %s", token) + } + return &authenticator.Response{User: &user.DefaultInfo{Name: "user"}}, true, nil + })) + resp, ok, err := auth.AuthenticateRequest(&http.Request{ + Header: http.Header{ + "Connection": []string{"not", "upgrade"}, + "Upgrade": []string{"websocket"}, + "Sec-Websocket-Protocol": []string{"base64url.bearer.authorization.k8s.io.dG9rZW4,dummy"}, + }, + }) + if !ok || resp == nil || err != nil { + t.Errorf("expected valid user") + } +} + func TestAuthenticateRequestTokenInvalid(t *testing.T) { auth := NewProtocolAuthenticator(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { return nil, false, nil