mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Zanzana: Refactor fixed roles (use global store) (#97884)
* Zanzana: Pass contextual tuples for authorization * global reconciler for fixed roles * inject tuples from global store * fix adding contextual tuples * cleanup * don't error on auth context fail * add todo * add context for List * add caching * remove unused * use constant for global namespace * Rename global namespace to cluster namespace
This commit is contained in:
parent
9558a25ebe
commit
7e5cb7d8d6
@ -359,6 +359,7 @@ 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 {
|
||||||
@ -400,6 +401,56 @@ func rolePermissionsCollector(store db.DB) legacyTupleCollector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fixedRolePermissionsCollector(store db.DB) globalTupleCollector {
|
||||||
|
return func(ctx context.Context) (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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
112
pkg/services/accesscontrol/dualwrite/global_reconciler.go
Normal file
112
pkg/services/accesscontrol/dualwrite/global_reconciler.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
package dualwrite
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
||||||
|
|
||||||
|
authzextv1 "github.com/grafana/grafana/pkg/services/authz/proto/v1"
|
||||||
|
"github.com/grafana/grafana/pkg/services/authz/zanzana"
|
||||||
|
)
|
||||||
|
|
||||||
|
type globalTupleCollector func(ctx context.Context) (map[string]map[string]*openfgav1.TupleKey, error)
|
||||||
|
|
||||||
|
type globalReconciler struct {
|
||||||
|
name string
|
||||||
|
globalCollector globalTupleCollector
|
||||||
|
zanzana zanzanaTupleCollector
|
||||||
|
client zanzana.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGlobalReconciler(name string, globalCollector globalTupleCollector, zanzana zanzanaTupleCollector, client zanzana.Client) globalReconciler {
|
||||||
|
return globalReconciler{name, globalCollector, zanzana, client}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r globalReconciler) reconcile(ctx context.Context) error {
|
||||||
|
namespace := zanzana.ClusterNamespace
|
||||||
|
|
||||||
|
// 1. Fetch grafana resources stored in grafana db.
|
||||||
|
res, err := r.globalCollector(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to collect legacy tuples for %s: %w", r.name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
writes = []*openfgav1.TupleKey{}
|
||||||
|
deletes = []*openfgav1.TupleKeyWithoutCondition{}
|
||||||
|
)
|
||||||
|
|
||||||
|
for object, tuples := range res {
|
||||||
|
// 2. Fetch all tuples for given object.
|
||||||
|
// Due to limitations in open fga api we need to collect tuples per object
|
||||||
|
zanzanaTuples, err := r.zanzana(ctx, r.client, object, namespace)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to collect zanzanaa tuples for %s: %w", r.name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Check if tuples from grafana db exists in zanzana and if not add them to writes
|
||||||
|
for key, t := range tuples {
|
||||||
|
stored, ok := zanzanaTuples[key]
|
||||||
|
if !ok {
|
||||||
|
writes = append(writes, t)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. For folder resource tuples we also need to compare the stored group_resources
|
||||||
|
if zanzana.IsFolderResourceTuple(t) && t.String() != stored.String() {
|
||||||
|
deletes = append(deletes, &openfgav1.TupleKeyWithoutCondition{
|
||||||
|
User: t.User,
|
||||||
|
Relation: t.Relation,
|
||||||
|
Object: t.Object,
|
||||||
|
})
|
||||||
|
|
||||||
|
writes = append(writes, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Check if tuple from zanzana don't exists in grafana db, if not add them to deletes.
|
||||||
|
for key, tuple := range zanzanaTuples {
|
||||||
|
_, ok := tuples[key]
|
||||||
|
if !ok {
|
||||||
|
deletes = append(deletes, &openfgav1.TupleKeyWithoutCondition{
|
||||||
|
User: tuple.User,
|
||||||
|
Relation: tuple.Relation,
|
||||||
|
Object: tuple.Object,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(writes) == 0 && len(deletes) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(deletes) > 0 {
|
||||||
|
err := batch(deletes, 100, func(items []*openfgav1.TupleKeyWithoutCondition) error {
|
||||||
|
return r.client.Write(ctx, &authzextv1.WriteRequest{
|
||||||
|
Namespace: namespace,
|
||||||
|
Deletes: &authzextv1.WriteRequestDeletes{TupleKeys: zanzana.ToAuthzExtTupleKeysWithoutCondition(items)},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(writes) > 0 {
|
||||||
|
err := batch(writes, 100, func(items []*openfgav1.TupleKey) error {
|
||||||
|
return r.client.Write(ctx, &authzextv1.WriteRequest{
|
||||||
|
Namespace: namespace,
|
||||||
|
Writes: &authzextv1.WriteRequestWrites{TupleKeys: zanzana.ToAuthzExtTupleKeys(items)},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -32,7 +32,8 @@ type ZanzanaReconciler struct {
|
|||||||
lock *serverlock.ServerLockService
|
lock *serverlock.ServerLockService
|
||||||
// reconcilers are migrations that tries to reconcile the state of grafana db to zanzana store.
|
// reconcilers are migrations that tries to reconcile the state of grafana db to zanzana store.
|
||||||
// These are run periodically to try to maintain a consistent state.
|
// These are run periodically to try to maintain a consistent state.
|
||||||
reconcilers []resourceReconciler
|
reconcilers []resourceReconciler
|
||||||
|
globalReconcilers []globalReconciler
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewZanzanaReconciler(cfg *setting.Cfg, client zanzana.Client, store db.DB, lock *serverlock.ServerLockService, folderService folder.Service) *ZanzanaReconciler {
|
func NewZanzanaReconciler(cfg *setting.Cfg, client zanzana.Client, store db.DB, lock *serverlock.ServerLockService, folderService folder.Service) *ZanzanaReconciler {
|
||||||
@ -92,6 +93,14 @@ func NewZanzanaReconciler(cfg *setting.Cfg, client zanzana.Client, store db.DB,
|
|||||||
client,
|
client,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
globalReconcilers: []globalReconciler{
|
||||||
|
newGlobalReconciler(
|
||||||
|
"fixed role pemissions",
|
||||||
|
fixedRolePermissionsCollector(store),
|
||||||
|
zanzanaCollector([]string{zanzana.RelationAssignee}),
|
||||||
|
client,
|
||||||
|
),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Anonymous.Enabled {
|
if cfg.Anonymous.Enabled {
|
||||||
@ -134,8 +143,19 @@ func (r *ZanzanaReconciler) ReconcileSync(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *ZanzanaReconciler) reconcile(ctx context.Context) {
|
func (r *ZanzanaReconciler) reconcile(ctx context.Context) {
|
||||||
|
runGlobal := func(ctx context.Context) {
|
||||||
|
for _, reconciler := range r.globalReconcilers {
|
||||||
|
r.log.Debug("Performing zanzana reconciliation", "reconciler", reconciler.name)
|
||||||
|
if err := reconciler.reconcile(ctx); err != nil {
|
||||||
|
r.log.Warn("Failed to perform reconciliation for resource", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
run := func(ctx context.Context, namespace string) {
|
run := func(ctx context.Context, namespace string) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
r.log.Debug("Started reconciliation")
|
||||||
|
|
||||||
for _, reconciler := range r.reconcilers {
|
for _, reconciler := range r.reconcilers {
|
||||||
r.log.Debug("Performing zanzana reconciliation", "reconciler", reconciler.name)
|
r.log.Debug("Performing zanzana reconciliation", "reconciler", reconciler.name)
|
||||||
if err := reconciler.reconcile(ctx, namespace); err != nil {
|
if err := reconciler.reconcile(ctx, namespace); err != nil {
|
||||||
@ -167,6 +187,7 @@ func (r *ZanzanaReconciler) reconcile(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if r.lock == nil {
|
if r.lock == nil {
|
||||||
|
runGlobal(ctx)
|
||||||
for _, ns := range namespaces {
|
for _, ns := range namespaces {
|
||||||
run(ctx, ns)
|
run(ctx, ns)
|
||||||
}
|
}
|
||||||
@ -175,6 +196,7 @@ func (r *ZanzanaReconciler) reconcile(ctx context.Context) {
|
|||||||
|
|
||||||
// We ignore the error for now
|
// We ignore the error for now
|
||||||
err := r.lock.LockExecuteAndRelease(ctx, "zanzana-reconciliation", 10*time.Hour, func(ctx context.Context) {
|
err := r.lock.LockExecuteAndRelease(ctx, "zanzana-reconciliation", 10*time.Hour, func(ctx context.Context) {
|
||||||
|
runGlobal(ctx)
|
||||||
for _, ns := range namespaces {
|
for _, ns := range namespaces {
|
||||||
run(ctx, ns)
|
run(ctx, ns)
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,8 @@ var RelationsFolder = append(
|
|||||||
RelationDelete,
|
RelationDelete,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ClusterNamespace = "cluster"
|
||||||
|
|
||||||
func IsGroupResourceRelation(relation string) bool {
|
func IsGroupResourceRelation(relation string) bool {
|
||||||
return isValidRelation(relation, RelationsGroupResource)
|
return isValidRelation(relation, RelationsGroupResource)
|
||||||
}
|
}
|
||||||
@ -259,6 +261,14 @@ func ToOpenFGATupleKey(t *authzextv1.TupleKey) *openfgav1.TupleKey {
|
|||||||
return tupleKey
|
return tupleKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ToOpenFGATupleKeys(tuples []*authzextv1.TupleKey) []*openfgav1.TupleKey {
|
||||||
|
result := make([]*openfgav1.TupleKey, 0, len(tuples))
|
||||||
|
for _, t := range tuples {
|
||||||
|
result = append(result, ToOpenFGATupleKey(t))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func ToOpenFGATupleKeyWithoutCondition(t *authzextv1.TupleKeyWithoutCondition) *openfgav1.TupleKeyWithoutCondition {
|
func ToOpenFGATupleKeyWithoutCondition(t *authzextv1.TupleKeyWithoutCondition) *openfgav1.TupleKeyWithoutCondition {
|
||||||
return &openfgav1.TupleKeyWithoutCondition{
|
return &openfgav1.TupleKeyWithoutCondition{
|
||||||
User: t.GetUser(),
|
User: t.GetUser(),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
authzextv1 "github.com/grafana/grafana/pkg/services/authz/proto/v1"
|
authzextv1 "github.com/grafana/grafana/pkg/services/authz/proto/v1"
|
||||||
|
"github.com/grafana/grafana/pkg/services/authz/zanzana/common"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -91,3 +93,71 @@ func NewAuthz(cfg *setting.Cfg, openfga openfgav1.OpenFGAServiceServer, opts ...
|
|||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) getGlobalAuthorizationContext(ctx context.Context) ([]*openfgav1.TupleKey, error) {
|
||||||
|
cacheKey := "global_authorization_context"
|
||||||
|
contextualTuples := make([]*openfgav1.TupleKey, 0)
|
||||||
|
|
||||||
|
cached, found := s.cache.Get(cacheKey)
|
||||||
|
if found {
|
||||||
|
contextualTuples = cached.([]*openfgav1.TupleKey)
|
||||||
|
return contextualTuples, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := s.Read(ctx, &authzextv1.ReadRequest{
|
||||||
|
Namespace: common.ClusterNamespace,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tuples := common.ToOpenFGATuples(res.Tuples)
|
||||||
|
for _, t := range tuples {
|
||||||
|
contextualTuples = append(contextualTuples, t.GetKey())
|
||||||
|
}
|
||||||
|
s.cache.SetDefault(cacheKey, contextualTuples)
|
||||||
|
|
||||||
|
return contextualTuples, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) addCheckAuthorizationContext(ctx context.Context, req *openfgav1.CheckRequest) error {
|
||||||
|
contextualTuples, err := s.getGlobalAuthorizationContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(contextualTuples) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.ContextualTuples == nil {
|
||||||
|
req.ContextualTuples = &openfgav1.ContextualTupleKeys{}
|
||||||
|
}
|
||||||
|
if req.ContextualTuples.TupleKeys == nil {
|
||||||
|
req.ContextualTuples.TupleKeys = make([]*openfgav1.TupleKey, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.ContextualTuples.TupleKeys = append(req.ContextualTuples.TupleKeys, contextualTuples...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) addListAuthorizationContext(ctx context.Context, req *openfgav1.ListObjectsRequest) error {
|
||||||
|
contextualTuples, err := s.getGlobalAuthorizationContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(contextualTuples) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.ContextualTuples == nil {
|
||||||
|
req.ContextualTuples = &openfgav1.ContextualTupleKeys{}
|
||||||
|
}
|
||||||
|
if req.ContextualTuples.TupleKeys == nil {
|
||||||
|
req.ContextualTuples.TupleKeys = make([]*openfgav1.TupleKey, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.ContextualTuples.TupleKeys = append(req.ContextualTuples.TupleKeys, contextualTuples...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -57,7 +57,7 @@ func (s *Server) checkGroupResource(ctx context.Context, subject, relation, grou
|
|||||||
common.AddRenderContext(req)
|
common.AddRenderContext(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := s.openfga.Check(ctx, req)
|
res, err := s.check(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ func (s *Server) checkTyped(ctx context.Context, subject, relation, name string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if subject has direct access to resource
|
// Check if subject has direct access to resource
|
||||||
res, err := s.openfga.Check(ctx, &openfgav1.CheckRequest{
|
res, err := s.check(ctx, &openfgav1.CheckRequest{
|
||||||
StoreId: store.ID,
|
StoreId: store.ID,
|
||||||
AuthorizationModelId: store.ModelID,
|
AuthorizationModelId: store.ModelID,
|
||||||
TupleKey: &openfgav1.CheckRequestTupleKey{
|
TupleKey: &openfgav1.CheckRequestTupleKey{
|
||||||
@ -103,7 +103,7 @@ func (s *Server) checkGeneric(ctx context.Context, subject, relation, group, res
|
|||||||
|
|
||||||
if folder != "" && common.IsFolderResourceRelation(folderRelation) {
|
if folder != "" && common.IsFolderResourceRelation(folderRelation) {
|
||||||
// Check if subject has access as a sub resource for the folder
|
// Check if subject has access as a sub resource for the folder
|
||||||
res, err := s.openfga.Check(ctx, &openfgav1.CheckRequest{
|
res, err := s.check(ctx, &openfgav1.CheckRequest{
|
||||||
StoreId: store.ID,
|
StoreId: store.ID,
|
||||||
AuthorizationModelId: store.ModelID,
|
AuthorizationModelId: store.ModelID,
|
||||||
TupleKey: &openfgav1.CheckRequestTupleKey{
|
TupleKey: &openfgav1.CheckRequestTupleKey{
|
||||||
@ -128,7 +128,7 @@ func (s *Server) checkGeneric(ctx context.Context, subject, relation, group, res
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if subject has direct access to resource
|
// Check if subject has direct access to resource
|
||||||
res, err := s.openfga.Check(ctx, &openfgav1.CheckRequest{
|
res, err := s.check(ctx, &openfgav1.CheckRequest{
|
||||||
StoreId: store.ID,
|
StoreId: store.ID,
|
||||||
AuthorizationModelId: store.ModelID,
|
AuthorizationModelId: store.ModelID,
|
||||||
TupleKey: &openfgav1.CheckRequestTupleKey{
|
TupleKey: &openfgav1.CheckRequestTupleKey{
|
||||||
@ -145,3 +145,12 @@ func (s *Server) checkGeneric(ctx context.Context, subject, relation, group, res
|
|||||||
|
|
||||||
return &authzv1.CheckResponse{Allowed: res.GetAllowed()}, nil
|
return &authzv1.CheckResponse{Allowed: res.GetAllowed()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) check(ctx context.Context, req *openfgav1.CheckRequest) (*openfgav1.CheckResponse, error) {
|
||||||
|
err := s.addCheckAuthorizationContext(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("failed to add authorization context", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.openfga.Check(ctx, req)
|
||||||
|
}
|
||||||
|
@ -39,6 +39,11 @@ func (s *Server) List(ctx context.Context, r *authzv1.ListRequest) (*authzv1.Lis
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) listObjects(ctx context.Context, req *openfgav1.ListObjectsRequest) (*openfgav1.ListObjectsResponse, error) {
|
func (s *Server) listObjects(ctx context.Context, req *openfgav1.ListObjectsRequest) (*openfgav1.ListObjectsResponse, error) {
|
||||||
|
err := s.addListAuthorizationContext(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error("failed to add authorization context", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
if s.cfg.UseStreamedListObjects {
|
if s.cfg.UseStreamedListObjects {
|
||||||
return s.streamedListObjects(ctx, req)
|
return s.streamedListObjects(ctx, req)
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,21 @@ func (s *Server) Read(ctx context.Context, req *authzextv1.ReadRequest) (*authze
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := s.openfga.Read(ctx, &openfgav1.ReadRequest{
|
readReq := &openfgav1.ReadRequest{
|
||||||
StoreId: storeInf.ID,
|
StoreId: storeInf.ID,
|
||||||
TupleKey: &openfgav1.ReadRequestTupleKey{
|
PageSize: req.GetPageSize(),
|
||||||
|
ContinuationToken: req.GetContinuationToken(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.TupleKey != nil {
|
||||||
|
readReq.TupleKey = &openfgav1.ReadRequestTupleKey{
|
||||||
User: req.GetTupleKey().GetUser(),
|
User: req.GetTupleKey().GetUser(),
|
||||||
Relation: req.GetTupleKey().GetRelation(),
|
Relation: req.GetTupleKey().GetRelation(),
|
||||||
Object: req.GetTupleKey().GetObject(),
|
Object: req.GetTupleKey().GetObject(),
|
||||||
},
|
}
|
||||||
PageSize: req.GetPageSize(),
|
}
|
||||||
ContinuationToken: req.GetContinuationToken(),
|
|
||||||
})
|
res, err := s.openfga.Read(ctx, readReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,8 @@ const (
|
|||||||
KindFolders string = "folders"
|
KindFolders string = "folders"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ClusterNamespace = common.ClusterNamespace
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ToAuthzExtTupleKey = common.ToAuthzExtTupleKey
|
ToAuthzExtTupleKey = common.ToAuthzExtTupleKey
|
||||||
ToAuthzExtTupleKeys = common.ToAuthzExtTupleKeys
|
ToAuthzExtTupleKeys = common.ToAuthzExtTupleKeys
|
||||||
|
Loading…
Reference in New Issue
Block a user