From bdbda3cca76dea5a56fdc460124e55d006257456 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 22 Jul 2022 09:55:27 -0500 Subject: [PATCH] chore: Add benchmark test for rbac.Filter --- coderd/rbac/authz.go | 16 +++------------- coderd/rbac/authz_test.go | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/coderd/rbac/authz.go b/coderd/rbac/authz.go index b9f9e1f825e9e..ae9bab45e7607 100644 --- a/coderd/rbac/authz.go +++ b/coderd/rbac/authz.go @@ -43,9 +43,8 @@ var policy string func NewAuthorizer() (*RegoAuthorizer, error) { ctx := context.Background() query, err := rego.New( - // allowed is the `allow` field from the prepared query. This is the field to check if authorization is - // granted. - rego.Query("allowed = data.authz.allow"), + // Query returns true/false for authorization access + rego.Query("data.authz.allow"), rego.Module("policy.rego", policy), ).PrepareForEval(ctx) @@ -92,16 +91,7 @@ func (a RegoAuthorizer) Authorize(ctx context.Context, subjectID string, roles [ return ForbiddenWithInternal(xerrors.Errorf("eval rego: %w", err), input, results) } - if len(results) != 1 { - return ForbiddenWithInternal(xerrors.Errorf("expect only 1 result, got %d", len(results)), input, results) - } - - allowedResult, ok := (results[0].Bindings["allowed"]).(bool) - if !ok { - return ForbiddenWithInternal(xerrors.Errorf("expected allowed to be a bool but got %T", allowedResult), input, results) - } - - if !allowedResult { + if !results.Allowed() { return ForbiddenWithInternal(xerrors.Errorf("policy disallows request"), input, results) } diff --git a/coderd/rbac/authz_test.go b/coderd/rbac/authz_test.go index e1ab601ee30eb..cf47f56118325 100644 --- a/coderd/rbac/authz_test.go +++ b/coderd/rbac/authz_test.go @@ -23,6 +23,29 @@ type subject struct { Roles []rbac.Role `json:"roles"` } +// BenchmarkRBACFilter benchmarks the rbac.Filter method. Authorizing batch +// objects has a noticeable cost on performance. +// go test -bench BenchmarkRBACFilter -benchmem -memprofile memprofile.out -cpuprofile profile.out +func BenchmarkRBACFilter(b *testing.B) { + ctx := context.Background() + objectList := make([]rbac.Object, b.N) + orgID := uuid.New() + for i := range objectList { + objectList[i] = rbac.ResourceWorkspace. + InOrg(orgID). + WithID(uuid.NewString()). + WithOwner("other") + } + + authorizer, err := rbac.NewAuthorizer() + require.NoError(b, err) + + roles := []string{rbac.RoleOrgAdmin(orgID)} + + b.ResetTimer() + rbac.Filter(ctx, authorizer, "me", roles, rbac.ActionRead, objectList) +} + func TestFilter(t *testing.T) { t.Parallel()