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 }