diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index a46518494..4abc4b921 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -278,7 +278,7 @@ func (s *APIServer) buildHandlerChain(stopCh <-chan struct{}) { basictoken.New(basic.NewBasicAuthenticator(im.NewOperator(s.KubernetesClient.KubeSphere(), s.InformerFactory))), bearertoken.New(jwttoken.NewTokenAuthenticator(token.NewJwtTokenIssuer(token.DefaultIssuerName, s.Config.AuthenticationOptions, s.CacheClient)))) handler = filters.WithAuthentication(handler, authn) - handler = filters.WithRequestInfo(handler, requestInfoResolver) + handler = filters.WithRequestInfo(handler, requestInfoResolver, s.Config.MultiClusterOptions.Enable) s.Server.Handler = handler } diff --git a/pkg/apiserver/dispatch/dispatch.go b/pkg/apiserver/dispatch/dispatch.go index d80f75564..6696c689c 100644 --- a/pkg/apiserver/dispatch/dispatch.go +++ b/pkg/apiserver/dispatch/dispatch.go @@ -151,6 +151,14 @@ func (c *clusterDispatch) Dispatch(w http.ResponseWriter, req *http.Request, han // designated cluster kube-apiserver, then copy req.Header['X-KubeSphere-Authorization'] to // req.Header['Authorization'] before authentication. req.Header.Set("X-KubeSphere-Authorization", req.Header.Get("Authorization")) + + // Dirty trick again. The kube-apiserver apiserver proxy rejects all proxy requests with dryRun parameter + // https://github.com/kubernetes/kubernetes/pull/66083 + // Really don't understand why they do this. And here we are, bypass with replacing 'dryRun' + // with dryrun and switch bach before send to kube-apiserver on the other side. + if len(u.Query()["dryRun"]) != 0 { + req.URL.RawQuery = strings.Replace(req.URL.RawQuery, "dryRun", "dryrun", 1) + } } else { // everything else goes to ks-apiserver, since our ks-apiserver has the ability to proxy kube-apiserver requests diff --git a/pkg/apiserver/filters/requestinfo.go b/pkg/apiserver/filters/requestinfo.go index 6f2211cda..7ee11fed2 100644 --- a/pkg/apiserver/filters/requestinfo.go +++ b/pkg/apiserver/filters/requestinfo.go @@ -21,9 +21,10 @@ import ( "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" "kubesphere.io/kubesphere/pkg/apiserver/request" "net/http" + "strings" ) -func WithRequestInfo(handler http.Handler, resolver request.RequestInfoResolver) http.Handler { +func WithRequestInfo(handler http.Handler, resolver request.RequestInfoResolver, multiClusterEnabled bool) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { ctx := req.Context() info, err := resolver.NewRequestInfo(req) @@ -32,16 +33,26 @@ func WithRequestInfo(handler http.Handler, resolver request.RequestInfoResolver) return } - // KubeSphere supports kube-apiserver proxy requests in multicluster mode. But kube-apiserver - // stripped all authorization headers. Use custom header to carry token to avoid losing authentication token. - // We may need a better way. See issue below. - // https://github.com/kubernetes/kubernetes/issues/38775#issuecomment-277915961 - authorization := req.Header.Get("Authorization") - if len(authorization) == 0 { - xAuthorization := req.Header.Get("X-KubeSphere-Authorization") - if len(xAuthorization) != 0 { - req.Header.Set("Authorization", xAuthorization) - req.Header.Del("X-KubeSphere-Authorization") + if multiClusterEnabled { + // KubeSphere supports kube-apiserver proxy requests in multicluster mode. But kube-apiserver + // stripped all authorization headers. Use custom header to carry token to avoid losing authentication token. + // We may need a better way. See issue below. + // https://github.com/kubernetes/kubernetes/issues/38775#issuecomment-277915961 + authorization := req.Header.Get("Authorization") + if len(authorization) == 0 { + xAuthorization := req.Header.Get("X-KubeSphere-Authorization") + if len(xAuthorization) != 0 { + req.Header.Set("Authorization", xAuthorization) + req.Header.Del("X-KubeSphere-Authorization") + } + } + + // kube-apiserver proxy rejects all proxy requests with dryRun, we had on choice but to + // replace it with 'dryrun' before proxy and convert it back before send it to kube-apiserver + // https://github.com/kubernetes/kubernetes/pull/66083 + // See pkg/apiserver/dispatch/dispatch.go for more details + if len(req.URL.Query()["dryrun"]) != 0 { + req.URL.RawQuery = strings.Replace(req.URL.RawQuery, "dryrun", "dryRun", 1) } }