Zanzana: Handle anonymous users (#97171)

* add anonymous users to schema

* sync anonymous user role

* remove unused

* fix linter

* only add anonymous reconciler if feature is enabled
This commit is contained in:
Alexander Zobnin
2024-12-11 12:22:42 +01:00
committed by GitHub
parent e8e0649ebd
commit 61d71ec5b1
5 changed files with 70 additions and 2 deletions
@@ -8,6 +8,7 @@ import (
"github.com/grafana/grafana/pkg/infra/db"
authzextv1 "github.com/grafana/grafana/pkg/services/authz/proto/v1"
"github.com/grafana/grafana/pkg/services/authz/zanzana"
"github.com/grafana/grafana/pkg/setting"
)
func teamMembershipCollector(store db.DB) legacyTupleCollector {
@@ -394,6 +395,35 @@ func rolePermissionsCollector(store db.DB) legacyTupleCollector {
}
}
// 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) {
tuples := make(map[string]map[string]*openfgav1.TupleKey)
object := zanzana.NewTupleEntry(zanzana.TypeRole, zanzana.TranslateBasicRole(cfg.AnonymousOrgRole), "")
// Object should be set to delete obsolete permissions
tuples[object] = make(map[string]*openfgav1.TupleKey)
o, err := getOrgByName(ctx, store, cfg.AnonymousOrgName)
if err != nil {
return tuples, nil
}
if o.ID != orgID {
return tuples, nil
}
tuple := &openfgav1.TupleKey{
User: zanzana.NewTupleEntry(zanzana.TypeAnonymous, "0", ""),
Relation: zanzana.RelationAssignee,
Object: object,
}
tuples[tuple.Object][tuple.String()] = tuple
return tuples, nil
}
}
func zanzanaCollector(relations []string) zanzanaTupleCollector {
return func(ctx context.Context, client zanzana.Client, object string, namespace string) (map[string]*openfgav1.TupleKey, error) {
// list will use continuation token to collect all tuples for object and relation
@@ -2,6 +2,7 @@ package dualwrite
import (
"context"
"fmt"
"strconv"
"time"
@@ -12,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/serverlock"
"github.com/grafana/grafana/pkg/services/authz/zanzana"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/setting"
)
@@ -33,7 +35,7 @@ type ZanzanaReconciler struct {
}
func NewZanzanaReconciler(cfg *setting.Cfg, client zanzana.Client, store db.DB, lock *serverlock.ServerLockService) *ZanzanaReconciler {
return &ZanzanaReconciler{
zanzanaReconciler := &ZanzanaReconciler{
cfg: cfg,
log: log.New("zanzana.reconciler"),
client: client,
@@ -90,6 +92,19 @@ func NewZanzanaReconciler(cfg *setting.Cfg, client zanzana.Client, store db.DB,
),
},
}
if cfg.AnonymousEnabled {
zanzanaReconciler.reconcilers = append(zanzanaReconciler.reconcilers,
newResourceReconciler(
"anonymous role binding",
anonymousRoleBindingsCollector(cfg, store),
zanzanaCollector([]string{zanzana.RelationAssignee}),
client,
),
)
}
return zanzanaReconciler
}
// Reconcile schedules as job that will run and reconcile resources between
@@ -182,3 +197,22 @@ func (r *ZanzanaReconciler) getOrgs(ctx context.Context) ([]int64, error) {
}
return orgs, nil
}
func getOrgByName(ctx context.Context, store db.DB, name string) (*org.Org, error) {
var orga org.Org
err := store.WithDbSession(ctx, func(dbSession *db.Session) error {
exists, err := dbSession.Where("name=?", name).Get(&orga)
if err != nil {
return err
}
if !exists {
return fmt.Errorf("org does not exist: %s", name)
}
return nil
})
if err != nil {
return nil, err
}
return &orga, nil
}
@@ -14,6 +14,7 @@ const (
TypeUser string = "user"
TypeServiceAccount string = "service-account"
TypeRenderService string = "render"
TypeAnonymous string = "anonymous"
TypeTeam string = "team"
TypeRole string = "role"
)
@@ -6,9 +6,11 @@ type service-account
type render
type anonymous
type role
relations
define assignee: [user, service-account, team#member, role#assignee]
define assignee: [user, service-account, anonymous, team#member, role#assignee]
type team
relations
+1
View File
@@ -14,6 +14,7 @@ const (
TypeUser = common.TypeUser
TypeServiceAccount = common.TypeServiceAccount
TypeRenderService = common.TypeRenderService
TypeAnonymous = common.TypeAnonymous
TypeTeam = common.TypeTeam
TypeRole = common.TypeRole
TypeFolder = common.TypeFolder