refactor: use own types for Check and ListObjects inside accesscontrol package

This commit is contained in:
Alexander Zobnin
2024-09-11 15:15:09 +02:00
parent c65cc7f0e1
commit dc6134f3f8
8 changed files with 63 additions and 47 deletions
+2 -6
View File
@@ -7,7 +7,6 @@ import (
"strings"
"github.com/grafana/authlib/claims"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
@@ -29,8 +28,8 @@ type AccessControl interface {
// specific scope prefix (ex: datasources:name:)
RegisterScopeAttributeResolver(prefix string, resolver ScopeAttributeResolver)
Check(ctx context.Context, in *openfgav1.CheckRequest) (*openfgav1.CheckResponse, error)
ListObjects(ctx context.Context, in *openfgav1.ListObjectsRequest) (*openfgav1.ListObjectsResponse, error)
Check(ctx context.Context, req CheckRequest) (bool, error)
ListObjects(ctx context.Context, req ListObjectsRequest) ([]string, error)
}
type Service interface {
@@ -62,9 +61,6 @@ type Service interface {
SyncUserRoles(ctx context.Context, orgID int64, cmd SyncUserRolesCommand) error
}
type ZanzanaChecker interface {
}
//go:generate mockery --name Store --structname MockStore --outpkg actest --filename store_mock.go --output ./actest/
type Store interface {
GetUserPermissions(ctx context.Context, query GetUserPermissionsQuery) ([]Permission, error)
@@ -119,26 +119,24 @@ func (a *AccessControl) evaluateZanzana(ctx context.Context, user identity.Reque
return eval.EvaluateCustom(func(action, scope string) (bool, error) {
kind, _, identifier := accesscontrol.SplitScope(scope)
key, ok := zanzana.TranslateToTuple(user.GetUID(), action, kind, identifier, user.GetOrgID())
tupleKey, ok := zanzana.TranslateToTuple(user.GetUID(), action, kind, identifier, user.GetOrgID())
if !ok {
// unsupported translation
return false, errAccessNotImplemented
}
a.log.Debug("evaluating zanzana", "user", key.User, "relation", key.Relation, "object", key.Object)
res, err := a.zclient.Check(ctx, &openfgav1.CheckRequest{
TupleKey: &openfgav1.CheckRequestTupleKey{
User: key.User,
Relation: key.Relation,
Object: key.Object,
},
a.log.Debug("evaluating zanzana", "user", tupleKey.User, "relation", tupleKey.Relation, "object", tupleKey.Object)
allowed, err := a.Check(ctx, accesscontrol.CheckRequest{
User: tupleKey.User,
Relation: tupleKey.Relation,
Object: tupleKey.Object,
})
if err != nil {
return false, err
}
return res.Allowed, nil
return allowed, nil
})
}
@@ -212,10 +210,29 @@ func (a *AccessControl) debug(ctx context.Context, ident identity.Requester, msg
a.log.FromContext(ctx).Debug(msg, "id", ident.GetID(), "orgID", ident.GetOrgID(), "permissions", eval.GoString())
}
func (a *AccessControl) Check(ctx context.Context, in *openfgav1.CheckRequest) (*openfgav1.CheckResponse, error) {
return a.zclient.Check(ctx, in)
func (a *AccessControl) Check(ctx context.Context, req accesscontrol.CheckRequest) (bool, error) {
key := &openfgav1.CheckRequestTupleKey{
User: req.User,
Relation: req.Relation,
Object: req.Object,
}
in := &openfgav1.CheckRequest{TupleKey: key}
res, err := a.zclient.Check(ctx, in)
if err != nil {
return false, err
}
return res.Allowed, err
}
func (a *AccessControl) ListObjects(ctx context.Context, in *openfgav1.ListObjectsRequest) (*openfgav1.ListObjectsResponse, error) {
return a.zclient.ListObjects(ctx, in)
func (a *AccessControl) ListObjects(ctx context.Context, req accesscontrol.ListObjectsRequest) ([]string, error) {
in := &openfgav1.ListObjectsRequest{
Type: req.Type,
User: req.User,
Relation: req.Relation,
}
res, err := a.zclient.ListObjects(ctx, in)
if err != nil {
return nil, err
}
return res.Objects, err
}
+3 -5
View File
@@ -3,8 +3,6 @@ package actest
import (
"context"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/accesscontrol"
)
@@ -77,11 +75,11 @@ func (f FakeAccessControl) Evaluate(ctx context.Context, user identity.Requester
func (f FakeAccessControl) RegisterScopeAttributeResolver(prefix string, resolver accesscontrol.ScopeAttributeResolver) {
}
func (f FakeAccessControl) Check(ctx context.Context, in *openfgav1.CheckRequest) (*openfgav1.CheckResponse, error) {
return nil, nil
func (f FakeAccessControl) Check(ctx context.Context, in accesscontrol.CheckRequest) (bool, error) {
return false, nil
}
func (f FakeAccessControl) ListObjects(ctx context.Context, in *openfgav1.ListObjectsRequest) (*openfgav1.ListObjectsResponse, error) {
func (f FakeAccessControl) ListObjects(ctx context.Context, in accesscontrol.ListObjectsRequest) ([]string, error) {
return nil, nil
}
+3 -5
View File
@@ -4,8 +4,6 @@ import (
"context"
"errors"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
@@ -268,10 +266,10 @@ func (m *Mock) SyncUserRoles(ctx context.Context, orgID int64, cmd accesscontrol
return nil
}
func (m *Mock) Check(ctx context.Context, in *openfgav1.CheckRequest) (*openfgav1.CheckResponse, error) {
return nil, nil
func (m *Mock) Check(ctx context.Context, in accesscontrol.CheckRequest) (bool, error) {
return false, nil
}
func (m *Mock) ListObjects(ctx context.Context, in *openfgav1.ListObjectsRequest) (*openfgav1.ListObjectsResponse, error) {
func (m *Mock) ListObjects(ctx context.Context, in accesscontrol.ListObjectsRequest) ([]string, error) {
return nil, nil
}
+12
View File
@@ -578,3 +578,15 @@ type QueryWithOrg struct {
OrgId *int64 `json:"orgId"`
Global bool `json:"global"`
}
type CheckRequest struct {
User string
Relation string
Object string
}
type ListObjectsRequest struct {
Type string
Relation string
User string
}
+6 -8
View File
@@ -8,9 +8,9 @@ import (
"sync"
"time"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
"github.com/prometheus/client_golang/prometheus"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/authz/zanzana"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
@@ -170,7 +170,7 @@ func (dr *DashboardServiceImpl) findDashboardsZanzanaList(ctx context.Context, q
}
func (dr *DashboardServiceImpl) listResources(ctx context.Context, query *dashboards.FindPersistedDashboardsQuery, resourceType string) ([]string, error) {
res, err := dr.ac.ListObjects(ctx, &openfgav1.ListObjectsRequest{
res, err := dr.ac.ListObjects(ctx, accesscontrol.ListObjectsRequest{
User: query.SignedInUser.GetUID(),
Type: resourceType,
Relation: "read",
@@ -187,7 +187,7 @@ func (dr *DashboardServiceImpl) listResources(ctx context.Context, query *dashbo
prefix := fmt.Sprintf("%s:%d-", resourceType, orgId)
resourceUIDs := make([]string, 0)
for _, d := range res.Objects {
for _, d := range res {
if uid, found := strings.CutPrefix(d, prefix); found {
resourceUIDs = append(resourceUIDs, uid)
}
@@ -234,19 +234,17 @@ func (dr *DashboardServiceImpl) checkDashboards(ctx context.Context, query *dash
objectType = zanzana.TypeFolder
}
object := zanzana.NewScopedTupleEntry(objectType, d.UID, "", strconv.FormatInt(orgId, 10))
key := &openfgav1.CheckRequestTupleKey{
req := accesscontrol.CheckRequest{
User: query.SignedInUser.GetUID(),
Relation: "read",
Object: object,
}
checkRes, err := dr.ac.Check(ctx, &openfgav1.CheckRequest{
TupleKey: key,
})
allowed, err := dr.ac.Check(ctx, req)
if err != nil {
errChan <- err
dr.log.Error("error checking access", "error", err)
} else if checkRes.Allowed {
} else if allowed {
allowedResults <- d
}
}
@@ -3,8 +3,6 @@ package accesscontrol
import (
"context"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/accesscontrol"
)
@@ -38,11 +36,11 @@ func (a *recordingAccessControlFake) IsDisabled() bool {
return a.Disabled
}
func (a *recordingAccessControlFake) Check(ctx context.Context, in *openfgav1.CheckRequest) (*openfgav1.CheckResponse, error) {
return nil, nil
func (a *recordingAccessControlFake) Check(ctx context.Context, in accesscontrol.CheckRequest) (bool, error) {
return false, nil
}
func (a *recordingAccessControlFake) ListObjects(ctx context.Context, in *openfgav1.ListObjectsRequest) (*openfgav1.ListObjectsResponse, error) {
func (a *recordingAccessControlFake) ListObjects(ctx context.Context, in accesscontrol.ListObjectsRequest) ([]string, error) {
return nil, nil
}
+4 -5
View File
@@ -7,10 +7,9 @@ import (
"testing"
"time"
openfgav1 "github.com/openfga/api/proto/openfga/v1"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/services/accesscontrol"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/ngalert/eval"
"github.com/grafana/grafana/pkg/services/ngalert/models"
@@ -134,11 +133,11 @@ func (a *recordingAccessControlFake) IsDisabled() bool {
return a.Disabled
}
func (a *recordingAccessControlFake) Check(ctx context.Context, in *openfgav1.CheckRequest) (*openfgav1.CheckResponse, error) {
return nil, nil
func (a *recordingAccessControlFake) Check(ctx context.Context, in accesscontrol.CheckRequest) (bool, error) {
return false, nil
}
func (a *recordingAccessControlFake) ListObjects(ctx context.Context, in *openfgav1.ListObjectsRequest) (*openfgav1.ListObjectsResponse, error) {
func (a *recordingAccessControlFake) ListObjects(ctx context.Context, in accesscontrol.ListObjectsRequest) ([]string, error) {
return nil, nil
}