The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/services/store/file_guardian.go

121 lines
2.8 KiB

package store
import (
"context"
"strings"
"github.com/grafana/grafana/pkg/infra/filestorage"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/user"
)
const (
ActionFilesRead = "files:read"
ActionFilesWrite = "files:write"
ActionFilesDelete = "files:delete"
)
var (
denyAllPathFilter = filestorage.NewDenyAllPathFilter()
allowAllPathFilter = filestorage.NewAllowAllPathFilter()
)
func isValidAction(action string) bool {
return action == ActionFilesRead || action == ActionFilesWrite || action == ActionFilesDelete
}
type storageAuthService interface {
newGuardian(ctx context.Context, user *user.SignedInUser, prefix string) fileGuardian
}
type fileGuardian interface {
canView(path string) bool
canWrite(path string) bool
canDelete(path string) bool
can(action string, path string) bool
getPathFilter(action string) filestorage.PathFilter
}
type pathFilterFileGuardian struct {
ctx context.Context
user *user.SignedInUser
prefix string
pathFilterByAction map[string]filestorage.PathFilter
log log.Logger
}
func (a *pathFilterFileGuardian) getPathFilter(action string) filestorage.PathFilter {
if !isValidAction(action) {
a.log.Warn("Unsupported action", "action", action)
return denyAllPathFilter
}
if filter, ok := a.pathFilterByAction[action]; ok {
return filter
}
return denyAllPathFilter
}
func (a *pathFilterFileGuardian) canWrite(path string) bool {
return a.can(ActionFilesWrite, path)
}
func (a *pathFilterFileGuardian) canView(path string) bool {
return a.can(ActionFilesRead, path)
}
func (a *pathFilterFileGuardian) canDelete(path string) bool {
return a.can(ActionFilesDelete, path)
}
func (a *pathFilterFileGuardian) can(action string, path string) bool {
if path == a.prefix {
path = filestorage.Delimiter
} else {
path = strings.TrimPrefix(path, a.prefix)
}
allow := false
if !isValidAction(action) {
a.log.Warn("Unsupported action", "action", action, "path", path)
return false
}
pathFilter, ok := a.pathFilterByAction[action]
if !ok {
a.log.Warn("Missing path filter", "action", action, "path", path)
return false
}
allow = pathFilter.IsAllowed(path)
if !allow {
a.log.Warn("Denying", "action", action, "path", path)
}
return allow
}
type denyAllFileGuardian struct {
}
func (d denyAllFileGuardian) canView(path string) bool {
return d.can(ActionFilesRead, path)
}
func (d denyAllFileGuardian) canWrite(path string) bool {
return d.can(ActionFilesWrite, path)
}
func (d denyAllFileGuardian) canDelete(path string) bool {
return d.can(ActionFilesDelete, path)
}
func (d denyAllFileGuardian) can(action string, path string) bool {
return false
}
func (d denyAllFileGuardian) getPathFilter(action string) filestorage.PathFilter {
return denyAllPathFilter
}