[v11.2.x] Zanzana: Evaluate dashboard and folder permissions (#92253)

Zanzana: Evaluate dashboard and folder permissions (#91539)

* Zanzana: basic folder permissions checks

* Fix managed permissions for teams

* fix sync batch size

* add dashboards actions translations

* migrate folder tree

* migrate dashboard folders

* remove action sets from schema

* Adding more dashboard and folder-related permissions

* refactor

* Correctly translate dashboard permissions in folders

* fix dashboard parent permissions

(cherry picked from commit 1cc438a56c)

Co-authored-by: Alexander Zobnin <alexanderzobnin@gmail.com>
This commit is contained in:
grafana-delivery-bot[bot]
2024-08-21 17:54:50 -04:00
committed by GitHub
parent 25c9b9d58e
commit 4115a67a42
5 changed files with 267 additions and 26 deletions
@@ -114,6 +114,7 @@ func (a *AccessControl) evaluateZanzana(ctx context.Context, user identity.Reque
return false, errAccessNotImplemented
}
a.log.Debug("evaluating zanzana", "user", key.User, "relation", key.Relation, "object", key.Object)
res, err := a.zclient.Check(ctx, &openfgav1.CheckRequest{
TupleKey: &openfgav1.CheckRequestTupleKey{
User: key.User,
+79 -4
View File
@@ -3,6 +3,7 @@ package migrator
import (
"context"
"fmt"
"strconv"
"strings"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
@@ -33,6 +34,8 @@ func NewZanzanaSynchroniser(client zanzana.Client, store db.DB, collectors ...Tu
collectors,
teamMembershipCollector(store),
managedPermissionsCollector(store),
folderTreeCollector(store),
dashboardFolderCollector(store),
)
return &ZanzanaSynchroniser{
@@ -111,9 +114,9 @@ func managedPermissionsCollector(store db.DB) TupleCollector {
for _, p := range permissions {
var subject string
if len(p.UserUID) > 0 {
subject = zanzana.NewObject(zanzana.TypeUser, p.UserUID)
subject = zanzana.NewTupleEntry(zanzana.TypeUser, p.UserUID, "")
} else if len(p.TeamUID) > 0 {
subject = zanzana.NewObject(zanzana.TypeTeam, p.TeamUID)
subject = zanzana.NewTupleEntry(zanzana.TypeTeam, p.TeamUID, "member")
} else {
// FIXME(kalleep): Unsuported role binding (org role). We need to have basic roles in place
continue
@@ -161,8 +164,8 @@ func teamMembershipCollector(store db.DB) TupleCollector {
for _, m := range memberships {
tuple := &openfgav1.TupleKey{
User: zanzana.NewObject(zanzana.TypeUser, m.UserUID),
Object: zanzana.NewObject(zanzana.TypeTeam, m.TeamUID),
User: zanzana.NewTupleEntry(zanzana.TypeUser, m.UserUID, ""),
Object: zanzana.NewTupleEntry(zanzana.TypeTeam, m.TeamUID, ""),
}
// Admin permission is 4 and member 0
@@ -178,3 +181,75 @@ func teamMembershipCollector(store db.DB) TupleCollector {
return nil
}
}
// folderTreeCollector collects folder tree structure and writes it as relation tuples
func folderTreeCollector(store db.DB) TupleCollector {
return func(ctx context.Context, tuples map[string][]*openfgav1.TupleKey) error {
const collectorID = "folder"
const query = `
SELECT uid, parent_uid, org_id FROM folder WHERE parent_uid IS NOT NULL
`
type folder struct {
OrgID int64 `xorm:"org_id"`
FolderUID string `xorm:"uid"`
ParentUID string `xorm:"parent_uid"`
}
var folders []folder
err := store.WithDbSession(ctx, func(sess *db.Session) error {
return sess.SQL(query).Find(&folders)
})
if err != nil {
return err
}
for _, f := range folders {
tuple := &openfgav1.TupleKey{
User: zanzana.NewScopedTupleEntry(zanzana.TypeFolder, f.ParentUID, "", strconv.FormatInt(f.OrgID, 10)),
Object: zanzana.NewScopedTupleEntry(zanzana.TypeFolder, f.FolderUID, "", strconv.FormatInt(f.OrgID, 10)),
Relation: zanzana.RelationParent,
}
tuples[collectorID] = append(tuples[collectorID], tuple)
}
return nil
}
}
// dashboardFolderCollector collects information about dashboards parent folders
func dashboardFolderCollector(store db.DB) TupleCollector {
return func(ctx context.Context, tuples map[string][]*openfgav1.TupleKey) error {
const collectorID = "folder"
const query = `
SELECT org_id, uid, folder_uid, is_folder FROM dashboard WHERE is_folder = 0 AND folder_uid IS NOT NULL
`
type dashboard struct {
OrgID int64 `xorm:"org_id"`
UID string `xorm:"uid"`
ParentUID string `xorm:"folder_uid"`
}
var dashboards []dashboard
err := store.WithDbSession(ctx, func(sess *db.Session) error {
return sess.SQL(query).Find(&dashboards)
})
if err != nil {
return err
}
for _, d := range dashboards {
tuple := &openfgav1.TupleKey{
User: zanzana.NewScopedTupleEntry(zanzana.TypeFolder, d.ParentUID, "", strconv.FormatInt(d.OrgID, 10)),
Object: zanzana.NewScopedTupleEntry(zanzana.TypeDashboard, d.UID, "", strconv.FormatInt(d.OrgID, 10)),
Relation: zanzana.RelationParent,
}
tuples[collectorID] = append(tuples[collectorID], tuple)
}
return nil
}
}