// authenticationHandler configures the authorization requirements for requests to reach the main handler
//nolint:funlen
authenticationHandler configures the authorization requirements for requests to reach the main handler
nolint:funlen
// authenticationHandler configures the authorization requirements for requests to reach the main handler // nolint : funlen
func authenticationHandler(v *viper.Viper, logger log.Logger, registry xmetrics.Registry) (*alice.Chain, error) {
	if registry == nil {
		return nil, errors.New("nil registry")
	}
	basculeMeasures := basculemetrics.NewAuthValidationMeasures(registry)
	capabilityCheckMeasures := basculechecks.NewAuthCapabilityCheckMeasures(registry)
	listener := basculemetrics.NewMetricListener(basculeMeasures)
	basicAllowed := make(map[string]string)
	basicAuth := v.GetStringSlice("authHeader")
	for _, a := range basicAuth {
		decoded, err := base64.StdEncoding.DecodeString(a)
		if err != nil {
			logging.Info(logger).Log(logging.MessageKey(), "failed to decode auth header", "authHeader", a, logging.ErrorKey(), err.Error())
			continue
		}
		i := bytes.IndexByte(decoded, ':')
		logging.Debug(logger).Log(logging.MessageKey(), "decoded string", "string", decoded, "i", i)
		if i > 0 {
			basicAllowed[string(decoded[:i])] = string(decoded[i+1:])
		}
	}
	logging.Debug(logger).Log(logging.MessageKey(), "Created list of allowed basic auths", "allowed", basicAllowed, "config", basicAuth)
	options := []basculehttp.COption{
		basculehttp.WithCLogger(getLogger),
		basculehttp.WithCErrorResponseFunc(listener.OnErrorResponse),
	}
	if len(basicAllowed) > 0 {
		options = append(options, basculehttp.WithTokenFactory("Basic", basculehttp.BasicTokenFactory(basicAllowed)))
	}
	var jwtVal JWTValidator
	v.UnmarshalKey("jwtValidator", &jwtVal)
	if jwtVal.Keys.URI != "" {
		resolver, err := jwtVal.Keys.NewResolver()
		if err != nil {
			return &alice.Chain{}, emperror.With(err, "failed to create resolver")
		}
		options = append(options, basculehttp.WithTokenFactory("Bearer", basculehttp.BearerTokenFactory{
			DefaultKeyID: DefaultKeyID,
			Resolver:     resolver,
			Parser:       bascule.DefaultJWTParser,
			Leeway:       jwtVal.Leeway,
		}))
	}
	authConstructor := basculehttp.NewConstructor(append([]basculehttp.COption{
		basculehttp.WithParseURLFunc(basculehttp.CreateRemovePrefixURLFunc("/"+apiBase+"/", basculehttp.DefaultParseURLFunc)),
	}, options...)...)
	authConstructorLegacy := basculehttp.NewConstructor(append([]basculehttp.COption{
		basculehttp.WithParseURLFunc(basculehttp.CreateRemovePrefixURLFunc("/api/"+prevAPIVersion+"/", basculehttp.DefaultParseURLFunc)),
		basculehttp.WithCErrorHTTPResponseFunc(basculehttp.LegacyOnErrorHTTPResponse),
	}, options...)...)
	bearerRules := bascule.Validators{
		bchecks.NonEmptyPrincipal(),
		bchecks.NonEmptyType(),
		bchecks.ValidType([]string{"jwt"}),
	}
	var capabilityCheck CapabilityConfig
	v.UnmarshalKey("capabilityCheck", &capabilityCheck)
	if capabilityCheck.Type == "enforce" || capabilityCheck.Type == "monitor" {
		var endpoints []*regexp.Regexp
		c, err := basculechecks.NewEndpointRegexCheck(capabilityCheck.Prefix, capabilityCheck.AcceptAllMethod)
		if err != nil {
			return nil, emperror.With(err, "failed to create capability check")
		}
		for _, e := range capabilityCheck.EndpointBuckets {
			r, err := regexp.Compile(e)
			if err != nil {
				logging.Error(logger).Log(logging.MessageKey(), "failed to compile regular expression", "regex", e, logging.ErrorKey(), err.Error())
				continue
			}
			endpoints = append(endpoints, r)
		}
		m := basculechecks.MetricValidator{
			C:         basculechecks.CapabilitiesValidator{Checker: c},
			Measures:  capabilityCheckMeasures,
			Endpoints: endpoints,
		}
		bearerRules = append(bearerRules, m.CreateValidator(capabilityCheck.Type == "enforce"))
	}
	authEnforcer := basculehttp.NewEnforcer(
		basculehttp.WithELogger(getLogger),
		basculehttp.WithRules("Basic", bascule.Validators{
			bchecks.AllowAll(),
		}),
		basculehttp.WithRules("Bearer", bearerRules),
		basculehttp.WithEErrorResponseFunc(listener.OnErrorResponse),
	)
	authChain := alice.New(setLogger(logger), authConstructor, authEnforcer, basculehttp.NewListenerDecorator(listener))
	authChainLegacy := alice.New(setLogger(logger), authConstructorLegacy, authEnforcer, basculehttp.NewListenerDecorator(listener))
	versionCompatibleAuth := alice.New(func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(r http.ResponseWriter, req *http.Request) {
			vars := mux.Vars(req)
			if vars != nil {
				if vars["version"] == prevAPIVersion {
					authChainLegacy.Then(next).ServeHTTP(r, req)
					return
				}
			}
			authChain.Then(next).ServeHTTP(r, req)
		})
	})
	return &versionCompatibleAuth, nil
}
func authenticationHandler ( v * viper . Viper , logger log . Logger , registry xmetrics . Registry ) ( * alice . Chain , error ) { if registry == nil { return nil , errors . New ( " " ) } basculeMeasures := basculemetrics . NewAuthValidationMeasures ( registry ) capabilityCheckMeasures := basculechecks . NewAuthCapabilityCheckMeasures ( registry ) listener := basculemetrics . NewMetricListener ( basculeMeasures ) basicAllowed := make ( map [ string ] string ) basicAuth := v . GetStringSlice ( " " ) for _ , a := range basicAuth { decoded , err := base64 . StdEncoding . DecodeString ( a ) if err != nil { logging . Info ( logger ) . Log ( logging . MessageKey ( ) , " " , " " , a , logging . ErrorKey ( ) , err . Error ( ) ) continue } i := bytes . IndexByte ( decoded , ':' ) logging . Debug ( logger ) . Log ( logging . MessageKey ( ) , " " , " " , decoded , " " , i ) if i > 0 { basicAllowed [ string ( decoded [ : i ] ) ] = string ( decoded [ i + 1 : ] ) } } logging . Debug ( logger ) . Log ( logging . MessageKey ( ) , " " , " " , basicAllowed , " " , basicAuth ) options := [ ] basculehttp . COption { basculehttp . WithCLogger ( getLogger ) , basculehttp . WithCErrorResponseFunc ( listener . OnErrorResponse ) , } if len ( basicAllowed ) > 0 { options = append ( options , basculehttp . WithTokenFactory ( " " , basculehttp . BasicTokenFactory ( basicAllowed ) ) ) } var jwtVal JWTValidator v . UnmarshalKey ( " " , & jwtVal ) if jwtVal . Keys . URI != " " { resolver , err := jwtVal . Keys . NewResolver ( ) if err != nil { return & alice . Chain { } , emperror . With ( err , " " ) } options = append ( options , basculehttp . WithTokenFactory ( " " , basculehttp . BearerTokenFactory { DefaultKeyID : DefaultKeyID , Resolver : resolver , Parser : bascule . DefaultJWTParser , Leeway : jwtVal . Leeway , } ) ) } authConstructor := basculehttp . NewConstructor ( append ( [ ] basculehttp . COption { basculehttp . WithParseURLFunc ( basculehttp . CreateRemovePrefixURLFunc ( " " + apiBase + " " , basculehttp . DefaultParseURLFunc ) ) , } , options ... ) ... ) authConstructorLegacy := basculehttp . NewConstructor ( append ( [ ] basculehttp . COption { basculehttp . WithParseURLFunc ( basculehttp . CreateRemovePrefixURLFunc ( " " + prevAPIVersion + " " , basculehttp . DefaultParseURLFunc ) ) , basculehttp . WithCErrorHTTPResponseFunc ( basculehttp . LegacyOnErrorHTTPResponse ) , } , options ... ) ... ) bearerRules := bascule . Validators { bchecks . NonEmptyPrincipal ( ) , bchecks . NonEmptyType ( ) , bchecks . ValidType ( [ ] string { " " } ) , } var capabilityCheck CapabilityConfig v . UnmarshalKey ( " " , & capabilityCheck ) if capabilityCheck . Type == " " || capabilityCheck . Type == " " { var endpoints [ ] * regexp . Regexp c , err := basculechecks . NewEndpointRegexCheck ( capabilityCheck . Prefix , capabilityCheck . AcceptAllMethod ) if err != nil { return nil , emperror . With ( err , " " ) } for _ , e := range capabilityCheck . EndpointBuckets { r , err := regexp . Compile ( e ) if err != nil { logging . Error ( logger ) . Log ( logging . MessageKey ( ) , " " , " " , e , logging . ErrorKey ( ) , err . Error ( ) ) continue } endpoints = append ( endpoints , r ) } m := basculechecks . MetricValidator { C : basculechecks . CapabilitiesValidator { Checker : c } , Measures : capabilityCheckMeasures , Endpoints : endpoints , } bearerRules = append ( bearerRules , m . CreateValidator ( capabilityCheck . Type == " " ) ) } authEnforcer := basculehttp . NewEnforcer ( basculehttp . WithELogger ( getLogger ) , basculehttp . WithRules ( " " , bascule . Validators { bchecks . AllowAll ( ) , } ) , basculehttp . WithRules ( " " , bearerRules ) , basculehttp . WithEErrorResponseFunc ( listener . OnErrorResponse ) , ) authChain := alice . New ( setLogger ( logger ) , authConstructor , authEnforcer , basculehttp . NewListenerDecorator ( listener ) ) authChainLegacy := alice . New ( setLogger ( logger ) , authConstructorLegacy , authEnforcer , basculehttp . NewListenerDecorator ( listener ) ) versionCompatibleAuth := alice . New ( func ( next http . Handler ) http . Handler { return http . HandlerFunc ( func ( r http . ResponseWriter , req * http . Request ) { vars := mux . Vars ( req ) if vars != nil { if vars [ " " ] == prevAPIVersion { authChainLegacy . Then ( next ) . ServeHTTP ( r , req ) return } } authChain . Then ( next ) . ServeHTTP ( r , req ) } ) } ) return & versionCompatibleAuth , nil }
authenticationHandler configures the authorization requirements for requests to reach the main handler
nolint:funlen
authenticationHandler configures the authorization requirements for requests to reach the main handler nolint : funlen
// only add capability check if the configuration is set