grafana/pkg/services/store/file_guardian.go

122 lines
2.8 KiB
Go

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
}