chore: Compile rego once to save CPU cycles in testing (#4169)

Compiling rego isn't very fast, so this should speed up tests in CI!
This commit is contained in:
Kyle Carberry 2022-09-23 11:26:04 -05:00 committed by GitHub
parent 1e1967e0db
commit 8738755ffc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 41 deletions

View File

@ -109,13 +109,7 @@ func New(options *Options) *API {
options.MetricsCacheRefreshInterval = time.Hour
}
if options.Authorizer == nil {
var err error
options.Authorizer, err = rbac.NewAuthorizer()
if err != nil {
// This should never happen, as the unit tests would fail if the
// default built in authorizer failed.
panic(xerrors.Errorf("rego authorize panic: %w", err))
}
options.Authorizer = rbac.NewAuthorizer()
}
if options.PrometheusRegistry == nil {
options.PrometheusRegistry = prometheus.NewRegistry()

View File

@ -4,6 +4,7 @@ import (
"context"
_ "embed"
"fmt"
"sync"
"github.com/open-policy-agent/opa/rego"
"go.opentelemetry.io/otel/attribute"
@ -66,32 +67,37 @@ type RegoAuthorizer struct {
var _ Authorizer = (*RegoAuthorizer)(nil)
// Load the policy from policy.rego in this directory.
//
//go:embed policy.rego
var policy string
var (
// Load the policy from policy.rego in this directory.
//
//go:embed policy.rego
policy string
queryOnce sync.Once
query rego.PreparedEvalQuery
)
const (
rolesOkCheck = "role_ok"
scopeOkCheck = "scope_ok"
)
func NewAuthorizer() (*RegoAuthorizer, error) {
ctx := context.Background()
query, err := rego.New(
// Bind the results to 2 variables for easy checking later.
rego.Query(
fmt.Sprintf("%s := data.authz.role_allow "+
"%s := data.authz.scope_allow",
rolesOkCheck, scopeOkCheck),
),
rego.Module("policy.rego", policy),
).PrepareForEval(ctx)
if err != nil {
return nil, xerrors.Errorf("prepare query: %w", err)
}
return &RegoAuthorizer{query: query}, nil
func NewAuthorizer() *RegoAuthorizer {
queryOnce.Do(func() {
var err error
query, err = rego.New(
// Bind the results to 2 variables for easy checking later.
rego.Query(
fmt.Sprintf("%s := data.authz.role_allow "+
"%s := data.authz.scope_allow",
rolesOkCheck, scopeOkCheck),
),
rego.Module("policy.rego", policy),
).PrepareForEval(context.Background())
if err != nil {
panic(xerrors.Errorf("compile rego: %w", err))
}
})
return &RegoAuthorizer{query: query}
}
type authSubject struct {

View File

@ -40,10 +40,8 @@ func (w fakeObject) RBACObject() Object {
func TestFilterError(t *testing.T) {
t.Parallel()
auth, err := NewAuthorizer()
require.NoError(t, err)
_, err = Filter(context.Background(), auth, uuid.NewString(), []string{}, ScopeAll, ActionRead, []Object{ResourceUser, ResourceWorkspace})
auth := NewAuthorizer()
_, err := Filter(context.Background(), auth, uuid.NewString(), []string{}, ScopeAll, ActionRead, []Object{ResourceUser, ResourceWorkspace})
require.ErrorContains(t, err, "object types must be uniform")
}
@ -160,8 +158,7 @@ func TestFilter(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
defer cancel()
auth, err := NewAuthorizer()
require.NoError(t, err, "new auth")
auth := NewAuthorizer()
scope := ScopeAll
if tc.Scope != "" {
@ -742,8 +739,7 @@ type authTestCase struct {
func testAuthorize(t *testing.T, name string, subject subject, sets ...[]authTestCase) {
t.Helper()
authorizer, err := NewAuthorizer()
require.NoError(t, err)
authorizer := NewAuthorizer()
for _, cases := range sets {
for i, c := range cases {
c := c

View File

@ -82,10 +82,7 @@ func BenchmarkRBACFilter(b *testing.B) {
},
}
authorizer, err := rbac.NewAuthorizer()
if err != nil {
require.NoError(b, err)
}
authorizer := rbac.NewAuthorizer()
for _, c := range benchCases {
b.Run(c.Name, func(b *testing.B) {
objects := benchmarkSetup(orgs, users, b.N)
@ -119,8 +116,7 @@ type authSubject struct {
func TestRolePermissions(t *testing.T) {
t.Parallel()
auth, err := rbac.NewAuthorizer()
require.NoError(t, err, "new rego authorizer")
auth := rbac.NewAuthorizer()
// currentUser is anything that references "me", "mine", or "my".
currentUser := uuid.New()