Authlib: Update authz client to use zookies (#111291)

* Authlib: Update authz client to use zookies

* fix zookie return

* fix linter
This commit is contained in:
Alexander Zobnin
2025-09-18 16:24:22 +02:00
committed by GitHub
parent 0aa5dee86a
commit 72d212c5f9
28 changed files with 89 additions and 81 deletions
+8 -8
View File
@@ -159,7 +159,7 @@ func (c authzLimitedClient) Check(ctx context.Context, id claims.AuthInfo, req c
}
// Compile implements claims.AccessClient.
func (c authzLimitedClient) Compile(ctx context.Context, id claims.AuthInfo, req claims.ListRequest) (claims.ItemChecker, error) {
func (c authzLimitedClient) Compile(ctx context.Context, id claims.AuthInfo, req claims.ListRequest) (claims.ItemChecker, claims.Zookie, error) {
t := time.Now()
fallbackUsed := FallbackUsed(ctx)
ctx, span := c.tracer.Start(ctx, "authzLimitedClient.Compile", trace.WithAttributes(
@@ -177,34 +177,34 @@ func (c authzLimitedClient) Compile(ctx context.Context, id claims.AuthInfo, req
span.SetStatus(codes.Error, "Namespace empty")
err := fmt.Errorf("namespace empty")
span.RecordError(err)
return nil, err
return nil, claims.NoopZookie{}, err
}
return func(name, folder string) bool {
return true
}, nil
}, claims.NoopZookie{}, nil
}
if !claims.NamespaceMatches(id.GetNamespace(), req.Namespace) {
span.SetAttributes(attribute.Bool("allowed", false))
span.SetStatus(codes.Error, "Namespace mismatch")
span.RecordError(claims.ErrNamespaceMismatch)
return nil, claims.ErrNamespaceMismatch
return nil, claims.NoopZookie{}, claims.ErrNamespaceMismatch
}
if !c.IsCompatibleWithRBAC(req.Group, req.Resource) {
return func(name, folder string) bool {
return true
}, nil
}, claims.NoopZookie{}, nil
}
checker, err := c.client.Compile(ctx, id, req)
checker, zookie, err := c.client.Compile(ctx, id, req)
if err != nil {
c.logger.Error("Compile", "group", req.Group, "resource", req.Resource, "error", err, "traceid", trace.SpanContextFromContext(ctx).TraceID().String())
c.metrics.errorsTotal.WithLabelValues(req.Group, req.Resource, req.Verb).Inc()
span.SetStatus(codes.Error, fmt.Sprintf("compile failed: %v", err))
span.RecordError(err)
return nil, err
return nil, zookie, err
}
c.metrics.compileDuration.WithLabelValues(req.Group, req.Resource, req.Verb).Observe(time.Since(t).Seconds())
return checker, nil
return checker, zookie, nil
}
func (c authzLimitedClient) IsCompatibleWithRBAC(group, resource string) bool {
+4 -3
View File
@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require"
authlib "github.com/grafana/authlib/types"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
)
@@ -60,7 +61,7 @@ func TestAuthzLimitedClient_Compile(t *testing.T) {
Verb: utils.VerbGet,
Namespace: "stacks-1",
}
checker, err := client.Compile(context.Background(), &identity.StaticRequester{Namespace: "stacks-1"}, req)
checker, _, err := client.Compile(context.Background(), &identity.StaticRequester{Namespace: "stacks-1"}, req)
assert.NoError(t, err)
assert.NotNil(t, checker)
@@ -143,7 +144,7 @@ func TestNamespaceMatching(t *testing.T) {
Verb: utils.VerbGet,
Namespace: tt.reqNamespace,
}
_, compileErr := client.Compile(ctx, user, compileReq)
_, _, compileErr := client.Compile(ctx, user, compileReq)
if tt.expectError {
require.Error(t, checkErr, "Check should return error")
@@ -207,7 +208,7 @@ func TestNamespaceMatchingFallback(t *testing.T) {
Verb: utils.VerbGet,
Namespace: tt.reqNamespace,
}
_, compileErr := client.Compile(ctx, user, compileReq)
_, _, compileErr := client.Compile(ctx, user, compileReq)
if tt.expectError {
require.Error(t, checkErr, "Check should return error")
+1 -1
View File
@@ -189,7 +189,7 @@ func (s *server) BulkProcess(stream resourcepb.BulkStore_BulkProcessServer) erro
}
// This will be called for each request -- with the folder ID
runner.checker[NSGR(k)], err = s.access.Compile(ctx, user, authlib.ListRequest{
runner.checker[NSGR(k)], _, err = s.access.Compile(ctx, user, authlib.ListRequest{
Namespace: k.Namespace,
Group: k.Group,
Resource: k.Resource,
+3 -3
View File
@@ -952,7 +952,7 @@ func (s *server) List(ctx context.Context, req *resourcepb.ListRequest) (*resour
rsp := &resourcepb.ListResponse{}
key := req.Options.Key
checker, err := s.access.Compile(ctx, user, claims.ListRequest{
checker, _, err := s.access.Compile(ctx, user, claims.ListRequest{
Group: key.Group,
Resource: key.Resource,
Namespace: key.Namespace,
@@ -960,7 +960,7 @@ func (s *server) List(ctx context.Context, req *resourcepb.ListRequest) (*resour
})
var trashChecker claims.ItemChecker // only for trash
if req.Source == resourcepb.ListRequest_TRASH {
trashChecker, err = s.access.Compile(ctx, user, claims.ListRequest{
trashChecker, _, err = s.access.Compile(ctx, user, claims.ListRequest{
Group: key.Group,
Resource: key.Resource,
Namespace: key.Namespace,
@@ -1097,7 +1097,7 @@ func (s *server) Watch(req *resourcepb.WatchRequest, srv resourcepb.ResourceStor
}
key := req.Options.Key
checker, err := s.access.Compile(ctx, user, claims.ListRequest{
checker, _, err := s.access.Compile(ctx, user, claims.ListRequest{
Group: key.Group,
Resource: key.Resource,
Namespace: key.Namespace,
+2 -2
View File
@@ -1181,7 +1181,7 @@ func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.R
verb = utils.VerbPatch
}
checker, err := access.Compile(ctx, auth, authlib.ListRequest{
checker, _, err := access.Compile(ctx, auth, authlib.ListRequest{
Namespace: b.key.Namespace,
Group: b.key.Group,
Resource: b.key.Resource,
@@ -1196,7 +1196,7 @@ func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.R
// handle federation
for _, federated := range req.Federated {
checker, err := access.Compile(ctx, auth, authlib.ListRequest{
checker, _, err := access.Compile(ctx, auth, authlib.ListRequest{
Namespace: federated.Namespace,
Group: federated.Group,
Resource: federated.Resource,
+2 -2
View File
@@ -638,10 +638,10 @@ func (nc *StubAccessClient) Check(ctx context.Context, id authlib.AuthInfo, req
return authlib.CheckResponse{Allowed: nc.resourceResponses[req.Resource]}, nil
}
func (nc *StubAccessClient) Compile(ctx context.Context, id authlib.AuthInfo, req authlib.ListRequest) (authlib.ItemChecker, error) {
func (nc *StubAccessClient) Compile(ctx context.Context, id authlib.AuthInfo, req authlib.ListRequest) (authlib.ItemChecker, authlib.Zookie, error) {
return func(name, folder string) bool {
return nc.resourceResponses[req.Resource]
}, nil
}, authlib.NoopZookie{}, nil
}
func (nc StubAccessClient) Read(ctx context.Context, req *authzextv1.ReadRequest) (*authzextv1.ReadResponse, error) {
+3 -3
View File
@@ -514,9 +514,9 @@ func (m *mockAccessClient) Check(ctx context.Context, user types.AuthInfo, req t
return types.CheckResponse{Allowed: m.allowed}, nil
}
func (m *mockAccessClient) Compile(ctx context.Context, user types.AuthInfo, req types.ListRequest) (types.ItemChecker, error) {
func (m *mockAccessClient) Compile(ctx context.Context, user types.AuthInfo, req types.ListRequest) (types.ItemChecker, types.Zookie, error) {
if m.compileFn != nil {
return m.compileFn(user, req), nil
return m.compileFn(user, req), types.NoopZookie{}, nil
}
return func(name, folder string) bool {
key := fmt.Sprintf("%s:%s", folder, req.Verb)
@@ -524,5 +524,5 @@ func (m *mockAccessClient) Compile(ctx context.Context, user types.AuthInfo, req
return allowed
}
return m.allowed
}, nil
}, types.NoopZookie{}, nil
}