106 lines
2.9 KiB
Go
106 lines
2.9 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/fullstorydev/grpchan/inprocgrpc"
|
|
authzv1 "github.com/grafana/authlib/authz/proto/v1"
|
|
openfgav1 "github.com/openfga/api/proto/openfga/v1"
|
|
"google.golang.org/protobuf/types/known/wrapperspb"
|
|
|
|
dashboardalpha1 "github.com/grafana/grafana/pkg/apis/dashboard/v2alpha1"
|
|
"github.com/grafana/grafana/pkg/infra/localcache"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
|
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"
|
|
)
|
|
|
|
const cacheCleanInterval = 2 * time.Minute
|
|
|
|
var _ authzv1.AuthzServiceServer = (*Server)(nil)
|
|
var _ authzextv1.AuthzExtentionServiceServer = (*Server)(nil)
|
|
|
|
type OpenFGAServer interface {
|
|
openfgav1.OpenFGAServiceServer
|
|
IsReady(ctx context.Context) (bool, error)
|
|
}
|
|
|
|
type Server struct {
|
|
authzv1.UnimplementedAuthzServiceServer
|
|
authzextv1.UnimplementedAuthzExtentionServiceServer
|
|
|
|
openfga OpenFGAServer
|
|
openfgaClient openfgav1.OpenFGAServiceClient
|
|
|
|
cfg setting.ZanzanaServerSettings
|
|
stores map[string]storeInfo
|
|
storesMU *sync.Mutex
|
|
cache *localcache.CacheService
|
|
|
|
logger log.Logger
|
|
tracer tracing.Tracer
|
|
}
|
|
|
|
type storeInfo struct {
|
|
ID string
|
|
ModelID string
|
|
}
|
|
|
|
func NewServer(cfg setting.ZanzanaServerSettings, openfga OpenFGAServer, logger log.Logger, tracer tracing.Tracer) (*Server, error) {
|
|
channel := &inprocgrpc.Channel{}
|
|
openfgav1.RegisterOpenFGAServiceServer(channel, openfga)
|
|
openFGAClient := openfgav1.NewOpenFGAServiceClient(channel)
|
|
|
|
s := &Server{
|
|
openfga: openfga,
|
|
openfgaClient: openFGAClient,
|
|
storesMU: &sync.Mutex{},
|
|
stores: make(map[string]storeInfo),
|
|
cfg: cfg,
|
|
cache: localcache.New(cfg.CheckQueryCacheTTL, cacheCleanInterval),
|
|
logger: logger,
|
|
tracer: tracer,
|
|
}
|
|
|
|
return s, nil
|
|
}
|
|
|
|
func (s *Server) IsHealthy(ctx context.Context) (bool, error) {
|
|
// FIXME: get back to openfga.IsReady() when issue is fixed
|
|
// https://github.com/openfga/openfga/issues/2251
|
|
_, err := s.openfga.ListStores(ctx, &openfgav1.ListStoresRequest{
|
|
PageSize: wrapperspb.Int32(1),
|
|
})
|
|
return err == nil, nil
|
|
}
|
|
|
|
func (s *Server) getContextuals(subject string) (*openfgav1.ContextualTupleKeys, error) {
|
|
contextuals := make([]*openfgav1.TupleKey, 0)
|
|
|
|
if strings.HasPrefix(subject, common.TypeRenderService+":") {
|
|
contextuals = append(
|
|
contextuals,
|
|
&openfgav1.TupleKey{
|
|
User: subject,
|
|
Relation: common.RelationSetView,
|
|
Object: common.NewGroupResourceIdent(
|
|
dashboardalpha1.DashboardResourceInfo.GroupResource().Group,
|
|
dashboardalpha1.DashboardResourceInfo.GroupResource().Resource,
|
|
"",
|
|
),
|
|
},
|
|
)
|
|
}
|
|
|
|
if len(contextuals) > 0 {
|
|
return &openfgav1.ContextualTupleKeys{TupleKeys: contextuals}, nil
|
|
}
|
|
|
|
return nil, nil
|
|
}
|