mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
feat: Add initial AuthzQuerier implementation - Adds package database/dbauthz that adds a database.Store implementation where each method goes through AuthZ checks - Implements all database.Store methods on AuthzQuerier - Updates and fixes unit tests where required - Updates coderd initialization to use AuthzQuerier if codersdk.ExperimentAuthzQuerier is enabled
112 lines
3.4 KiB
Go
112 lines
3.4 KiB
Go
package coderdtest_test
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/coder/coder/coderd/coderdtest"
|
|
"github.com/coder/coder/coderd/rbac"
|
|
"github.com/coder/coder/codersdk"
|
|
)
|
|
|
|
func TestAuthorizeAllEndpoints(t *testing.T) {
|
|
if strings.Contains(os.Getenv("CODER_EXPERIMENTS_TEST"), string(codersdk.ExperimentAuthzQuerier)) {
|
|
t.Skip("Skipping TestAuthorizeAllEndpoints for authz_querier experiment")
|
|
}
|
|
t.Parallel()
|
|
client, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{
|
|
// Required for any subdomain-based proxy tests to pass.
|
|
AppHostname: "*.test.coder.com",
|
|
Authorizer: &coderdtest.RecordingAuthorizer{Wrapped: &coderdtest.FakeAuthorizer{}},
|
|
IncludeProvisionerDaemon: true,
|
|
})
|
|
admin := coderdtest.CreateFirstUser(t, client)
|
|
a := coderdtest.NewAuthTester(context.Background(), t, client, api, admin)
|
|
skipRoute, assertRoute := coderdtest.AGPLRoutes(a)
|
|
a.Test(context.Background(), assertRoute, skipRoute)
|
|
}
|
|
|
|
func TestAuthzRecorder(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("Authorize", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
rec := &coderdtest.RecordingAuthorizer{
|
|
Wrapped: &coderdtest.FakeAuthorizer{},
|
|
}
|
|
sub := coderdtest.RandomRBACSubject()
|
|
pairs := fuzzAuthz(t, sub, rec, 10)
|
|
rec.AssertActor(t, sub, pairs...)
|
|
require.NoError(t, rec.AllAsserted(), "all assertions should have been made")
|
|
})
|
|
|
|
t.Run("Authorize2Subjects", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
rec := &coderdtest.RecordingAuthorizer{
|
|
Wrapped: &coderdtest.FakeAuthorizer{},
|
|
}
|
|
a := coderdtest.RandomRBACSubject()
|
|
aPairs := fuzzAuthz(t, a, rec, 10)
|
|
|
|
b := coderdtest.RandomRBACSubject()
|
|
bPairs := fuzzAuthz(t, b, rec, 10)
|
|
|
|
rec.AssertActor(t, b, bPairs...)
|
|
rec.AssertActor(t, a, aPairs...)
|
|
require.NoError(t, rec.AllAsserted(), "all assertions should have been made")
|
|
})
|
|
|
|
t.Run("Authorize&Prepared", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
rec := &coderdtest.RecordingAuthorizer{
|
|
Wrapped: &coderdtest.FakeAuthorizer{},
|
|
}
|
|
a := coderdtest.RandomRBACSubject()
|
|
aPairs := fuzzAuthz(t, a, rec, 10)
|
|
|
|
b := coderdtest.RandomRBACSubject()
|
|
|
|
act, objTy := coderdtest.RandomRBACAction(), coderdtest.RandomRBACObject().Type
|
|
prep, _ := rec.Prepare(context.Background(), b, act, objTy)
|
|
bPairs := fuzzAuthzPrep(t, prep, 10, act, objTy)
|
|
|
|
rec.AssertActor(t, b, bPairs...)
|
|
rec.AssertActor(t, a, aPairs...)
|
|
require.NoError(t, rec.AllAsserted(), "all assertions should have been made")
|
|
})
|
|
}
|
|
|
|
// fuzzAuthzPrep has same action and object types for all calls.
|
|
func fuzzAuthzPrep(t *testing.T, prep rbac.PreparedAuthorized, n int, action rbac.Action, objectType string) []coderdtest.ActionObjectPair {
|
|
t.Helper()
|
|
pairs := make([]coderdtest.ActionObjectPair, 0, n)
|
|
|
|
for i := 0; i < n; i++ {
|
|
obj := coderdtest.RandomRBACObject()
|
|
obj.Type = objectType
|
|
p := coderdtest.ActionObjectPair{Action: action, Object: obj}
|
|
_ = prep.Authorize(context.Background(), p.Object)
|
|
pairs = append(pairs, p)
|
|
}
|
|
return pairs
|
|
}
|
|
|
|
func fuzzAuthz(t *testing.T, sub rbac.Subject, rec rbac.Authorizer, n int) []coderdtest.ActionObjectPair {
|
|
t.Helper()
|
|
pairs := make([]coderdtest.ActionObjectPair, 0, n)
|
|
|
|
for i := 0; i < n; i++ {
|
|
p := coderdtest.ActionObjectPair{Action: coderdtest.RandomRBACAction(), Object: coderdtest.RandomRBACObject()}
|
|
_ = rec.Authorize(context.Background(), sub, p.Action, p.Object)
|
|
pairs = append(pairs, p)
|
|
}
|
|
return pairs
|
|
}
|