Ejemplo n.º 1
0
// handlerChain is a method to build the handler chain for this API server.  We need a custom handler chain so that we
// can have custom handling for `/apis`, since we're hosting discovery differently from anyone else and we're hosting
// the endpoints differently, since we're proxying all groups except for apiregistration.k8s.io.
func (h *handlerChainConfig) handlerChain(apiHandler http.Handler, c *genericapiserver.Config) (secure, insecure http.Handler) {
	// add this as a filter so that we never collide with "already registered" failures on `/apis`
	handler := WithAPIs(apiHandler, h.informers.Apiregistration().InternalVersion().APIServices())

	handler = apiserverfilters.WithAuthorization(handler, c.RequestContextMapper, c.Authorizer)

	// this mux is NOT protected by authorization, but DOES have authentication information
	// this is so that everyone can hit the proxy and we can properly identify the user.  The backing
	// API server will deal with authorization
	handler = WithProxyMux(handler, h.proxyMux)

	handler = apiserverfilters.WithImpersonation(handler, c.RequestContextMapper, c.Authorizer)
	// audit to stdout to help with debugging as we get this started
	handler = apiserverfilters.WithAudit(handler, c.RequestContextMapper, os.Stdout)
	handler = authhandlers.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, authhandlers.Unauthorized(c.SupportsBasicAuth))

	handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true")
	handler = genericfilters.WithPanicRecovery(handler, c.RequestContextMapper)
	handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc)
	handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.RequestContextMapper, c.LongRunningFunc)
	handler = apiserverfilters.WithRequestInfo(handler, genericapiserver.NewRequestInfoResolver(c), c.RequestContextMapper)
	handler = api.WithRequestContext(handler, c.RequestContextMapper)

	return handler, nil
}
Ejemplo n.º 2
0
func (c *MasterConfig) buildHandlerChain(assetConfig *AssetConfig) (func(http.Handler, *genericapiserver.Config) (secure, insecure http.Handler), []string, error) {
	var messages []string
	if c.Options.OAuthConfig != nil {
		messages = append(messages, fmt.Sprintf("Started OAuth2 API at %%s%s", OpenShiftOAuthAPIPrefix))
	}

	if assetConfig != nil {
		publicURL, err := url.Parse(assetConfig.Options.PublicURL)
		if err != nil {
			return nil, nil, err
		}
		messages = append(messages, fmt.Sprintf("Started Web Console %%s%s", publicURL.Path))
	}

	// TODO(sttts): resync with upstream handler chain and re-use upstream filters as much as possible
	return func(apiHandler http.Handler, kc *genericapiserver.Config) (secure, insecure http.Handler) {
		attributeGetter := kapiserverfilters.NewRequestAttributeGetter(c.RequestContextMapper)

		handler := c.versionSkewFilter(apiHandler, c.getRequestContextMapper())
		handler = c.authorizationFilter(handler)
		handler = c.impersonationFilter(handler)

		// audit handler must comes before the impersonationFilter to read the original user
		if c.Options.AuditConfig.Enabled {
			var writer io.Writer
			if len(c.Options.AuditConfig.AuditFilePath) > 0 {
				writer = &lumberjack.Logger{
					Filename:   c.Options.AuditConfig.AuditFilePath,
					MaxAge:     c.Options.AuditConfig.MaximumFileRetentionDays,
					MaxBackups: c.Options.AuditConfig.MaximumRetainedFiles,
					MaxSize:    c.Options.AuditConfig.MaximumFileSizeMegabytes,
				}
			} else {
				// backwards compatible writer to regular log
				writer = cmdutil.NewGLogWriterV(0)
			}
			handler = kapiserverfilters.WithAudit(handler, attributeGetter, writer)
		}
		handler = authenticationHandlerFilter(handler, c.Authenticator, c.getRequestContextMapper())
		handler = namespacingFilter(handler, c.getRequestContextMapper())
		handler = cacheControlFilter(handler, "no-store") // protected endpoints should not be cached

		if c.Options.OAuthConfig != nil {
			authConfig, err := BuildAuthConfig(c)
			if err != nil {
				glog.Fatalf("Failed to setup OAuth2: %v", err)
			}
			handler, err = authConfig.WithOAuth(handler)
			if err != nil {
				glog.Fatalf("Failed to setup OAuth2: %v", err)
			}
		}

		handler, err := assetConfig.WithAssets(handler)
		if err != nil {
			glog.Fatalf("Failed to setup serving of assets: %v", err)
		}

		// skip authz/n for the index handler
		handler = WithPatternsHandler(handler, apiHandler, "/", "")

		if c.WebConsoleEnabled() {
			handler = WithAssetServerRedirect(handler, c.Options.AssetConfig.PublicURL)
		}

		handler = kgenericfilters.WithCORS(handler, c.Options.CORSAllowedOrigins, nil, nil, nil, "true")
		handler = kgenericfilters.WithPanicRecovery(handler, c.RequestContextMapper)
		handler = kgenericfilters.WithTimeoutForNonLongRunningRequests(handler, kc.LongRunningFunc)
		// TODO: MaxRequestsInFlight should be subdivided by intent, type of behavior, and speed of
		// execution - updates vs reads, long reads vs short reads, fat reads vs skinny reads.
		// NOTE: read vs. write is implemented in Kube 1.6+
		handler = kgenericfilters.WithMaxInFlightLimit(handler, kc.MaxRequestsInFlight, kc.LongRunningFunc)
		handler = kapiserverfilters.WithRequestInfo(handler, genericapiserver.NewRequestInfoResolver(kc), kc.RequestContextMapper)
		handler = kapi.WithRequestContext(handler, kc.RequestContextMapper)

		return handler, nil
	}, messages, nil
}