// init initializes GenericAPIServer. func (s *GenericAPIServer) init(c *Config) { if c.ProxyDialer != nil || c.ProxyTLSClientConfig != nil { s.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{ Dial: c.ProxyDialer, TLSClientConfig: c.ProxyTLSClientConfig, }) } // Register root handler. // We do not register this using restful Webservice since we do not want to surface this in api docs. // Allow GenericAPIServer to be embedded in contexts which already have something registered at the root if c.EnableIndex { s.mux.HandleFunc("/", apiserver.IndexHandler(s.HandlerContainer, s.MuxHelper)) } if c.EnableLogsSupport { apiserver.InstallLogsSupport(s.MuxHelper) } if c.EnableUISupport { ui.InstallSupport(s.MuxHelper, s.enableSwaggerSupport && s.enableSwaggerUI) } if c.EnableProfiling { s.mux.HandleFunc("/debug/pprof/", pprof.Index) s.mux.HandleFunc("/debug/pprof/profile", pprof.Profile) s.mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) } apiserver.InstallVersionHandler(s.MuxHelper, s.HandlerContainer) handler := http.Handler(s.mux.(*http.ServeMux)) // TODO: handle CORS and auth using go-restful // See github.com/emicklei/go-restful/blob/GenericAPIServer/examples/restful-CORS-filter.go, and // github.com/emicklei/go-restful/blob/GenericAPIServer/examples/restful-basic-authentication.go if len(c.CorsAllowedOriginList) > 0 { allowedOriginRegexps, err := util.CompileRegexps(c.CorsAllowedOriginList) if err != nil { glog.Fatalf("Invalid CORS allowed origin, --cors-allowed-origins flag was set to %v - %v", strings.Join(c.CorsAllowedOriginList, ","), err) } handler = apiserver.CORS(handler, allowedOriginRegexps, nil, nil, "true") } s.InsecureHandler = handler attributeGetter := apiserver.NewRequestAttributeGetter(s.RequestContextMapper, s.NewRequestInfoResolver()) handler = apiserver.WithAuthorizationCheck(handler, attributeGetter, s.authorizer) handler = apiserver.WithImpersonation(handler, s.RequestContextMapper, s.authorizer) // Install Authenticator if c.Authenticator != nil { authenticatedHandler, err := handlers.NewRequestAuthenticator(s.RequestContextMapper, c.Authenticator, handlers.Unauthorized(c.SupportsBasicAuth), handler) if err != nil { glog.Fatalf("Could not initialize authenticator: %v", err) } handler = authenticatedHandler } // TODO: Make this optional? Consumers of GenericAPIServer depend on this currently. s.Handler = handler // After all wrapping is done, put a context filter around both handlers if handler, err := api.NewRequestContextFilter(s.RequestContextMapper, s.Handler); err != nil { glog.Fatalf("Could not initialize request context filter for s.Handler: %v", err) } else { s.Handler = handler } if handler, err := api.NewRequestContextFilter(s.RequestContextMapper, s.InsecureHandler); err != nil { glog.Fatalf("Could not initialize request context filter for s.InsecureHandler: %v", err) } else { s.InsecureHandler = handler } s.installGroupsDiscoveryHandler() }
// New returns a new instance of GenericAPIServer from the given config. // Certain config fields will be set to a default value if unset, // including: // ServiceClusterIPRange // ServiceNodePortRange // MasterCount // ReadWritePort // PublicAddress // Public fields: // Handler -- The returned GenericAPIServer has a field TopHandler which is an // http.Handler which handles all the endpoints provided by the GenericAPIServer, // including the API, the UI, and miscellaneous debugging endpoints. All // these are subject to authorization and authentication. // InsecureHandler -- an http.Handler which handles all the same // endpoints as Handler, but no authorization and authentication is done. // Public methods: // HandleWithAuth -- Allows caller to add an http.Handler for an endpoint // that uses the same authentication and authorization (if any is configured) // as the GenericAPIServer's built-in endpoints. // If the caller wants to add additional endpoints not using the GenericAPIServer's // auth, then the caller should create a handler for those endpoints, which delegates the // any unhandled paths to "Handler". func (c Config) New() (*GenericAPIServer, error) { if c.Serializer == nil { return nil, fmt.Errorf("Genericapiserver.New() called with config.Serializer == nil") } c.setDefaults() s := &GenericAPIServer{ ServiceClusterIPRange: c.ServiceClusterIPRange, ServiceNodePortRange: c.ServiceNodePortRange, legacyAPIPrefix: c.APIPrefix, apiPrefix: c.APIGroupPrefix, admissionControl: c.AdmissionControl, requestContextMapper: c.RequestContextMapper, Serializer: c.Serializer, minRequestTimeout: time.Duration(c.MinRequestTimeout) * time.Second, enableSwaggerSupport: c.EnableSwaggerSupport, MasterCount: c.MasterCount, ExternalAddress: c.ExternalHost, ClusterIP: c.PublicAddress, PublicReadWritePort: c.ReadWritePort, ServiceReadWriteIP: c.ServiceReadWriteIP, ServiceReadWritePort: c.ServiceReadWritePort, ExtraServicePorts: c.ExtraServicePorts, ExtraEndpointPorts: c.ExtraEndpointPorts, KubernetesServiceNodePort: c.KubernetesServiceNodePort, apiGroupsForDiscovery: map[string]unversioned.APIGroup{}, enableOpenAPISupport: c.EnableOpenAPISupport, openAPIInfo: c.OpenAPIInfo, openAPIDefaultResponse: c.OpenAPIDefaultResponse, } if c.EnableWatchCache { s.storageDecorator = registry.StorageWithCacher } else { s.storageDecorator = generic.UndecoratedStorage } if c.RestfulContainer != nil { s.mux = c.RestfulContainer.ServeMux s.HandlerContainer = c.RestfulContainer } else { mux := http.NewServeMux() s.mux = mux s.HandlerContainer = NewHandlerContainer(mux, c.Serializer) } // Use CurlyRouter to be able to use regular expressions in paths. Regular expressions are required in paths for example for proxy (where the path is proxy/{kind}/{name}/{*}) s.HandlerContainer.Router(restful.CurlyRouter{}) s.MuxHelper = &apiserver.MuxHelper{Mux: s.mux, RegisteredPaths: []string{}} if c.ProxyDialer != nil || c.ProxyTLSClientConfig != nil { s.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{ Dial: c.ProxyDialer, TLSClientConfig: c.ProxyTLSClientConfig, }) } // Register root handler. // We do not register this using restful Webservice since we do not want to surface this in api docs. // Allow GenericAPIServer to be embedded in contexts which already have something registered at the root if c.EnableIndex { s.mux.HandleFunc("/", apiserver.IndexHandler(s.HandlerContainer, s.MuxHelper)) } if c.EnableLogsSupport { apiserver.InstallLogsSupport(s.MuxHelper, s.HandlerContainer) } if c.EnableUISupport { ui.InstallSupport(s.MuxHelper, c.EnableSwaggerSupport && c.EnableSwaggerUI) } if c.EnableProfiling { s.mux.HandleFunc("/debug/pprof/", pprof.Index) s.mux.HandleFunc("/debug/pprof/profile", pprof.Profile) s.mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol) } apiserver.InstallVersionHandler(s.MuxHelper, s.HandlerContainer) handler := http.Handler(s.mux.(*http.ServeMux)) // TODO: handle CORS and auth using go-restful // See github.com/emicklei/go-restful/blob/master/examples/restful-CORS-filter.go, and // github.com/emicklei/go-restful/blob/master/examples/restful-basic-authentication.go if len(c.CorsAllowedOriginList) > 0 { allowedOriginRegexps, err := util.CompileRegexps(c.CorsAllowedOriginList) if err != nil { glog.Fatalf("Invalid CORS allowed origin, --cors-allowed-origins flag was set to %v - %v", strings.Join(c.CorsAllowedOriginList, ","), err) } handler = apiserver.CORS(handler, allowedOriginRegexps, nil, nil, "true") } s.InsecureHandler = handler attributeGetter := apiserver.NewRequestAttributeGetter(c.RequestContextMapper, s.NewRequestInfoResolver()) handler = apiserver.WithAuthorizationCheck(handler, attributeGetter, c.Authorizer) if len(c.AuditLogPath) != 0 { // audit handler must comes before the impersonationFilter to read the original user writer := &lumberjack.Logger{ Filename: c.AuditLogPath, MaxAge: c.AuditLogMaxAge, MaxBackups: c.AuditLogMaxBackups, MaxSize: c.AuditLogMaxSize, } handler = audit.WithAudit(handler, attributeGetter, writer) defer writer.Close() } handler = apiserver.WithImpersonation(handler, c.RequestContextMapper, c.Authorizer) // Install Authenticator if c.Authenticator != nil { authenticatedHandler, err := handlers.NewRequestAuthenticator(c.RequestContextMapper, c.Authenticator, handlers.Unauthorized(c.SupportsBasicAuth), handler) if err != nil { glog.Fatalf("Could not initialize authenticator: %v", err) } handler = authenticatedHandler } // TODO: Make this optional? Consumers of GenericAPIServer depend on this currently. s.Handler = handler // After all wrapping is done, put a context filter around both handlers var err error handler, err = api.NewRequestContextFilter(c.RequestContextMapper, s.Handler) if err != nil { glog.Fatalf("Could not initialize request context filter for s.Handler: %v", err) } s.Handler = handler handler, err = api.NewRequestContextFilter(c.RequestContextMapper, s.InsecureHandler) if err != nil { glog.Fatalf("Could not initialize request context filter for s.InsecureHandler: %v", err) } s.InsecureHandler = handler s.installGroupsDiscoveryHandler() return s, nil }