mirror of https://github.com/grafana/grafana
Storage: use static access rules (#52334)
* Storage: use static access rules * Storage: use static access rules * Storage: add testspull/51707/head^2
parent
e6a5b9ee7f
commit
6188526e1d
@ -0,0 +1,121 @@ |
||||
package store |
||||
|
||||
import ( |
||||
"context" |
||||
"strings" |
||||
|
||||
"github.com/grafana/grafana/pkg/infra/filestorage" |
||||
"github.com/grafana/grafana/pkg/infra/log" |
||||
"github.com/grafana/grafana/pkg/models" |
||||
) |
||||
|
||||
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 *models.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 *models.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 |
||||
} |
@ -0,0 +1,41 @@ |
||||
package store |
||||
|
||||
import ( |
||||
"context" |
||||
|
||||
"github.com/grafana/grafana/pkg/infra/filestorage" |
||||
"github.com/grafana/grafana/pkg/infra/log" |
||||
"github.com/grafana/grafana/pkg/models" |
||||
) |
||||
|
||||
type createPathFilterByAction func(ctx context.Context, user *models.SignedInUser, storageName string) map[string]filestorage.PathFilter |
||||
|
||||
func newStaticStorageAuthService(createPathFilterByAction createPathFilterByAction) storageAuthService { |
||||
return &staticStorageAuth{ |
||||
denyAllFileGuardian: &denyAllFileGuardian{}, |
||||
createPathFilterByAction: createPathFilterByAction, |
||||
log: log.New("staticStorageAuthService"), |
||||
} |
||||
} |
||||
|
||||
type staticStorageAuth struct { |
||||
log log.Logger |
||||
denyAllFileGuardian fileGuardian |
||||
createPathFilterByAction createPathFilterByAction |
||||
} |
||||
|
||||
func (a *staticStorageAuth) newGuardian(ctx context.Context, user *models.SignedInUser, storageName string) fileGuardian { |
||||
pathFilter := a.createPathFilterByAction(ctx, user, storageName) |
||||
|
||||
if pathFilter == nil { |
||||
return a.denyAllFileGuardian |
||||
} |
||||
|
||||
return &pathFilterFileGuardian{ |
||||
ctx: ctx, |
||||
user: user, |
||||
log: a.log, |
||||
prefix: storageName, |
||||
pathFilterByAction: pathFilter, |
||||
} |
||||
} |
Loading…
Reference in new issue