Skip to content

Commit cf763cb

Browse files
committed
Verify the correct error is returned on disallow auth
1 parent 7ba3482 commit cf763cb

File tree

2 files changed

+44
-19
lines changed

2 files changed

+44
-19
lines changed

coderd/authzquery/methods_test.go

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ package authzquery_test
22

33
import (
44
"context"
5+
"database/sql"
56
"fmt"
67
"reflect"
78
"sort"
89
"strings"
910
"testing"
1011

12+
"golang.org/x/xerrors"
13+
1114
"github.com/coder/coder/coderd/rbac/regosql"
1215

1316
"github.com/google/uuid"
@@ -95,10 +98,11 @@ func (s *MethodTestSuite) RunMethodTest(testCaseF func(t *testing.T, db database
9598
s.methodAccounting[methodName]++
9699

97100
db := dbfake.New()
101+
fakeAuthorizer := &coderdtest.FakeAuthorizer{
102+
AlwaysReturn: nil,
103+
}
98104
rec := &coderdtest.RecordingAuthorizer{
99-
Wrapped: &coderdtest.FakeAuthorizer{
100-
AlwaysReturn: nil,
101-
},
105+
Wrapped: fakeAuthorizer,
102106
}
103107
az := authzquery.NewAuthzQuerier(db, rec, slog.Make())
104108
actor := rbac.Subject{
@@ -118,22 +122,25 @@ MethodLoop:
118122
for i := 0; i < azt.NumMethod(); i++ {
119123
method := azt.Method(i)
120124
if method.Name == methodName {
125+
if len(testCase.Assertions) > 0 {
126+
fakeAuthorizer.AlwaysReturn = xerrors.New("Always fail authz")
127+
// If we have assertions, that means the method should FAIL
128+
// if RBAC will disallow the request. The returned error should
129+
// be expected to be a NotAuthorizedError.
130+
erroredResp := reflect.ValueOf(az).Method(i).Call(append([]reflect.Value{reflect.ValueOf(ctx)}, testCase.Inputs...))
131+
err := findError(t, erroredResp)
132+
require.Errorf(t, err, "method %q should an error with disallow authz", testName)
133+
require.ErrorIsf(t, err, sql.ErrNoRows, "error should match sql.ErrNoRows")
134+
require.ErrorAs(t, err, &authzquery.NotAuthorizedError{}, "error should be NotAuthorizedError")
135+
// Set things back to normal.
136+
fakeAuthorizer.AlwaysReturn = nil
137+
rec.Reset()
138+
}
139+
121140
resp := reflect.ValueOf(az).Method(i).Call(append([]reflect.Value{reflect.ValueOf(ctx)}, testCase.Inputs...))
122141
// TODO: Should we assert the object returned is the correct one?
123-
for _, r := range resp {
124-
if r.Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
125-
if r.IsNil() {
126-
// no error!
127-
break
128-
}
129-
err, ok := r.Interface().(error)
130-
if !ok {
131-
t.Fatal("error is not an error?!")
132-
}
133-
require.NoError(t, err, "method %q returned an error", testName)
134-
break
135-
}
136-
}
142+
err := findError(t, resp)
143+
require.NoError(t, err, "method %q returned an error", testName)
137144
found = true
138145
break MethodLoop
139146
}
@@ -155,6 +162,24 @@ MethodLoop:
155162
require.NoError(t, rec.AllAsserted(), "all rbac calls must be asserted")
156163
}
157164

165+
func findError(t *testing.T, values []reflect.Value) error {
166+
for _, r := range values {
167+
if r.Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
168+
if r.IsNil() {
169+
// Error is found, but it's nil!
170+
return nil
171+
}
172+
err, ok := r.Interface().(error)
173+
if !ok {
174+
t.Fatal("error is not an error?!")
175+
}
176+
return err
177+
}
178+
}
179+
t.Fatal("no expected error value found in responses (error can be nil)")
180+
panic("unreachable") // For compile reasons
181+
}
182+
158183
// A MethodCase contains the inputs to be provided to a single method call,
159184
// and the assertions to be made on the RBAC checks.
160185
type MethodCase struct {

coderd/coderdtest/authorize.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ func (a *AuthTester) Test(ctx context.Context, assertRoute map[string]RouteCheck
486486
return nil
487487
}
488488
a.t.Run(name, func(t *testing.T) {
489-
a.authorizer.reset()
489+
a.authorizer.Reset()
490490
routeKey := strings.TrimRight(name, "/")
491491

492492
routeAssertions, ok := assertRoute[routeKey]
@@ -676,7 +676,7 @@ func (r *RecordingAuthorizer) Prepare(_ context.Context, subject rbac.Subject, a
676676
}, nil
677677
}
678678

679-
func (r *RecordingAuthorizer) reset() {
679+
func (r *RecordingAuthorizer) Reset() {
680680
r.Lock()
681681
defer r.Unlock()
682682
r.Called = nil

0 commit comments

Comments
 (0)