mirror of
https://github.com/grafana/grafana.git
synced 2025-08-06 05:56:24 +08:00
Zanzana: Fix reconciliation for roles (#103889)
* Zanzana: Fix reconciliation for roles * update go workspaces * update go.sum
This commit is contained in:
@ -247,53 +247,9 @@ func basicRoleBindingsCollector(store db.DB) legacyTupleCollector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func teamRoleBindingsCollector(store db.DB) legacyTupleCollector {
|
func roleBindingsCollector(store db.DB) legacyTupleCollector {
|
||||||
return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) {
|
return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) {
|
||||||
query := `
|
userQuery := `
|
||||||
SELECT t.uid AS team_uid, r.uid AS role_uid
|
|
||||||
FROM team_role tr
|
|
||||||
INNER JOIN team t ON tr.team_id = t.id
|
|
||||||
INNER JOIN role r ON tr.role_id = r.id
|
|
||||||
WHERE t.org_id = ?
|
|
||||||
AND r.name NOT LIKE 'managed:%'
|
|
||||||
`
|
|
||||||
type Binding struct {
|
|
||||||
TeamUID string `xorm:"team_uid"`
|
|
||||||
RoleUID string `xorm:"role_uid"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var bindings []Binding
|
|
||||||
err := store.WithDbSession(ctx, func(sess *db.Session) error {
|
|
||||||
return sess.SQL(query, orgID).Find(&bindings)
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tuples := make(map[string]map[string]*openfgav1.TupleKey)
|
|
||||||
|
|
||||||
for _, b := range bindings {
|
|
||||||
tuple := &openfgav1.TupleKey{
|
|
||||||
User: zanzana.NewTupleEntry(zanzana.TypeTeam, b.TeamUID, zanzana.RelationTeamMember),
|
|
||||||
Relation: zanzana.RelationAssignee,
|
|
||||||
Object: zanzana.NewTupleEntry(zanzana.TypeRole, b.RoleUID, ""),
|
|
||||||
}
|
|
||||||
|
|
||||||
if tuples[tuple.Object] == nil {
|
|
||||||
tuples[tuple.Object] = make(map[string]*openfgav1.TupleKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
tuples[tuple.Object][tuple.String()] = tuple
|
|
||||||
}
|
|
||||||
|
|
||||||
return tuples, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func userRoleBindingsCollector(store db.DB) legacyTupleCollector {
|
|
||||||
return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) {
|
|
||||||
query := `
|
|
||||||
SELECT u.uid AS user_uid, u.is_service_account as is_service_account, r.uid AS role_uid
|
SELECT u.uid AS user_uid, u.is_service_account as is_service_account, r.uid AS role_uid
|
||||||
FROM user_role ur
|
FROM user_role ur
|
||||||
INNER JOIN ` + store.GetDialect().Quote("user") + ` u ON ur.user_id = u.id
|
INNER JOIN ` + store.GetDialect().Quote("user") + ` u ON ur.user_id = u.id
|
||||||
@ -304,34 +260,66 @@ func userRoleBindingsCollector(store db.DB) legacyTupleCollector {
|
|||||||
type Binding struct {
|
type Binding struct {
|
||||||
UserUID string `xorm:"user_uid"`
|
UserUID string `xorm:"user_uid"`
|
||||||
IsServiceAccount bool `xorm:"is_service_account"`
|
IsServiceAccount bool `xorm:"is_service_account"`
|
||||||
|
TeamUID string `xorm:"team_uid"`
|
||||||
RoleUID string `xorm:"role_uid"`
|
RoleUID string `xorm:"role_uid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var bindings []Binding
|
bindings := make([]Binding, 0)
|
||||||
|
var userBindings []Binding
|
||||||
err := store.WithDbSession(ctx, func(sess *db.Session) error {
|
err := store.WithDbSession(ctx, func(sess *db.Session) error {
|
||||||
return sess.SQL(query, orgID).Find(&bindings)
|
return sess.SQL(userQuery, orgID).Find(&userBindings)
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
bindings = append(bindings, userBindings...)
|
||||||
|
|
||||||
|
teamQuery := `
|
||||||
|
SELECT t.uid AS team_uid, r.uid AS role_uid
|
||||||
|
FROM team_role tr
|
||||||
|
INNER JOIN team t ON tr.team_id = t.id
|
||||||
|
INNER JOIN role r ON tr.role_id = r.id
|
||||||
|
WHERE t.org_id = ?
|
||||||
|
AND r.name NOT LIKE 'managed:%'
|
||||||
|
`
|
||||||
|
var teamBindings []Binding
|
||||||
|
err = store.WithDbSession(ctx, func(sess *db.Session) error {
|
||||||
|
return sess.SQL(teamQuery, orgID).Find(&teamBindings)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bindings = append(bindings, teamBindings...)
|
||||||
|
|
||||||
tuples := make(map[string]map[string]*openfgav1.TupleKey)
|
tuples := make(map[string]map[string]*openfgav1.TupleKey)
|
||||||
|
|
||||||
for _, b := range bindings {
|
for _, b := range bindings {
|
||||||
userType := zanzana.TypeUser
|
var tuple *openfgav1.TupleKey
|
||||||
if b.IsServiceAccount {
|
|
||||||
userType = zanzana.TypeServiceAccount
|
|
||||||
}
|
|
||||||
|
|
||||||
tuple := &openfgav1.TupleKey{
|
if b.UserUID != "" {
|
||||||
User: zanzana.NewTupleEntry(userType, b.UserUID, ""),
|
userType := zanzana.TypeUser
|
||||||
Relation: zanzana.RelationAssignee,
|
if b.IsServiceAccount {
|
||||||
Object: zanzana.NewTupleEntry(zanzana.TypeRole, b.RoleUID, ""),
|
userType = zanzana.TypeServiceAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
if tuples[tuple.Object] == nil {
|
tuple = &openfgav1.TupleKey{
|
||||||
tuples[tuple.Object] = make(map[string]*openfgav1.TupleKey)
|
User: zanzana.NewTupleEntry(userType, b.UserUID, ""),
|
||||||
|
Relation: zanzana.RelationAssignee,
|
||||||
|
Object: zanzana.NewTupleEntry(zanzana.TypeRole, b.RoleUID, ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
if tuples[tuple.Object] == nil {
|
||||||
|
tuples[tuple.Object] = make(map[string]*openfgav1.TupleKey)
|
||||||
|
}
|
||||||
|
} else if b.TeamUID != "" {
|
||||||
|
tuple = &openfgav1.TupleKey{
|
||||||
|
User: zanzana.NewTupleEntry(zanzana.TypeTeam, b.TeamUID, zanzana.RelationTeamMember),
|
||||||
|
Relation: zanzana.RelationAssignee,
|
||||||
|
Object: zanzana.NewTupleEntry(zanzana.TypeRole, b.RoleUID, ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
if tuples[tuple.Object] == nil {
|
||||||
|
tuples[tuple.Object] = make(map[string]*openfgav1.TupleKey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tuples[tuple.Object][tuple.String()] = tuple
|
tuples[tuple.Object][tuple.String()] = tuple
|
||||||
@ -350,7 +338,6 @@ func rolePermissionsCollector(store db.DB) legacyTupleCollector {
|
|||||||
LEFT JOIN builtin_role br ON r.id = br.role_id
|
LEFT JOIN builtin_role br ON r.id = br.role_id
|
||||||
WHERE (r.org_id = 0 OR r.org_id = ?)
|
WHERE (r.org_id = 0 OR r.org_id = ?)
|
||||||
AND r.name NOT LIKE 'managed:%'
|
AND r.name NOT LIKE 'managed:%'
|
||||||
AND r.name NOT LIKE 'fixed:%'
|
|
||||||
`
|
`
|
||||||
|
|
||||||
type Permission struct {
|
type Permission struct {
|
||||||
@ -404,67 +391,6 @@ func rolePermissionsCollector(store db.DB) legacyTupleCollector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fixedRolePermissionsCollector(store db.DB) legacyTupleCollector {
|
|
||||||
return func(ctx context.Context, _ int64) (map[string]map[string]*openfgav1.TupleKey, error) {
|
|
||||||
var query = `
|
|
||||||
SELECT r.uid as role_uid, p.action, p.kind, p.identifier
|
|
||||||
FROM permission p
|
|
||||||
INNER JOIN role r ON p.role_id = r.id
|
|
||||||
LEFT JOIN builtin_role br ON r.id = br.role_id
|
|
||||||
WHERE r.org_id = 0
|
|
||||||
AND r.name LIKE 'fixed:%'
|
|
||||||
`
|
|
||||||
|
|
||||||
type Permission struct {
|
|
||||||
Action string `xorm:"action"`
|
|
||||||
Kind string
|
|
||||||
Identifier string
|
|
||||||
RoleUID string `xorm:"role_uid"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var permissions []Permission
|
|
||||||
err := store.WithDbSession(ctx, func(sess *db.Session) error {
|
|
||||||
return sess.SQL(query).Find(&permissions)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tuples := make(map[string]map[string]*openfgav1.TupleKey)
|
|
||||||
|
|
||||||
for _, p := range permissions {
|
|
||||||
tuple, ok := zanzana.TranslateToResourceTuple(
|
|
||||||
zanzana.NewTupleEntry(zanzana.TypeRole, p.RoleUID, zanzana.RelationAssignee),
|
|
||||||
p.Action,
|
|
||||||
p.Kind,
|
|
||||||
p.Identifier,
|
|
||||||
)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if tuples[tuple.Object] == nil {
|
|
||||||
tuples[tuple.Object] = make(map[string]*openfgav1.TupleKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// For resource actions on folders we need to merge the tuples into one with combined subresources.
|
|
||||||
if zanzana.IsFolderResourceTuple(tuple) {
|
|
||||||
key := tupleStringWithoutCondition(tuple)
|
|
||||||
if t, ok := tuples[tuple.Object][key]; ok {
|
|
||||||
zanzana.MergeFolderResourceTuples(t, tuple)
|
|
||||||
} else {
|
|
||||||
tuples[tuple.Object][key] = tuple
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
tuples[tuple.Object][tuple.String()] = tuple
|
|
||||||
}
|
|
||||||
|
|
||||||
return tuples, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// basicRoleBindingsCollector collects role bindings for basic roles
|
// basicRoleBindingsCollector collects role bindings for basic roles
|
||||||
func anonymousRoleBindingsCollector(cfg *setting.Cfg, store db.DB) legacyTupleCollector {
|
func anonymousRoleBindingsCollector(cfg *setting.Cfg, store db.DB) legacyTupleCollector {
|
||||||
return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) {
|
return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) {
|
||||||
|
@ -83,23 +83,11 @@ func ProvideZanzanaReconciler(cfg *setting.Cfg, features featuremgmt.FeatureTogg
|
|||||||
client,
|
client,
|
||||||
),
|
),
|
||||||
newResourceReconciler(
|
newResourceReconciler(
|
||||||
"team role bindings",
|
"role bindings",
|
||||||
teamRoleBindingsCollector(store),
|
roleBindingsCollector(store),
|
||||||
zanzanaCollector([]string{zanzana.RelationAssignee}),
|
zanzanaCollector([]string{zanzana.RelationAssignee}),
|
||||||
client,
|
client,
|
||||||
),
|
),
|
||||||
newResourceReconciler(
|
|
||||||
"user role bindings",
|
|
||||||
userRoleBindingsCollector(store),
|
|
||||||
zanzanaCollector([]string{zanzana.RelationAssignee}),
|
|
||||||
client,
|
|
||||||
),
|
|
||||||
newResourceReconciler(
|
|
||||||
"fixed role pemissions",
|
|
||||||
fixedRolePermissionsCollector(store),
|
|
||||||
zanzanaCollector(zanzana.RelationsFolder),
|
|
||||||
client,
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user