[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:
co-authored by
Alexander Zobnin
parent
25c9b9d58e
commit
4115a67a42
@@ -11,6 +11,47 @@ type org
|
||||
define member: [user]
|
||||
define viewer: [user]
|
||||
|
||||
# team management
|
||||
define team_create: [role#assignee]
|
||||
define team_read: [role#assignee]
|
||||
define team_write: [role#assignee] or team_create
|
||||
define team_delete: [role#assignee] or team_write
|
||||
define team_permissions_write: [role#assignee]
|
||||
define team_permissions_read: [role#assignee] or team_permissions_write
|
||||
|
||||
define folder_create: [role#assignee]
|
||||
define folder_read: [role#assignee] or folder_delete
|
||||
define folder_write: [role#assignee] or folder_create
|
||||
define folder_delete: [role#assignee] or folder_write
|
||||
define folder_permissions_write: [role#assignee]
|
||||
define folder_permissions_read: [role#assignee] or folder_permissions_write
|
||||
|
||||
define dashboard_annotations_create: [role#assignee]
|
||||
define dashboard_annotations_read: [role#assignee]
|
||||
define dashboard_annotations_write: [role#assignee]
|
||||
define dashboard_annotations_delete: [role#assignee]
|
||||
define dashboard_create: [role#assignee]
|
||||
define dashboard_delete: [role#assignee]
|
||||
define dashboard_permissions_read: [role#assignee]
|
||||
define dashboard_permissions_write: [role#assignee]
|
||||
define dashboard_public_write: [role#assignee] or dashboard_write
|
||||
define dashboard_read: [role#assignee]
|
||||
define dashboard_write: [role#assignee]
|
||||
|
||||
define library_panel_create: [role#assignee]
|
||||
define library_panel_read: [role#assignee] or library_panel_write
|
||||
define library_panel_write: [role#assignee] or library_panel_create
|
||||
define library_panel_delete: [role#assignee] or library_panel_create
|
||||
|
||||
define alert_rule_create: [role#assignee]
|
||||
define alert_rule_read: [role#assignee] or alert_rule_write
|
||||
define alert_rule_write: [role#assignee] or alert_rule_create
|
||||
define alert_rule_delete: [role#assignee] or alert_rule_write
|
||||
define alert_silence_create: [role#assignee]
|
||||
define alert_silence_delete: [role#assignee] or alert_silence_write
|
||||
define alert_silence_read: [role#assignee] or alert_silence_write
|
||||
define alert_silence_write: [role#assignee] or alert_silence_create
|
||||
|
||||
type role
|
||||
relations
|
||||
define org: [org]
|
||||
@@ -22,3 +63,65 @@ type team
|
||||
define org: [org]
|
||||
define admin: [user]
|
||||
define member: [user] or admin
|
||||
|
||||
define read: [role#assignee] or member or team_read from org
|
||||
define write: [role#assignee] or admin or team_write from org
|
||||
define delete: [role#assignee] or admin or team_delete from org
|
||||
define permissions_read: [role#assignee] or admin or team_permissions_read from org
|
||||
define permissions_write: [role#assignee] or admin or team_permissions_write from org
|
||||
|
||||
type folder
|
||||
relations
|
||||
define parent: [folder]
|
||||
define org: [org]
|
||||
|
||||
define create: [user, team#member, role#assignee] or create from parent or folder_create from org
|
||||
define read: [user, team#member, role#assignee] or read from parent or folder_read from org
|
||||
define write: [user, team#member, role#assignee] or write from parent or folder_write from org
|
||||
define delete: [user, team#member, role#assignee] or delete from parent or folder_delete from org
|
||||
define permissions_read: [user, team#member, role#assignee] or permissions_read from parent or folder_permissions_read from org
|
||||
define permissions_write: [user, team#member, role#assignee] or permissions_write from parent or folder_permissions_write from org
|
||||
|
||||
define dashboard_create: [user, team#member, role#assignee] or dashboard_create from parent or dashboard_create from org
|
||||
define dashboard_read: [user, team#member, role#assignee] or dashboard_read from parent or dashboard_read from org
|
||||
define dashboard_write: [user, team#member, role#assignee] or dashboard_write from parent or dashboard_write from org
|
||||
define dashboard_delete: [user, team#member, role#assignee] or dashboard_delete from parent or dashboard_delete from org
|
||||
define dashboard_permissions_read: [user, team#member, role#assignee] or dashboard_permissions_read from parent or dashboard_permissions_read from org
|
||||
define dashboard_permissions_write: [user, team#member, role#assignee] or dashboard_permissions_write from parent or dashboard_permissions_write from org
|
||||
define dashboard_public_write: [user, team#member, role#assignee] or dashboard_public_write from parent or dashboard_public_write from org or dashboard_write
|
||||
define dashboard_annotations_create: [user, team#member, role#assignee] or dashboard_annotations_create from parent or dashboard_annotations_create from org
|
||||
define dashboard_annotations_read: [user, team#member, role#assignee] or dashboard_annotations_read from parent or dashboard_annotations_read from org
|
||||
define dashboard_annotations_write: [user, team#member, role#assignee] or dashboard_annotations_write from parent or dashboard_annotations_write from org
|
||||
define dashboard_annotations_delete: [user, team#member, role#assignee] or dashboard_annotations_delete from parent or dashboard_annotations_delete from org
|
||||
|
||||
define library_panel_create: [user, team#member, role#assignee] or library_panel_create from parent or library_panel_create from org
|
||||
define library_panel_read: [user, team#member, role#assignee] or library_panel_read from parent or library_panel_read from org or library_panel_write
|
||||
define library_panel_write: [user, team#member, role#assignee] or library_panel_write from parent or library_panel_write from org or library_panel_create
|
||||
define library_panel_delete: [user, team#member, role#assignee] or library_panel_delete from parent or library_panel_delete from org or library_panel_create
|
||||
|
||||
define alert_rule_create: [user, team#member, role#assignee] or alert_rule_create from parent or alert_rule_create from org
|
||||
define alert_rule_read: [user, team#member, role#assignee] or alert_rule_read from parent or alert_rule_read from org or alert_rule_write
|
||||
define alert_rule_write: [user, team#member, role#assignee] or alert_rule_write from parent or alert_rule_write from org or alert_rule_create
|
||||
define alert_rule_delete: [user, team#member, role#assignee] or alert_rule_delete from parent or alert_rule_delete from org or alert_rule_write
|
||||
define alert_silence_create: [user, team#member, role#assignee] or alert_silence_create from parent or alert_silence_create from org
|
||||
define alert_silence_read: [user, team#member, role#assignee] or alert_silence_read from parent or alert_silence_read from org or alert_silence_write
|
||||
define alert_silence_write: [user, team#member, role#assignee] or alert_silence_write from parent or alert_silence_write from org or alert_silence_create
|
||||
|
||||
# Dashboard
|
||||
type dashboard
|
||||
relations
|
||||
define org: [org]
|
||||
define parent: [folder]
|
||||
|
||||
define read: [user, team#member, role#assignee] or dashboard_read from parent or dashboard_read from org
|
||||
define write: [user, team#member, role#assignee] or dashboard_write from parent or dashboard_write from org
|
||||
define delete: [user, team#member, role#assignee] or dashboard_delete from parent or dashboard_delete from org
|
||||
define create: [user, team#member, role#assignee] or dashboard_create from parent or dashboard_create from org
|
||||
define permissions_read: [user, team#member, role#assignee] or dashboard_permissions_read from parent or dashboard_permissions_read from org
|
||||
define permissions_write: [user, team#member, role#assignee] or dashboard_permissions_write from parent or dashboard_permissions_write from org
|
||||
|
||||
define public_write: [user, team#member, role#assignee] or dashboard_public_write from parent or dashboard_public_write from org or write
|
||||
define annotations_create: [user, team#member, role#assignee] or dashboard_annotations_create from parent or dashboard_annotations_create from org
|
||||
define annotations_read: [user, team#member, role#assignee] or dashboard_annotations_read from parent or dashboard_annotations_read from org
|
||||
define annotations_write: [user, team#member, role#assignee] or dashboard_annotations_write from parent or dashboard_annotations_write from org
|
||||
define annotations_delete: [user, team#member, role#assignee] or dashboard_annotations_delete from parent or dashboard_annotations_delete from org
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package zanzana
|
||||
|
||||
type actionKindTranslation struct {
|
||||
objectType string
|
||||
orgScoped bool
|
||||
translations map[string]string
|
||||
}
|
||||
|
||||
// rbac action to relation translation
|
||||
var folderActions = map[string]string{
|
||||
"folders:create": "create",
|
||||
"folders:read": "read",
|
||||
"folders:write": "write",
|
||||
"folders:delete": "delete",
|
||||
"folders.permissions:read": "permissions_read",
|
||||
"folders.permissions:write": "permissions_write",
|
||||
|
||||
"dashboards:create": "dashboard_create",
|
||||
"dashboards:read": "dashboard_read",
|
||||
"dashboards:write": "dashboard_write",
|
||||
"dashboards:delete": "dashboard_delete",
|
||||
"dashboards.permissions:read": "dashboard_permissions_read",
|
||||
"dashboards.permissions:write": "dashboard_permissions_write",
|
||||
|
||||
"library.panels:create": "library_panel_create",
|
||||
"library.panels:read": "library_panel_read",
|
||||
"library.panels:write": "library_panel_write",
|
||||
"library.panels:delete": "library_panel_delete",
|
||||
|
||||
"alert.rules:create": "alert_rule_create",
|
||||
"alert.rules:read": "alert_rule_read",
|
||||
"alert.rules:write": "alert_rule_write",
|
||||
"alert.rules:delete": "alert_rule_delete",
|
||||
|
||||
"alert.silences:create": "alert_silence_create",
|
||||
"alert.silences:read": "alert_silence_read",
|
||||
"alert.silences:write": "alert_silence_write",
|
||||
}
|
||||
|
||||
var dashboardActions = map[string]string{
|
||||
"dashboards:create": "create",
|
||||
"dashboards:read": "read",
|
||||
"dashboards:write": "write",
|
||||
"dashboards:delete": "delete",
|
||||
"dashboards.permissions:read": "permissions_read",
|
||||
"dashboards.permissions:write": "permissions_write",
|
||||
}
|
||||
|
||||
// RBAC to OpenFGA translations grouped by kind
|
||||
var actionKindTranslations = map[string]actionKindTranslation{
|
||||
"folders": {
|
||||
objectType: "folder",
|
||||
orgScoped: true,
|
||||
translations: folderActions,
|
||||
},
|
||||
"dashboards": {
|
||||
objectType: "dashboard",
|
||||
orgScoped: true,
|
||||
translations: dashboardActions,
|
||||
},
|
||||
}
|
||||
@@ -8,41 +8,42 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
TypeUser string = "user"
|
||||
TypeTeam string = "team"
|
||||
TypeUser string = "user"
|
||||
TypeTeam string = "team"
|
||||
TypeFolder string = "folder"
|
||||
TypeDashboard string = "dashboard"
|
||||
)
|
||||
|
||||
const (
|
||||
RelationTeamMember string = "member"
|
||||
RelationTeamAdmin string = "admin"
|
||||
RelationParent string = "parent"
|
||||
)
|
||||
|
||||
func NewObject(typ, id string) string {
|
||||
return fmt.Sprintf("%s:%s", typ, id)
|
||||
// NewTupleEntry constructs new openfga entry type:id[#relation].
|
||||
// Relation allows to specify group of users (subjects) related to type:id
|
||||
// (for example, team:devs#member refers to users which are members of team devs)
|
||||
func NewTupleEntry(objectType, id, relation string) string {
|
||||
obj := fmt.Sprintf("%s:%s", objectType, id)
|
||||
if relation != "" {
|
||||
obj = fmt.Sprintf("%s#%s", obj, relation)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
func NewScopedObject(typ, id, scope string) string {
|
||||
return NewObject(typ, fmt.Sprintf("%s-%s", scope, id))
|
||||
// NewScopedTupleEntry constructs new openfga entry type:id[#relation]
|
||||
// with id prefixed by scope (usually org id)
|
||||
func NewScopedTupleEntry(objectType, id, relation, scope string) string {
|
||||
return NewTupleEntry(objectType, fmt.Sprintf("%s-%s", scope, id), "")
|
||||
}
|
||||
|
||||
// rbac action to relation translation
|
||||
var actionTranslations = map[string]string{}
|
||||
|
||||
type kindTranslation struct {
|
||||
typ string
|
||||
orgScoped bool
|
||||
}
|
||||
|
||||
// all kinds that we can translate into a openFGA object
|
||||
var kindTranslations = map[string]kindTranslation{}
|
||||
|
||||
func TranslateToTuple(user string, action, kind, identifier string, orgID int64) (*openfgav1.TupleKey, bool) {
|
||||
relation, ok := actionTranslations[action]
|
||||
typeTranslation, ok := actionKindTranslations[kind]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
t, ok := kindTranslations[kind]
|
||||
relation, ok := typeTranslation.translations[action]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
@@ -55,10 +56,10 @@ func TranslateToTuple(user string, action, kind, identifier string, orgID int64)
|
||||
tuple.Relation = relation
|
||||
|
||||
// Some uid:s in grafana are not guarantee to be unique across orgs so we need to scope them.
|
||||
if t.orgScoped {
|
||||
tuple.Object = NewScopedObject(t.typ, identifier, strconv.FormatInt(orgID, 10))
|
||||
if typeTranslation.orgScoped {
|
||||
tuple.Object = NewScopedTupleEntry(typeTranslation.objectType, identifier, "", strconv.FormatInt(orgID, 10))
|
||||
} else {
|
||||
tuple.Object = NewObject(t.typ, identifier)
|
||||
tuple.Object = NewTupleEntry(typeTranslation.objectType, identifier, "")
|
||||
}
|
||||
|
||||
return tuple, true
|
||||
|
||||
Reference in New Issue
Block a user