fix kubeapiserver proxy rejects all dryRun requests (#2240)

This commit is contained in:
zryfish
2020-06-22 14:24:59 +08:00
committed by GitHub
parent 60444ba945
commit 5caee71b25
3 changed files with 31 additions and 12 deletions

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)
}
}