Zanzana: Fix reconciliation for roles (#103889)

* Zanzana: Fix reconciliation for roles

* update go workspaces

* update go.sum
pull/104025/head
Alexander Zobnin 3 months ago committed by GitHub
parent 3bdcbc5d37
commit 4ea56b2cfb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 166
      pkg/services/accesscontrol/dualwrite/collectors.go
  2. 16
      pkg/services/accesscontrol/dualwrite/reconciler.go

@ -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) {
query := `
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 := `
userQuery := `
SELECT u.uid AS user_uid, u.is_service_account as is_service_account, r.uid AS role_uid
FROM user_role ur
INNER JOIN ` + store.GetDialect().Quote("user") + ` u ON ur.user_id = u.id
@ -304,97 +260,66 @@ func userRoleBindingsCollector(store db.DB) legacyTupleCollector {
type Binding struct {
UserUID string `xorm:"user_uid"`
IsServiceAccount bool `xorm:"is_service_account"`
TeamUID string `xorm:"team_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 {
return sess.SQL(query, orgID).Find(&bindings)
return sess.SQL(userQuery, orgID).Find(&userBindings)
})
if err != nil {
return nil, err
}
bindings = append(bindings, userBindings...)
tuples := make(map[string]map[string]*openfgav1.TupleKey)
for _, b := range bindings {
userType := zanzana.TypeUser
if b.IsServiceAccount {
userType = zanzana.TypeServiceAccount
}
tuple := &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)
}
tuples[tuple.Object][tuple.String()] = tuple
}
return tuples, nil
}
}
func rolePermissionsCollector(store db.DB) legacyTupleCollector {
return func(ctx context.Context, orgID 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 OR r.org_id = ?)
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:%'
AND r.name NOT 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, orgID).Find(&permissions)
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)
for _, b := range bindings {
var tuple *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 b.UserUID != "" {
userType := zanzana.TypeUser
if b.IsServiceAccount {
userType = zanzana.TypeServiceAccount
}
if tuples[tuple.Object] == nil {
tuples[tuple.Object] = make(map[string]*openfgav1.TupleKey)
}
tuple = &openfgav1.TupleKey{
User: zanzana.NewTupleEntry(userType, b.UserUID, ""),
Relation: zanzana.RelationAssignee,
Object: zanzana.NewTupleEntry(zanzana.TypeRole, b.RoleUID, ""),
}
// 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
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, ""),
}
continue
if tuples[tuple.Object] == nil {
tuples[tuple.Object] = make(map[string]*openfgav1.TupleKey)
}
}
tuples[tuple.Object][tuple.String()] = tuple
@ -404,15 +329,15 @@ 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) {
func rolePermissionsCollector(store db.DB) legacyTupleCollector {
return func(ctx context.Context, orgID 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:%'
WHERE (r.org_id = 0 OR r.org_id = ?)
AND r.name NOT LIKE 'managed:%'
`
type Permission struct {
@ -424,7 +349,7 @@ func fixedRolePermissionsCollector(store db.DB) legacyTupleCollector {
var permissions []Permission
err := store.WithDbSession(ctx, func(sess *db.Session) error {
return sess.SQL(query).Find(&permissions)
return sess.SQL(query, orgID).Find(&permissions)
})
if err != nil {
return nil, err
@ -455,6 +380,7 @@ func fixedRolePermissionsCollector(store db.DB) legacyTupleCollector {
} else {
tuples[tuple.Object][key] = tuple
}
continue
}

@ -83,23 +83,11 @@ func ProvideZanzanaReconciler(cfg *setting.Cfg, features featuremgmt.FeatureTogg
client,
),
newResourceReconciler(
"team role bindings",
teamRoleBindingsCollector(store),
"role bindings",
roleBindingsCollector(store),
zanzanaCollector([]string{zanzana.RelationAssignee}),
client,
),
newResourceReconciler(
"user role bindings",
userRoleBindingsCollector(store),
zanzanaCollector([]string{zanzana.RelationAssignee}),
client,
),
newResourceReconciler(
"fixed role pemissions",
fixedRolePermissionsCollector(store),
zanzanaCollector(zanzana.RelationsFolder),
client,
),
},
}

Loading…
Cancel
Save