diff --git a/pkg/services/accesscontrol/dualwrite/collectors.go b/pkg/services/accesscontrol/dualwrite/collectors.go index 1580b151b09..34b50b16549 100644 --- a/pkg/services/accesscontrol/dualwrite/collectors.go +++ b/pkg/services/accesscontrol/dualwrite/collectors.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,34 +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...) + + 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) - for _, b := range bindings { - userType := zanzana.TypeUser - if b.IsServiceAccount { - userType = zanzana.TypeServiceAccount - } + var tuple *openfgav1.TupleKey - tuple := &openfgav1.TupleKey{ - User: zanzana.NewTupleEntry(userType, b.UserUID, ""), - Relation: zanzana.RelationAssignee, - Object: zanzana.NewTupleEntry(zanzana.TypeRole, b.RoleUID, ""), - } + 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, ""), + } + + 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 @@ -350,7 +338,6 @@ func rolePermissionsCollector(store db.DB) legacyTupleCollector { LEFT JOIN builtin_role br ON r.id = br.role_id WHERE (r.org_id = 0 OR r.org_id = ?) AND r.name NOT LIKE 'managed:%' - AND r.name NOT LIKE 'fixed:%' ` 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 func anonymousRoleBindingsCollector(cfg *setting.Cfg, store db.DB) legacyTupleCollector { return func(ctx context.Context, orgID int64) (map[string]map[string]*openfgav1.TupleKey, error) { diff --git a/pkg/services/accesscontrol/dualwrite/reconciler.go b/pkg/services/accesscontrol/dualwrite/reconciler.go index 7bca9dc1903..6aa17b67c52 100644 --- a/pkg/services/accesscontrol/dualwrite/reconciler.go +++ b/pkg/services/accesscontrol/dualwrite/reconciler.go @@ -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, - ), }, }