Skip to content

Commit 5d83571

Browse files
committed
chore: implement method to customize authz a bit more
1 parent e48cb86 commit 5d83571

File tree

3 files changed

+42
-11
lines changed

3 files changed

+42
-11
lines changed

coderd/coderdtest/authorize.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,17 @@ func (s *PreparedRecorder) CompileToSQL(ctx context.Context, cfg regosql.Convert
356356
// FakeAuthorizer is an Authorizer that always returns the same error.
357357
type FakeAuthorizer struct {
358358
// AlwaysReturn is the error that will be returned by Authorize.
359-
AlwaysReturn error
359+
AlwaysReturn error
360+
ConditionalReturn func(context.Context, rbac.Subject, policy.Action, rbac.Object) error
360361
}
361362

362363
var _ rbac.Authorizer = (*FakeAuthorizer)(nil)
363364

364-
func (d *FakeAuthorizer) Authorize(_ context.Context, _ rbac.Subject, _ policy.Action, _ rbac.Object) error {
365+
func (d *FakeAuthorizer) Authorize(ctx context.Context, subject rbac.Subject, action policy.Action, object rbac.Object) error {
366+
if d.ConditionalReturn != nil {
367+
return d.ConditionalReturn(ctx, subject, action, object)
368+
369+
}
365370
return d.AlwaysReturn
366371
}
367372

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -342,18 +342,21 @@ func (s *MethodTestSuite) TestGroup() {
342342
dbgen.GroupMember(s.T(), db, database.GroupMemberTable{GroupID: g.ID, UserID: u.ID})
343343
check.Asserts(rbac.ResourceSystem, policy.ActionRead)
344344
}))
345-
s.Run("GetGroups", s.Subtest(func(db database.Store, check *expects) {
345+
s.Run("System/GetGroups", s.Subtest(func(db database.Store, check *expects) {
346346
_ = dbgen.Group(s.T(), db, database.Group{})
347-
check.Asserts(rbac.ResourceSystem, policy.ActionRead)
347+
check.Args(database.GetGroupsParams{}).
348+
Asserts(rbac.ResourceSystem, policy.ActionRead)
348349
}))
349-
s.Run("GetGroupsByOrganizationAndUserID", s.Subtest(func(db database.Store, check *expects) {
350+
s.Run("GetGroups", s.Subtest(func(db database.Store, check *expects) {
350351
g := dbgen.Group(s.T(), db, database.Group{})
351352
u := dbgen.User(s.T(), db, database.User{})
352353
gm := dbgen.GroupMember(s.T(), db, database.GroupMemberTable{GroupID: g.ID, UserID: u.ID})
353-
check.Args(database.GetGroupsByOrganizationAndUserIDParams{
354+
check.Args(database.GetGroupsParams{
354355
OrganizationID: g.OrganizationID,
355-
UserID: gm.UserID,
356-
}).Asserts(g, policy.ActionRead)
356+
HasMemberID: gm.UserID,
357+
}).Asserts(rbac.ResourceSystem, policy.ActionRead, g, policy.ActionRead).
358+
// Fail the system resource skip
359+
FailSystemObjectChecks()
357360
}))
358361
s.Run("InsertAllUsersGroup", s.Subtest(func(db database.Store, check *expects) {
359362
o := dbgen.Organization(s.T(), db, database.Organization{})
@@ -597,12 +600,16 @@ func (s *MethodTestSuite) TestLicense() {
597600
}
598601

599602
func (s *MethodTestSuite) TestOrganization() {
600-
s.Run("GetGroupsByOrganizationID", s.Subtest(func(db database.Store, check *expects) {
603+
s.Run("ByOrganization/GetGroups", s.Subtest(func(db database.Store, check *expects) {
601604
o := dbgen.Organization(s.T(), db, database.Organization{})
602605
a := dbgen.Group(s.T(), db, database.Group{OrganizationID: o.ID})
603606
b := dbgen.Group(s.T(), db, database.Group{OrganizationID: o.ID})
604-
check.Args(o.ID).Asserts(a, policy.ActionRead, b, policy.ActionRead).
605-
Returns([]database.Group{a, b})
607+
check.Args(database.GetGroupsParams{
608+
OrganizationID: o.ID,
609+
}).Asserts(rbac.ResourceSystem, policy.ActionRead, a, policy.ActionRead, b, policy.ActionRead).
610+
Returns([]database.Group{a, b}).
611+
// Fail the system check shortcut
612+
FailSystemObjectChecks()
606613
}))
607614
s.Run("GetOrganizationByID", s.Subtest(func(db database.Store, check *expects) {
608615
o := dbgen.Organization(s.T(), db, database.Organization{})

coderd/database/dbauthz/setup_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ func (s *MethodTestSuite) Subtest(testCaseF func(db database.Store, check *expec
175175
s.Run("Success", func() {
176176
rec.Reset()
177177
fakeAuthorizer.AlwaysReturn = nil
178+
fakeAuthorizer.ConditionalReturn = testCase.successAuthorizer
178179

179180
outputs, err := callMethod(ctx)
180181
if testCase.err == nil {
@@ -324,6 +325,7 @@ type expects struct {
324325
// instead.
325326
notAuthorizedExpect string
326327
cancelledCtxExpect string
328+
successAuthorizer func(ctx context.Context, subject rbac.Subject, action policy.Action, obj rbac.Object) error
327329
}
328330

329331
// Asserts is required. Asserts the RBAC authorize calls that should be made.
@@ -354,6 +356,23 @@ func (m *expects) Errors(err error) *expects {
354356
return m
355357
}
356358

359+
func (m *expects) FailSystemObjectChecks() *expects {
360+
return m.WithSuccessAuthorizer(func(ctx context.Context, subject rbac.Subject, action policy.Action, obj rbac.Object) error {
361+
if obj.Type == rbac.ResourceSystem.Type {
362+
return xerrors.Errorf("hard coded system authz failed")
363+
}
364+
return nil
365+
})
366+
}
367+
368+
// WithSuccessAuthorizer is helpful when an optimization authz check is made
369+
// to skip some RBAC checks. This check in testing would prevent the ability
370+
// to assert the more nuanced RBAC checks.
371+
func (m *expects) WithSuccessAuthorizer(f func(ctx context.Context, subject rbac.Subject, action policy.Action, obj rbac.Object) error) *expects {
372+
m.successAuthorizer = f
373+
return m
374+
}
375+
357376
func (m *expects) WithNotAuthorized(contains string) *expects {
358377
m.notAuthorizedExpect = contains
359378
return m

0 commit comments

Comments
 (0)