// namespacingFilter adds a filter that adds the namespace of the request to the context. Not all requests will have namespaces, // but any that do will have the appropriate value added. func namespacingFilter(handler http.Handler, contextMapper kapi.RequestContextMapper) http.Handler { infoResolver := &apiserver.APIRequestInfoResolver{util.NewStringSet("api", "osapi", "oapi"), latest.RESTMapper} return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { ctx, ok := contextMapper.Get(req) if !ok { http.Error(w, "Unable to find request context", http.StatusInternalServerError) return } if _, exists := kapi.NamespaceFrom(ctx); !exists { if requestInfo, err := infoResolver.GetAPIRequestInfo(req); err == nil { // only set the namespace if the apiRequestInfo was resolved // keep in mind that GetAPIRequestInfo will fail on non-api requests, so don't fail the entire http request on that // kind of failure. // TODO reconsider special casing this. Having the special case hereallow us to fully share the kube // APIRequestInfoResolver without any modification or customization. namespace := requestInfo.Namespace if (requestInfo.Resource == "projects") && (len(requestInfo.Name) > 0) { namespace = requestInfo.Name } ctx = kapi.WithNamespace(ctx, namespace) contextMapper.Update(req, ctx) } } handler.ServeHTTP(w, req) }) }
// NewRequestAuthenticator creates an http handler that tries to authenticate the given request as a user, and then // stores any such user found onto the provided context for the request. If authentication fails or returns an error // the failed handler is used. On success, handler is invoked to serve the request. func NewRequestAuthenticator(mapper api.RequestContextMapper, auth authenticator.Request, failed http.Handler, handler http.Handler) (http.Handler, error) { return api.NewRequestContextFilter( mapper, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { user, ok, err := auth.AuthenticateRequest(req) if err != nil || !ok { if err != nil { glog.Errorf("Unable to authenticate the request due to an error: %v", err) } failed.ServeHTTP(w, req) return } if ctx, ok := mapper.Get(req); ok { mapper.Update(req, api.WithUser(ctx, user)) } handler.ServeHTTP(w, req) }), ) }
// authenticationHandlerFilter creates a filter object that will enforce authentication directly func authenticationHandlerFilter(handler http.Handler, authenticator authenticator.Request, contextMapper kapi.RequestContextMapper) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { user, ok, err := authenticator.AuthenticateRequest(req) if err != nil || !ok { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } ctx, ok := contextMapper.Get(req) if !ok { http.Error(w, "Unable to find request context", http.StatusInternalServerError) return } if err := contextMapper.Update(req, kapi.WithUser(ctx, user)); err != nil { glog.V(4).Infof("Error setting authenticated context: %v", err) http.Error(w, "Unable to set authenticated request context", http.StatusInternalServerError) return } handler.ServeHTTP(w, req) }) }