90 lines
2.4 KiB
Go
90 lines
2.4 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
|
|
authzv1 "github.com/grafana/authlib/authz/proto/v1"
|
|
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/common"
|
|
)
|
|
|
|
func (s *Server) BatchCheck(ctx context.Context, r *authzextv1.BatchCheckRequest) (*authzextv1.BatchCheckResponse, error) {
|
|
ctx, span := s.tracer.Start(ctx, "server.BatchCheck")
|
|
defer span.End()
|
|
|
|
if err := authorize(ctx, r.GetNamespace()); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
batchRes := &authzextv1.BatchCheckResponse{
|
|
Groups: make(map[string]*authzextv1.BatchCheckGroupResource),
|
|
}
|
|
|
|
store, err := s.getStoreInfo(ctx, r.GetNamespace())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
contextuals, err := s.getContextuals(r.GetSubject())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
groupResourceAccess := make(map[string]bool)
|
|
|
|
for _, item := range r.GetItems() {
|
|
res, err := s.batchCheckItem(ctx, r, item, contextuals, store, groupResourceAccess)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
groupResource := common.FormatGroupResource(item.GetGroup(), item.GetResource(), item.GetSubresource())
|
|
if _, ok := batchRes.Groups[groupResource]; !ok {
|
|
batchRes.Groups[groupResource] = &authzextv1.BatchCheckGroupResource{
|
|
Items: make(map[string]bool),
|
|
}
|
|
}
|
|
batchRes.Groups[groupResource].Items[item.GetName()] = res.GetAllowed()
|
|
}
|
|
|
|
return batchRes, nil
|
|
}
|
|
|
|
func (s *Server) batchCheckItem(
|
|
ctx context.Context,
|
|
r *authzextv1.BatchCheckRequest,
|
|
item *authzextv1.BatchCheckItem,
|
|
contextuals *openfgav1.ContextualTupleKeys,
|
|
store *storeInfo,
|
|
groupResourceAccess map[string]bool,
|
|
) (*authzv1.CheckResponse, error) {
|
|
var (
|
|
relation = common.VerbMapping[item.GetVerb()]
|
|
resource = common.NewResourceInfoFromBatchItem(item)
|
|
groupResource = resource.GroupResource()
|
|
)
|
|
|
|
allowed, ok := groupResourceAccess[groupResource]
|
|
if !ok {
|
|
res, err := s.checkGroupResource(ctx, r.GetSubject(), relation, resource, contextuals, store)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
allowed = res.GetAllowed()
|
|
groupResourceAccess[groupResource] = res.GetAllowed()
|
|
}
|
|
|
|
if allowed {
|
|
return &authzv1.CheckResponse{Allowed: true}, nil
|
|
}
|
|
|
|
if resource.IsGeneric() {
|
|
return s.checkGeneric(ctx, r.GetSubject(), relation, resource, contextuals, store)
|
|
}
|
|
|
|
return s.checkTyped(ctx, r.GetSubject(), relation, resource, contextuals, store)
|
|
}
|