2025-04-01 10:38:02 +09:00

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
}