Zanzana: Handle renderer service authorization requests (#97201)

* Zanzana: Handle renderer service authorization requests

* only add context if render service is authorizing

* use group and resource from API definitions

* check prefix instead of full identity

* fix AddRenderContext

* remove unused type
pull/97629/head
Alexander Zobnin 7 months ago committed by GitHub
parent 4f1307edb1
commit cd7772204e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 20
      pkg/services/authz/zanzana/common/tuple.go
  2. 14
      pkg/services/authz/zanzana/schema/schema_core.fga
  3. 11
      pkg/services/authz/zanzana/server/server_check.go
  4. 1
      pkg/services/authz/zanzana/zanzana.go

@ -6,12 +6,14 @@ import (
openfgav1 "github.com/openfga/api/proto/openfga/v1"
"google.golang.org/protobuf/types/known/structpb"
dashboardalpha1 "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
authzextv1 "github.com/grafana/grafana/pkg/services/authz/proto/v1"
)
const (
TypeUser string = "user"
TypeServiceAccount string = "service-account"
TypeRenderService string = "render"
TypeTeam string = "team"
TypeRole string = "role"
TypeFolder string = "folder"
@ -245,3 +247,21 @@ func ToOpenFGATuples(tuples []*authzextv1.Tuple) []*openfgav1.Tuple {
}
return result
}
func AddRenderContext(req *openfgav1.CheckRequest) {
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, &openfgav1.TupleKey{
User: req.TupleKey.User,
Relation: "view",
Object: NewNamespaceResourceIdent(
dashboardalpha1.DashboardResourceInfo.GroupResource().Group,
dashboardalpha1.DashboardResourceInfo.GroupResource().Resource,
),
})
}

@ -1,22 +1,24 @@
module core
type user
type service-account
type render
type namespace
relations
define view: [user, service-account, team#member, role#assignee] or edit
define view: [user, service-account, render, team#member, role#assignee] or edit
define edit: [user, service-account, team#member, role#assignee] or admin
define admin: [user, service-account, team#member, role#assignee]
define read: [user, service-account, team#member, role#assignee] or view
define read: [user, service-account, render, team#member, role#assignee] or view
define create: [user, service-account, team#member, role#assignee] or edit
define write: [user, service-account, team#member, role#assignee] or edit
define delete: [user, service-account, team#member, role#assignee] or edit
define permissions_read: [user, service-account, team#member, role#assignee] or admin
define permissions_write: [user, service-account, team#member, role#assignee] or admin
type user
type service-account
type role
relations
define assignee: [user, service-account, team#member, role#assignee]

@ -2,6 +2,8 @@ package server
import (
"context"
"fmt"
"strings"
authzv1 "github.com/grafana/authlib/authz/proto/v1"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
@ -40,7 +42,7 @@ func (s *Server) Check(ctx context.Context, r *authzv1.CheckRequest) (*authzv1.C
// checkTyped performes check on the root "namespace". If subject has access through the namespace they have access to
// every resource for that "GroupResource".
func (s *Server) checkNamespace(ctx context.Context, subject, relation, group, resource string, store *storeInfo) (*authzv1.CheckResponse, error) {
res, err := s.openfga.Check(ctx, &openfgav1.CheckRequest{
req := &openfgav1.CheckRequest{
StoreId: store.ID,
AuthorizationModelId: store.ModelID,
TupleKey: &openfgav1.CheckRequestTupleKey{
@ -48,7 +50,12 @@ func (s *Server) checkNamespace(ctx context.Context, subject, relation, group, r
Relation: relation,
Object: common.NewNamespaceResourceIdent(group, resource),
},
})
}
if strings.HasPrefix(subject, fmt.Sprintf("%s:", common.TypeRenderService)) {
common.AddRenderContext(req)
}
res, err := s.openfga.Check(ctx, req)
if err != nil {
return nil, err
}

@ -13,6 +13,7 @@ import (
const (
TypeUser = common.TypeUser
TypeServiceAccount = common.TypeServiceAccount
TypeRenderService = common.TypeRenderService
TypeTeam = common.TypeTeam
TypeRole = common.TypeRole
TypeFolder = common.TypeFolder

Loading…
Cancel
Save