github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/api/authz/authz.go (about)

     1  package authz
     2  
     3  import (
     4  	"net/http"
     5  
     6  	"github.com/sirupsen/logrus"
     7  
     8  	"github.com/pyroscope-io/pyroscope/pkg/model"
     9  	"github.com/pyroscope-io/pyroscope/pkg/server/httputils"
    10  )
    11  
    12  type Authorizer struct {
    13  	logger    logrus.FieldLogger
    14  	httpUtils httputils.Utils
    15  }
    16  
    17  func NewAuthorizer(logger logrus.FieldLogger, httpUtils httputils.Utils) Authorizer {
    18  	return Authorizer{
    19  		logger:    logger,
    20  		httpUtils: httpUtils,
    21  	}
    22  }
    23  
    24  func (a Authorizer) RequireRole(role model.Role) func(next http.Handler) http.Handler {
    25  	return a.Require(Role(role))
    26  }
    27  
    28  func (a Authorizer) RequireAdminRole(next http.Handler) http.Handler {
    29  	return a.RequireRole(model.AdminRole)(next)
    30  }
    31  
    32  func (a Authorizer) RequireAuthenticatedUser(next http.Handler) http.Handler {
    33  	return a.Require(AuthenticatedUser)(next)
    34  }
    35  
    36  func (a Authorizer) Require(funcs ...func(r *http.Request) bool) func(next http.Handler) http.Handler {
    37  	return func(next http.Handler) http.Handler {
    38  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    39  			for _, fn := range funcs {
    40  				if !fn(r) {
    41  					a.httpUtils.HandleError(r, w, model.ErrPermissionDenied)
    42  					return
    43  				}
    44  			}
    45  			next.ServeHTTP(w, r)
    46  		})
    47  	}
    48  }
    49  
    50  func (a Authorizer) RequireOneOf(funcs ...func(r *http.Request) bool) func(next http.Handler) http.Handler {
    51  	return func(next http.Handler) http.Handler {
    52  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    53  			for _, fn := range funcs {
    54  				if fn(r) {
    55  					next.ServeHTTP(w, r)
    56  					return
    57  				}
    58  			}
    59  			a.httpUtils.HandleError(r, w, model.ErrPermissionDenied)
    60  		})
    61  	}
    62  }
    63  
    64  // Role verifies if the identity (user or API key) associated
    65  // with the request has the given role.
    66  func Role(role model.Role) func(r *http.Request) bool {
    67  	return func(r *http.Request) bool {
    68  		ctx := r.Context()
    69  		if k, ok := model.APIKeyFromContext(ctx); ok {
    70  			return k.Role == role
    71  		}
    72  		if u, ok := model.UserFromContext(ctx); ok {
    73  			return u.Role == role
    74  		}
    75  		return false
    76  	}
    77  }
    78  
    79  // AuthenticatedUser authorizes any authenticated user.
    80  //
    81  // Note that authenticated API key is not linked to any user,
    82  // therefore this check will fail.
    83  // Also note that when auth is disabled this check also fails
    84  func AuthenticatedUser(r *http.Request) bool {
    85  	_, ok := model.UserFromContext(r.Context())
    86  	return ok
    87  }