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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user