Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 73 additions & 6 deletions coderd/coderdtest/authorize.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import (
"testing"
"time"

"github.com/coder/coder/cryptorand"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/moby/moby/pkg/namesgenerator"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
Expand Down Expand Up @@ -543,9 +546,7 @@ func (a *AuthTester) Test(ctx context.Context, assertRoute map[string]RouteCheck
}

type authCall struct {
Actor rbac.Subject
Action rbac.Action
Object rbac.Object
rbac.AuthCall

asserted bool
}
Expand Down Expand Up @@ -621,9 +622,11 @@ func (r *RecordingAuthorizer) recordAuthorize(subject rbac.Subject, action rbac.
r.Lock()
defer r.Unlock()
r.Called = append(r.Called, authCall{
Actor: subject,
Action: action,
Object: object,
AuthCall: rbac.AuthCall{
Actor: subject,
Action: action,
Object: object,
},
})
}

Expand Down Expand Up @@ -743,3 +746,67 @@ func (f *fakePreparedAuthorizer) Authorize(ctx context.Context, object rbac.Obje
func (*fakePreparedAuthorizer) CompileToSQL(_ context.Context, _ regosql.ConvertConfig) (string, error) {
return "not a valid sql string", nil
}

// Random rbac helper funcs

func RandomRBACAction() rbac.Action {
all := rbac.AllActions()
return all[must(cryptorand.Intn(len(all)))]
}

func RandomRBACObject() rbac.Object {
return rbac.Object{
ID: uuid.NewString(),
Owner: uuid.NewString(),
OrgID: uuid.NewString(),
Type: randomRBACType(),
ACLUserList: map[string][]rbac.Action{
namesgenerator.GetRandomName(1): {RandomRBACAction()},
},
ACLGroupList: map[string][]rbac.Action{
namesgenerator.GetRandomName(1): {RandomRBACAction()},
},
}
}

func randomRBACType() string {
all := []string{
rbac.ResourceWorkspace.Type,
rbac.ResourceWorkspaceExecution.Type,
rbac.ResourceWorkspaceApplicationConnect.Type,
rbac.ResourceAuditLog.Type,
rbac.ResourceTemplate.Type,
rbac.ResourceGroup.Type,
rbac.ResourceFile.Type,
rbac.ResourceProvisionerDaemon.Type,
rbac.ResourceOrganization.Type,
rbac.ResourceRoleAssignment.Type,
rbac.ResourceOrgRoleAssignment.Type,
rbac.ResourceAPIKey.Type,
rbac.ResourceUser.Type,
rbac.ResourceUserData.Type,
rbac.ResourceOrganizationMember.Type,
rbac.ResourceWildcard.Type,
rbac.ResourceLicense.Type,
rbac.ResourceDeploymentConfig.Type,
rbac.ResourceReplicas.Type,
rbac.ResourceDebugInfo.Type,
}
return all[must(cryptorand.Intn(len(all)))]
}

func RandomRBACSubject() rbac.Subject {
return rbac.Subject{
ID: uuid.NewString(),
Roles: rbac.RoleNames{rbac.RoleMember()},
Groups: []string{namesgenerator.GetRandomName(1)},
Scope: rbac.ScopeAll,
}
}

func must[T any](value T, err error) T {
if err != nil {
panic(err)
}
return value
}
45 changes: 8 additions & 37 deletions coderd/coderdtest/authorize_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"testing"

"github.com/moby/moby/pkg/namesgenerator"
"github.com/stretchr/testify/require"

"github.com/coder/coder/coderd/coderdtest"
Expand Down Expand Up @@ -34,7 +33,7 @@ func TestAuthzRecorder(t *testing.T) {
rec := &coderdtest.RecordingAuthorizer{
Wrapped: &coderdtest.FakeAuthorizer{},
}
sub := randomSubject()
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")
Expand All @@ -46,10 +45,10 @@ func TestAuthzRecorder(t *testing.T) {
rec := &coderdtest.RecordingAuthorizer{
Wrapped: &coderdtest.FakeAuthorizer{},
}
a := randomSubject()
a := coderdtest.RandomRBACSubject()
aPairs := fuzzAuthz(t, a, rec, 10)

b := randomSubject()
b := coderdtest.RandomRBACSubject()
bPairs := fuzzAuthz(t, b, rec, 10)

rec.AssertActor(t, b, bPairs...)
Expand All @@ -63,12 +62,12 @@ func TestAuthzRecorder(t *testing.T) {
rec := &coderdtest.RecordingAuthorizer{
Wrapped: &coderdtest.FakeAuthorizer{},
}
a := randomSubject()
a := coderdtest.RandomRBACSubject()
aPairs := fuzzAuthz(t, a, rec, 10)

b := randomSubject()
b := coderdtest.RandomRBACSubject()

act, objTy := randomAction(), randomObject().Type
act, objTy := coderdtest.RandomRBACAction(), coderdtest.RandomRBACObject().Type
prep, _ := rec.Prepare(context.Background(), b, act, objTy)
bPairs := fuzzAuthzPrep(t, prep, 10, act, objTy)

Expand All @@ -84,7 +83,7 @@ func fuzzAuthzPrep(t *testing.T, prep rbac.PreparedAuthorized, n int, action rba
pairs := make([]coderdtest.ActionObjectPair, 0, n)

for i := 0; i < n; i++ {
obj := randomObject()
obj := coderdtest.RandomRBACObject()
obj.Type = objectType
p := coderdtest.ActionObjectPair{Action: action, Object: obj}
_ = prep.Authorize(context.Background(), p.Object)
Expand All @@ -98,37 +97,9 @@ func fuzzAuthz(t *testing.T, sub rbac.Subject, rec rbac.Authorizer, n int) []cod
pairs := make([]coderdtest.ActionObjectPair, 0, n)

for i := 0; i < n; i++ {
p := coderdtest.ActionObjectPair{Action: randomAction(), Object: randomObject()}
p := coderdtest.ActionObjectPair{Action: coderdtest.RandomRBACAction(), Object: coderdtest.RandomRBACObject()}
_ = 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,
}
}
5 changes: 5 additions & 0 deletions coderd/rbac/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ const (
ActionUpdate Action = "update"
ActionDelete Action = "delete"
)

// AllActions is a helper function to return all the possible actions types.
func AllActions() []Action {
return []Action{ActionCreate, ActionRead, ActionUpdate, ActionDelete}
}
Loading