mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
* chore: Allow RecordingAuthorizer to record multiple rbac authz calls Prior iteration only recorded the last call. This is required for more comprehensive testing
135 lines
3.8 KiB
Go
135 lines
3.8 KiB
Go
package coderdtest_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/moby/moby/pkg/namesgenerator"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/coder/coder/coderd/coderdtest"
|
|
"github.com/coder/coder/coderd/rbac"
|
|
)
|
|
|
|
func TestAuthorizeAllEndpoints(t *testing.T) {
|
|
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 := randomSubject()
|
|
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 := randomSubject()
|
|
aPairs := fuzzAuthz(t, a, rec, 10)
|
|
|
|
b := randomSubject()
|
|
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 := randomSubject()
|
|
aPairs := fuzzAuthz(t, a, rec, 10)
|
|
|
|
b := randomSubject()
|
|
|
|
act, objTy := randomAction(), randomObject().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 := randomObject()
|
|
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: randomAction(), Object: randomObject()}
|
|
_ = rec.Authorize(context.Background(), sub, p.Action, p.Object)
|
|
pairs = append(pairs, p)
|
|
}
|
|
return pairs
|
|
}
|
|
|
|
func randomAction() rbac.Action {
|
|
return rbac.Action(namesgenerator.GetRandomName(1))
|
|
}
|
|
|
|
func randomObject() rbac.Object {
|
|
return rbac.Object{
|
|
ID: namesgenerator.GetRandomName(1),
|
|
Owner: namesgenerator.GetRandomName(1),
|
|
OrgID: namesgenerator.GetRandomName(1),
|
|
Type: namesgenerator.GetRandomName(1),
|
|
ACLUserList: map[string][]rbac.Action{
|
|
namesgenerator.GetRandomName(1): {rbac.ActionRead},
|
|
},
|
|
ACLGroupList: map[string][]rbac.Action{
|
|
namesgenerator.GetRandomName(1): {rbac.ActionRead},
|
|
},
|
|
}
|
|
}
|
|
|
|
func randomSubject() rbac.Subject {
|
|
return rbac.Subject{
|
|
ID: namesgenerator.GetRandomName(1),
|
|
Roles: rbac.RoleNames{rbac.RoleMember()},
|
|
Groups: []string{namesgenerator.GetRandomName(1)},
|
|
Scope: rbac.ScopeAll,
|
|
}
|
|
}
|