From b2f9524e2a388169042c58cab7a34be226cdeebe Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Tue, 14 May 2024 14:18:09 -0500 Subject: [PATCH] chore: push rbac actions to policy package Moving to support more verbs. It is easier to keep the verbs in their own package for autogen reasons. Autogen will generate content in the rbac package. If the verbs are in the rbac package, then the autogen can fail if the autogen produces no-valid go code. It's a circular dependency that this commit avoids --- coderd/apikey.go | 4 +- coderd/authorize.go | 11 +- coderd/coderd.go | 3 +- coderd/coderdtest/authorize.go | 29 +- coderd/coderdtest/authorize_test.go | 3 +- coderd/database/dbauthz/dbauthz.go | 521 ++++++++++---------- coderd/database/dbauthz/dbauthz_test.go | 625 ++++++++++++------------ coderd/database/dbauthz/setup_test.go | 21 +- coderd/database/dbgen/dbgen.go | 3 +- coderd/database/dbmetrics/dbmetrics.go | 4 +- coderd/database/types.go | 6 +- coderd/debug.go | 3 +- coderd/deployment.go | 5 +- coderd/insights.go | 3 +- coderd/insights_test.go | 5 +- coderd/rbac/astvalue.go | 18 +- coderd/rbac/authz.go | 47 +- coderd/rbac/authz_internal_test.go | 129 ++--- coderd/rbac/authz_test.go | 37 +- coderd/rbac/error.go | 5 +- coderd/rbac/object.go | 16 +- coderd/rbac/object_test.go | 55 ++- coderd/rbac/policy/policy.go | 11 + coderd/rbac/roles.go | 86 ++-- coderd/rbac/roles_internal_test.go | 36 +- coderd/rbac/roles_test.go | 57 +-- coderd/rbac/scopes.go | 8 +- coderd/roles.go | 5 +- coderd/templates.go | 7 +- coderd/templateversions.go | 11 +- coderd/templateversions_test.go | 5 +- coderd/users.go | 5 +- coderd/users_test.go | 5 +- coderd/workspaceagents.go | 4 +- coderd/workspaceapps.go | 4 +- coderd/workspaceapps/db.go | 5 +- coderd/workspacebuilds.go | 5 +- coderd/workspaces.go | 9 +- coderd/workspaces_test.go | 3 +- coderd/wsbuilder/wsbuilder.go | 17 +- enterprise/coderd/appearance.go | 3 +- enterprise/coderd/coderd.go | 5 +- enterprise/coderd/coderd_test.go | 3 +- enterprise/coderd/groups.go | 4 +- enterprise/coderd/licenses.go | 9 +- enterprise/coderd/provisionerdaemons.go | 5 +- enterprise/coderd/replicas.go | 3 +- enterprise/coderd/templates.go | 13 +- enterprise/coderd/workspaceproxy.go | 4 +- enterprise/coderd/workspacequota.go | 4 +- enterprise/tailnet/pgcoord.go | 3 +- support/support.go | 4 +- 52 files changed, 971 insertions(+), 925 deletions(-) create mode 100644 coderd/rbac/policy/policy.go diff --git a/coderd/apikey.go b/coderd/apikey.go index 10a83a05f4a24..fe32b771e61ef 100644 --- a/coderd/apikey.go +++ b/coderd/apikey.go @@ -18,7 +18,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" - "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/telemetry" "github.com/coder/coder/v2/codersdk" ) @@ -255,7 +255,7 @@ func (api *API) tokens(rw http.ResponseWriter, r *http.Request) { } } - keys, err = AuthorizeFilter(api.HTTPAuth, r, rbac.ActionRead, keys) + keys, err = AuthorizeFilter(api.HTTPAuth, r, policy.ActionRead, keys) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Internal error fetching keys.", diff --git a/coderd/authorize.go b/coderd/authorize.go index 764f573ecfdc7..9adff89769805 100644 --- a/coderd/authorize.go +++ b/coderd/authorize.go @@ -11,13 +11,14 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" ) // AuthorizeFilter takes a list of objects and returns the filtered list of // objects that the user is authorized to perform the given action on. // This is faster than calling Authorize() on each object. -func AuthorizeFilter[O rbac.Objecter](h *HTTPAuthorizer, r *http.Request, action rbac.Action, objects []O) ([]O, error) { +func AuthorizeFilter[O rbac.Objecter](h *HTTPAuthorizer, r *http.Request, action policy.Action, objects []O) ([]O, error) { roles := httpmw.UserAuthorization(r) objects, err := rbac.Filter(r.Context(), h.Authorizer, roles, action, objects) if err != nil { @@ -50,7 +51,7 @@ type HTTPAuthorizer struct { // httpapi.Forbidden(rw) // return // } -func (api *API) Authorize(r *http.Request, action rbac.Action, object rbac.Objecter) bool { +func (api *API) Authorize(r *http.Request, action policy.Action, object rbac.Objecter) bool { return api.HTTPAuth.Authorize(r, action, object) } @@ -63,7 +64,7 @@ func (api *API) Authorize(r *http.Request, action rbac.Action, object rbac.Objec // httpapi.Forbidden(rw) // return // } -func (h *HTTPAuthorizer) Authorize(r *http.Request, action rbac.Action, object rbac.Objecter) bool { +func (h *HTTPAuthorizer) Authorize(r *http.Request, action policy.Action, object rbac.Objecter) bool { roles := httpmw.UserAuthorization(r) err := h.Authorizer.Authorize(r.Context(), roles, action, object.RBACObject()) if err != nil { @@ -95,7 +96,7 @@ func (h *HTTPAuthorizer) Authorize(r *http.Request, action rbac.Action, object r // from postgres are already authorized, and the caller does not need to // call 'Authorize()' on the returned objects. // Note the authorization is only for the given action and object type. -func (h *HTTPAuthorizer) AuthorizeSQLFilter(r *http.Request, action rbac.Action, objectType string) (rbac.PreparedAuthorized, error) { +func (h *HTTPAuthorizer) AuthorizeSQLFilter(r *http.Request, action policy.Action, objectType string) (rbac.PreparedAuthorized, error) { roles := httpmw.UserAuthorization(r) prepared, err := h.Authorizer.Prepare(r.Context(), roles, action, objectType) if err != nil { @@ -219,7 +220,7 @@ func (api *API) checkAuthorization(rw http.ResponseWriter, r *http.Request) { obj = dbObj.RBACObject() } - err := api.Authorizer.Authorize(ctx, auth, rbac.Action(v.Action), obj) + err := api.Authorizer.Authorize(ctx, auth, policy.Action(v.Action), obj) response[k] = err == nil } diff --git a/coderd/coderd.go b/coderd/coderd.go index 9dcda1a71536e..c0631c0752c0c 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -60,6 +60,7 @@ import ( "github.com/coder/coder/v2/coderd/prometheusmetrics" "github.com/coder/coder/v2/coderd/provisionerdserver" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/schedule" "github.com/coder/coder/v2/coderd/telemetry" "github.com/coder/coder/v2/coderd/tracing" @@ -1106,7 +1107,7 @@ func New(options *Options) *API { // Ensure only owners can access debug endpoints. func(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - if !api.Authorize(r, rbac.ActionRead, rbac.ResourceDebugInfo) { + if !api.Authorize(r, policy.ActionRead, rbac.ResourceDebugInfo) { httpapi.ResourceNotFound(rw) return } diff --git a/coderd/coderdtest/authorize.go b/coderd/coderdtest/authorize.go index 01210f9a7056e..6c38063a0dbbe 100644 --- a/coderd/coderdtest/authorize.go +++ b/coderd/coderdtest/authorize.go @@ -20,6 +20,7 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbauthz" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/rbac/regosql" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/cryptorand" @@ -84,7 +85,7 @@ func (a RBACAsserter) AllCalls() []AuthCall { // AssertChecked will assert a given rbac check was performed. It does not care // about order of checks, or any other checks. This is useful when you do not // care about asserting every check that was performed. -func (a RBACAsserter) AssertChecked(t *testing.T, action rbac.Action, objects ...interface{}) { +func (a RBACAsserter) AssertChecked(t *testing.T, action policy.Action, objects ...interface{}) { converted := a.convertObjects(t, objects...) pairs := make([]ActionObjectPair, 0, len(converted)) for _, obj := range converted { @@ -95,7 +96,7 @@ func (a RBACAsserter) AssertChecked(t *testing.T, action rbac.Action, objects .. // AssertInOrder must be called in the correct order of authz checks. If the objects // or actions are not in the correct order, the test will fail. -func (a RBACAsserter) AssertInOrder(t *testing.T, action rbac.Action, objects ...interface{}) { +func (a RBACAsserter) AssertInOrder(t *testing.T, action policy.Action, objects ...interface{}) { converted := a.convertObjects(t, objects...) pairs := make([]ActionObjectPair, 0, len(converted)) for _, obj := range converted { @@ -155,13 +156,13 @@ type RecordingAuthorizer struct { } type ActionObjectPair struct { - Action rbac.Action + Action policy.Action Object rbac.Object } // Pair is on the RecordingAuthorizer to be easy to find and keep the pkg // interface smaller. -func (*RecordingAuthorizer) Pair(action rbac.Action, object rbac.Objecter) ActionObjectPair { +func (*RecordingAuthorizer) Pair(action policy.Action, object rbac.Objecter) ActionObjectPair { return ActionObjectPair{ Action: action, Object: object.RBACObject(), @@ -248,7 +249,7 @@ func (r *RecordingAuthorizer) AssertActor(t *testing.T, actor rbac.Subject, did } // recordAuthorize is the internal method that records the Authorize() call. -func (r *RecordingAuthorizer) recordAuthorize(subject rbac.Subject, action rbac.Action, object rbac.Object) { +func (r *RecordingAuthorizer) recordAuthorize(subject rbac.Subject, action policy.Action, object rbac.Object) { r.Lock() defer r.Unlock() @@ -283,7 +284,7 @@ func caller(skip int) string { return str } -func (r *RecordingAuthorizer) Authorize(ctx context.Context, subject rbac.Subject, action rbac.Action, object rbac.Object) error { +func (r *RecordingAuthorizer) Authorize(ctx context.Context, subject rbac.Subject, action policy.Action, object rbac.Object) error { r.recordAuthorize(subject, action, object) if r.Wrapped == nil { panic("Developer error: RecordingAuthorizer.Wrapped is nil") @@ -291,7 +292,7 @@ func (r *RecordingAuthorizer) Authorize(ctx context.Context, subject rbac.Subjec return r.Wrapped.Authorize(ctx, subject, action, object) } -func (r *RecordingAuthorizer) Prepare(ctx context.Context, subject rbac.Subject, action rbac.Action, objectType string) (rbac.PreparedAuthorized, error) { +func (r *RecordingAuthorizer) Prepare(ctx context.Context, subject rbac.Subject, action policy.Action, objectType string) (rbac.PreparedAuthorized, error) { r.RLock() defer r.RUnlock() if r.Wrapped == nil { @@ -325,7 +326,7 @@ type PreparedRecorder struct { rec *RecordingAuthorizer prepped rbac.PreparedAuthorized subject rbac.Subject - action rbac.Action + action policy.Action rw sync.Mutex usingSQL bool @@ -357,11 +358,11 @@ type FakeAuthorizer struct { var _ rbac.Authorizer = (*FakeAuthorizer)(nil) -func (d *FakeAuthorizer) Authorize(_ context.Context, _ rbac.Subject, _ rbac.Action, _ rbac.Object) error { +func (d *FakeAuthorizer) Authorize(_ context.Context, _ rbac.Subject, _ policy.Action, _ rbac.Object) error { return d.AlwaysReturn } -func (d *FakeAuthorizer) Prepare(_ context.Context, subject rbac.Subject, action rbac.Action, _ string) (rbac.PreparedAuthorized, error) { +func (d *FakeAuthorizer) Prepare(_ context.Context, subject rbac.Subject, action policy.Action, _ string) (rbac.PreparedAuthorized, error) { return &fakePreparedAuthorizer{ Original: d, Subject: subject, @@ -377,7 +378,7 @@ type fakePreparedAuthorizer struct { sync.RWMutex Original *FakeAuthorizer Subject rbac.Subject - Action rbac.Action + Action policy.Action } func (f *fakePreparedAuthorizer) Authorize(ctx context.Context, object rbac.Object) error { @@ -392,7 +393,7 @@ func (*fakePreparedAuthorizer) CompileToSQL(_ context.Context, _ regosql.Convert // Random rbac helper funcs -func RandomRBACAction() rbac.Action { +func RandomRBACAction() policy.Action { all := rbac.AllActions() return all[must(cryptorand.Intn(len(all)))] } @@ -403,10 +404,10 @@ func RandomRBACObject() rbac.Object { Owner: uuid.NewString(), OrgID: uuid.NewString(), Type: randomRBACType(), - ACLUserList: map[string][]rbac.Action{ + ACLUserList: map[string][]policy.Action{ namesgenerator.GetRandomName(1): {RandomRBACAction()}, }, - ACLGroupList: map[string][]rbac.Action{ + ACLGroupList: map[string][]policy.Action{ namesgenerator.GetRandomName(1): {RandomRBACAction()}, }, } diff --git a/coderd/coderdtest/authorize_test.go b/coderd/coderdtest/authorize_test.go index 13a04200a9d2f..5cdcd26869cf3 100644 --- a/coderd/coderdtest/authorize_test.go +++ b/coderd/coderdtest/authorize_test.go @@ -9,6 +9,7 @@ import ( "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" ) func TestAuthzRecorder(t *testing.T) { @@ -101,7 +102,7 @@ func TestAuthzRecorder(t *testing.T) { } // 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 { +func fuzzAuthzPrep(t *testing.T, prep rbac.PreparedAuthorized, n int, action policy.Action, objectType string) []coderdtest.ActionObjectPair { t.Helper() pairs := make([]coderdtest.ActionObjectPair, 0, n) diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index aaf623c7a70b5..3d9129928c811 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -21,6 +21,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/httpapi/httpapiconstraints" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/util/slice" "github.com/coder/coder/v2/provisionersdk" ) @@ -130,7 +131,7 @@ func (q *querier) Wrappers() []string { } // authorizeContext is a helper function to authorize an action on an object. -func (q *querier) authorizeContext(ctx context.Context, action rbac.Action, object rbac.Objecter) error { +func (q *querier) authorizeContext(ctx context.Context, action policy.Action, object rbac.Objecter) error { act, ok := ActorFromContext(ctx) if !ok { return NoActorError @@ -161,20 +162,20 @@ var ( { Name: "provisionerd", DisplayName: "Provisioner Daemon", - Site: rbac.Permissions(map[string][]rbac.Action{ + Site: rbac.Permissions(map[string][]policy.Action{ // TODO: Add ProvisionerJob resource type. - rbac.ResourceFile.Type: {rbac.ActionRead}, + rbac.ResourceFile.Type: {policy.ActionRead}, rbac.ResourceSystem.Type: {rbac.WildcardSymbol}, - rbac.ResourceTemplate.Type: {rbac.ActionRead, rbac.ActionUpdate}, - rbac.ResourceUser.Type: {rbac.ActionRead}, - rbac.ResourceWorkspace.Type: {rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, - rbac.ResourceWorkspaceBuild.Type: {rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, - rbac.ResourceUserData.Type: {rbac.ActionRead, rbac.ActionUpdate}, + rbac.ResourceTemplate.Type: {policy.ActionRead, policy.ActionUpdate}, + rbac.ResourceUser.Type: {policy.ActionRead}, + rbac.ResourceWorkspace.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + rbac.ResourceWorkspaceBuild.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + rbac.ResourceUserData.Type: {policy.ActionRead, policy.ActionUpdate}, rbac.ResourceAPIKey.Type: {rbac.WildcardSymbol}, // When org scoped provisioner credentials are implemented, // this can be reduced to read a specific org. - rbac.ResourceOrganization.Type: {rbac.ActionRead}, - rbac.ResourceGroup.Type: {rbac.ActionRead}, + rbac.ResourceOrganization.Type: {policy.ActionRead}, + rbac.ResourceGroup.Type: {policy.ActionRead}, }), Org: map[string][]rbac.Permission{}, User: []rbac.Permission{}, @@ -190,12 +191,12 @@ var ( { Name: "autostart", DisplayName: "Autostart Daemon", - Site: rbac.Permissions(map[string][]rbac.Action{ + Site: rbac.Permissions(map[string][]policy.Action{ rbac.ResourceSystem.Type: {rbac.WildcardSymbol}, - rbac.ResourceTemplate.Type: {rbac.ActionRead, rbac.ActionUpdate}, - rbac.ResourceWorkspace.Type: {rbac.ActionRead, rbac.ActionUpdate}, - rbac.ResourceWorkspaceBuild.Type: {rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, - rbac.ResourceUser.Type: {rbac.ActionRead}, + rbac.ResourceTemplate.Type: {policy.ActionRead, policy.ActionUpdate}, + rbac.ResourceWorkspace.Type: {policy.ActionRead, policy.ActionUpdate}, + rbac.ResourceWorkspaceBuild.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + rbac.ResourceUser.Type: {policy.ActionRead}, }), Org: map[string][]rbac.Permission{}, User: []rbac.Permission{}, @@ -212,10 +213,10 @@ var ( { Name: "hangdetector", DisplayName: "Hang Detector Daemon", - Site: rbac.Permissions(map[string][]rbac.Action{ + Site: rbac.Permissions(map[string][]policy.Action{ rbac.ResourceSystem.Type: {rbac.WildcardSymbol}, - rbac.ResourceTemplate.Type: {rbac.ActionRead}, - rbac.ResourceWorkspace.Type: {rbac.ActionRead, rbac.ActionUpdate}, + rbac.ResourceTemplate.Type: {policy.ActionRead}, + rbac.ResourceWorkspace.Type: {policy.ActionRead, policy.ActionUpdate}, }), Org: map[string][]rbac.Permission{}, User: []rbac.Permission{}, @@ -231,22 +232,22 @@ var ( { Name: "system", DisplayName: "Coder", - Site: rbac.Permissions(map[string][]rbac.Action{ - rbac.ResourceWildcard.Type: {rbac.ActionRead}, - rbac.ResourceAPIKey.Type: {rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete}, - rbac.ResourceGroup.Type: {rbac.ActionCreate, rbac.ActionUpdate}, - rbac.ResourceRoleAssignment.Type: {rbac.ActionCreate, rbac.ActionDelete}, + Site: rbac.Permissions(map[string][]policy.Action{ + rbac.ResourceWildcard.Type: {policy.ActionRead}, + rbac.ResourceAPIKey.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, + rbac.ResourceGroup.Type: {policy.ActionCreate, policy.ActionUpdate}, + rbac.ResourceRoleAssignment.Type: {policy.ActionCreate, policy.ActionDelete}, rbac.ResourceSystem.Type: {rbac.WildcardSymbol}, - rbac.ResourceOrganization.Type: {rbac.ActionCreate, rbac.ActionRead}, - rbac.ResourceOrganizationMember.Type: {rbac.ActionCreate}, - rbac.ResourceOrgRoleAssignment.Type: {rbac.ActionCreate}, - rbac.ResourceProvisionerDaemon.Type: {rbac.ActionCreate, rbac.ActionUpdate}, - rbac.ResourceUser.Type: {rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete}, - rbac.ResourceUserData.Type: {rbac.ActionCreate, rbac.ActionUpdate}, - rbac.ResourceWorkspace.Type: {rbac.ActionUpdate}, - rbac.ResourceWorkspaceBuild.Type: {rbac.ActionUpdate}, - rbac.ResourceWorkspaceExecution.Type: {rbac.ActionCreate}, - rbac.ResourceWorkspaceProxy.Type: {rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete}, + rbac.ResourceOrganization.Type: {policy.ActionCreate, policy.ActionRead}, + rbac.ResourceOrganizationMember.Type: {policy.ActionCreate}, + rbac.ResourceOrgRoleAssignment.Type: {policy.ActionCreate}, + rbac.ResourceProvisionerDaemon.Type: {policy.ActionCreate, policy.ActionUpdate}, + rbac.ResourceUser.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, + rbac.ResourceUserData.Type: {policy.ActionCreate, policy.ActionUpdate}, + rbac.ResourceWorkspace.Type: {policy.ActionUpdate}, + rbac.ResourceWorkspaceBuild.Type: {policy.ActionUpdate}, + rbac.ResourceWorkspaceExecution.Type: {policy.ActionCreate}, + rbac.ResourceWorkspaceProxy.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, }), Org: map[string][]rbac.Permission{}, User: []rbac.Permission{}, @@ -302,7 +303,7 @@ func As(ctx context.Context, actor rbac.Subject) context.Context { // Generic functions used to implement the database.Store methods. // -// insert runs an rbac.ActionCreate on the rbac object argument before +// insert runs an policy.ActionCreate on the rbac object argument before // running the insertFunc. The insertFunc is expected to return the object that // was inserted. func insert[ @@ -323,7 +324,7 @@ func insert[ } // Authorize the action - err = authorizer.Authorize(ctx, act, rbac.ActionCreate, object.RBACObject()) + err = authorizer.Authorize(ctx, act, policy.ActionCreate, object.RBACObject()) if err != nil { return empty, logNotAuthorizedError(ctx, logger, err) } @@ -345,7 +346,7 @@ func deleteQ[ deleteFunc Delete, ) Delete { return fetchAndExec(logger, authorizer, - rbac.ActionDelete, fetchFunc, deleteFunc) + policy.ActionDelete, fetchFunc, deleteFunc) } func updateWithReturn[ @@ -359,7 +360,7 @@ func updateWithReturn[ fetchFunc Fetch, updateQuery UpdateQuery, ) UpdateQuery { - return fetchAndQuery(logger, authorizer, rbac.ActionUpdate, fetchFunc, updateQuery) + return fetchAndQuery(logger, authorizer, policy.ActionUpdate, fetchFunc, updateQuery) } func update[ @@ -373,7 +374,7 @@ func update[ fetchFunc Fetch, updateExec Exec, ) Exec { - return fetchAndExec(logger, authorizer, rbac.ActionUpdate, fetchFunc, updateExec) + return fetchAndExec(logger, authorizer, policy.ActionUpdate, fetchFunc, updateExec) } // fetch is a generic function that wraps a database @@ -406,7 +407,7 @@ func fetch[ } // Authorize the action - err = authorizer.Authorize(ctx, act, rbac.ActionRead, object.RBACObject()) + err = authorizer.Authorize(ctx, act, policy.ActionRead, object.RBACObject()) if err != nil { return empty, logNotAuthorizedError(ctx, logger, err) } @@ -426,7 +427,7 @@ func fetchAndExec[ ]( logger slog.Logger, authorizer rbac.Authorizer, - action rbac.Action, + action policy.Action, fetchFunc Fetch, execFunc Exec, ) Exec { @@ -452,7 +453,7 @@ func fetchAndQuery[ ]( logger slog.Logger, authorizer rbac.Authorizer, - action rbac.Action, + action policy.Action, fetchFunc Fetch, queryFunc Query, ) Query { @@ -503,13 +504,13 @@ func fetchWithPostFilter[ } // Authorize the action - return rbac.Filter(ctx, authorizer, act, rbac.ActionRead, objects) + return rbac.Filter(ctx, authorizer, act, policy.ActionRead, objects) } } // prepareSQLFilter is a helper function that prepares a SQL filter using the // given authorization context. -func prepareSQLFilter(ctx context.Context, authorizer rbac.Authorizer, action rbac.Action, resourceType string) (rbac.PreparedAuthorized, error) { +func prepareSQLFilter(ctx context.Context, authorizer rbac.Authorizer, action policy.Action, resourceType string) (rbac.PreparedAuthorized, error) { act, ok := ActorFromContext(ctx) if !ok { return nil, NoActorError @@ -543,7 +544,7 @@ func (q *querier) authorizeUpdateFileTemplate(ctx context.Context, file database // 1, so check them all. for _, tpl := range tpls { // If the user has update access to any template, they have read access to the file. - if err := q.authorizeContext(ctx, rbac.ActionUpdate, tpl); err == nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, tpl); err == nil { return nil } } @@ -584,13 +585,13 @@ func (q *querier) canAssignRoles(ctx context.Context, orgID *uuid.UUID, added, r } if len(added) > 0 { - if err := q.authorizeContext(ctx, rbac.ActionCreate, roleAssign); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, roleAssign); err != nil { return err } } if len(removed) > 0 { - if err := q.authorizeContext(ctx, rbac.ActionDelete, roleAssign); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, roleAssign); err != nil { return err } } @@ -660,7 +661,7 @@ func (q *querier) AcquireLock(ctx context.Context, id int64) error { // TODO: We need to create a ProvisionerJob resource type func (q *querier) AcquireProvisionerJob(ctx context.Context, arg database.AcquireProvisionerJobParams) (database.ProvisionerJob, error) { - // if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + // if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { // return database.ProvisionerJob{}, err // } return q.db.AcquireProvisionerJob(ctx, arg) @@ -676,7 +677,7 @@ func (q *querier) ActivityBumpWorkspace(ctx context.Context, arg database.Activi func (q *querier) AllUserIDs(ctx context.Context) ([]uuid.UUID, error) { // Although this technically only reads users, only system-related functions should be // allowed to call this. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.AllUserIDs(ctx) @@ -687,7 +688,7 @@ func (q *querier) ArchiveUnusedTemplateVersions(ctx context.Context, arg databas if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, tpl); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, tpl); err != nil { return nil, err } return q.db.ArchiveUnusedTemplateVersions(ctx, arg) @@ -696,28 +697,28 @@ func (q *querier) ArchiveUnusedTemplateVersions(ctx context.Context, arg databas func (q *querier) BatchUpdateWorkspaceLastUsedAt(ctx context.Context, arg database.BatchUpdateWorkspaceLastUsedAtParams) error { // Could be any workspace and checking auth to each workspace is overkill for the purpose // of this function. - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceWorkspace.All()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceWorkspace.All()); err != nil { return err } return q.db.BatchUpdateWorkspaceLastUsedAt(ctx, arg) } func (q *querier) CleanTailnetCoordinators(ctx context.Context) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return err } return q.db.CleanTailnetCoordinators(ctx) } func (q *querier) CleanTailnetLostPeers(ctx context.Context) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return err } return q.db.CleanTailnetLostPeers(ctx) } func (q *querier) CleanTailnetTunnels(ctx context.Context) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return err } return q.db.CleanTailnetTunnels(ctx) @@ -729,7 +730,7 @@ func (q *querier) DeleteAPIKeyByID(ctx context.Context, id string) error { func (q *querier) DeleteAPIKeysByUserID(ctx context.Context, userID uuid.UUID) error { // TODO: This is not 100% correct because it omits apikey IDs. - err := q.authorizeContext(ctx, rbac.ActionDelete, + err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceAPIKey.WithOwner(userID.String())) if err != nil { return err @@ -738,14 +739,14 @@ func (q *querier) DeleteAPIKeysByUserID(ctx context.Context, userID uuid.UUID) e } func (q *querier) DeleteAllTailnetClientSubscriptions(ctx context.Context, arg database.DeleteAllTailnetClientSubscriptionsParams) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return err } return q.db.DeleteAllTailnetClientSubscriptions(ctx, arg) } func (q *querier) DeleteAllTailnetTunnels(ctx context.Context, arg database.DeleteAllTailnetTunnelsParams) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return err } return q.db.DeleteAllTailnetTunnels(ctx, arg) @@ -753,7 +754,7 @@ func (q *querier) DeleteAllTailnetTunnels(ctx context.Context, arg database.Dele func (q *querier) DeleteApplicationConnectAPIKeysByUserID(ctx context.Context, userID uuid.UUID) error { // TODO: This is not 100% correct because it omits apikey IDs. - err := q.authorizeContext(ctx, rbac.ActionDelete, + err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceAPIKey.WithOwner(userID.String())) if err != nil { return err @@ -762,7 +763,7 @@ func (q *querier) DeleteApplicationConnectAPIKeysByUserID(ctx context.Context, u } func (q *querier) DeleteCoordinator(ctx context.Context, id uuid.UUID) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return err } return q.db.DeleteCoordinator(ctx, id) @@ -803,7 +804,7 @@ func (q *querier) DeleteLicense(ctx context.Context, id int32) (int32, error) { } func (q *querier) DeleteOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceOAuth2ProviderApp); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceOAuth2ProviderApp); err != nil { return err } return q.db.DeleteOAuth2ProviderAppByID(ctx, id) @@ -814,14 +815,14 @@ func (q *querier) DeleteOAuth2ProviderAppCodeByID(ctx context.Context, id uuid.U if err != nil { return err } - if err := q.authorizeContext(ctx, rbac.ActionDelete, code); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, code); err != nil { return err } return q.db.DeleteOAuth2ProviderAppCodeByID(ctx, id) } func (q *querier) DeleteOAuth2ProviderAppCodesByAppAndUserID(ctx context.Context, arg database.DeleteOAuth2ProviderAppCodesByAppAndUserIDParams) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(arg.UserID.String())); err != nil { return err } @@ -829,14 +830,14 @@ func (q *querier) DeleteOAuth2ProviderAppCodesByAppAndUserID(ctx context.Context } func (q *querier) DeleteOAuth2ProviderAppSecretByID(ctx context.Context, id uuid.UUID) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceOAuth2ProviderAppSecret); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceOAuth2ProviderAppSecret); err != nil { return err } return q.db.DeleteOAuth2ProviderAppSecretByID(ctx, id) } func (q *querier) DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx context.Context, arg database.DeleteOAuth2ProviderAppTokensByAppAndUserIDParams) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(arg.UserID.String())); err != nil { return err } @@ -844,63 +845,63 @@ func (q *querier) DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx context.Contex } func (q *querier) DeleteOldProvisionerDaemons(ctx context.Context) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil { return err } return q.db.DeleteOldProvisionerDaemons(ctx) } func (q *querier) DeleteOldWorkspaceAgentLogs(ctx context.Context) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil { return err } return q.db.DeleteOldWorkspaceAgentLogs(ctx) } func (q *querier) DeleteOldWorkspaceAgentStats(ctx context.Context) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil { return err } return q.db.DeleteOldWorkspaceAgentStats(ctx) } func (q *querier) DeleteReplicasUpdatedBefore(ctx context.Context, updatedAt time.Time) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceSystem); err != nil { return err } return q.db.DeleteReplicasUpdatedBefore(ctx, updatedAt) } func (q *querier) DeleteTailnetAgent(ctx context.Context, arg database.DeleteTailnetAgentParams) (database.DeleteTailnetAgentRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { return database.DeleteTailnetAgentRow{}, err } return q.db.DeleteTailnetAgent(ctx, arg) } func (q *querier) DeleteTailnetClient(ctx context.Context, arg database.DeleteTailnetClientParams) (database.DeleteTailnetClientRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return database.DeleteTailnetClientRow{}, err } return q.db.DeleteTailnetClient(ctx, arg) } func (q *querier) DeleteTailnetClientSubscription(ctx context.Context, arg database.DeleteTailnetClientSubscriptionParams) error { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return err } return q.db.DeleteTailnetClientSubscription(ctx, arg) } func (q *querier) DeleteTailnetPeer(ctx context.Context, arg database.DeleteTailnetPeerParams) (database.DeleteTailnetPeerRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return database.DeleteTailnetPeerRow{}, err } return q.db.DeleteTailnetPeer(ctx, arg) } func (q *querier) DeleteTailnetTunnel(ctx context.Context, arg database.DeleteTailnetTunnelParams) (database.DeleteTailnetTunnelRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { return database.DeleteTailnetTunnelRow{}, err } return q.db.DeleteTailnetTunnel(ctx, arg) @@ -913,7 +914,7 @@ func (q *querier) DeleteWorkspaceAgentPortShare(ctx context.Context, arg databas } // deleting a workspace port share is more akin to just updating the workspace. - if err = q.authorizeContext(ctx, rbac.ActionUpdate, w.RBACObject()); err != nil { + if err = q.authorizeContext(ctx, policy.ActionUpdate, w.RBACObject()); err != nil { return xerrors.Errorf("authorize context: %w", err) } @@ -926,7 +927,7 @@ func (q *querier) DeleteWorkspaceAgentPortSharesByTemplate(ctx context.Context, return err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return err } @@ -961,7 +962,7 @@ func (q *querier) GetAPIKeysLastUsedAfter(ctx context.Context, lastUsed time.Tim } func (q *querier) GetActiveUserCount(ctx context.Context) (int64, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return 0, err } return q.db.GetActiveUserCount(ctx) @@ -969,35 +970,35 @@ func (q *querier) GetActiveUserCount(ctx context.Context) (int64, error) { func (q *querier) GetActiveWorkspaceBuildsByTemplateID(ctx context.Context, templateID uuid.UUID) ([]database.WorkspaceBuild, error) { // This is a system-only function. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return []database.WorkspaceBuild{}, err } return q.db.GetActiveWorkspaceBuildsByTemplateID(ctx, templateID) } func (q *querier) GetAllTailnetAgents(ctx context.Context) ([]database.TailnetAgent, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { return []database.TailnetAgent{}, err } return q.db.GetAllTailnetAgents(ctx) } func (q *querier) GetAllTailnetCoordinators(ctx context.Context) ([]database.TailnetCoordinator, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { return nil, err } return q.db.GetAllTailnetCoordinators(ctx) } func (q *querier) GetAllTailnetPeers(ctx context.Context) ([]database.TailnetPeer, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { return nil, err } return q.db.GetAllTailnetPeers(ctx) } func (q *querier) GetAllTailnetTunnels(ctx context.Context) ([]database.TailnetTunnel, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { return nil, err } return q.db.GetAllTailnetTunnels(ctx) @@ -1017,28 +1018,28 @@ func (q *querier) GetAuditLogsOffset(ctx context.Context, arg database.GetAuditL // To optimize audit logs, we only check the global audit log permission once. // This is because we expect a large unbounded set of audit logs, and applying a SQL // filter would slow down the query for no benefit. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceAuditLog); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceAuditLog); err != nil { return nil, err } return q.db.GetAuditLogsOffset(ctx, arg) } func (q *querier) GetAuthorizationUserRoles(ctx context.Context, userID uuid.UUID) (database.GetAuthorizationUserRolesRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return database.GetAuthorizationUserRolesRow{}, err } return q.db.GetAuthorizationUserRoles(ctx, userID) } func (q *querier) GetDBCryptKeys(ctx context.Context) ([]database.DBCryptKey, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetDBCryptKeys(ctx) } func (q *querier) GetDERPMeshKey(ctx context.Context) (string, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return "", err } return q.db.GetDERPMeshKey(ctx) @@ -1057,7 +1058,7 @@ func (q *querier) GetDefaultProxyConfig(ctx context.Context) (database.GetDefaul // Only used by metrics cache. func (q *querier) GetDeploymentDAUs(ctx context.Context, tzOffset int32) ([]database.GetDeploymentDAUsRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetDeploymentDAUs(ctx, tzOffset) @@ -1089,7 +1090,7 @@ func (q *querier) GetFileByHashAndCreator(ctx context.Context, arg database.GetF if err != nil { return database.File{}, err } - err = q.authorizeContext(ctx, rbac.ActionRead, file) + err = q.authorizeContext(ctx, policy.ActionRead, file) if err != nil { // Check the user's access to the file's templates. if q.authorizeUpdateFileTemplate(ctx, file) != nil { @@ -1105,7 +1106,7 @@ func (q *querier) GetFileByID(ctx context.Context, id uuid.UUID) (database.File, if err != nil { return database.File{}, err } - err = q.authorizeContext(ctx, rbac.ActionRead, file) + err = q.authorizeContext(ctx, policy.ActionRead, file) if err != nil { // Check the user's access to the file's templates. if q.authorizeUpdateFileTemplate(ctx, file) != nil { @@ -1117,7 +1118,7 @@ func (q *querier) GetFileByID(ctx context.Context, id uuid.UUID) (database.File, } func (q *querier) GetFileTemplates(ctx context.Context, fileID uuid.UUID) ([]database.GetFileTemplatesRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetFileTemplates(ctx, fileID) @@ -1157,7 +1158,7 @@ func (q *querier) GetHealthSettings(ctx context.Context) (string, error) { // TODO: We need to create a ProvisionerJob resource type func (q *querier) GetHungProvisionerJobs(ctx context.Context, hungSince time.Time) ([]database.ProvisionerJob, error) { - // if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + // if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { // return nil, err // } return q.db.GetHungProvisionerJobs(ctx, hungSince) @@ -1171,7 +1172,7 @@ func (q *querier) GetJFrogXrayScanByWorkspaceAndAgentID(ctx context.Context, arg } func (q *querier) GetLastUpdateCheck(ctx context.Context) (string, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return "", err } return q.db.GetLastUpdateCheck(ctx) @@ -1189,7 +1190,7 @@ func (q *querier) GetLatestWorkspaceBuilds(ctx context.Context) ([]database.Work // This is because we need to query for all related workspaces to the returned builds. // This is a very inefficient method of fetching the latest workspace builds. // We should just join the rbac properties. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetLatestWorkspaceBuilds(ctx) @@ -1197,7 +1198,7 @@ func (q *querier) GetLatestWorkspaceBuilds(ctx context.Context) ([]database.Work func (q *querier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceBuild, error) { // This function is a system function until we implement a join for workspace builds. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } @@ -1226,7 +1227,7 @@ func (q *querier) GetNotificationBanners(ctx context.Context) (string, error) { } func (q *querier) GetOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID) (database.OAuth2ProviderApp, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderApp); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOAuth2ProviderApp); err != nil { return database.OAuth2ProviderApp{}, err } return q.db.GetOAuth2ProviderAppByID(ctx, id) @@ -1241,7 +1242,7 @@ func (q *querier) GetOAuth2ProviderAppCodeByPrefix(ctx context.Context, secretPr } func (q *querier) GetOAuth2ProviderAppSecretByID(ctx context.Context, id uuid.UUID) (database.OAuth2ProviderAppSecret, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderAppSecret); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOAuth2ProviderAppSecret); err != nil { return database.OAuth2ProviderAppSecret{}, err } return q.db.GetOAuth2ProviderAppSecretByID(ctx, id) @@ -1252,7 +1253,7 @@ func (q *querier) GetOAuth2ProviderAppSecretByPrefix(ctx context.Context, secret } func (q *querier) GetOAuth2ProviderAppSecretsByAppID(ctx context.Context, appID uuid.UUID) ([]database.OAuth2ProviderAppSecret, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderAppSecret); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOAuth2ProviderAppSecret); err != nil { return []database.OAuth2ProviderAppSecret{}, err } return q.db.GetOAuth2ProviderAppSecretsByAppID(ctx, appID) @@ -1268,14 +1269,14 @@ func (q *querier) GetOAuth2ProviderAppTokenByPrefix(ctx context.Context, hashPre if err != nil { return database.OAuth2ProviderAppToken{}, err } - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(key.UserID.String())); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(key.UserID.String())); err != nil { return database.OAuth2ProviderAppToken{}, err } return token, nil } func (q *querier) GetOAuth2ProviderApps(ctx context.Context) ([]database.OAuth2ProviderApp, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderApp); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOAuth2ProviderApp); err != nil { return []database.OAuth2ProviderApp{}, err } return q.db.GetOAuth2ProviderApps(ctx) @@ -1283,7 +1284,7 @@ func (q *querier) GetOAuth2ProviderApps(ctx context.Context) ([]database.OAuth2P func (q *querier) GetOAuth2ProviderAppsByUserID(ctx context.Context, userID uuid.UUID) ([]database.GetOAuth2ProviderAppsByUserIDRow, error) { // This authz check is to make sure the caller can read all their own tokens. - if err := q.authorizeContext(ctx, rbac.ActionRead, + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(userID.String())); err != nil { return []database.GetOAuth2ProviderAppsByUserIDRow{}, err } @@ -1291,7 +1292,7 @@ func (q *querier) GetOAuth2ProviderAppsByUserID(ctx context.Context, userID uuid } func (q *querier) GetOAuthSigningKey(ctx context.Context) (string, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return "", err } return q.db.GetOAuthSigningKey(ctx) @@ -1344,7 +1345,7 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI object = version.RBACObject(tpl) } - err = q.authorizeContext(ctx, rbac.ActionRead, object) + err = q.authorizeContext(ctx, policy.ActionRead, object) if err != nil { return nil, err } @@ -1355,7 +1356,7 @@ func (q *querier) GetPreviousTemplateVersion(ctx context.Context, arg database.G // An actor can read the previous template version if they can read the related template. // If no linked template exists, we check if the actor can read *a* template. if !arg.TemplateID.Valid { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplate.InOrg(arg.OrganizationID)); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate.InOrg(arg.OrganizationID)); err != nil { return database.TemplateVersion{}, err } } @@ -1401,7 +1402,7 @@ func (q *querier) GetProvisionerJobByID(ctx context.Context, id uuid.UUID) (data // TODO: we need to add a provisioner job resource func (q *querier) GetProvisionerJobsByIDs(ctx context.Context, ids []uuid.UUID) ([]database.ProvisionerJob, error) { - // if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + // if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { // return nil, err // } return q.db.GetProvisionerJobsByIDs(ctx, ids) @@ -1414,7 +1415,7 @@ func (q *querier) GetProvisionerJobsByIDsWithQueuePosition(ctx context.Context, // TODO: We need to create a ProvisionerJob resource type func (q *querier) GetProvisionerJobsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.ProvisionerJob, error) { - // if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + // if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { // return nil, err // } return q.db.GetProvisionerJobsCreatedAfter(ctx, createdAt) @@ -1430,7 +1431,7 @@ func (q *querier) GetProvisionerLogsAfterID(ctx context.Context, arg database.Ge } func (q *querier) GetQuotaAllowanceForUser(ctx context.Context, userID uuid.UUID) (int64, error) { - err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceUserObject(userID)) + err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceUserObject(userID)) if err != nil { return -1, err } @@ -1438,7 +1439,7 @@ func (q *querier) GetQuotaAllowanceForUser(ctx context.Context, userID uuid.UUID } func (q *querier) GetQuotaConsumedForUser(ctx context.Context, userID uuid.UUID) (int64, error) { - err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceUserObject(userID)) + err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceUserObject(userID)) if err != nil { return -1, err } @@ -1446,49 +1447,49 @@ func (q *querier) GetQuotaConsumedForUser(ctx context.Context, userID uuid.UUID) } func (q *querier) GetReplicaByID(ctx context.Context, id uuid.UUID) (database.Replica, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return database.Replica{}, err } return q.db.GetReplicaByID(ctx, id) } func (q *querier) GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Time) ([]database.Replica, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetReplicasUpdatedAfter(ctx, updatedAt) } func (q *querier) GetTailnetAgents(ctx context.Context, id uuid.UUID) ([]database.TailnetAgent, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { return nil, err } return q.db.GetTailnetAgents(ctx, id) } func (q *querier) GetTailnetClientsForAgent(ctx context.Context, agentID uuid.UUID) ([]database.TailnetClient, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { return nil, err } return q.db.GetTailnetClientsForAgent(ctx, agentID) } func (q *querier) GetTailnetPeers(ctx context.Context, id uuid.UUID) ([]database.TailnetPeer, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { return nil, err } return q.db.GetTailnetPeers(ctx, id) } func (q *querier) GetTailnetTunnelPeerBindings(ctx context.Context, srcID uuid.UUID) ([]database.GetTailnetTunnelPeerBindingsRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { return nil, err } return q.db.GetTailnetTunnelPeerBindings(ctx, srcID) } func (q *querier) GetTailnetTunnelPeerIDs(ctx context.Context, srcID uuid.UUID) ([]database.GetTailnetTunnelPeerIDsRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTailnetCoordinator); err != nil { return nil, err } return q.db.GetTailnetTunnelPeerIDs(ctx, srcID) @@ -1497,19 +1498,19 @@ func (q *querier) GetTailnetTunnelPeerIDs(ctx context.Context, srcID uuid.UUID) func (q *querier) GetTemplateAppInsights(ctx context.Context, arg database.GetTemplateAppInsightsParams) ([]database.GetTemplateAppInsightsRow, error) { // Used by TemplateAppInsights endpoint // For auditors, check read template_insights, and fall back to update template. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplateInsights); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplateInsights); err != nil { for _, templateID := range arg.TemplateIDs { template, err := q.db.GetTemplateByID(ctx, templateID) if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return nil, err } } if len(arg.TemplateIDs) == 0 { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { return nil, err } } @@ -1519,7 +1520,7 @@ func (q *querier) GetTemplateAppInsights(ctx context.Context, arg database.GetTe func (q *querier) GetTemplateAppInsightsByTemplate(ctx context.Context, arg database.GetTemplateAppInsightsByTemplateParams) ([]database.GetTemplateAppInsightsByTemplateRow, error) { // Only used by prometheus metrics, so we don't strictly need to check update template perms. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplateInsights); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplateInsights); err != nil { return nil, err } return q.db.GetTemplateAppInsightsByTemplate(ctx, arg) @@ -1527,7 +1528,7 @@ func (q *querier) GetTemplateAppInsightsByTemplate(ctx context.Context, arg data // Only used by metrics cache. func (q *querier) GetTemplateAverageBuildTime(ctx context.Context, arg database.GetTemplateAverageBuildTimeParams) (database.GetTemplateAverageBuildTimeRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return database.GetTemplateAverageBuildTimeRow{}, err } return q.db.GetTemplateAverageBuildTime(ctx, arg) @@ -1543,7 +1544,7 @@ func (q *querier) GetTemplateByOrganizationAndName(ctx context.Context, arg data // Only used by metrics cache. func (q *querier) GetTemplateDAUs(ctx context.Context, arg database.GetTemplateDAUsParams) ([]database.GetTemplateDAUsRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetTemplateDAUs(ctx, arg) @@ -1552,19 +1553,19 @@ func (q *querier) GetTemplateDAUs(ctx context.Context, arg database.GetTemplateD func (q *querier) GetTemplateInsights(ctx context.Context, arg database.GetTemplateInsightsParams) (database.GetTemplateInsightsRow, error) { // Used by TemplateInsights endpoint // For auditors, check read template_insights, and fall back to update template. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplateInsights); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplateInsights); err != nil { for _, templateID := range arg.TemplateIDs { template, err := q.db.GetTemplateByID(ctx, templateID) if err != nil { return database.GetTemplateInsightsRow{}, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return database.GetTemplateInsightsRow{}, err } } if len(arg.TemplateIDs) == 0 { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { return database.GetTemplateInsightsRow{}, err } } @@ -1575,19 +1576,19 @@ func (q *querier) GetTemplateInsights(ctx context.Context, arg database.GetTempl func (q *querier) GetTemplateInsightsByInterval(ctx context.Context, arg database.GetTemplateInsightsByIntervalParams) ([]database.GetTemplateInsightsByIntervalRow, error) { // Used by TemplateInsights endpoint // For auditors, check read template_insights, and fall back to update template. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplateInsights); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplateInsights); err != nil { for _, templateID := range arg.TemplateIDs { template, err := q.db.GetTemplateByID(ctx, templateID) if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return nil, err } } if len(arg.TemplateIDs) == 0 { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { return nil, err } } @@ -1597,7 +1598,7 @@ func (q *querier) GetTemplateInsightsByInterval(ctx context.Context, arg databas func (q *querier) GetTemplateInsightsByTemplate(ctx context.Context, arg database.GetTemplateInsightsByTemplateParams) ([]database.GetTemplateInsightsByTemplateRow, error) { // Only used by prometheus metrics collector. No need to check update template perms. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplateInsights); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplateInsights); err != nil { return nil, err } return q.db.GetTemplateInsightsByTemplate(ctx, arg) @@ -1606,19 +1607,19 @@ func (q *querier) GetTemplateInsightsByTemplate(ctx context.Context, arg databas func (q *querier) GetTemplateParameterInsights(ctx context.Context, arg database.GetTemplateParameterInsightsParams) ([]database.GetTemplateParameterInsightsRow, error) { // Used by both insights endpoint and prometheus collector. // For auditors, check read template_insights, and fall back to update template. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplateInsights); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplateInsights); err != nil { for _, templateID := range arg.TemplateIDs { template, err := q.db.GetTemplateByID(ctx, templateID) if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return nil, err } } if len(arg.TemplateIDs) == 0 { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { return nil, err } } @@ -1629,19 +1630,19 @@ func (q *querier) GetTemplateParameterInsights(ctx context.Context, arg database func (q *querier) GetTemplateUsageStats(ctx context.Context, arg database.GetTemplateUsageStatsParams) ([]database.TemplateUsageStat, error) { // Used by dbrollup tests, use same safe-guard as other insights endpoints. // For auditors, check read template_insights, and fall back to update template. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplateInsights); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplateInsights); err != nil { for _, templateID := range arg.TemplateIDs { template, err := q.db.GetTemplateByID(ctx, templateID) if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return nil, err } } if len(arg.TemplateIDs) == 0 { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { return nil, err } } @@ -1656,7 +1657,7 @@ func (q *querier) GetTemplateVersionByID(ctx context.Context, tvid uuid.UUID) (d } if !tv.TemplateID.Valid { // If no linked template exists, check if the actor can read a template in the organization. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplate.InOrg(tv.OrganizationID)); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate.InOrg(tv.OrganizationID)); err != nil { return database.TemplateVersion{}, err } } else if _, err := q.GetTemplateByID(ctx, tv.TemplateID.UUID); err != nil { @@ -1673,7 +1674,7 @@ func (q *querier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.UUID } if !tv.TemplateID.Valid { // If no linked template exists, check if the actor can read a template in the organization. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplate.InOrg(tv.OrganizationID)); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate.InOrg(tv.OrganizationID)); err != nil { return database.TemplateVersion{}, err } } else if _, err := q.GetTemplateByID(ctx, tv.TemplateID.UUID); err != nil { @@ -1690,7 +1691,7 @@ func (q *querier) GetTemplateVersionByTemplateIDAndName(ctx context.Context, arg } if !tv.TemplateID.Valid { // If no linked template exists, check if the actor can read a template in the organization. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplate.InOrg(tv.OrganizationID)); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate.InOrg(tv.OrganizationID)); err != nil { return database.TemplateVersion{}, err } } else if _, err := q.GetTemplateByID(ctx, tv.TemplateID.UUID); err != nil { @@ -1718,7 +1719,7 @@ func (q *querier) GetTemplateVersionParameters(ctx context.Context, templateVers object = tv.RBACObject(template) } - if err := q.authorizeContext(ctx, rbac.ActionRead, object); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, object); err != nil { return nil, err } return q.db.GetTemplateVersionParameters(ctx, templateVersionID) @@ -1741,7 +1742,7 @@ func (q *querier) GetTemplateVersionVariables(ctx context.Context, templateVersi object = tv.RBACObject(template) } - if err := q.authorizeContext(ctx, rbac.ActionRead, object); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, object); err != nil { return nil, err } return q.db.GetTemplateVersionVariables(ctx, templateVersionID) @@ -1750,7 +1751,7 @@ func (q *querier) GetTemplateVersionVariables(ctx context.Context, templateVersi // GetTemplateVersionsByIDs is only used for workspace build data. // The workspace is already fetched. func (q *querier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UUID) ([]database.TemplateVersion, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetTemplateVersionsByIDs(ctx, ids) @@ -1763,7 +1764,7 @@ func (q *querier) GetTemplateVersionsByTemplateID(ctx context.Context, arg datab return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionRead, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, template); err != nil { return nil, err } @@ -1772,21 +1773,21 @@ func (q *querier) GetTemplateVersionsByTemplateID(ctx context.Context, arg datab func (q *querier) GetTemplateVersionsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.TemplateVersion, error) { // An actor can read execute this query if they can read all templates. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplate.All()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate.All()); err != nil { return nil, err } return q.db.GetTemplateVersionsCreatedAfter(ctx, createdAt) } func (q *querier) GetTemplates(ctx context.Context) ([]database.Template, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetTemplates(ctx) } func (q *querier) GetTemplatesWithFilter(ctx context.Context, arg database.GetTemplatesWithFilterParams) ([]database.Template, error) { - prep, err := prepareSQLFilter(ctx, q.auth, rbac.ActionRead, rbac.ResourceTemplate.Type) + prep, err := prepareSQLFilter(ctx, q.auth, policy.ActionRead, rbac.ResourceTemplate.Type) if err != nil { return nil, xerrors.Errorf("(dev error) prepare sql filter: %w", err) } @@ -1794,7 +1795,7 @@ func (q *querier) GetTemplatesWithFilter(ctx context.Context, arg database.GetTe } func (q *querier) GetUnexpiredLicenses(ctx context.Context) ([]database.License, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetUnexpiredLicenses(ctx) @@ -1802,19 +1803,19 @@ func (q *querier) GetUnexpiredLicenses(ctx context.Context) ([]database.License, func (q *querier) GetUserActivityInsights(ctx context.Context, arg database.GetUserActivityInsightsParams) ([]database.GetUserActivityInsightsRow, error) { // Used by insights endpoints. Need to check both for auditors and for regular users with template acl perms. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplateInsights); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplateInsights); err != nil { for _, templateID := range arg.TemplateIDs { template, err := q.db.GetTemplateByID(ctx, templateID) if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return nil, err } } if len(arg.TemplateIDs) == 0 { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { return nil, err } } @@ -1831,7 +1832,7 @@ func (q *querier) GetUserByID(ctx context.Context, id uuid.UUID) (database.User, } func (q *querier) GetUserCount(ctx context.Context) (int64, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return 0, err } return q.db.GetUserCount(ctx) @@ -1839,19 +1840,19 @@ func (q *querier) GetUserCount(ctx context.Context) (int64, error) { func (q *querier) GetUserLatencyInsights(ctx context.Context, arg database.GetUserLatencyInsightsParams) ([]database.GetUserLatencyInsightsRow, error) { // Used by insights endpoints. Need to check both for auditors and for regular users with template acl perms. - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceTemplateInsights); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplateInsights); err != nil { for _, templateID := range arg.TemplateIDs { template, err := q.db.GetTemplateByID(ctx, templateID) if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return nil, err } } if len(arg.TemplateIDs) == 0 { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTemplate.All()); err != nil { return nil, err } } @@ -1860,21 +1861,21 @@ func (q *querier) GetUserLatencyInsights(ctx context.Context, arg database.GetUs } func (q *querier) GetUserLinkByLinkedID(ctx context.Context, linkedID string) (database.UserLink, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return database.UserLink{}, err } return q.db.GetUserLinkByLinkedID(ctx, linkedID) } func (q *querier) GetUserLinkByUserIDLoginType(ctx context.Context, arg database.GetUserLinkByUserIDLoginTypeParams) (database.UserLink, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return database.UserLink{}, err } return q.db.GetUserLinkByUserIDLoginType(ctx, arg) } func (q *querier) GetUserLinksByUserID(ctx context.Context, userID uuid.UUID) ([]database.UserLink, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetUserLinksByUserID(ctx, userID) @@ -1885,7 +1886,7 @@ func (q *querier) GetUserWorkspaceBuildParameters(ctx context.Context, params da if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionRead, u.UserWorkspaceBuildParametersObject()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, u.UserWorkspaceBuildParametersObject()); err != nil { return nil, err } return q.db.GetUserWorkspaceBuildParameters(ctx, params) @@ -1893,7 +1894,7 @@ func (q *querier) GetUserWorkspaceBuildParameters(ctx context.Context, params da func (q *querier) GetUsers(ctx context.Context, arg database.GetUsersParams) ([]database.GetUsersRow, error) { // This does the filtering in SQL. - prep, err := prepareSQLFilter(ctx, q.auth, rbac.ActionRead, rbac.ResourceUser.Type) + prep, err := prepareSQLFilter(ctx, q.auth, policy.ActionRead, rbac.ResourceUser.Type) if err != nil { return nil, xerrors.Errorf("(dev error) prepare sql filter: %w", err) } @@ -1905,7 +1906,7 @@ func (q *querier) GetUsers(ctx context.Context, arg database.GetUsersParams) ([] // itself. func (q *querier) GetUsersByIDs(ctx context.Context, ids []uuid.UUID) ([]database.User, error) { for _, uid := range ids { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceUserObject(uid)); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceUserObject(uid)); err != nil { return nil, err } } @@ -1914,7 +1915,7 @@ func (q *querier) GetUsersByIDs(ctx context.Context, ids []uuid.UUID) ([]databas func (q *querier) GetWorkspaceAgentAndLatestBuildByAuthToken(ctx context.Context, authToken uuid.UUID) (database.GetWorkspaceAgentAndLatestBuildByAuthTokenRow, error) { // This is a system function - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return database.GetWorkspaceAgentAndLatestBuildByAuthTokenRow{}, err } return q.db.GetWorkspaceAgentAndLatestBuildByAuthToken(ctx, authToken) @@ -1952,7 +1953,7 @@ func (q *querier) GetWorkspaceAgentLifecycleStateByID(ctx context.Context, id uu } func (q *querier) GetWorkspaceAgentLogSourcesByAgentIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceAgentLogSource, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceAgentLogSourcesByAgentIDs(ctx, ids) @@ -1972,7 +1973,7 @@ func (q *querier) GetWorkspaceAgentMetadata(ctx context.Context, arg database.Ge return nil, err } - err = q.authorizeContext(ctx, rbac.ActionRead, workspace) + err = q.authorizeContext(ctx, policy.ActionRead, workspace) if err != nil { return nil, err } @@ -1987,7 +1988,7 @@ func (q *querier) GetWorkspaceAgentPortShare(ctx context.Context, arg database.G } // reading a workspace port share is more akin to just reading the workspace. - if err = q.authorizeContext(ctx, rbac.ActionRead, w.RBACObject()); err != nil { + if err = q.authorizeContext(ctx, policy.ActionRead, w.RBACObject()); err != nil { return database.WorkspaceAgentPortShare{}, xerrors.Errorf("authorize context: %w", err) } @@ -1995,7 +1996,7 @@ func (q *querier) GetWorkspaceAgentPortShare(ctx context.Context, arg database.G } func (q *querier) GetWorkspaceAgentScriptsByAgentIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceAgentScript, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceAgentScriptsByAgentIDs(ctx, ids) @@ -2012,14 +2013,14 @@ func (q *querier) GetWorkspaceAgentStatsAndLabels(ctx context.Context, createdAf // GetWorkspaceAgentsByResourceIDs // The workspace/job is already fetched. func (q *querier) GetWorkspaceAgentsByResourceIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceAgent, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceAgentsByResourceIDs(ctx, ids) } func (q *querier) GetWorkspaceAgentsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceAgent, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceAgentsCreatedAfter(ctx, createdAt) @@ -2053,14 +2054,14 @@ func (q *querier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid.UU // GetWorkspaceAppsByAgentIDs // The workspace/job is already fetched. func (q *querier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceApp, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceAppsByAgentIDs(ctx, ids) } func (q *querier) GetWorkspaceAppsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceApp, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceAppsCreatedAfter(ctx, createdAt) @@ -2119,7 +2120,7 @@ func (q *querier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg datab // telemetry data. Never called by a user. func (q *querier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceBuild, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceBuildsCreatedAfter(ctx, createdAt) @@ -2148,7 +2149,7 @@ func (q *querier) GetWorkspaceProxies(ctx context.Context) ([]database.Workspace } func (q *querier) GetWorkspaceProxyByHostname(ctx context.Context, params database.GetWorkspaceProxyByHostnameParams) (database.WorkspaceProxy, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return database.WorkspaceProxy{}, err } return q.db.GetWorkspaceProxyByHostname(ctx, params) @@ -2180,14 +2181,14 @@ func (q *querier) GetWorkspaceResourceByID(ctx context.Context, id uuid.UUID) (d // GetWorkspaceResourceMetadataByResourceIDs is only used for build data. // The workspace/job is already fetched. func (q *querier) GetWorkspaceResourceMetadataByResourceIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceResourceMetadatum, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceResourceMetadataByResourceIDs(ctx, ids) } func (q *querier) GetWorkspaceResourceMetadataCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceResourceMetadatum, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceResourceMetadataCreatedAfter(ctx, createdAt) @@ -2232,7 +2233,7 @@ func (q *querier) GetWorkspaceResourcesByJobID(ctx context.Context, jobID uuid.U return nil, xerrors.Errorf("unknown job type: %s", job.Type) } - if err := q.authorizeContext(ctx, rbac.ActionRead, obj); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, obj); err != nil { return nil, err } return q.db.GetWorkspaceResourcesByJobID(ctx, jobID) @@ -2242,28 +2243,28 @@ func (q *querier) GetWorkspaceResourcesByJobID(ctx context.Context, jobID uuid.U // The workspace is already fetched. // TODO: Find a way to replace this with proper authz. func (q *querier) GetWorkspaceResourcesByJobIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceResource, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceResourcesByJobIDs(ctx, ids) } func (q *querier) GetWorkspaceResourcesCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.WorkspaceResource, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceResourcesCreatedAfter(ctx, createdAt) } func (q *querier) GetWorkspaceUniqueOwnerCountByTemplateIDs(ctx context.Context, templateIds []uuid.UUID) ([]database.GetWorkspaceUniqueOwnerCountByTemplateIDsRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { return nil, err } return q.db.GetWorkspaceUniqueOwnerCountByTemplateIDs(ctx, templateIds) } func (q *querier) GetWorkspaces(ctx context.Context, arg database.GetWorkspacesParams) ([]database.GetWorkspacesRow, error) { - prep, err := prepareSQLFilter(ctx, q.auth, rbac.ActionRead, rbac.ResourceWorkspace.Type) + prep, err := prepareSQLFilter(ctx, q.auth, policy.ActionRead, rbac.ResourceWorkspace.Type) if err != nil { return nil, xerrors.Errorf("(dev error) prepare sql filter: %w", err) } @@ -2290,21 +2291,21 @@ func (q *querier) InsertAuditLog(ctx context.Context, arg database.InsertAuditLo } func (q *querier) InsertDBCryptKey(ctx context.Context, arg database.InsertDBCryptKeyParams) error { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return err } return q.db.InsertDBCryptKey(ctx, arg) } func (q *querier) InsertDERPMeshKey(ctx context.Context, value string) error { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return err } return q.db.InsertDERPMeshKey(ctx, value) } func (q *querier) InsertDeploymentID(ctx context.Context, value string) error { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return err } return q.db.InsertDeploymentID(ctx, value) @@ -2334,28 +2335,28 @@ func (q *querier) InsertGroupMember(ctx context.Context, arg database.InsertGrou } func (q *querier) InsertLicense(ctx context.Context, arg database.InsertLicenseParams) (database.License, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceLicense); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceLicense); err != nil { return database.License{}, err } return q.db.InsertLicense(ctx, arg) } func (q *querier) InsertMissingGroups(ctx context.Context, arg database.InsertMissingGroupsParams) ([]database.Group, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return nil, err } return q.db.InsertMissingGroups(ctx, arg) } func (q *querier) InsertOAuth2ProviderApp(ctx context.Context, arg database.InsertOAuth2ProviderAppParams) (database.OAuth2ProviderApp, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceOAuth2ProviderApp); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceOAuth2ProviderApp); err != nil { return database.OAuth2ProviderApp{}, err } return q.db.InsertOAuth2ProviderApp(ctx, arg) } func (q *querier) InsertOAuth2ProviderAppCode(ctx context.Context, arg database.InsertOAuth2ProviderAppCodeParams) (database.OAuth2ProviderAppCode, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(arg.UserID.String())); err != nil { return database.OAuth2ProviderAppCode{}, err } @@ -2363,7 +2364,7 @@ func (q *querier) InsertOAuth2ProviderAppCode(ctx context.Context, arg database. } func (q *querier) InsertOAuth2ProviderAppSecret(ctx context.Context, arg database.InsertOAuth2ProviderAppSecretParams) (database.OAuth2ProviderAppSecret, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceOAuth2ProviderAppSecret); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceOAuth2ProviderAppSecret); err != nil { return database.OAuth2ProviderAppSecret{}, err } return q.db.InsertOAuth2ProviderAppSecret(ctx, arg) @@ -2374,7 +2375,7 @@ func (q *querier) InsertOAuth2ProviderAppToken(ctx context.Context, arg database if err != nil { return database.OAuth2ProviderAppToken{}, err } - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(key.UserID.String())); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(key.UserID.String())); err != nil { return database.OAuth2ProviderAppToken{}, err } return q.db.InsertOAuth2ProviderAppToken(ctx, arg) @@ -2398,7 +2399,7 @@ func (q *querier) InsertOrganizationMember(ctx context.Context, arg database.Ins // TODO: We need to create a ProvisionerJob resource type func (q *querier) InsertProvisionerJob(ctx context.Context, arg database.InsertProvisionerJobParams) (database.ProvisionerJob, error) { - // if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + // if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { // return database.ProvisionerJob{}, err // } return q.db.InsertProvisionerJob(ctx, arg) @@ -2406,14 +2407,14 @@ func (q *querier) InsertProvisionerJob(ctx context.Context, arg database.InsertP // TODO: We need to create a ProvisionerJob resource type func (q *querier) InsertProvisionerJobLogs(ctx context.Context, arg database.InsertProvisionerJobLogsParams) ([]database.ProvisionerJobLog, error) { - // if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + // if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { // return nil, err // } return q.db.InsertProvisionerJobLogs(ctx, arg) } func (q *querier) InsertReplica(ctx context.Context, arg database.InsertReplicaParams) (database.Replica, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return database.Replica{}, err } return q.db.InsertReplica(ctx, arg) @@ -2421,7 +2422,7 @@ func (q *querier) InsertReplica(ctx context.Context, arg database.InsertReplicaP func (q *querier) InsertTemplate(ctx context.Context, arg database.InsertTemplateParams) error { obj := rbac.ResourceTemplate.InOrg(arg.OrganizationID) - if err := q.authorizeContext(ctx, rbac.ActionCreate, obj); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, obj); err != nil { return err } return q.db.InsertTemplate(ctx, arg) @@ -2430,7 +2431,7 @@ func (q *querier) InsertTemplate(ctx context.Context, arg database.InsertTemplat func (q *querier) InsertTemplateVersion(ctx context.Context, arg database.InsertTemplateVersionParams) error { if !arg.TemplateID.Valid { // Making a new template version is the same permission as creating a new template. - err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceTemplate.InOrg(arg.OrganizationID)) + err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceTemplate.InOrg(arg.OrganizationID)) if err != nil { return err } @@ -2441,7 +2442,7 @@ func (q *querier) InsertTemplateVersion(ctx context.Context, arg database.Insert return err } // Check the create permission on the template. - err = q.authorizeContext(ctx, rbac.ActionCreate, tpl) + err = q.authorizeContext(ctx, policy.ActionCreate, tpl) if err != nil { return err } @@ -2451,14 +2452,14 @@ func (q *querier) InsertTemplateVersion(ctx context.Context, arg database.Insert } func (q *querier) InsertTemplateVersionParameter(ctx context.Context, arg database.InsertTemplateVersionParameterParams) (database.TemplateVersionParameter, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return database.TemplateVersionParameter{}, err } return q.db.InsertTemplateVersionParameter(ctx, arg) } func (q *querier) InsertTemplateVersionVariable(ctx context.Context, arg database.InsertTemplateVersionVariableParams) (database.TemplateVersionVariable, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return database.TemplateVersionVariable{}, err } return q.db.InsertTemplateVersionVariable(ctx, arg) @@ -2487,7 +2488,7 @@ func (q *querier) InsertUserGroupsByName(ctx context.Context, arg database.Inser // TODO: Should this be in system.go? func (q *querier) InsertUserLink(ctx context.Context, arg database.InsertUserLinkParams) (database.UserLink, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceUserObject(arg.UserID)); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceUserObject(arg.UserID)); err != nil { return database.UserLink{}, err } return q.db.InsertUserLink(ctx, arg) @@ -2499,7 +2500,7 @@ func (q *querier) InsertWorkspace(ctx context.Context, arg database.InsertWorksp } func (q *querier) InsertWorkspaceAgent(ctx context.Context, arg database.InsertWorkspaceAgentParams) (database.WorkspaceAgent, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return database.WorkspaceAgent{}, err } return q.db.InsertWorkspaceAgent(ctx, arg) @@ -2518,7 +2519,7 @@ func (q *querier) InsertWorkspaceAgentLogs(ctx context.Context, arg database.Ins func (q *querier) InsertWorkspaceAgentMetadata(ctx context.Context, arg database.InsertWorkspaceAgentMetadataParams) error { // We don't check for workspace ownership here since the agent metadata may // be associated with an orphaned agent used by a dry run build. - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return err } @@ -2526,14 +2527,14 @@ func (q *querier) InsertWorkspaceAgentMetadata(ctx context.Context, arg database } func (q *querier) InsertWorkspaceAgentScripts(ctx context.Context, arg database.InsertWorkspaceAgentScriptsParams) ([]database.WorkspaceAgentScript, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return []database.WorkspaceAgentScript{}, err } return q.db.InsertWorkspaceAgentScripts(ctx, arg) } func (q *querier) InsertWorkspaceAgentStats(ctx context.Context, arg database.InsertWorkspaceAgentStatsParams) error { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return err } @@ -2541,14 +2542,14 @@ func (q *querier) InsertWorkspaceAgentStats(ctx context.Context, arg database.In } func (q *querier) InsertWorkspaceApp(ctx context.Context, arg database.InsertWorkspaceAppParams) (database.WorkspaceApp, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return database.WorkspaceApp{}, err } return q.db.InsertWorkspaceApp(ctx, arg) } func (q *querier) InsertWorkspaceAppStats(ctx context.Context, arg database.InsertWorkspaceAppStatsParams) error { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return err } return q.db.InsertWorkspaceAppStats(ctx, arg) @@ -2560,9 +2561,9 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW return xerrors.Errorf("get workspace by id: %w", err) } - var action rbac.Action = rbac.ActionUpdate + var action policy.Action = policy.ActionUpdate if arg.Transition == database.WorkspaceTransitionDelete { - action = rbac.ActionDelete + action = policy.ActionDelete } if err = q.authorizeContext(ctx, action, w.WorkspaceBuildRBAC(arg.Transition)); err != nil { @@ -2583,7 +2584,7 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW // to use a non-active version then we must fail the request. if accessControl.RequireActiveVersion { if arg.TemplateVersionID != t.ActiveVersionID { - if err = q.authorizeContext(ctx, rbac.ActionUpdate, t); err != nil { + if err = q.authorizeContext(ctx, policy.ActionUpdate, t); err != nil { return xerrors.Errorf("cannot use non-active version: %w", err) } } @@ -2605,7 +2606,7 @@ func (q *querier) InsertWorkspaceBuildParameters(ctx context.Context, arg databa return err } - err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace) + err = q.authorizeContext(ctx, policy.ActionUpdate, workspace) if err != nil { return err } @@ -2618,14 +2619,14 @@ func (q *querier) InsertWorkspaceProxy(ctx context.Context, arg database.InsertW } func (q *querier) InsertWorkspaceResource(ctx context.Context, arg database.InsertWorkspaceResourceParams) (database.WorkspaceResource, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return database.WorkspaceResource{}, err } return q.db.InsertWorkspaceResource(ctx, arg) } func (q *querier) InsertWorkspaceResourceMetadata(ctx context.Context, arg database.InsertWorkspaceResourceMetadataParams) ([]database.WorkspaceResourceMetadatum, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return nil, err } return q.db.InsertWorkspaceResourceMetadata(ctx, arg) @@ -2638,7 +2639,7 @@ func (q *querier) ListWorkspaceAgentPortShares(ctx context.Context, workspaceID } // listing port shares is more akin to reading the workspace. - if err := q.authorizeContext(ctx, rbac.ActionRead, workspace); err != nil { + if err := q.authorizeContext(ctx, policy.ActionRead, workspace); err != nil { return nil, err } @@ -2651,7 +2652,7 @@ func (q *querier) ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate(ctx co return err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return err } @@ -2667,14 +2668,14 @@ func (q *querier) RegisterWorkspaceProxy(ctx context.Context, arg database.Regis func (q *querier) RemoveUserFromAllGroups(ctx context.Context, userID uuid.UUID) error { // This is a system function to clear user groups in group sync. - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return err } return q.db.RemoveUserFromAllGroups(ctx, userID) } func (q *querier) RevokeDBCryptKey(ctx context.Context, activeKeyDigest string) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return err } return q.db.RevokeDBCryptKey(ctx, activeKeyDigest) @@ -2694,7 +2695,7 @@ func (q *querier) UnarchiveTemplateVersion(ctx context.Context, arg database.Una if err != nil { return err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, tpl); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, tpl); err != nil { return err } return q.db.UnarchiveTemplateVersion(ctx, arg) @@ -2736,7 +2737,7 @@ func (q *querier) UpdateGroupByID(ctx context.Context, arg database.UpdateGroupB } func (q *querier) UpdateInactiveUsersToDormant(ctx context.Context, lastSeenAfter database.UpdateInactiveUsersToDormantParams) ([]database.UpdateInactiveUsersToDormantRow, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { return nil, err } return q.db.UpdateInactiveUsersToDormant(ctx, lastSeenAfter) @@ -2764,21 +2765,21 @@ func (q *querier) UpdateMemberRoles(ctx context.Context, arg database.UpdateMemb } func (q *querier) UpdateOAuth2ProviderAppByID(ctx context.Context, arg database.UpdateOAuth2ProviderAppByIDParams) (database.OAuth2ProviderApp, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceOAuth2ProviderApp); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceOAuth2ProviderApp); err != nil { return database.OAuth2ProviderApp{}, err } return q.db.UpdateOAuth2ProviderAppByID(ctx, arg) } func (q *querier) UpdateOAuth2ProviderAppSecretByID(ctx context.Context, arg database.UpdateOAuth2ProviderAppSecretByIDParams) (database.OAuth2ProviderAppSecret, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceOAuth2ProviderAppSecret); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceOAuth2ProviderAppSecret); err != nil { return database.OAuth2ProviderAppSecret{}, err } return q.db.UpdateOAuth2ProviderAppSecretByID(ctx, arg) } func (q *querier) UpdateProvisionerDaemonLastSeenAt(ctx context.Context, arg database.UpdateProvisionerDaemonLastSeenAtParams) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceProvisionerDaemon); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceProvisionerDaemon); err != nil { return err } return q.db.UpdateProvisionerDaemonLastSeenAt(ctx, arg) @@ -2786,7 +2787,7 @@ func (q *querier) UpdateProvisionerDaemonLastSeenAt(ctx context.Context, arg dat // TODO: We need to create a ProvisionerJob resource type func (q *querier) UpdateProvisionerJobByID(ctx context.Context, arg database.UpdateProvisionerJobByIDParams) error { - // if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + // if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { // return err // } return q.db.UpdateProvisionerJobByID(ctx, arg) @@ -2827,7 +2828,7 @@ func (q *querier) UpdateProvisionerJobWithCancelByID(ctx context.Context, arg da } } - err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace) + err = q.authorizeContext(ctx, policy.ActionUpdate, workspace) if err != nil { return err } @@ -2843,12 +2844,12 @@ func (q *querier) UpdateProvisionerJobWithCancelByID(ctx context.Context, arg da if err != nil { return err } - err = q.authorizeContext(ctx, rbac.ActionUpdate, templateVersion.RBACObject(template)) + err = q.authorizeContext(ctx, policy.ActionUpdate, templateVersion.RBACObject(template)) if err != nil { return err } } else { - err = q.authorizeContext(ctx, rbac.ActionUpdate, templateVersion.RBACObjectNoTemplate()) + err = q.authorizeContext(ctx, policy.ActionUpdate, templateVersion.RBACObjectNoTemplate()) if err != nil { return err } @@ -2861,14 +2862,14 @@ func (q *querier) UpdateProvisionerJobWithCancelByID(ctx context.Context, arg da // TODO: We need to create a ProvisionerJob resource type func (q *querier) UpdateProvisionerJobWithCompleteByID(ctx context.Context, arg database.UpdateProvisionerJobWithCompleteByIDParams) error { - // if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + // if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { // return err // } return q.db.UpdateProvisionerJobWithCompleteByID(ctx, arg) } func (q *querier) UpdateReplica(ctx context.Context, arg database.UpdateReplicaParams) (database.Replica, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return database.Replica{}, err } return q.db.UpdateReplica(ctx, arg) @@ -2880,7 +2881,7 @@ func (q *querier) UpdateTemplateACLByID(ctx context.Context, arg database.Update } // UpdateTemplateACL uses the ActionCreate action. Only users that can create the template // may update the ACL. - return fetchAndExec(q.log, q.auth, rbac.ActionCreate, fetch, q.db.UpdateTemplateACLByID)(ctx, arg) + return fetchAndExec(q.log, q.auth, policy.ActionCreate, fetch, q.db.UpdateTemplateACLByID)(ctx, arg) } func (q *querier) UpdateTemplateAccessControlByID(ctx context.Context, arg database.UpdateTemplateAccessControlByIDParams) error { @@ -2932,7 +2933,7 @@ func (q *querier) UpdateTemplateVersionByID(ctx context.Context, arg database.Up } obj = tpl } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, obj); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, obj); err != nil { return err } return q.db.UpdateTemplateVersionByID(ctx, arg) @@ -2954,7 +2955,7 @@ func (q *querier) UpdateTemplateVersionDescriptionByJobID(ctx context.Context, a } obj = tpl } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, obj); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, obj); err != nil { return err } return q.db.UpdateTemplateVersionDescriptionByJobID(ctx, arg) @@ -2976,7 +2977,7 @@ func (q *querier) UpdateTemplateVersionExternalAuthProvidersByJobID(ctx context. } obj = tpl } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, obj); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, obj); err != nil { return err } return q.db.UpdateTemplateVersionExternalAuthProvidersByJobID(ctx, arg) @@ -2987,7 +2988,7 @@ func (q *querier) UpdateTemplateWorkspacesLastUsedAt(ctx context.Context, arg da return q.db.GetTemplateByID(ctx, arg.TemplateID) } - return fetchAndExec(q.log, q.auth, rbac.ActionUpdate, fetch, q.db.UpdateTemplateWorkspacesLastUsedAt)(ctx, arg) + return fetchAndExec(q.log, q.auth, policy.ActionUpdate, fetch, q.db.UpdateTemplateWorkspacesLastUsedAt)(ctx, arg) } func (q *querier) UpdateUserAppearanceSettings(ctx context.Context, arg database.UpdateUserAppearanceSettingsParams) (database.User, error) { @@ -2995,7 +2996,7 @@ func (q *querier) UpdateUserAppearanceSettings(ctx context.Context, arg database if err != nil { return database.User{}, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, u.UserDataRBACObject()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, u.UserDataRBACObject()); err != nil { return database.User{}, err } return q.db.UpdateUserAppearanceSettings(ctx, arg) @@ -3011,10 +3012,10 @@ func (q *querier) UpdateUserHashedPassword(ctx context.Context, arg database.Upd return err } - err = q.authorizeContext(ctx, rbac.ActionUpdate, user.UserDataRBACObject()) + err = q.authorizeContext(ctx, policy.ActionUpdate, user.UserDataRBACObject()) if err != nil { // Admins can update passwords for other users. - err = q.authorizeContext(ctx, rbac.ActionUpdate, user.RBACObject()) + err = q.authorizeContext(ctx, policy.ActionUpdate, user.RBACObject()) if err != nil { return err } @@ -3041,14 +3042,14 @@ func (q *querier) UpdateUserLink(ctx context.Context, arg database.UpdateUserLin } func (q *querier) UpdateUserLinkedID(ctx context.Context, arg database.UpdateUserLinkedIDParams) (database.UserLink, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return database.UserLink{}, err } return q.db.UpdateUserLinkedID(ctx, arg) } func (q *querier) UpdateUserLoginType(ctx context.Context, arg database.UpdateUserLoginTypeParams) (database.User, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return database.User{}, err } return q.db.UpdateUserLoginType(ctx, arg) @@ -3059,7 +3060,7 @@ func (q *querier) UpdateUserProfile(ctx context.Context, arg database.UpdateUser if err != nil { return database.User{}, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, u.UserDataRBACObject()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, u.UserDataRBACObject()); err != nil { return database.User{}, err } return q.db.UpdateUserProfile(ctx, arg) @@ -3070,7 +3071,7 @@ func (q *querier) UpdateUserQuietHoursSchedule(ctx context.Context, arg database if err != nil { return database.User{}, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, u.UserDataRBACObject()); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, u.UserDataRBACObject()); err != nil { return database.User{}, err } return q.db.UpdateUserQuietHoursSchedule(ctx, arg) @@ -3114,7 +3115,7 @@ func (q *querier) UpdateWorkspace(ctx context.Context, arg database.UpdateWorksp } func (q *querier) UpdateWorkspaceAgentConnectionByID(ctx context.Context, arg database.UpdateWorkspaceAgentConnectionByIDParams) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return err } return q.db.UpdateWorkspaceAgentConnectionByID(ctx, arg) @@ -3126,7 +3127,7 @@ func (q *querier) UpdateWorkspaceAgentLifecycleStateByID(ctx context.Context, ar return err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, workspace); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, workspace); err != nil { return err } @@ -3144,7 +3145,7 @@ func (q *querier) UpdateWorkspaceAgentLogOverflowByID(ctx context.Context, arg d return err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, workspace); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, workspace); err != nil { return err } @@ -3157,7 +3158,7 @@ func (q *querier) UpdateWorkspaceAgentMetadata(ctx context.Context, arg database return err } - err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace) + err = q.authorizeContext(ctx, policy.ActionUpdate, workspace) if err != nil { return err } @@ -3176,7 +3177,7 @@ func (q *querier) UpdateWorkspaceAgentStartupByID(ctx context.Context, arg datab return err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, workspace); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, workspace); err != nil { return err } @@ -3190,7 +3191,7 @@ func (q *querier) UpdateWorkspaceAppHealthByID(ctx context.Context, arg database return err } - err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace.RBACObject()) + err = q.authorizeContext(ctx, policy.ActionUpdate, workspace.RBACObject()) if err != nil { return err } @@ -3203,7 +3204,7 @@ func (q *querier) UpdateWorkspaceAutomaticUpdates(ctx context.Context, arg datab return err } - err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace.RBACObject()) + err = q.authorizeContext(ctx, policy.ActionUpdate, workspace.RBACObject()) if err != nil { return err } @@ -3219,7 +3220,7 @@ func (q *querier) UpdateWorkspaceAutostart(ctx context.Context, arg database.Upd // UpdateWorkspaceBuildCostByID is used by the provisioning system to update the cost of a workspace build. func (q *querier) UpdateWorkspaceBuildCostByID(ctx context.Context, arg database.UpdateWorkspaceBuildCostByIDParams) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return err } return q.db.UpdateWorkspaceBuildCostByID(ctx, arg) @@ -3236,7 +3237,7 @@ func (q *querier) UpdateWorkspaceBuildDeadlineByID(ctx context.Context, arg data return err } - err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace.RBACObject()) + err = q.authorizeContext(ctx, policy.ActionUpdate, workspace.RBACObject()) if err != nil { return err } @@ -3244,7 +3245,7 @@ func (q *querier) UpdateWorkspaceBuildDeadlineByID(ctx context.Context, arg data } func (q *querier) UpdateWorkspaceBuildProvisionerStateByID(ctx context.Context, arg database.UpdateWorkspaceBuildProvisionerStateByIDParams) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return err } return q.db.UpdateWorkspaceBuildProvisionerStateByID(ctx, arg) @@ -3300,7 +3301,7 @@ func (q *querier) UpdateWorkspacesDormantDeletingAtByTemplateID(ctx context.Cont return q.db.GetTemplateByID(ctx, arg.TemplateID) } - return fetchAndExec(q.log, q.auth, rbac.ActionUpdate, fetch, q.db.UpdateWorkspacesDormantDeletingAtByTemplateID)(ctx, arg) + return fetchAndExec(q.log, q.auth, policy.ActionUpdate, fetch, q.db.UpdateWorkspacesDormantDeletingAtByTemplateID)(ctx, arg) } func (q *querier) UpsertAppSecurityKey(ctx context.Context, data string) error { @@ -3309,21 +3310,21 @@ func (q *querier) UpsertAppSecurityKey(ctx context.Context, data string) error { } func (q *querier) UpsertApplicationName(ctx context.Context, value string) error { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceDeploymentValues); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceDeploymentValues); err != nil { return err } return q.db.UpsertApplicationName(ctx, value) } func (q *querier) UpsertDefaultProxy(ctx context.Context, arg database.UpsertDefaultProxyParams) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return err } return q.db.UpsertDefaultProxy(ctx, arg) } func (q *querier) UpsertHealthSettings(ctx context.Context, value string) error { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceDeploymentValues); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceDeploymentValues); err != nil { return err } return q.db.UpsertHealthSettings(ctx, value) @@ -3344,35 +3345,35 @@ func (q *querier) UpsertJFrogXrayScanByWorkspaceAndAgentID(ctx context.Context, // Only template admins should be able to write JFrog Xray scans to a workspace. // We don't want this to be a workspace-level permission because then users // could overwrite their own results. - if err := q.authorizeContext(ctx, rbac.ActionCreate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, template); err != nil { return err } return q.db.UpsertJFrogXrayScanByWorkspaceAndAgentID(ctx, arg) } func (q *querier) UpsertLastUpdateCheck(ctx context.Context, value string) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return err } return q.db.UpsertLastUpdateCheck(ctx, value) } func (q *querier) UpsertLogoURL(ctx context.Context, value string) error { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceDeploymentValues); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceDeploymentValues); err != nil { return err } return q.db.UpsertLogoURL(ctx, value) } func (q *querier) UpsertNotificationBanners(ctx context.Context, value string) error { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceDeploymentValues); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceDeploymentValues); err != nil { return err } return q.db.UpsertNotificationBanners(ctx, value) } func (q *querier) UpsertOAuthSigningKey(ctx context.Context, value string) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return err } return q.db.UpsertOAuthSigningKey(ctx, value) @@ -3383,56 +3384,56 @@ func (q *querier) UpsertProvisionerDaemon(ctx context.Context, arg database.Upse if arg.Tags[provisionersdk.TagScope] == provisionersdk.ScopeUser { res.Owner = arg.Tags[provisionersdk.TagOwner] } - if err := q.authorizeContext(ctx, rbac.ActionCreate, res); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, res); err != nil { return database.ProvisionerDaemon{}, err } return q.db.UpsertProvisionerDaemon(ctx, arg) } func (q *querier) UpsertTailnetAgent(ctx context.Context, arg database.UpsertTailnetAgentParams) (database.TailnetAgent, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { return database.TailnetAgent{}, err } return q.db.UpsertTailnetAgent(ctx, arg) } func (q *querier) UpsertTailnetClient(ctx context.Context, arg database.UpsertTailnetClientParams) (database.TailnetClient, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { return database.TailnetClient{}, err } return q.db.UpsertTailnetClient(ctx, arg) } func (q *querier) UpsertTailnetClientSubscription(ctx context.Context, arg database.UpsertTailnetClientSubscriptionParams) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { return err } return q.db.UpsertTailnetClientSubscription(ctx, arg) } func (q *querier) UpsertTailnetCoordinator(ctx context.Context, id uuid.UUID) (database.TailnetCoordinator, error) { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceTailnetCoordinator); err != nil { return database.TailnetCoordinator{}, err } return q.db.UpsertTailnetCoordinator(ctx, id) } func (q *querier) UpsertTailnetPeer(ctx context.Context, arg database.UpsertTailnetPeerParams) (database.TailnetPeer, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceTailnetCoordinator); err != nil { return database.TailnetPeer{}, err } return q.db.UpsertTailnetPeer(ctx, arg) } func (q *querier) UpsertTailnetTunnel(ctx context.Context, arg database.UpsertTailnetTunnelParams) (database.TailnetTunnel, error) { - if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceTailnetCoordinator); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceTailnetCoordinator); err != nil { return database.TailnetTunnel{}, err } return q.db.UpsertTailnetTunnel(ctx, arg) } func (q *querier) UpsertTemplateUsageStats(ctx context.Context) error { - if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { return err } return q.db.UpsertTemplateUsageStats(ctx) @@ -3444,7 +3445,7 @@ func (q *querier) UpsertWorkspaceAgentPortShare(ctx context.Context, arg databas return database.WorkspaceAgentPortShare{}, err } - err = q.authorizeContext(ctx, rbac.ActionUpdate, workspace) + err = q.authorizeContext(ctx, policy.ActionUpdate, workspace) if err != nil { return database.WorkspaceAgentPortShare{}, err } @@ -3463,7 +3464,7 @@ func (q *querier) GetTemplateGroupRoles(ctx context.Context, id uuid.UUID) ([]da if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return nil, err } return q.db.GetTemplateGroupRoles(ctx, id) @@ -3475,7 +3476,7 @@ func (q *querier) GetTemplateUserRoles(ctx context.Context, id uuid.UUID) ([]dat if err != nil { return nil, err } - if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil { + if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil { return nil, err } return q.db.GetTemplateUserRoles(ctx, id) diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index 48435a0141c64..92dbbb8e7bce1 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -13,6 +13,7 @@ import ( "golang.org/x/xerrors" "cdr.dev/slog" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/database" @@ -119,7 +120,7 @@ func TestNew(t *testing.T) { require.NoError(t, err, "must not error") require.Equal(t, exp, w, "must be equal") - rec.AssertActor(t, subj, rec.Pair(rbac.ActionRead, exp)) + rec.AssertActor(t, subj, rec.Pair(policy.ActionRead, exp)) require.NoError(t, rec.AllAsserted(), "should only be 1 rbac call") } @@ -167,11 +168,11 @@ func must[T any](value T, err error) T { func (s *MethodTestSuite) TestAPIKey() { s.Run("DeleteAPIKeyByID", s.Subtest(func(db database.Store, check *expects) { key, _ := dbgen.APIKey(s.T(), db, database.APIKey{}) - check.Args(key.ID).Asserts(key, rbac.ActionDelete).Returns() + check.Args(key.ID).Asserts(key, policy.ActionDelete).Returns() })) s.Run("GetAPIKeyByID", s.Subtest(func(db database.Store, check *expects) { key, _ := dbgen.APIKey(s.T(), db, database.APIKey{}) - check.Args(key.ID).Asserts(key, rbac.ActionRead).Returns(key) + check.Args(key.ID).Asserts(key, policy.ActionRead).Returns(key) })) s.Run("GetAPIKeyByName", s.Subtest(func(db database.Store, check *expects) { key, _ := dbgen.APIKey(s.T(), db, database.APIKey{ @@ -181,14 +182,14 @@ func (s *MethodTestSuite) TestAPIKey() { check.Args(database.GetAPIKeyByNameParams{ TokenName: key.TokenName, UserID: key.UserID, - }).Asserts(key, rbac.ActionRead).Returns(key) + }).Asserts(key, policy.ActionRead).Returns(key) })) s.Run("GetAPIKeysByLoginType", s.Subtest(func(db database.Store, check *expects) { a, _ := dbgen.APIKey(s.T(), db, database.APIKey{LoginType: database.LoginTypePassword}) b, _ := dbgen.APIKey(s.T(), db, database.APIKey{LoginType: database.LoginTypePassword}) _, _ = dbgen.APIKey(s.T(), db, database.APIKey{LoginType: database.LoginTypeGithub}) check.Args(database.LoginTypePassword). - Asserts(a, rbac.ActionRead, b, rbac.ActionRead). + Asserts(a, policy.ActionRead, b, policy.ActionRead). Returns(slice.New(a, b)) })) s.Run("GetAPIKeysByUserID", s.Subtest(func(db database.Store, check *expects) { @@ -200,7 +201,7 @@ func (s *MethodTestSuite) TestAPIKey() { _, _ = dbgen.APIKey(s.T(), db, database.APIKey{UserID: idC, LoginType: database.LoginTypeToken}) check.Args(database.GetAPIKeysByUserIDParams{LoginType: database.LoginTypeToken, UserID: idAB}). - Asserts(keyA, rbac.ActionRead, keyB, rbac.ActionRead). + Asserts(keyA, policy.ActionRead, keyB, policy.ActionRead). Returns(slice.New(keyA, keyB)) })) s.Run("GetAPIKeysLastUsedAfter", s.Subtest(func(db database.Store, check *expects) { @@ -208,7 +209,7 @@ func (s *MethodTestSuite) TestAPIKey() { b, _ := dbgen.APIKey(s.T(), db, database.APIKey{LastUsed: time.Now().Add(time.Hour)}) _, _ = dbgen.APIKey(s.T(), db, database.APIKey{LastUsed: time.Now().Add(-time.Hour)}) check.Args(time.Now()). - Asserts(a, rbac.ActionRead, b, rbac.ActionRead). + Asserts(a, policy.ActionRead, b, policy.ActionRead). Returns(slice.New(a, b)) })) s.Run("InsertAPIKey", s.Subtest(func(db database.Store, check *expects) { @@ -217,33 +218,33 @@ func (s *MethodTestSuite) TestAPIKey() { UserID: u.ID, LoginType: database.LoginTypePassword, Scope: database.APIKeyScopeAll, - }).Asserts(rbac.ResourceAPIKey.WithOwner(u.ID.String()), rbac.ActionCreate) + }).Asserts(rbac.ResourceAPIKey.WithOwner(u.ID.String()), policy.ActionCreate) })) s.Run("UpdateAPIKeyByID", s.Subtest(func(db database.Store, check *expects) { a, _ := dbgen.APIKey(s.T(), db, database.APIKey{}) check.Args(database.UpdateAPIKeyByIDParams{ ID: a.ID, - }).Asserts(a, rbac.ActionUpdate).Returns() + }).Asserts(a, policy.ActionUpdate).Returns() })) s.Run("DeleteApplicationConnectAPIKeysByUserID", s.Subtest(func(db database.Store, check *expects) { a, _ := dbgen.APIKey(s.T(), db, database.APIKey{ Scope: database.APIKeyScopeApplicationConnect, }) - check.Args(a.UserID).Asserts(rbac.ResourceAPIKey.WithOwner(a.UserID.String()), rbac.ActionDelete).Returns() + check.Args(a.UserID).Asserts(rbac.ResourceAPIKey.WithOwner(a.UserID.String()), policy.ActionDelete).Returns() })) s.Run("DeleteExternalAuthLink", s.Subtest(func(db database.Store, check *expects) { a := dbgen.ExternalAuthLink(s.T(), db, database.ExternalAuthLink{}) check.Args(database.DeleteExternalAuthLinkParams{ ProviderID: a.ProviderID, UserID: a.UserID, - }).Asserts(a, rbac.ActionDelete).Returns() + }).Asserts(a, policy.ActionDelete).Returns() })) s.Run("GetExternalAuthLinksByUserID", s.Subtest(func(db database.Store, check *expects) { a := dbgen.ExternalAuthLink(s.T(), db, database.ExternalAuthLink{}) b := dbgen.ExternalAuthLink(s.T(), db, database.ExternalAuthLink{ UserID: a.UserID, }) - check.Args(a.UserID).Asserts(a, rbac.ActionRead, b, rbac.ActionRead) + check.Args(a.UserID).Asserts(a, policy.ActionRead, b, policy.ActionRead) })) } @@ -252,14 +253,14 @@ func (s *MethodTestSuite) TestAuditLogs() { check.Args(database.InsertAuditLogParams{ ResourceType: database.ResourceTypeOrganization, Action: database.AuditActionCreate, - }).Asserts(rbac.ResourceAuditLog, rbac.ActionCreate) + }).Asserts(rbac.ResourceAuditLog, policy.ActionCreate) })) s.Run("GetAuditLogsOffset", s.Subtest(func(db database.Store, check *expects) { _ = dbgen.AuditLog(s.T(), db, database.AuditLog{}) _ = dbgen.AuditLog(s.T(), db, database.AuditLog{}) check.Args(database.GetAuditLogsOffsetParams{ Limit: 10, - }).Asserts(rbac.ResourceAuditLog, rbac.ActionRead) + }).Asserts(rbac.ResourceAuditLog, policy.ActionRead) })) } @@ -269,24 +270,24 @@ func (s *MethodTestSuite) TestFile() { check.Args(database.GetFileByHashAndCreatorParams{ Hash: f.Hash, CreatedBy: f.CreatedBy, - }).Asserts(f, rbac.ActionRead).Returns(f) + }).Asserts(f, policy.ActionRead).Returns(f) })) s.Run("GetFileByID", s.Subtest(func(db database.Store, check *expects) { f := dbgen.File(s.T(), db, database.File{}) - check.Args(f.ID).Asserts(f, rbac.ActionRead).Returns(f) + check.Args(f.ID).Asserts(f, policy.ActionRead).Returns(f) })) s.Run("InsertFile", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) check.Args(database.InsertFileParams{ CreatedBy: u.ID, - }).Asserts(rbac.ResourceFile.WithOwner(u.ID.String()), rbac.ActionCreate) + }).Asserts(rbac.ResourceFile.WithOwner(u.ID.String()), policy.ActionCreate) })) } func (s *MethodTestSuite) TestGroup() { s.Run("DeleteGroupByID", s.Subtest(func(db database.Store, check *expects) { g := dbgen.Group(s.T(), db, database.Group{}) - check.Args(g.ID).Asserts(g, rbac.ActionDelete).Returns() + check.Args(g.ID).Asserts(g, policy.ActionDelete).Returns() })) s.Run("DeleteGroupMemberFromGroup", s.Subtest(func(db database.Store, check *expects) { g := dbgen.Group(s.T(), db, database.Group{}) @@ -296,23 +297,23 @@ func (s *MethodTestSuite) TestGroup() { check.Args(database.DeleteGroupMemberFromGroupParams{ UserID: m.UserID, GroupID: g.ID, - }).Asserts(g, rbac.ActionUpdate).Returns() + }).Asserts(g, policy.ActionUpdate).Returns() })) s.Run("GetGroupByID", s.Subtest(func(db database.Store, check *expects) { g := dbgen.Group(s.T(), db, database.Group{}) - check.Args(g.ID).Asserts(g, rbac.ActionRead).Returns(g) + check.Args(g.ID).Asserts(g, policy.ActionRead).Returns(g) })) s.Run("GetGroupByOrgAndName", s.Subtest(func(db database.Store, check *expects) { g := dbgen.Group(s.T(), db, database.Group{}) check.Args(database.GetGroupByOrgAndNameParams{ OrganizationID: g.OrganizationID, Name: g.Name, - }).Asserts(g, rbac.ActionRead).Returns(g) + }).Asserts(g, policy.ActionRead).Returns(g) })) s.Run("GetGroupMembers", s.Subtest(func(db database.Store, check *expects) { g := dbgen.Group(s.T(), db, database.Group{}) _ = dbgen.GroupMember(s.T(), db, database.GroupMember{}) - check.Args(g.ID).Asserts(g, rbac.ActionRead) + check.Args(g.ID).Asserts(g, policy.ActionRead) })) s.Run("GetGroupsByOrganizationAndUserID", s.Subtest(func(db database.Store, check *expects) { g := dbgen.Group(s.T(), db, database.Group{}) @@ -320,25 +321,25 @@ func (s *MethodTestSuite) TestGroup() { check.Args(database.GetGroupsByOrganizationAndUserIDParams{ OrganizationID: g.OrganizationID, UserID: gm.UserID, - }).Asserts(g, rbac.ActionRead) + }).Asserts(g, policy.ActionRead) })) s.Run("InsertAllUsersGroup", s.Subtest(func(db database.Store, check *expects) { o := dbgen.Organization(s.T(), db, database.Organization{}) - check.Args(o.ID).Asserts(rbac.ResourceGroup.InOrg(o.ID), rbac.ActionCreate) + check.Args(o.ID).Asserts(rbac.ResourceGroup.InOrg(o.ID), policy.ActionCreate) })) s.Run("InsertGroup", s.Subtest(func(db database.Store, check *expects) { o := dbgen.Organization(s.T(), db, database.Organization{}) check.Args(database.InsertGroupParams{ OrganizationID: o.ID, Name: "test", - }).Asserts(rbac.ResourceGroup.InOrg(o.ID), rbac.ActionCreate) + }).Asserts(rbac.ResourceGroup.InOrg(o.ID), policy.ActionCreate) })) s.Run("InsertGroupMember", s.Subtest(func(db database.Store, check *expects) { g := dbgen.Group(s.T(), db, database.Group{}) check.Args(database.InsertGroupMemberParams{ UserID: uuid.New(), GroupID: g.ID, - }).Asserts(g, rbac.ActionUpdate).Returns() + }).Asserts(g, policy.ActionUpdate).Returns() })) s.Run("InsertUserGroupsByName", s.Subtest(func(db database.Store, check *expects) { o := dbgen.Organization(s.T(), db, database.Organization{}) @@ -350,7 +351,7 @@ func (s *MethodTestSuite) TestGroup() { OrganizationID: o.ID, UserID: u1.ID, GroupNames: slice.New(g1.Name, g2.Name), - }).Asserts(rbac.ResourceGroup.InOrg(o.ID), rbac.ActionUpdate).Returns() + }).Asserts(rbac.ResourceGroup.InOrg(o.ID), policy.ActionUpdate).Returns() })) s.Run("RemoveUserFromAllGroups", s.Subtest(func(db database.Store, check *expects) { o := dbgen.Organization(s.T(), db, database.Organization{}) @@ -359,13 +360,13 @@ func (s *MethodTestSuite) TestGroup() { g2 := dbgen.Group(s.T(), db, database.Group{OrganizationID: o.ID}) _ = dbgen.GroupMember(s.T(), db, database.GroupMember{GroupID: g1.ID, UserID: u1.ID}) _ = dbgen.GroupMember(s.T(), db, database.GroupMember{GroupID: g2.ID, UserID: u1.ID}) - check.Args(u1.ID).Asserts(rbac.ResourceSystem, rbac.ActionUpdate).Returns() + check.Args(u1.ID).Asserts(rbac.ResourceSystem, policy.ActionUpdate).Returns() })) s.Run("UpdateGroupByID", s.Subtest(func(db database.Store, check *expects) { g := dbgen.Group(s.T(), db, database.Group{}) check.Args(database.UpdateGroupByIDParams{ ID: g.ID, - }).Asserts(g, rbac.ActionUpdate) + }).Asserts(g, policy.ActionUpdate) })) } @@ -388,7 +389,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { TemplateID: tpl.ID, TemplateVersionID: uuid.Nil, JobStatus: database.NullProvisionerJobStatus{}, - }).Asserts(v.RBACObject(tpl), rbac.ActionUpdate) + }).Asserts(v.RBACObject(tpl), policy.ActionUpdate) })) s.Run("UnarchiveTemplateVersion", s.Subtest(func(db database.Store, check *expects) { j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ @@ -403,7 +404,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { check.Args(database.UnarchiveTemplateVersionParams{ UpdatedAt: dbtime.Now(), TemplateVersionID: v.ID, - }).Asserts(v.RBACObject(tpl), rbac.ActionUpdate) + }).Asserts(v.RBACObject(tpl), policy.ActionUpdate) })) s.Run("Build/GetProvisionerJobByID", s.Subtest(func(db database.Store, check *expects) { w := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -411,7 +412,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { Type: database.ProvisionerJobTypeWorkspaceBuild, }) _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{JobID: j.ID, WorkspaceID: w.ID}) - check.Args(j.ID).Asserts(w, rbac.ActionRead).Returns(j) + check.Args(j.ID).Asserts(w, policy.ActionRead).Returns(j) })) s.Run("TemplateVersion/GetProvisionerJobByID", s.Subtest(func(db database.Store, check *expects) { j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ @@ -422,7 +423,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, JobID: j.ID, }) - check.Args(j.ID).Asserts(v.RBACObject(tpl), rbac.ActionRead).Returns(j) + check.Args(j.ID).Asserts(v.RBACObject(tpl), policy.ActionRead).Returns(j) })) s.Run("TemplateVersionDryRun/GetProvisionerJobByID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -435,7 +436,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { TemplateVersionID uuid.UUID `json:"template_version_id"` }{TemplateVersionID: v.ID})), }) - check.Args(j.ID).Asserts(v.RBACObject(tpl), rbac.ActionRead).Returns(j) + check.Args(j.ID).Asserts(v.RBACObject(tpl), policy.ActionRead).Returns(j) })) s.Run("Build/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{AllowUserCancelWorkspaceJobs: true}) @@ -444,7 +445,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { Type: database.ProvisionerJobTypeWorkspaceBuild, }) _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{JobID: j.ID, WorkspaceID: w.ID}) - check.Args(database.UpdateProvisionerJobWithCancelByIDParams{ID: j.ID}).Asserts(w, rbac.ActionUpdate).Returns() + check.Args(database.UpdateProvisionerJobWithCancelByIDParams{ID: j.ID}).Asserts(w, policy.ActionUpdate).Returns() })) s.Run("BuildFalseCancel/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{AllowUserCancelWorkspaceJobs: false}) @@ -453,7 +454,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { Type: database.ProvisionerJobTypeWorkspaceBuild, }) _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{JobID: j.ID, WorkspaceID: w.ID}) - check.Args(database.UpdateProvisionerJobWithCancelByIDParams{ID: j.ID}).Asserts(w, rbac.ActionUpdate).Returns() + check.Args(database.UpdateProvisionerJobWithCancelByIDParams{ID: j.ID}).Asserts(w, policy.ActionUpdate).Returns() })) s.Run("TemplateVersion/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) { j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ @@ -465,7 +466,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { JobID: j.ID, }) check.Args(database.UpdateProvisionerJobWithCancelByIDParams{ID: j.ID}). - Asserts(v.RBACObject(tpl), []rbac.Action{rbac.ActionRead, rbac.ActionUpdate}).Returns() + Asserts(v.RBACObject(tpl), []policy.Action{policy.ActionRead, policy.ActionUpdate}).Returns() })) s.Run("TemplateVersionNoTemplate/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) { j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ @@ -476,7 +477,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { JobID: j.ID, }) check.Args(database.UpdateProvisionerJobWithCancelByIDParams{ID: j.ID}). - Asserts(v.RBACObjectNoTemplate(), []rbac.Action{rbac.ActionRead, rbac.ActionUpdate}).Returns() + Asserts(v.RBACObjectNoTemplate(), []policy.Action{policy.ActionRead, policy.ActionUpdate}).Returns() })) s.Run("TemplateVersionDryRun/UpdateProvisionerJobWithCancelByID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -490,7 +491,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { }{TemplateVersionID: v.ID})), }) check.Args(database.UpdateProvisionerJobWithCancelByIDParams{ID: j.ID}). - Asserts(v.RBACObject(tpl), []rbac.Action{rbac.ActionRead, rbac.ActionUpdate}).Returns() + Asserts(v.RBACObject(tpl), []policy.Action{policy.ActionRead, policy.ActionUpdate}).Returns() })) s.Run("GetProvisionerJobsByIDs", s.Subtest(func(db database.Store, check *expects) { a := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{}) @@ -505,7 +506,7 @@ func (s *MethodTestSuite) TestProvisionerJob() { _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{JobID: j.ID, WorkspaceID: w.ID}) check.Args(database.GetProvisionerLogsAfterIDParams{ JobID: j.ID, - }).Asserts(w, rbac.ActionRead).Returns([]database.ProvisionerJobLog{}) + }).Asserts(w, policy.ActionRead).Returns([]database.ProvisionerJobLog{}) })) } @@ -515,32 +516,32 @@ func (s *MethodTestSuite) TestLicense() { UUID: uuid.New(), }) require.NoError(s.T(), err) - check.Args().Asserts(l, rbac.ActionRead). + check.Args().Asserts(l, policy.ActionRead). Returns([]database.License{l}) })) s.Run("InsertLicense", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertLicenseParams{}). - Asserts(rbac.ResourceLicense, rbac.ActionCreate) + Asserts(rbac.ResourceLicense, policy.ActionCreate) })) s.Run("UpsertLogoURL", s.Subtest(func(db database.Store, check *expects) { - check.Args("value").Asserts(rbac.ResourceDeploymentValues, rbac.ActionCreate) + check.Args("value").Asserts(rbac.ResourceDeploymentValues, policy.ActionCreate) })) s.Run("UpsertNotificationBanners", s.Subtest(func(db database.Store, check *expects) { - check.Args("value").Asserts(rbac.ResourceDeploymentValues, rbac.ActionCreate) + check.Args("value").Asserts(rbac.ResourceDeploymentValues, policy.ActionCreate) })) s.Run("GetLicenseByID", s.Subtest(func(db database.Store, check *expects) { l, err := db.InsertLicense(context.Background(), database.InsertLicenseParams{ UUID: uuid.New(), }) require.NoError(s.T(), err) - check.Args(l.ID).Asserts(l, rbac.ActionRead).Returns(l) + check.Args(l.ID).Asserts(l, policy.ActionRead).Returns(l) })) s.Run("DeleteLicense", s.Subtest(func(db database.Store, check *expects) { l, err := db.InsertLicense(context.Background(), database.InsertLicenseParams{ UUID: uuid.New(), }) require.NoError(s.T(), err) - check.Args(l.ID).Asserts(l, rbac.ActionDelete) + check.Args(l.ID).Asserts(l, policy.ActionDelete) })) s.Run("GetDeploymentID", s.Subtest(func(db database.Store, check *expects) { check.Args().Asserts().Returns("") @@ -568,20 +569,20 @@ func (s *MethodTestSuite) TestOrganization() { o := dbgen.Organization(s.T(), db, database.Organization{}) a := dbgen.Group(s.T(), db, database.Group{OrganizationID: o.ID}) b := dbgen.Group(s.T(), db, database.Group{OrganizationID: o.ID}) - check.Args(o.ID).Asserts(a, rbac.ActionRead, b, rbac.ActionRead). + check.Args(o.ID).Asserts(a, policy.ActionRead, b, policy.ActionRead). Returns([]database.Group{a, b}) })) s.Run("GetOrganizationByID", s.Subtest(func(db database.Store, check *expects) { o := dbgen.Organization(s.T(), db, database.Organization{}) - check.Args(o.ID).Asserts(o, rbac.ActionRead).Returns(o) + check.Args(o.ID).Asserts(o, policy.ActionRead).Returns(o) })) s.Run("GetDefaultOrganization", s.Subtest(func(db database.Store, check *expects) { o, _ := db.GetDefaultOrganization(context.Background()) - check.Args().Asserts(o, rbac.ActionRead).Returns(o) + check.Args().Asserts(o, policy.ActionRead).Returns(o) })) s.Run("GetOrganizationByName", s.Subtest(func(db database.Store, check *expects) { o := dbgen.Organization(s.T(), db, database.Organization{}) - check.Args(o.Name).Asserts(o, rbac.ActionRead).Returns(o) + check.Args(o.Name).Asserts(o, policy.ActionRead).Returns(o) })) s.Run("GetOrganizationIDsByMemberIDs", s.Subtest(func(db database.Store, check *expects) { oa := dbgen.Organization(s.T(), db, database.Organization{}) @@ -589,26 +590,26 @@ func (s *MethodTestSuite) TestOrganization() { ma := dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{OrganizationID: oa.ID}) mb := dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{OrganizationID: ob.ID}) check.Args([]uuid.UUID{ma.UserID, mb.UserID}). - Asserts(rbac.ResourceUserObject(ma.UserID), rbac.ActionRead, rbac.ResourceUserObject(mb.UserID), rbac.ActionRead) + Asserts(rbac.ResourceUserObject(ma.UserID), policy.ActionRead, rbac.ResourceUserObject(mb.UserID), policy.ActionRead) })) s.Run("GetOrganizationMemberByUserID", s.Subtest(func(db database.Store, check *expects) { mem := dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{}) check.Args(database.GetOrganizationMemberByUserIDParams{ OrganizationID: mem.OrganizationID, UserID: mem.UserID, - }).Asserts(mem, rbac.ActionRead).Returns(mem) + }).Asserts(mem, policy.ActionRead).Returns(mem) })) s.Run("GetOrganizationMembershipsByUserID", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) a := dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{UserID: u.ID}) b := dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{UserID: u.ID}) - check.Args(u.ID).Asserts(a, rbac.ActionRead, b, rbac.ActionRead).Returns(slice.New(a, b)) + check.Args(u.ID).Asserts(a, policy.ActionRead, b, policy.ActionRead).Returns(slice.New(a, b)) })) s.Run("GetOrganizations", s.Subtest(func(db database.Store, check *expects) { def, _ := db.GetDefaultOrganization(context.Background()) a := dbgen.Organization(s.T(), db, database.Organization{}) b := dbgen.Organization(s.T(), db, database.Organization{}) - check.Args().Asserts(def, rbac.ActionRead, a, rbac.ActionRead, b, rbac.ActionRead).Returns(slice.New(def, a, b)) + check.Args().Asserts(def, policy.ActionRead, a, policy.ActionRead, b, policy.ActionRead).Returns(slice.New(def, a, b)) })) s.Run("GetOrganizationsByUserID", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) @@ -616,13 +617,13 @@ func (s *MethodTestSuite) TestOrganization() { _ = dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{UserID: u.ID, OrganizationID: a.ID}) b := dbgen.Organization(s.T(), db, database.Organization{}) _ = dbgen.OrganizationMember(s.T(), db, database.OrganizationMember{UserID: u.ID, OrganizationID: b.ID}) - check.Args(u.ID).Asserts(a, rbac.ActionRead, b, rbac.ActionRead).Returns(slice.New(a, b)) + check.Args(u.ID).Asserts(a, policy.ActionRead, b, policy.ActionRead).Returns(slice.New(a, b)) })) s.Run("InsertOrganization", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertOrganizationParams{ ID: uuid.New(), Name: "random", - }).Asserts(rbac.ResourceOrganization, rbac.ActionCreate) + }).Asserts(rbac.ResourceOrganization, policy.ActionCreate) })) s.Run("InsertOrganizationMember", s.Subtest(func(db database.Store, check *expects) { o := dbgen.Organization(s.T(), db, database.Organization{}) @@ -633,8 +634,8 @@ func (s *MethodTestSuite) TestOrganization() { UserID: u.ID, Roles: []string{rbac.RoleOrgAdmin(o.ID)}, }).Asserts( - rbac.ResourceRoleAssignment.InOrg(o.ID), rbac.ActionCreate, - rbac.ResourceOrganizationMember.InOrg(o.ID).WithID(u.ID), rbac.ActionCreate) + rbac.ResourceRoleAssignment.InOrg(o.ID), policy.ActionCreate, + rbac.ResourceOrganizationMember.InOrg(o.ID).WithID(u.ID), policy.ActionCreate) })) s.Run("UpdateMemberRoles", s.Subtest(func(db database.Store, check *expects) { o := dbgen.Organization(s.T(), db, database.Organization{}) @@ -652,9 +653,9 @@ func (s *MethodTestSuite) TestOrganization() { UserID: u.ID, OrgID: o.ID, }).Asserts( - mem, rbac.ActionRead, - rbac.ResourceRoleAssignment.InOrg(o.ID), rbac.ActionCreate, // org-mem - rbac.ResourceRoleAssignment.InOrg(o.ID), rbac.ActionDelete, // org-admin + mem, policy.ActionRead, + rbac.ResourceRoleAssignment.InOrg(o.ID), policy.ActionCreate, // org-mem + rbac.ResourceRoleAssignment.InOrg(o.ID), policy.ActionDelete, // org-admin ).Returns(out) })) } @@ -663,39 +664,39 @@ func (s *MethodTestSuite) TestWorkspaceProxy() { s.Run("InsertWorkspaceProxy", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertWorkspaceProxyParams{ ID: uuid.New(), - }).Asserts(rbac.ResourceWorkspaceProxy, rbac.ActionCreate) + }).Asserts(rbac.ResourceWorkspaceProxy, policy.ActionCreate) })) s.Run("RegisterWorkspaceProxy", s.Subtest(func(db database.Store, check *expects) { p, _ := dbgen.WorkspaceProxy(s.T(), db, database.WorkspaceProxy{}) check.Args(database.RegisterWorkspaceProxyParams{ ID: p.ID, - }).Asserts(p, rbac.ActionUpdate) + }).Asserts(p, policy.ActionUpdate) })) s.Run("GetWorkspaceProxyByID", s.Subtest(func(db database.Store, check *expects) { p, _ := dbgen.WorkspaceProxy(s.T(), db, database.WorkspaceProxy{}) - check.Args(p.ID).Asserts(p, rbac.ActionRead).Returns(p) + check.Args(p.ID).Asserts(p, policy.ActionRead).Returns(p) })) s.Run("GetWorkspaceProxyByName", s.Subtest(func(db database.Store, check *expects) { p, _ := dbgen.WorkspaceProxy(s.T(), db, database.WorkspaceProxy{}) - check.Args(p.Name).Asserts(p, rbac.ActionRead).Returns(p) + check.Args(p.Name).Asserts(p, policy.ActionRead).Returns(p) })) s.Run("UpdateWorkspaceProxyDeleted", s.Subtest(func(db database.Store, check *expects) { p, _ := dbgen.WorkspaceProxy(s.T(), db, database.WorkspaceProxy{}) check.Args(database.UpdateWorkspaceProxyDeletedParams{ ID: p.ID, Deleted: true, - }).Asserts(p, rbac.ActionDelete) + }).Asserts(p, policy.ActionDelete) })) s.Run("UpdateWorkspaceProxy", s.Subtest(func(db database.Store, check *expects) { p, _ := dbgen.WorkspaceProxy(s.T(), db, database.WorkspaceProxy{}) check.Args(database.UpdateWorkspaceProxyParams{ ID: p.ID, - }).Asserts(p, rbac.ActionUpdate) + }).Asserts(p, policy.ActionUpdate) })) s.Run("GetWorkspaceProxies", s.Subtest(func(db database.Store, check *expects) { p1, _ := dbgen.WorkspaceProxy(s.T(), db, database.WorkspaceProxy{}) p2, _ := dbgen.WorkspaceProxy(s.T(), db, database.WorkspaceProxy{}) - check.Args().Asserts(p1, rbac.ActionRead, p2, rbac.ActionRead).Returns(slice.New(p1, p2)) + check.Args().Asserts(p1, policy.ActionRead, p2, policy.ActionRead).Returns(slice.New(p1, p2)) })) } @@ -725,11 +726,11 @@ func (s *MethodTestSuite) TestTemplate() { Name: t1.Name, OrganizationID: o1.ID, TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, - }).Asserts(t1, rbac.ActionRead).Returns(b) + }).Asserts(t1, policy.ActionRead).Returns(b) })) s.Run("GetTemplateByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) - check.Args(t1.ID).Asserts(t1, rbac.ActionRead).Returns(t1) + check.Args(t1.ID).Asserts(t1, policy.ActionRead).Returns(t1) })) s.Run("GetTemplateByOrganizationAndName", s.Subtest(func(db database.Store, check *expects) { o1 := dbgen.Organization(s.T(), db, database.Organization{}) @@ -739,14 +740,14 @@ func (s *MethodTestSuite) TestTemplate() { check.Args(database.GetTemplateByOrganizationAndNameParams{ Name: t1.Name, OrganizationID: o1.ID, - }).Asserts(t1, rbac.ActionRead).Returns(t1) + }).Asserts(t1, policy.ActionRead).Returns(t1) })) s.Run("GetTemplateVersionByJobID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{ TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, }) - check.Args(tv.JobID).Asserts(t1, rbac.ActionRead).Returns(tv) + check.Args(tv.JobID).Asserts(t1, policy.ActionRead).Returns(tv) })) s.Run("GetTemplateVersionByTemplateIDAndName", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) @@ -756,14 +757,14 @@ func (s *MethodTestSuite) TestTemplate() { check.Args(database.GetTemplateVersionByTemplateIDAndNameParams{ Name: tv.Name, TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, - }).Asserts(t1, rbac.ActionRead).Returns(tv) + }).Asserts(t1, policy.ActionRead).Returns(tv) })) s.Run("GetTemplateVersionParameters", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{ TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, }) - check.Args(tv.ID).Asserts(t1, rbac.ActionRead).Returns([]database.TemplateVersionParameter{}) + check.Args(tv.ID).Asserts(t1, policy.ActionRead).Returns([]database.TemplateVersionParameter{}) })) s.Run("GetTemplateVersionVariables", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) @@ -773,22 +774,22 @@ func (s *MethodTestSuite) TestTemplate() { tvv1 := dbgen.TemplateVersionVariable(s.T(), db, database.TemplateVersionVariable{ TemplateVersionID: tv.ID, }) - check.Args(tv.ID).Asserts(t1, rbac.ActionRead).Returns([]database.TemplateVersionVariable{tvv1}) + check.Args(tv.ID).Asserts(t1, policy.ActionRead).Returns([]database.TemplateVersionVariable{tvv1}) })) s.Run("GetTemplateGroupRoles", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) - check.Args(t1.ID).Asserts(t1, rbac.ActionUpdate) + check.Args(t1.ID).Asserts(t1, policy.ActionUpdate) })) s.Run("GetTemplateUserRoles", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) - check.Args(t1.ID).Asserts(t1, rbac.ActionUpdate) + check.Args(t1.ID).Asserts(t1, policy.ActionUpdate) })) s.Run("GetTemplateVersionByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{ TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, }) - check.Args(tv.ID).Asserts(t1, rbac.ActionRead).Returns(tv) + check.Args(tv.ID).Asserts(t1, policy.ActionRead).Returns(tv) })) s.Run("GetTemplateVersionsByTemplateID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) @@ -800,7 +801,7 @@ func (s *MethodTestSuite) TestTemplate() { }) check.Args(database.GetTemplateVersionsByTemplateIDParams{ TemplateID: t1.ID, - }).Asserts(t1, rbac.ActionRead). + }).Asserts(t1, policy.ActionRead). Returns(slice.New(a, b)) })) s.Run("GetTemplateVersionsCreatedAfter", s.Subtest(func(db database.Store, check *expects) { @@ -814,7 +815,7 @@ func (s *MethodTestSuite) TestTemplate() { TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, CreatedAt: now.Add(-2 * time.Hour), }) - check.Args(now.Add(-time.Hour)).Asserts(rbac.ResourceTemplate.All(), rbac.ActionRead) + check.Args(now.Add(-time.Hour)).Asserts(rbac.ResourceTemplate.All(), policy.ActionRead) })) s.Run("GetTemplatesWithFilter", s.Subtest(func(db database.Store, check *expects) { a := dbgen.Template(s.T(), db, database.Template{}) @@ -835,48 +836,48 @@ func (s *MethodTestSuite) TestTemplate() { Provisioner: "echo", OrganizationID: orgID, MaxPortSharingLevel: database.AppSharingLevelOwner, - }).Asserts(rbac.ResourceTemplate.InOrg(orgID), rbac.ActionCreate) + }).Asserts(rbac.ResourceTemplate.InOrg(orgID), policy.ActionCreate) })) s.Run("InsertTemplateVersion", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) check.Args(database.InsertTemplateVersionParams{ TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, OrganizationID: t1.OrganizationID, - }).Asserts(t1, rbac.ActionRead, t1, rbac.ActionCreate) + }).Asserts(t1, policy.ActionRead, t1, policy.ActionCreate) })) s.Run("SoftDeleteTemplateByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) - check.Args(t1.ID).Asserts(t1, rbac.ActionDelete) + check.Args(t1.ID).Asserts(t1, policy.ActionDelete) })) s.Run("UpdateTemplateACLByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) check.Args(database.UpdateTemplateACLByIDParams{ ID: t1.ID, - }).Asserts(t1, rbac.ActionCreate) + }).Asserts(t1, policy.ActionCreate) })) s.Run("UpdateTemplateAccessControlByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) check.Args(database.UpdateTemplateAccessControlByIDParams{ ID: t1.ID, - }).Asserts(t1, rbac.ActionUpdate) + }).Asserts(t1, policy.ActionUpdate) })) s.Run("UpdateTemplateScheduleByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) check.Args(database.UpdateTemplateScheduleByIDParams{ ID: t1.ID, - }).Asserts(t1, rbac.ActionUpdate) + }).Asserts(t1, policy.ActionUpdate) })) s.Run("UpdateTemplateWorkspacesLastUsedAt", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) check.Args(database.UpdateTemplateWorkspacesLastUsedAtParams{ TemplateID: t1.ID, - }).Asserts(t1, rbac.ActionUpdate) + }).Asserts(t1, policy.ActionUpdate) })) s.Run("UpdateWorkspacesDormantDeletingAtByTemplateID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) check.Args(database.UpdateWorkspacesDormantDeletingAtByTemplateIDParams{ TemplateID: t1.ID, - }).Asserts(t1, rbac.ActionUpdate) + }).Asserts(t1, policy.ActionUpdate) })) s.Run("UpdateTemplateActiveVersionByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{ @@ -889,21 +890,21 @@ func (s *MethodTestSuite) TestTemplate() { check.Args(database.UpdateTemplateActiveVersionByIDParams{ ID: t1.ID, ActiveVersionID: tv.ID, - }).Asserts(t1, rbac.ActionUpdate).Returns() + }).Asserts(t1, policy.ActionUpdate).Returns() })) s.Run("UpdateTemplateDeletedByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) check.Args(database.UpdateTemplateDeletedByIDParams{ ID: t1.ID, Deleted: true, - }).Asserts(t1, rbac.ActionDelete).Returns() + }).Asserts(t1, policy.ActionDelete).Returns() })) s.Run("UpdateTemplateMetaByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) check.Args(database.UpdateTemplateMetaByIDParams{ ID: t1.ID, MaxPortSharingLevel: "owner", - }).Asserts(t1, rbac.ActionUpdate) + }).Asserts(t1, policy.ActionUpdate) })) s.Run("UpdateTemplateVersionByID", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) @@ -915,7 +916,7 @@ func (s *MethodTestSuite) TestTemplate() { TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, Name: tv.Name, UpdatedAt: tv.UpdatedAt, - }).Asserts(t1, rbac.ActionUpdate) + }).Asserts(t1, policy.ActionUpdate) })) s.Run("UpdateTemplateVersionDescriptionByJobID", s.Subtest(func(db database.Store, check *expects) { jobID := uuid.New() @@ -927,7 +928,7 @@ func (s *MethodTestSuite) TestTemplate() { check.Args(database.UpdateTemplateVersionDescriptionByJobIDParams{ JobID: jobID, Readme: "foo", - }).Asserts(t1, rbac.ActionUpdate).Returns() + }).Asserts(t1, policy.ActionUpdate).Returns() })) s.Run("UpdateTemplateVersionExternalAuthProvidersByJobID", s.Subtest(func(db database.Store, check *expects) { jobID := uuid.New() @@ -938,37 +939,37 @@ func (s *MethodTestSuite) TestTemplate() { }) check.Args(database.UpdateTemplateVersionExternalAuthProvidersByJobIDParams{ JobID: jobID, - }).Asserts(t1, rbac.ActionUpdate).Returns() + }).Asserts(t1, policy.ActionUpdate).Returns() })) s.Run("GetTemplateInsights", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetTemplateInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, rbac.ActionRead) + check.Args(database.GetTemplateInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, policy.ActionRead) })) s.Run("GetUserLatencyInsights", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetUserLatencyInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, rbac.ActionRead) + check.Args(database.GetUserLatencyInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, policy.ActionRead) })) s.Run("GetUserActivityInsights", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetUserActivityInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, rbac.ActionRead).Errors(sql.ErrNoRows) + check.Args(database.GetUserActivityInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, policy.ActionRead).Errors(sql.ErrNoRows) })) s.Run("GetTemplateParameterInsights", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetTemplateParameterInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, rbac.ActionRead) + check.Args(database.GetTemplateParameterInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, policy.ActionRead) })) s.Run("GetTemplateInsightsByInterval", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetTemplateInsightsByIntervalParams{}).Asserts(rbac.ResourceTemplateInsights, rbac.ActionRead) + check.Args(database.GetTemplateInsightsByIntervalParams{}).Asserts(rbac.ResourceTemplateInsights, policy.ActionRead) })) s.Run("GetTemplateInsightsByTemplate", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetTemplateInsightsByTemplateParams{}).Asserts(rbac.ResourceTemplateInsights, rbac.ActionRead) + check.Args(database.GetTemplateInsightsByTemplateParams{}).Asserts(rbac.ResourceTemplateInsights, policy.ActionRead) })) s.Run("GetTemplateAppInsights", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetTemplateAppInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, rbac.ActionRead) + check.Args(database.GetTemplateAppInsightsParams{}).Asserts(rbac.ResourceTemplateInsights, policy.ActionRead) })) s.Run("GetTemplateAppInsightsByTemplate", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetTemplateAppInsightsByTemplateParams{}).Asserts(rbac.ResourceTemplateInsights, rbac.ActionRead) + check.Args(database.GetTemplateAppInsightsByTemplateParams{}).Asserts(rbac.ResourceTemplateInsights, policy.ActionRead) })) s.Run("GetTemplateUsageStats", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetTemplateUsageStatsParams{}).Asserts(rbac.ResourceTemplateInsights, rbac.ActionRead).Errors(sql.ErrNoRows) + check.Args(database.GetTemplateUsageStatsParams{}).Asserts(rbac.ResourceTemplateInsights, policy.ActionRead).Errors(sql.ErrNoRows) })) s.Run("UpsertTemplateUsageStats", s.Subtest(func(db database.Store, check *expects) { - check.Asserts(rbac.ResourceSystem, rbac.ActionUpdate) + check.Asserts(rbac.ResourceSystem, policy.ActionUpdate) })) } @@ -981,32 +982,32 @@ func (s *MethodTestSuite) TestUser() { })) s.Run("DeleteAPIKeysByUserID", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) - check.Args(u.ID).Asserts(rbac.ResourceAPIKey.WithOwner(u.ID.String()), rbac.ActionDelete).Returns() + check.Args(u.ID).Asserts(rbac.ResourceAPIKey.WithOwner(u.ID.String()), policy.ActionDelete).Returns() })) s.Run("GetQuotaAllowanceForUser", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) - check.Args(u.ID).Asserts(u, rbac.ActionRead).Returns(int64(0)) + check.Args(u.ID).Asserts(u, policy.ActionRead).Returns(int64(0)) })) s.Run("GetQuotaConsumedForUser", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) - check.Args(u.ID).Asserts(u, rbac.ActionRead).Returns(int64(0)) + check.Args(u.ID).Asserts(u, policy.ActionRead).Returns(int64(0)) })) s.Run("GetUserByEmailOrUsername", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) check.Args(database.GetUserByEmailOrUsernameParams{ Username: u.Username, Email: u.Email, - }).Asserts(u, rbac.ActionRead).Returns(u) + }).Asserts(u, policy.ActionRead).Returns(u) })) s.Run("GetUserByID", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) - check.Args(u.ID).Asserts(u, rbac.ActionRead).Returns(u) + check.Args(u.ID).Asserts(u, policy.ActionRead).Returns(u) })) s.Run("GetUsersByIDs", s.Subtest(func(db database.Store, check *expects) { a := dbgen.User(s.T(), db, database.User{CreatedAt: dbtime.Now().Add(-time.Hour)}) b := dbgen.User(s.T(), db, database.User{CreatedAt: dbtime.Now()}) check.Args([]uuid.UUID{a.ID, b.ID}). - Asserts(a, rbac.ActionRead, b, rbac.ActionRead). + Asserts(a, policy.ActionRead, b, policy.ActionRead). Returns(slice.New(a, b)) })) s.Run("GetUsers", s.Subtest(func(db database.Store, check *expects) { @@ -1020,30 +1021,30 @@ func (s *MethodTestSuite) TestUser() { check.Args(database.InsertUserParams{ ID: uuid.New(), LoginType: database.LoginTypePassword, - }).Asserts(rbac.ResourceRoleAssignment, rbac.ActionCreate, rbac.ResourceUser, rbac.ActionCreate) + }).Asserts(rbac.ResourceRoleAssignment, policy.ActionCreate, rbac.ResourceUser, policy.ActionCreate) })) s.Run("InsertUserLink", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) check.Args(database.InsertUserLinkParams{ UserID: u.ID, LoginType: database.LoginTypeOIDC, - }).Asserts(u, rbac.ActionUpdate) + }).Asserts(u, policy.ActionUpdate) })) s.Run("UpdateUserDeletedByID", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) - check.Args(u.ID).Asserts(u, rbac.ActionDelete).Returns() + check.Args(u.ID).Asserts(u, policy.ActionDelete).Returns() })) s.Run("UpdateUserHashedPassword", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) check.Args(database.UpdateUserHashedPasswordParams{ ID: u.ID, - }).Asserts(u.UserDataRBACObject(), rbac.ActionUpdate).Returns() + }).Asserts(u.UserDataRBACObject(), policy.ActionUpdate).Returns() })) s.Run("UpdateUserQuietHoursSchedule", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) check.Args(database.UpdateUserQuietHoursScheduleParams{ ID: u.ID, - }).Asserts(u.UserDataRBACObject(), rbac.ActionUpdate) + }).Asserts(u.UserDataRBACObject(), policy.ActionUpdate) })) s.Run("UpdateUserLastSeenAt", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) @@ -1051,7 +1052,7 @@ func (s *MethodTestSuite) TestUser() { ID: u.ID, UpdatedAt: u.UpdatedAt, LastSeenAt: u.LastSeenAt, - }).Asserts(u, rbac.ActionUpdate).Returns(u) + }).Asserts(u, policy.ActionUpdate).Returns(u) })) s.Run("UpdateUserProfile", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) @@ -1060,7 +1061,7 @@ func (s *MethodTestSuite) TestUser() { Email: u.Email, Username: u.Username, UpdatedAt: u.UpdatedAt, - }).Asserts(u.UserDataRBACObject(), rbac.ActionUpdate).Returns(u) + }).Asserts(u.UserDataRBACObject(), policy.ActionUpdate).Returns(u) })) s.Run("GetUserWorkspaceBuildParameters", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) @@ -1069,7 +1070,7 @@ func (s *MethodTestSuite) TestUser() { OwnerID: u.ID, TemplateID: uuid.UUID{}, }, - ).Asserts(u.UserWorkspaceBuildParametersObject(), rbac.ActionRead).Returns( + ).Asserts(u.UserWorkspaceBuildParametersObject(), policy.ActionRead).Returns( []database.GetUserWorkspaceBuildParametersRow{}, ) })) @@ -1079,7 +1080,7 @@ func (s *MethodTestSuite) TestUser() { ID: u.ID, ThemePreference: u.ThemePreference, UpdatedAt: u.UpdatedAt, - }).Asserts(u.UserDataRBACObject(), rbac.ActionUpdate).Returns(u) + }).Asserts(u.UserDataRBACObject(), policy.ActionUpdate).Returns(u) })) s.Run("UpdateUserStatus", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) @@ -1087,42 +1088,42 @@ func (s *MethodTestSuite) TestUser() { ID: u.ID, Status: u.Status, UpdatedAt: u.UpdatedAt, - }).Asserts(u, rbac.ActionUpdate).Returns(u) + }).Asserts(u, policy.ActionUpdate).Returns(u) })) s.Run("DeleteGitSSHKey", s.Subtest(func(db database.Store, check *expects) { key := dbgen.GitSSHKey(s.T(), db, database.GitSSHKey{}) - check.Args(key.UserID).Asserts(key, rbac.ActionDelete).Returns() + check.Args(key.UserID).Asserts(key, policy.ActionDelete).Returns() })) s.Run("GetGitSSHKey", s.Subtest(func(db database.Store, check *expects) { key := dbgen.GitSSHKey(s.T(), db, database.GitSSHKey{}) - check.Args(key.UserID).Asserts(key, rbac.ActionRead).Returns(key) + check.Args(key.UserID).Asserts(key, policy.ActionRead).Returns(key) })) s.Run("InsertGitSSHKey", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) check.Args(database.InsertGitSSHKeyParams{ UserID: u.ID, - }).Asserts(rbac.ResourceUserData.WithID(u.ID).WithOwner(u.ID.String()), rbac.ActionCreate) + }).Asserts(rbac.ResourceUserData.WithID(u.ID).WithOwner(u.ID.String()), policy.ActionCreate) })) s.Run("UpdateGitSSHKey", s.Subtest(func(db database.Store, check *expects) { key := dbgen.GitSSHKey(s.T(), db, database.GitSSHKey{}) check.Args(database.UpdateGitSSHKeyParams{ UserID: key.UserID, UpdatedAt: key.UpdatedAt, - }).Asserts(key, rbac.ActionUpdate).Returns(key) + }).Asserts(key, policy.ActionUpdate).Returns(key) })) s.Run("GetExternalAuthLink", s.Subtest(func(db database.Store, check *expects) { link := dbgen.ExternalAuthLink(s.T(), db, database.ExternalAuthLink{}) check.Args(database.GetExternalAuthLinkParams{ ProviderID: link.ProviderID, UserID: link.UserID, - }).Asserts(link, rbac.ActionRead).Returns(link) + }).Asserts(link, policy.ActionRead).Returns(link) })) s.Run("InsertExternalAuthLink", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) check.Args(database.InsertExternalAuthLinkParams{ ProviderID: uuid.NewString(), UserID: u.ID, - }).Asserts(rbac.ResourceUserData.WithOwner(u.ID.String()).WithID(u.ID), rbac.ActionCreate) + }).Asserts(rbac.ResourceUserData.WithOwner(u.ID.String()).WithID(u.ID), policy.ActionCreate) })) s.Run("UpdateExternalAuthLink", s.Subtest(func(db database.Store, check *expects) { link := dbgen.ExternalAuthLink(s.T(), db, database.ExternalAuthLink{}) @@ -1133,7 +1134,7 @@ func (s *MethodTestSuite) TestUser() { OAuthRefreshToken: link.OAuthRefreshToken, OAuthExpiry: link.OAuthExpiry, UpdatedAt: link.UpdatedAt, - }).Asserts(link, rbac.ActionUpdate).Returns(link) + }).Asserts(link, policy.ActionUpdate).Returns(link) })) s.Run("UpdateUserLink", s.Subtest(func(db database.Store, check *expects) { link := dbgen.UserLink(s.T(), db, database.UserLink{}) @@ -1144,7 +1145,7 @@ func (s *MethodTestSuite) TestUser() { UserID: link.UserID, LoginType: link.LoginType, DebugContext: json.RawMessage("{}"), - }).Asserts(link, rbac.ActionUpdate).Returns(link) + }).Asserts(link, policy.ActionUpdate).Returns(link) })) s.Run("UpdateUserRoles", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{RBACRoles: []string{rbac.RoleTemplateAdmin()}}) @@ -1154,22 +1155,22 @@ func (s *MethodTestSuite) TestUser() { GrantedRoles: []string{rbac.RoleUserAdmin()}, ID: u.ID, }).Asserts( - u, rbac.ActionRead, - rbac.ResourceRoleAssignment, rbac.ActionCreate, - rbac.ResourceRoleAssignment, rbac.ActionDelete, + u, policy.ActionRead, + rbac.ResourceRoleAssignment, policy.ActionCreate, + rbac.ResourceRoleAssignment, policy.ActionDelete, ).Returns(o) })) s.Run("AllUserIDs", s.Subtest(func(db database.Store, check *expects) { a := dbgen.User(s.T(), db, database.User{}) b := dbgen.User(s.T(), db, database.User{}) - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionRead).Returns(slice.New(a.ID, b.ID)) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(slice.New(a.ID, b.ID)) })) } func (s *MethodTestSuite) TestWorkspace() { s.Run("GetWorkspaceByID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) - check.Args(ws.ID).Asserts(ws, rbac.ActionRead) + check.Args(ws.ID).Asserts(ws, policy.ActionRead) })) s.Run("GetWorkspaces", s.Subtest(func(db database.Store, check *expects) { _ = dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1186,7 +1187,7 @@ func (s *MethodTestSuite) TestWorkspace() { s.Run("GetLatestWorkspaceBuildByWorkspaceID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) - check.Args(ws.ID).Asserts(ws, rbac.ActionRead).Returns(b) + check.Args(ws.ID).Asserts(ws, policy.ActionRead).Returns(b) })) s.Run("GetWorkspaceAgentByID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1196,7 +1197,7 @@ func (s *MethodTestSuite) TestWorkspace() { build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) - check.Args(agt.ID).Asserts(ws, rbac.ActionRead).Returns(agt) + check.Args(agt.ID).Asserts(ws, policy.ActionRead).Returns(agt) })) s.Run("GetWorkspaceAgentLifecycleStateByID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1206,7 +1207,7 @@ func (s *MethodTestSuite) TestWorkspace() { build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) - check.Args(agt.ID).Asserts(ws, rbac.ActionRead) + check.Args(agt.ID).Asserts(ws, policy.ActionRead) })) s.Run("GetWorkspaceAgentMetadata", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1224,7 +1225,7 @@ func (s *MethodTestSuite) TestWorkspace() { check.Args(database.GetWorkspaceAgentMetadataParams{ WorkspaceAgentID: agt.ID, Keys: []string{"test"}, - }).Asserts(ws, rbac.ActionRead) + }).Asserts(ws, policy.ActionRead) })) s.Run("GetWorkspaceAgentByInstanceID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1234,7 +1235,7 @@ func (s *MethodTestSuite) TestWorkspace() { build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) - check.Args(agt.AuthInstanceID.String).Asserts(ws, rbac.ActionRead).Returns(agt) + check.Args(agt.AuthInstanceID.String).Asserts(ws, policy.ActionRead).Returns(agt) })) s.Run("UpdateWorkspaceAgentLifecycleStateByID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1247,7 +1248,7 @@ func (s *MethodTestSuite) TestWorkspace() { check.Args(database.UpdateWorkspaceAgentLifecycleStateByIDParams{ ID: agt.ID, LifecycleState: database.WorkspaceAgentLifecycleStateCreated, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("UpdateWorkspaceAgentMetadata", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1259,7 +1260,7 @@ func (s *MethodTestSuite) TestWorkspace() { agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) check.Args(database.UpdateWorkspaceAgentMetadataParams{ WorkspaceAgentID: agt.ID, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("UpdateWorkspaceAgentLogOverflowByID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1272,7 +1273,7 @@ func (s *MethodTestSuite) TestWorkspace() { check.Args(database.UpdateWorkspaceAgentLogOverflowByIDParams{ ID: agt.ID, LogsOverflowed: true, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("UpdateWorkspaceAgentStartupByID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1287,7 +1288,7 @@ func (s *MethodTestSuite) TestWorkspace() { Subsystems: []database.WorkspaceAgentSubsystem{ database.WorkspaceAgentSubsystemEnvbox, }, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("GetWorkspaceAgentLogsAfter", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1299,7 +1300,7 @@ func (s *MethodTestSuite) TestWorkspace() { agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) check.Args(database.GetWorkspaceAgentLogsAfterParams{ AgentID: agt.ID, - }).Asserts(ws, rbac.ActionRead).Returns([]database.WorkspaceAgentLog{}) + }).Asserts(ws, policy.ActionRead).Returns([]database.WorkspaceAgentLog{}) })) s.Run("GetWorkspaceAppByAgentIDAndSlug", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1314,7 +1315,7 @@ func (s *MethodTestSuite) TestWorkspace() { check.Args(database.GetWorkspaceAppByAgentIDAndSlugParams{ AgentID: agt.ID, Slug: app.Slug, - }).Asserts(ws, rbac.ActionRead).Returns(app) + }).Asserts(ws, policy.ActionRead).Returns(app) })) s.Run("GetWorkspaceAppsByAgentID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1327,17 +1328,17 @@ func (s *MethodTestSuite) TestWorkspace() { a := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: agt.ID}) b := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: agt.ID}) - check.Args(agt.ID).Asserts(ws, rbac.ActionRead).Returns(slice.New(a, b)) + check.Args(agt.ID).Asserts(ws, policy.ActionRead).Returns(slice.New(a, b)) })) s.Run("GetWorkspaceBuildByID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) - check.Args(build.ID).Asserts(ws, rbac.ActionRead).Returns(build) + check.Args(build.ID).Asserts(ws, policy.ActionRead).Returns(build) })) s.Run("GetWorkspaceBuildByJobID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) - check.Args(build.JobID).Asserts(ws, rbac.ActionRead).Returns(build) + check.Args(build.JobID).Asserts(ws, policy.ActionRead).Returns(build) })) s.Run("GetWorkspaceBuildByWorkspaceIDAndBuildNumber", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1345,12 +1346,12 @@ func (s *MethodTestSuite) TestWorkspace() { check.Args(database.GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams{ WorkspaceID: ws.ID, BuildNumber: build.BuildNumber, - }).Asserts(ws, rbac.ActionRead).Returns(build) + }).Asserts(ws, policy.ActionRead).Returns(build) })) s.Run("GetWorkspaceBuildParameters", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) - check.Args(build.ID).Asserts(ws, rbac.ActionRead). + check.Args(build.ID).Asserts(ws, policy.ActionRead). Returns([]database.WorkspaceBuildParameter{}) })) s.Run("GetWorkspaceBuildsByWorkspaceID", s.Subtest(func(db database.Store, check *expects) { @@ -1358,7 +1359,7 @@ func (s *MethodTestSuite) TestWorkspace() { _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 1}) _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 2}) _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, BuildNumber: 3}) - check.Args(database.GetWorkspaceBuildsByWorkspaceIDParams{WorkspaceID: ws.ID}).Asserts(ws, rbac.ActionRead) // ordering + check.Args(database.GetWorkspaceBuildsByWorkspaceIDParams{WorkspaceID: ws.ID}).Asserts(ws, policy.ActionRead) // ordering })) s.Run("GetWorkspaceByAgentID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -1368,7 +1369,7 @@ func (s *MethodTestSuite) TestWorkspace() { build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) - check.Args(agt.ID).Asserts(ws, rbac.ActionRead).Returns(database.GetWorkspaceByAgentIDRow{ + check.Args(agt.ID).Asserts(ws, policy.ActionRead).Returns(database.GetWorkspaceByAgentIDRow{ Workspace: ws, TemplateName: tpl.Name, }) @@ -1381,7 +1382,7 @@ func (s *MethodTestSuite) TestWorkspace() { build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) - check.Args(ws.ID).Asserts(ws, rbac.ActionRead) + check.Args(ws.ID).Asserts(ws, policy.ActionRead) })) s.Run("GetWorkspaceByOwnerIDAndName", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1389,26 +1390,26 @@ func (s *MethodTestSuite) TestWorkspace() { OwnerID: ws.OwnerID, Deleted: ws.Deleted, Name: ws.Name, - }).Asserts(ws, rbac.ActionRead).Returns(ws) + }).Asserts(ws, policy.ActionRead).Returns(ws) })) s.Run("GetWorkspaceResourceByID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) _ = dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild}) res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) - check.Args(res.ID).Asserts(ws, rbac.ActionRead).Returns(res) + check.Args(res.ID).Asserts(ws, policy.ActionRead).Returns(res) })) s.Run("Build/GetWorkspaceResourcesByJobID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild}) - check.Args(job.ID).Asserts(ws, rbac.ActionRead).Returns([]database.WorkspaceResource{}) + check.Args(job.ID).Asserts(ws, policy.ActionRead).Returns([]database.WorkspaceResource{}) })) s.Run("Template/GetWorkspaceResourcesByJobID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) v := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, JobID: uuid.New()}) job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: v.JobID, Type: database.ProvisionerJobTypeTemplateVersionImport}) - check.Args(job.ID).Asserts(v.RBACObject(tpl), []rbac.Action{rbac.ActionRead, rbac.ActionRead}).Returns([]database.WorkspaceResource{}) + check.Args(job.ID).Asserts(v.RBACObject(tpl), []policy.Action{policy.ActionRead, policy.ActionRead}).Returns([]database.WorkspaceResource{}) })) s.Run("InsertWorkspace", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) @@ -1418,7 +1419,7 @@ func (s *MethodTestSuite) TestWorkspace() { OwnerID: u.ID, OrganizationID: o.ID, AutomaticUpdates: database.AutomaticUpdatesNever, - }).Asserts(rbac.ResourceWorkspace.WithOwner(u.ID.String()).InOrg(o.ID), rbac.ActionCreate) + }).Asserts(rbac.ResourceWorkspace.WithOwner(u.ID.String()).InOrg(o.ID), policy.ActionCreate) })) s.Run("Start/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) { t := dbgen.Template(s.T(), db, database.Template{}) @@ -1429,7 +1430,7 @@ func (s *MethodTestSuite) TestWorkspace() { WorkspaceID: w.ID, Transition: database.WorkspaceTransitionStart, Reason: database.BuildReasonInitiator, - }).Asserts(w.WorkspaceBuildRBAC(database.WorkspaceTransitionStart), rbac.ActionUpdate) + }).Asserts(w.WorkspaceBuildRBAC(database.WorkspaceTransitionStart), policy.ActionUpdate) })) s.Run("Start/RequireActiveVersion/VersionMismatch/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) { t := dbgen.Template(s.T(), db, database.Template{}) @@ -1451,8 +1452,8 @@ func (s *MethodTestSuite) TestWorkspace() { Reason: database.BuildReasonInitiator, TemplateVersionID: v.ID, }).Asserts( - w.WorkspaceBuildRBAC(database.WorkspaceTransitionStart), rbac.ActionUpdate, - t, rbac.ActionUpdate, + w.WorkspaceBuildRBAC(database.WorkspaceTransitionStart), policy.ActionUpdate, + t, policy.ActionUpdate, ) })) s.Run("Start/RequireActiveVersion/VersionsMatch/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) { @@ -1479,7 +1480,7 @@ func (s *MethodTestSuite) TestWorkspace() { Reason: database.BuildReasonInitiator, TemplateVersionID: v.ID, }).Asserts( - w.WorkspaceBuildRBAC(database.WorkspaceTransitionStart), rbac.ActionUpdate, + w.WorkspaceBuildRBAC(database.WorkspaceTransitionStart), policy.ActionUpdate, ) })) s.Run("Delete/InsertWorkspaceBuild", s.Subtest(func(db database.Store, check *expects) { @@ -1488,7 +1489,7 @@ func (s *MethodTestSuite) TestWorkspace() { WorkspaceID: w.ID, Transition: database.WorkspaceTransitionDelete, Reason: database.BuildReasonInitiator, - }).Asserts(w.WorkspaceBuildRBAC(database.WorkspaceTransitionDelete), rbac.ActionDelete) + }).Asserts(w.WorkspaceBuildRBAC(database.WorkspaceTransitionDelete), policy.ActionDelete) })) s.Run("InsertWorkspaceBuildParameters", s.Subtest(func(db database.Store, check *expects) { w := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1497,7 +1498,7 @@ func (s *MethodTestSuite) TestWorkspace() { WorkspaceBuildID: b.ID, Name: []string{"foo", "bar"}, Value: []string{"baz", "qux"}, - }).Asserts(w, rbac.ActionUpdate) + }).Asserts(w, policy.ActionUpdate) })) s.Run("UpdateWorkspace", s.Subtest(func(db database.Store, check *expects) { w := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1505,20 +1506,20 @@ func (s *MethodTestSuite) TestWorkspace() { expected.Name = "" check.Args(database.UpdateWorkspaceParams{ ID: w.ID, - }).Asserts(w, rbac.ActionUpdate).Returns(expected) + }).Asserts(w, policy.ActionUpdate).Returns(expected) })) s.Run("UpdateWorkspaceDormantDeletingAt", s.Subtest(func(db database.Store, check *expects) { w := dbgen.Workspace(s.T(), db, database.Workspace{}) check.Args(database.UpdateWorkspaceDormantDeletingAtParams{ ID: w.ID, - }).Asserts(w, rbac.ActionUpdate) + }).Asserts(w, policy.ActionUpdate) })) s.Run("UpdateWorkspaceAutomaticUpdates", s.Subtest(func(db database.Store, check *expects) { w := dbgen.Workspace(s.T(), db, database.Workspace{}) check.Args(database.UpdateWorkspaceAutomaticUpdatesParams{ ID: w.ID, AutomaticUpdates: database.AutomaticUpdatesAlways, - }).Asserts(w, rbac.ActionUpdate) + }).Asserts(w, policy.ActionUpdate) })) s.Run("UpdateWorkspaceAppHealthByID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1529,13 +1530,13 @@ func (s *MethodTestSuite) TestWorkspace() { check.Args(database.UpdateWorkspaceAppHealthByIDParams{ ID: app.ID, Health: database.WorkspaceAppHealthDisabled, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("UpdateWorkspaceAutostart", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) check.Args(database.UpdateWorkspaceAutostartParams{ ID: ws.ID, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("UpdateWorkspaceBuildDeadlineByID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1544,38 +1545,38 @@ func (s *MethodTestSuite) TestWorkspace() { ID: build.ID, UpdatedAt: build.UpdatedAt, Deadline: build.Deadline, - }).Asserts(ws, rbac.ActionUpdate) + }).Asserts(ws, policy.ActionUpdate) })) s.Run("SoftDeleteWorkspaceByID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) ws.Deleted = true - check.Args(ws.ID).Asserts(ws, rbac.ActionDelete).Returns() + check.Args(ws.ID).Asserts(ws, policy.ActionDelete).Returns() })) s.Run("UpdateWorkspaceDeletedByID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{Deleted: true}) check.Args(database.UpdateWorkspaceDeletedByIDParams{ ID: ws.ID, Deleted: true, - }).Asserts(ws, rbac.ActionDelete).Returns() + }).Asserts(ws, policy.ActionDelete).Returns() })) s.Run("UpdateWorkspaceLastUsedAt", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) check.Args(database.UpdateWorkspaceLastUsedAtParams{ ID: ws.ID, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("BatchUpdateWorkspaceLastUsedAt", s.Subtest(func(db database.Store, check *expects) { ws1 := dbgen.Workspace(s.T(), db, database.Workspace{}) ws2 := dbgen.Workspace(s.T(), db, database.Workspace{}) check.Args(database.BatchUpdateWorkspaceLastUsedAtParams{ IDs: []uuid.UUID{ws1.ID, ws2.ID}, - }).Asserts(rbac.ResourceWorkspace.All(), rbac.ActionUpdate).Returns() + }).Asserts(rbac.ResourceWorkspace.All(), policy.ActionUpdate).Returns() })) s.Run("UpdateWorkspaceTTL", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) check.Args(database.UpdateWorkspaceTTLParams{ ID: ws.ID, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("GetWorkspaceByWorkspaceAppID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1583,7 +1584,7 @@ func (s *MethodTestSuite) TestWorkspace() { res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) app := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: agt.ID}) - check.Args(app.ID).Asserts(ws, rbac.ActionRead).Returns(ws) + check.Args(app.ID).Asserts(ws, policy.ActionRead).Returns(ws) })) s.Run("ActivityBumpWorkspace", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1591,17 +1592,17 @@ func (s *MethodTestSuite) TestWorkspace() { dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild}) check.Args(database.ActivityBumpWorkspaceParams{ WorkspaceID: ws.ID, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("FavoriteWorkspace", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID}) - check.Args(ws.ID).Asserts(ws, rbac.ActionUpdate).Returns() + check.Args(ws.ID).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("UnfavoriteWorkspace", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID}) - check.Args(ws.ID).Asserts(ws, rbac.ActionUpdate).Returns() + check.Args(ws.ID).Asserts(ws, policy.ActionUpdate).Returns() })) } @@ -1617,7 +1618,7 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() { Port: ps.Port, ShareLevel: ps.ShareLevel, Protocol: ps.Protocol, - }).Asserts(ws, rbac.ActionUpdate).Returns(ps) + }).Asserts(ws, policy.ActionUpdate).Returns(ps) })) s.Run("GetWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) @@ -1627,13 +1628,13 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() { WorkspaceID: ps.WorkspaceID, AgentName: ps.AgentName, Port: ps.Port, - }).Asserts(ws, rbac.ActionRead).Returns(ps) + }).Asserts(ws, policy.ActionRead).Returns(ps) })) s.Run("ListWorkspaceAgentPortShares", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID}) ps := dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID}) - check.Args(ws.ID).Asserts(ws, rbac.ActionRead).Returns([]database.WorkspaceAgentPortShare{ps}) + check.Args(ws.ID).Asserts(ws, policy.ActionRead).Returns([]database.WorkspaceAgentPortShare{ps}) })) s.Run("DeleteWorkspaceAgentPortShare", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) @@ -1643,21 +1644,21 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() { WorkspaceID: ps.WorkspaceID, AgentName: ps.AgentName, Port: ps.Port, - }).Asserts(ws, rbac.ActionUpdate).Returns() + }).Asserts(ws, policy.ActionUpdate).Returns() })) s.Run("DeleteWorkspaceAgentPortSharesByTemplate", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) t := dbgen.Template(s.T(), db, database.Template{}) ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID, TemplateID: t.ID}) _ = dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID}) - check.Args(t.ID).Asserts(t, rbac.ActionUpdate).Returns() + check.Args(t.ID).Asserts(t, policy.ActionUpdate).Returns() })) s.Run("ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) t := dbgen.Template(s.T(), db, database.Template{}) ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID, TemplateID: t.ID}) _ = dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID}) - check.Args(t.ID).Asserts(t, rbac.ActionUpdate).Returns() + check.Args(t.ID).Asserts(t, policy.ActionUpdate).Returns() })) } @@ -1669,7 +1670,7 @@ func (s *MethodTestSuite) TestExtraMethods() { }), }) s.NoError(err, "insert provisioner daemon") - check.Args().Asserts(d, rbac.ActionRead) + check.Args().Asserts(d, policy.ActionRead) })) s.Run("DeleteOldProvisionerDaemons", s.Subtest(func(db database.Store, check *expects) { _, err := db.UpsertProvisionerDaemon(context.Background(), database.UpsertProvisionerDaemonParams{ @@ -1678,7 +1679,7 @@ func (s *MethodTestSuite) TestExtraMethods() { }), }) s.NoError(err, "insert provisioner daemon") - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionDelete) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionDelete) })) s.Run("UpdateProvisionerDaemonLastSeenAt", s.Subtest(func(db database.Store, check *expects) { d, err := db.UpsertProvisionerDaemon(context.Background(), database.UpsertProvisionerDaemonParams{ @@ -1690,7 +1691,7 @@ func (s *MethodTestSuite) TestExtraMethods() { check.Args(database.UpdateProvisionerDaemonLastSeenAtParams{ ID: d.ID, LastSeenAt: sql.NullTime{Time: dbtime.Now(), Valid: true}, - }).Asserts(rbac.ResourceProvisionerDaemon, rbac.ActionUpdate) + }).Asserts(rbac.ResourceProvisionerDaemon, policy.ActionUpdate) })) } @@ -1699,134 +1700,134 @@ func (s *MethodTestSuite) TestExtraMethods() { func (s *MethodTestSuite) TestTailnetFunctions() { s.Run("CleanTailnetCoordinators", s.Subtest(func(db database.Store, check *expects) { check.Args(). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("CleanTailnetLostPeers", s.Subtest(func(db database.Store, check *expects) { check.Args(). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("CleanTailnetTunnels", s.Subtest(func(db database.Store, check *expects) { check.Args(). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("DeleteAllTailnetClientSubscriptions", s.Subtest(func(db database.Store, check *expects) { check.Args(database.DeleteAllTailnetClientSubscriptionsParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("DeleteAllTailnetTunnels", s.Subtest(func(db database.Store, check *expects) { check.Args(database.DeleteAllTailnetTunnelsParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("DeleteCoordinator", s.Subtest(func(db database.Store, check *expects) { check.Args(uuid.New()). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("DeleteTailnetAgent", s.Subtest(func(db database.Store, check *expects) { check.Args(database.DeleteTailnetAgentParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionUpdate). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionUpdate). Errors(dbmem.ErrUnimplemented) })) s.Run("DeleteTailnetClient", s.Subtest(func(db database.Store, check *expects) { check.Args(database.DeleteTailnetClientParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("DeleteTailnetClientSubscription", s.Subtest(func(db database.Store, check *expects) { check.Args(database.DeleteTailnetClientSubscriptionParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("DeleteTailnetPeer", s.Subtest(func(db database.Store, check *expects) { check.Args(database.DeleteTailnetPeerParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("DeleteTailnetTunnel", s.Subtest(func(db database.Store, check *expects) { check.Args(database.DeleteTailnetTunnelParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionDelete). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionDelete). Errors(dbmem.ErrUnimplemented) })) s.Run("GetAllTailnetAgents", s.Subtest(func(db database.Store, check *expects) { check.Args(). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionRead). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionRead). Errors(dbmem.ErrUnimplemented) })) s.Run("GetTailnetAgents", s.Subtest(func(db database.Store, check *expects) { check.Args(uuid.New()). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionRead). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionRead). Errors(dbmem.ErrUnimplemented) })) s.Run("GetTailnetClientsForAgent", s.Subtest(func(db database.Store, check *expects) { check.Args(uuid.New()). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionRead). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionRead). Errors(dbmem.ErrUnimplemented) })) s.Run("GetTailnetPeers", s.Subtest(func(db database.Store, check *expects) { check.Args(uuid.New()). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionRead). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionRead). Errors(dbmem.ErrUnimplemented) })) s.Run("GetTailnetTunnelPeerBindings", s.Subtest(func(db database.Store, check *expects) { check.Args(uuid.New()). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionRead). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionRead). Errors(dbmem.ErrUnimplemented) })) s.Run("GetTailnetTunnelPeerIDs", s.Subtest(func(db database.Store, check *expects) { check.Args(uuid.New()). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionRead). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionRead). Errors(dbmem.ErrUnimplemented) })) s.Run("GetAllTailnetCoordinators", s.Subtest(func(db database.Store, check *expects) { check.Args(). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionRead). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionRead). Errors(dbmem.ErrUnimplemented) })) s.Run("GetAllTailnetPeers", s.Subtest(func(db database.Store, check *expects) { check.Args(). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionRead). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionRead). Errors(dbmem.ErrUnimplemented) })) s.Run("GetAllTailnetTunnels", s.Subtest(func(db database.Store, check *expects) { check.Args(). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionRead). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionRead). Errors(dbmem.ErrUnimplemented) })) s.Run("UpsertTailnetAgent", s.Subtest(func(db database.Store, check *expects) { check.Args(database.UpsertTailnetAgentParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionUpdate). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionUpdate). Errors(dbmem.ErrUnimplemented) })) s.Run("UpsertTailnetClient", s.Subtest(func(db database.Store, check *expects) { check.Args(database.UpsertTailnetClientParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionUpdate). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionUpdate). Errors(dbmem.ErrUnimplemented) })) s.Run("UpsertTailnetClientSubscription", s.Subtest(func(db database.Store, check *expects) { check.Args(database.UpsertTailnetClientSubscriptionParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionUpdate). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionUpdate). Errors(dbmem.ErrUnimplemented) })) s.Run("UpsertTailnetCoordinator", s.Subtest(func(db database.Store, check *expects) { check.Args(uuid.New()). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionUpdate). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionUpdate). Errors(dbmem.ErrUnimplemented) })) s.Run("UpsertTailnetPeer", s.Subtest(func(db database.Store, check *expects) { check.Args(database.UpsertTailnetPeerParams{ Status: database.TailnetStatusOk, }). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionCreate). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionCreate). Errors(dbmem.ErrUnimplemented) })) s.Run("UpsertTailnetTunnel", s.Subtest(func(db database.Store, check *expects) { check.Args(database.UpsertTailnetTunnelParams{}). - Asserts(rbac.ResourceTailnetCoordinator, rbac.ActionCreate). + Asserts(rbac.ResourceTailnetCoordinator, policy.ActionCreate). Errors(dbmem.ErrUnimplemented) })) } @@ -1834,12 +1835,12 @@ func (s *MethodTestSuite) TestTailnetFunctions() { func (s *MethodTestSuite) TestDBCrypt() { s.Run("GetDBCryptKeys", s.Subtest(func(db database.Store, check *expects) { check.Args(). - Asserts(rbac.ResourceSystem, rbac.ActionRead). + Asserts(rbac.ResourceSystem, policy.ActionRead). Returns([]database.DBCryptKey{}) })) s.Run("InsertDBCryptKey", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertDBCryptKeyParams{}). - Asserts(rbac.ResourceSystem, rbac.ActionCreate). + Asserts(rbac.ResourceSystem, policy.ActionCreate). Returns() })) s.Run("RevokeDBCryptKey", s.Subtest(func(db database.Store, check *expects) { @@ -1848,7 +1849,7 @@ func (s *MethodTestSuite) TestDBCrypt() { }) s.NoError(err) check.Args("revoke me"). - Asserts(rbac.ResourceSystem, rbac.ActionUpdate). + Asserts(rbac.ResourceSystem, policy.ActionUpdate). Returns() })) } @@ -1861,56 +1862,56 @@ func (s *MethodTestSuite) TestSystemFunctions() { UserID: u.ID, LinkedID: l.LinkedID, LoginType: database.LoginTypeGithub, - }).Asserts(rbac.ResourceSystem, rbac.ActionUpdate).Returns(l) + }).Asserts(rbac.ResourceSystem, policy.ActionUpdate).Returns(l) })) s.Run("GetLatestWorkspaceBuildsByWorkspaceIDs", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID}) - check.Args([]uuid.UUID{ws.ID}).Asserts(rbac.ResourceSystem, rbac.ActionRead).Returns(slice.New(b)) + check.Args([]uuid.UUID{ws.ID}).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(slice.New(b)) })) s.Run("UpsertDefaultProxy", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.UpsertDefaultProxyParams{}).Asserts(rbac.ResourceSystem, rbac.ActionUpdate).Returns() + check.Args(database.UpsertDefaultProxyParams{}).Asserts(rbac.ResourceSystem, policy.ActionUpdate).Returns() })) s.Run("GetUserLinkByLinkedID", s.Subtest(func(db database.Store, check *expects) { l := dbgen.UserLink(s.T(), db, database.UserLink{}) - check.Args(l.LinkedID).Asserts(rbac.ResourceSystem, rbac.ActionRead).Returns(l) + check.Args(l.LinkedID).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(l) })) s.Run("GetUserLinkByUserIDLoginType", s.Subtest(func(db database.Store, check *expects) { l := dbgen.UserLink(s.T(), db, database.UserLink{}) check.Args(database.GetUserLinkByUserIDLoginTypeParams{ UserID: l.UserID, LoginType: l.LoginType, - }).Asserts(rbac.ResourceSystem, rbac.ActionRead).Returns(l) + }).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(l) })) s.Run("GetLatestWorkspaceBuilds", s.Subtest(func(db database.Store, check *expects) { dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{}) dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{}) - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetActiveUserCount", s.Subtest(func(db database.Store, check *expects) { - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionRead).Returns(int64(0)) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(int64(0)) })) s.Run("GetUnexpiredLicenses", s.Subtest(func(db database.Store, check *expects) { - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetAuthorizationUserRoles", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) - check.Args(u.ID).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(u.ID).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetDERPMeshKey", s.Subtest(func(db database.Store, check *expects) { db.InsertDERPMeshKey(context.Background(), "testing") - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("InsertDERPMeshKey", s.Subtest(func(db database.Store, check *expects) { - check.Args("value").Asserts(rbac.ResourceSystem, rbac.ActionCreate).Returns() + check.Args("value").Asserts(rbac.ResourceSystem, policy.ActionCreate).Returns() })) s.Run("InsertDeploymentID", s.Subtest(func(db database.Store, check *expects) { - check.Args("value").Asserts(rbac.ResourceSystem, rbac.ActionCreate).Returns() + check.Args("value").Asserts(rbac.ResourceSystem, policy.ActionCreate).Returns() })) s.Run("InsertReplica", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertReplicaParams{ ID: uuid.New(), - }).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + }).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("UpdateReplica", s.Subtest(func(db database.Store, check *expects) { replica, err := db.InsertReplica(context.Background(), database.InsertReplicaParams{ID: uuid.New()}) @@ -1918,24 +1919,24 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args(database.UpdateReplicaParams{ ID: replica.ID, DatabaseLatency: 100, - }).Asserts(rbac.ResourceSystem, rbac.ActionUpdate) + }).Asserts(rbac.ResourceSystem, policy.ActionUpdate) })) s.Run("DeleteReplicasUpdatedBefore", s.Subtest(func(db database.Store, check *expects) { _, err := db.InsertReplica(context.Background(), database.InsertReplicaParams{ID: uuid.New(), UpdatedAt: time.Now()}) require.NoError(s.T(), err) - check.Args(time.Now().Add(time.Hour)).Asserts(rbac.ResourceSystem, rbac.ActionDelete) + check.Args(time.Now().Add(time.Hour)).Asserts(rbac.ResourceSystem, policy.ActionDelete) })) s.Run("GetReplicasUpdatedAfter", s.Subtest(func(db database.Store, check *expects) { _, err := db.InsertReplica(context.Background(), database.InsertReplicaParams{ID: uuid.New(), UpdatedAt: time.Now()}) require.NoError(s.T(), err) - check.Args(time.Now().Add(time.Hour*-1)).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(time.Now().Add(time.Hour*-1)).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetUserCount", s.Subtest(func(db database.Store, check *expects) { - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionRead).Returns(int64(0)) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(int64(0)) })) s.Run("GetTemplates", s.Subtest(func(db database.Store, check *expects) { _ = dbgen.Template(s.T(), db, database.Template{}) - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("UpdateWorkspaceBuildCostByID", s.Subtest(func(db database.Store, check *expects) { b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{}) @@ -1944,7 +1945,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args(database.UpdateWorkspaceBuildCostByIDParams{ ID: b.ID, DailyCost: 10, - }).Asserts(rbac.ResourceSystem, rbac.ActionUpdate) + }).Asserts(rbac.ResourceSystem, policy.ActionUpdate) })) s.Run("UpdateWorkspaceBuildProvisionerStateByID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -1952,43 +1953,43 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args(database.UpdateWorkspaceBuildProvisionerStateByIDParams{ ID: build.ID, ProvisionerState: []byte("testing"), - }).Asserts(rbac.ResourceSystem, rbac.ActionUpdate) + }).Asserts(rbac.ResourceSystem, policy.ActionUpdate) })) s.Run("UpsertLastUpdateCheck", s.Subtest(func(db database.Store, check *expects) { - check.Args("value").Asserts(rbac.ResourceSystem, rbac.ActionUpdate) + check.Args("value").Asserts(rbac.ResourceSystem, policy.ActionUpdate) })) s.Run("GetLastUpdateCheck", s.Subtest(func(db database.Store, check *expects) { err := db.UpsertLastUpdateCheck(context.Background(), "value") require.NoError(s.T(), err) - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetWorkspaceBuildsCreatedAfter", s.Subtest(func(db database.Store, check *expects) { _ = dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{CreatedAt: time.Now().Add(-time.Hour)}) - check.Args(time.Now()).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(time.Now()).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetWorkspaceAgentsCreatedAfter", s.Subtest(func(db database.Store, check *expects) { _ = dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{CreatedAt: time.Now().Add(-time.Hour)}) - check.Args(time.Now()).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(time.Now()).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetWorkspaceAppsCreatedAfter", s.Subtest(func(db database.Store, check *expects) { _ = dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{CreatedAt: time.Now().Add(-time.Hour)}) - check.Args(time.Now()).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(time.Now()).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetWorkspaceResourcesCreatedAfter", s.Subtest(func(db database.Store, check *expects) { _ = dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{CreatedAt: time.Now().Add(-time.Hour)}) - check.Args(time.Now()).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(time.Now()).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetWorkspaceResourceMetadataCreatedAfter", s.Subtest(func(db database.Store, check *expects) { _ = dbgen.WorkspaceResourceMetadatums(s.T(), db, database.WorkspaceResourceMetadatum{}) - check.Args(time.Now()).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(time.Now()).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("DeleteOldWorkspaceAgentStats", s.Subtest(func(db database.Store, check *expects) { - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionDelete) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionDelete) })) s.Run("GetProvisionerJobsCreatedAfter", s.Subtest(func(db database.Store, check *expects) { // TODO: add provisioner job resource type _ = dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{CreatedAt: time.Now().Add(-time.Hour)}) - check.Args(time.Now()).Asserts( /*rbac.ResourceSystem, rbac.ActionRead*/ ) + check.Args(time.Now()).Asserts( /*rbac.ResourceSystem, policy.ActionRead*/ ) })) s.Run("GetTemplateVersionsByIDs", s.Subtest(func(db database.Store, check *expects) { t1 := dbgen.Template(s.T(), db, database.Template{}) @@ -2003,7 +2004,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { TemplateID: uuid.NullUUID{UUID: t2.ID, Valid: true}, }) check.Args([]uuid.UUID{tv1.ID, tv2.ID, tv3.ID}). - Asserts(rbac.ResourceSystem, rbac.ActionRead). + Asserts(rbac.ResourceSystem, policy.ActionRead). Returns(slice.New(tv1, tv2, tv3)) })) s.Run("GetParameterSchemasByJobID", s.Subtest(func(db database.Store, check *expects) { @@ -2013,7 +2014,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { }) job := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: tv.JobID}) check.Args(job.ID). - Asserts(tpl, rbac.ActionRead).Errors(sql.ErrNoRows) + Asserts(tpl, policy.ActionRead).Errors(sql.ErrNoRows) })) s.Run("GetWorkspaceAppsByAgentIDs", s.Subtest(func(db database.Store, check *expects) { aWs := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -2029,7 +2030,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { b := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: bAgt.ID}) check.Args([]uuid.UUID{a.AgentID, b.AgentID}). - Asserts(rbac.ResourceSystem, rbac.ActionRead). + Asserts(rbac.ResourceSystem, policy.ActionRead). Returns([]database.WorkspaceApp{a, b}) })) s.Run("GetWorkspaceResourcesByJobIDs", s.Subtest(func(db database.Store, check *expects) { @@ -2041,7 +2042,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { build := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: ws.ID, JobID: uuid.New()}) wJob := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ID: build.JobID, Type: database.ProvisionerJobTypeWorkspaceBuild}) check.Args([]uuid.UUID{tJob.ID, wJob.ID}). - Asserts(rbac.ResourceSystem, rbac.ActionRead). + Asserts(rbac.ResourceSystem, policy.ActionRead). Returns([]database.WorkspaceResource{}) })) s.Run("GetWorkspaceResourceMetadataByResourceIDs", s.Subtest(func(db database.Store, check *expects) { @@ -2051,7 +2052,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { a := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) b := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) check.Args([]uuid.UUID{a.ID, b.ID}). - Asserts(rbac.ResourceSystem, rbac.ActionRead) + Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetWorkspaceAgentsByResourceIDs", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -2059,7 +2060,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: build.JobID}) agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) check.Args([]uuid.UUID{res.ID}). - Asserts(rbac.ResourceSystem, rbac.ActionRead). + Asserts(rbac.ResourceSystem, policy.ActionRead). Returns([]database.WorkspaceAgent{agt}) })) s.Run("GetProvisionerJobsByIDs", s.Subtest(func(db database.Store, check *expects) { @@ -2067,25 +2068,25 @@ func (s *MethodTestSuite) TestSystemFunctions() { a := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{}) b := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{}) check.Args([]uuid.UUID{a.ID, b.ID}). - Asserts( /*rbac.ResourceSystem, rbac.ActionRead*/ ). + Asserts( /*rbac.ResourceSystem, policy.ActionRead*/ ). Returns(slice.New(a, b)) })) s.Run("InsertWorkspaceAgent", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertWorkspaceAgentParams{ ID: uuid.New(), - }).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + }).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("InsertWorkspaceApp", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertWorkspaceAppParams{ ID: uuid.New(), Health: database.WorkspaceAppHealthDisabled, SharingLevel: database.AppSharingLevelOwner, - }).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + }).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("InsertWorkspaceResourceMetadata", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertWorkspaceResourceMetadataParams{ WorkspaceResourceID: uuid.New(), - }).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + }).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("UpdateWorkspaceAgentConnectionByID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -2094,7 +2095,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) check.Args(database.UpdateWorkspaceAgentConnectionByIDParams{ ID: agt.ID, - }).Asserts(rbac.ResourceSystem, rbac.ActionUpdate).Returns() + }).Asserts(rbac.ResourceSystem, policy.ActionUpdate).Returns() })) s.Run("AcquireProvisionerJob", s.Subtest(func(db database.Store, check *expects) { // TODO: we need to create a ProvisionerJob resource @@ -2102,14 +2103,14 @@ func (s *MethodTestSuite) TestSystemFunctions() { StartedAt: sql.NullTime{Valid: false}, }) check.Args(database.AcquireProvisionerJobParams{OrganizationID: j.OrganizationID, Types: []database.ProvisionerType{j.Provisioner}, Tags: must(json.Marshal(j.Tags))}). - Asserts( /*rbac.ResourceSystem, rbac.ActionUpdate*/ ) + Asserts( /*rbac.ResourceSystem, policy.ActionUpdate*/ ) })) s.Run("UpdateProvisionerJobWithCompleteByID", s.Subtest(func(db database.Store, check *expects) { // TODO: we need to create a ProvisionerJob resource j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{}) check.Args(database.UpdateProvisionerJobWithCompleteByIDParams{ ID: j.ID, - }).Asserts( /*rbac.ResourceSystem, rbac.ActionUpdate*/ ) + }).Asserts( /*rbac.ResourceSystem, policy.ActionUpdate*/ ) })) s.Run("UpdateProvisionerJobByID", s.Subtest(func(db database.Store, check *expects) { // TODO: we need to create a ProvisionerJob resource @@ -2117,7 +2118,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args(database.UpdateProvisionerJobByIDParams{ ID: j.ID, UpdatedAt: time.Now(), - }).Asserts( /*rbac.ResourceSystem, rbac.ActionUpdate*/ ) + }).Asserts( /*rbac.ResourceSystem, policy.ActionUpdate*/ ) })) s.Run("InsertProvisionerJob", s.Subtest(func(db database.Store, check *expects) { // TODO: we need to create a ProvisionerJob resource @@ -2126,14 +2127,14 @@ func (s *MethodTestSuite) TestSystemFunctions() { Provisioner: database.ProvisionerTypeEcho, StorageMethod: database.ProvisionerStorageMethodFile, Type: database.ProvisionerJobTypeWorkspaceBuild, - }).Asserts( /*rbac.ResourceSystem, rbac.ActionCreate*/ ) + }).Asserts( /*rbac.ResourceSystem, policy.ActionCreate*/ ) })) s.Run("InsertProvisionerJobLogs", s.Subtest(func(db database.Store, check *expects) { // TODO: we need to create a ProvisionerJob resource j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{}) check.Args(database.InsertProvisionerJobLogsParams{ JobID: j.ID, - }).Asserts( /*rbac.ResourceSystem, rbac.ActionCreate*/ ) + }).Asserts( /*rbac.ResourceSystem, policy.ActionCreate*/ ) })) s.Run("UpsertProvisionerDaemon", s.Subtest(func(db database.Store, check *expects) { pd := rbac.ResourceProvisionerDaemon.All() @@ -2141,41 +2142,41 @@ func (s *MethodTestSuite) TestSystemFunctions() { Tags: database.StringMap(map[string]string{ provisionersdk.TagScope: provisionersdk.ScopeOrganization, }), - }).Asserts(pd, rbac.ActionCreate) + }).Asserts(pd, policy.ActionCreate) check.Args(database.UpsertProvisionerDaemonParams{ Tags: database.StringMap(map[string]string{ provisionersdk.TagScope: provisionersdk.ScopeUser, provisionersdk.TagOwner: "11111111-1111-1111-1111-111111111111", }), - }).Asserts(pd.WithOwner("11111111-1111-1111-1111-111111111111"), rbac.ActionCreate) + }).Asserts(pd.WithOwner("11111111-1111-1111-1111-111111111111"), policy.ActionCreate) })) s.Run("InsertTemplateVersionParameter", s.Subtest(func(db database.Store, check *expects) { v := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{}) check.Args(database.InsertTemplateVersionParameterParams{ TemplateVersionID: v.ID, - }).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + }).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("InsertWorkspaceResource", s.Subtest(func(db database.Store, check *expects) { r := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{}) check.Args(database.InsertWorkspaceResourceParams{ ID: r.ID, Transition: database.WorkspaceTransitionStart, - }).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + }).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("DeleteOldWorkspaceAgentLogs", s.Subtest(func(db database.Store, check *expects) { - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionDelete) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionDelete) })) s.Run("InsertWorkspaceAgentStats", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.InsertWorkspaceAgentStatsParams{}).Asserts(rbac.ResourceSystem, rbac.ActionCreate).Errors(errMatchAny) + check.Args(database.InsertWorkspaceAgentStatsParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate).Errors(errMatchAny) })) s.Run("InsertWorkspaceAppStats", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.InsertWorkspaceAppStatsParams{}).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + check.Args(database.InsertWorkspaceAppStatsParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("InsertWorkspaceAgentScripts", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.InsertWorkspaceAgentScriptsParams{}).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + check.Args(database.InsertWorkspaceAgentScriptsParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("InsertWorkspaceAgentMetadata", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.InsertWorkspaceAgentMetadataParams{}).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + check.Args(database.InsertWorkspaceAgentMetadataParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("InsertWorkspaceAgentLogs", s.Subtest(func(db database.Store, check *expects) { check.Args(database.InsertWorkspaceAgentLogsParams{}).Asserts() @@ -2184,13 +2185,13 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args(database.InsertWorkspaceAgentLogSourcesParams{}).Asserts() })) s.Run("GetTemplateDAUs", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetTemplateDAUsParams{}).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(database.GetTemplateDAUsParams{}).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetActiveWorkspaceBuildsByTemplateID", s.Subtest(func(db database.Store, check *expects) { - check.Args(uuid.New()).Asserts(rbac.ResourceSystem, rbac.ActionRead).Errors(sql.ErrNoRows) + check.Args(uuid.New()).Asserts(rbac.ResourceSystem, policy.ActionRead).Errors(sql.ErrNoRows) })) s.Run("GetDeploymentDAUs", s.Subtest(func(db database.Store, check *expects) { - check.Args(int32(0)).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(int32(0)).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetAppSecurityKey", s.Subtest(func(db database.Store, check *expects) { check.Args().Asserts() @@ -2203,13 +2204,13 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args().Asserts() })) s.Run("UpsertApplicationName", s.Subtest(func(db database.Store, check *expects) { - check.Args("").Asserts(rbac.ResourceDeploymentValues, rbac.ActionCreate) + check.Args("").Asserts(rbac.ResourceDeploymentValues, policy.ActionCreate) })) s.Run("GetHealthSettings", s.Subtest(func(db database.Store, check *expects) { check.Args().Asserts() })) s.Run("UpsertHealthSettings", s.Subtest(func(db database.Store, check *expects) { - check.Args("foo").Asserts(rbac.ResourceDeploymentValues, rbac.ActionCreate) + check.Args("foo").Asserts(rbac.ResourceDeploymentValues, policy.ActionCreate) })) s.Run("GetDeploymentWorkspaceAgentStats", s.Subtest(func(db database.Store, check *expects) { check.Args(time.Time{}).Asserts() @@ -2218,27 +2219,27 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args().Asserts() })) s.Run("GetFileTemplates", s.Subtest(func(db database.Store, check *expects) { - check.Args(uuid.New()).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(uuid.New()).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetHungProvisionerJobs", s.Subtest(func(db database.Store, check *expects) { check.Args(time.Time{}).Asserts() })) s.Run("UpsertOAuthSigningKey", s.Subtest(func(db database.Store, check *expects) { - check.Args("foo").Asserts(rbac.ResourceSystem, rbac.ActionUpdate) + check.Args("foo").Asserts(rbac.ResourceSystem, policy.ActionUpdate) })) s.Run("GetOAuthSigningKey", s.Subtest(func(db database.Store, check *expects) { db.UpsertOAuthSigningKey(context.Background(), "foo") - check.Args().Asserts(rbac.ResourceSystem, rbac.ActionUpdate) + check.Args().Asserts(rbac.ResourceSystem, policy.ActionUpdate) })) s.Run("InsertMissingGroups", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.InsertMissingGroupsParams{}).Asserts(rbac.ResourceSystem, rbac.ActionCreate).Errors(errMatchAny) + check.Args(database.InsertMissingGroupsParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate).Errors(errMatchAny) })) s.Run("UpdateUserLoginType", s.Subtest(func(db database.Store, check *expects) { u := dbgen.User(s.T(), db, database.User{}) check.Args(database.UpdateUserLoginTypeParams{ NewLoginType: database.LoginTypePassword, UserID: u.ID, - }).Asserts(rbac.ResourceSystem, rbac.ActionUpdate) + }).Asserts(rbac.ResourceSystem, policy.ActionUpdate) })) s.Run("GetWorkspaceAgentStatsAndLabels", s.Subtest(func(db database.Store, check *expects) { check.Args(time.Time{}).Asserts() @@ -2253,40 +2254,40 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args(database.GetWorkspaceProxyByHostnameParams{ Hostname: "foo.example.com", AllowWildcardHostname: true, - }).Asserts(rbac.ResourceSystem, rbac.ActionRead).Returns(p) + }).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(p) })) s.Run("GetTemplateAverageBuildTime", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.GetTemplateAverageBuildTimeParams{}).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(database.GetTemplateAverageBuildTimeParams{}).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetWorkspacesEligibleForTransition", s.Subtest(func(db database.Store, check *expects) { check.Args(time.Time{}).Asserts() })) s.Run("InsertTemplateVersionVariable", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.InsertTemplateVersionVariableParams{}).Asserts(rbac.ResourceSystem, rbac.ActionCreate) + check.Args(database.InsertTemplateVersionVariableParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("UpdateInactiveUsersToDormant", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.UpdateInactiveUsersToDormantParams{}).Asserts(rbac.ResourceSystem, rbac.ActionCreate).Errors(sql.ErrNoRows) + check.Args(database.UpdateInactiveUsersToDormantParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate).Errors(sql.ErrNoRows) })) s.Run("GetWorkspaceUniqueOwnerCountByTemplateIDs", s.Subtest(func(db database.Store, check *expects) { - check.Args([]uuid.UUID{uuid.New()}).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args([]uuid.UUID{uuid.New()}).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetWorkspaceAgentScriptsByAgentIDs", s.Subtest(func(db database.Store, check *expects) { - check.Args([]uuid.UUID{uuid.New()}).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args([]uuid.UUID{uuid.New()}).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetWorkspaceAgentLogSourcesByAgentIDs", s.Subtest(func(db database.Store, check *expects) { - check.Args([]uuid.UUID{uuid.New()}).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args([]uuid.UUID{uuid.New()}).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetProvisionerJobsByIDsWithQueuePosition", s.Subtest(func(db database.Store, check *expects) { check.Args([]uuid.UUID{}).Asserts() })) s.Run("GetReplicaByID", s.Subtest(func(db database.Store, check *expects) { - check.Args(uuid.New()).Asserts(rbac.ResourceSystem, rbac.ActionRead).Errors(sql.ErrNoRows) + check.Args(uuid.New()).Asserts(rbac.ResourceSystem, policy.ActionRead).Errors(sql.ErrNoRows) })) s.Run("GetWorkspaceAgentAndLatestBuildByAuthToken", s.Subtest(func(db database.Store, check *expects) { - check.Args(uuid.New()).Asserts(rbac.ResourceSystem, rbac.ActionRead).Errors(sql.ErrNoRows) + check.Args(uuid.New()).Asserts(rbac.ResourceSystem, policy.ActionRead).Errors(sql.ErrNoRows) })) s.Run("GetUserLinksByUserID", s.Subtest(func(db database.Store, check *expects) { - check.Args(uuid.New()).Asserts(rbac.ResourceSystem, rbac.ActionRead) + check.Args(uuid.New()).Asserts(rbac.ResourceSystem, policy.ActionRead) })) s.Run("GetJFrogXrayScanByWorkspaceAndAgentID", s.Subtest(func(db database.Store, check *expects) { ws := dbgen.Workspace(s.T(), db, database.Workspace{}) @@ -2314,7 +2315,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args(database.GetJFrogXrayScanByWorkspaceAndAgentIDParams{ WorkspaceID: ws.ID, AgentID: agent.ID, - }).Asserts(ws, rbac.ActionRead).Returns(expect) + }).Asserts(ws, policy.ActionRead).Returns(expect) })) s.Run("UpsertJFrogXrayScanByWorkspaceAndAgentID", s.Subtest(func(db database.Store, check *expects) { tpl := dbgen.Template(s.T(), db, database.Template{}) @@ -2324,7 +2325,7 @@ func (s *MethodTestSuite) TestSystemFunctions() { check.Args(database.UpsertJFrogXrayScanByWorkspaceAndAgentIDParams{ WorkspaceID: ws.ID, AgentID: uuid.New(), - }).Asserts(tpl, rbac.ActionCreate) + }).Asserts(tpl, policy.ActionCreate) })) } @@ -2334,11 +2335,11 @@ func (s *MethodTestSuite) TestOAuth2ProviderApps() { dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{Name: "first"}), dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{Name: "last"}), } - check.Args().Asserts(rbac.ResourceOAuth2ProviderApp, rbac.ActionRead).Returns(apps) + check.Args().Asserts(rbac.ResourceOAuth2ProviderApp, policy.ActionRead).Returns(apps) })) s.Run("GetOAuth2ProviderAppByID", s.Subtest(func(db database.Store, check *expects) { app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{}) - check.Args(app.ID).Asserts(rbac.ResourceOAuth2ProviderApp, rbac.ActionRead).Returns(app) + check.Args(app.ID).Asserts(rbac.ResourceOAuth2ProviderApp, policy.ActionRead).Returns(app) })) s.Run("GetOAuth2ProviderAppsByUserID", s.Subtest(func(db database.Store, check *expects) { user := dbgen.User(s.T(), db, database.User{}) @@ -2356,7 +2357,7 @@ func (s *MethodTestSuite) TestOAuth2ProviderApps() { APIKeyID: key.ID, }) } - check.Args(user.ID).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionRead).Returns([]database.GetOAuth2ProviderAppsByUserIDRow{ + check.Args(user.ID).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), policy.ActionRead).Returns([]database.GetOAuth2ProviderAppsByUserIDRow{ { OAuth2ProviderApp: database.OAuth2ProviderApp{ ID: app.ID, @@ -2369,7 +2370,7 @@ func (s *MethodTestSuite) TestOAuth2ProviderApps() { }) })) s.Run("InsertOAuth2ProviderApp", s.Subtest(func(db database.Store, check *expects) { - check.Args(database.InsertOAuth2ProviderAppParams{}).Asserts(rbac.ResourceOAuth2ProviderApp, rbac.ActionCreate) + check.Args(database.InsertOAuth2ProviderAppParams{}).Asserts(rbac.ResourceOAuth2ProviderApp, policy.ActionCreate) })) s.Run("UpdateOAuth2ProviderAppByID", s.Subtest(func(db database.Store, check *expects) { app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{}) @@ -2380,11 +2381,11 @@ func (s *MethodTestSuite) TestOAuth2ProviderApps() { Name: app.Name, CallbackURL: app.CallbackURL, UpdatedAt: app.UpdatedAt, - }).Asserts(rbac.ResourceOAuth2ProviderApp, rbac.ActionUpdate).Returns(app) + }).Asserts(rbac.ResourceOAuth2ProviderApp, policy.ActionUpdate).Returns(app) })) s.Run("DeleteOAuth2ProviderAppByID", s.Subtest(func(db database.Store, check *expects) { app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{}) - check.Args(app.ID).Asserts(rbac.ResourceOAuth2ProviderApp, rbac.ActionDelete) + check.Args(app.ID).Asserts(rbac.ResourceOAuth2ProviderApp, policy.ActionDelete) })) } @@ -2404,27 +2405,27 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppSecrets() { _ = dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{ AppID: app2.ID, }) - check.Args(app1.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secrets) + check.Args(app1.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, policy.ActionRead).Returns(secrets) })) s.Run("GetOAuth2ProviderAppSecretByID", s.Subtest(func(db database.Store, check *expects) { app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{}) secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{ AppID: app.ID, }) - check.Args(secret.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secret) + check.Args(secret.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, policy.ActionRead).Returns(secret) })) s.Run("GetOAuth2ProviderAppSecretByPrefix", s.Subtest(func(db database.Store, check *expects) { app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{}) secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{ AppID: app.ID, }) - check.Args(secret.SecretPrefix).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secret) + check.Args(secret.SecretPrefix).Asserts(rbac.ResourceOAuth2ProviderAppSecret, policy.ActionRead).Returns(secret) })) s.Run("InsertOAuth2ProviderAppSecret", s.Subtest(func(db database.Store, check *expects) { app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{}) check.Args(database.InsertOAuth2ProviderAppSecretParams{ AppID: app.ID, - }).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionCreate) + }).Asserts(rbac.ResourceOAuth2ProviderAppSecret, policy.ActionCreate) })) s.Run("UpdateOAuth2ProviderAppSecretByID", s.Subtest(func(db database.Store, check *expects) { app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{}) @@ -2435,14 +2436,14 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppSecrets() { check.Args(database.UpdateOAuth2ProviderAppSecretByIDParams{ ID: secret.ID, LastUsedAt: secret.LastUsedAt, - }).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionUpdate).Returns(secret) + }).Asserts(rbac.ResourceOAuth2ProviderAppSecret, policy.ActionUpdate).Returns(secret) })) s.Run("DeleteOAuth2ProviderAppSecretByID", s.Subtest(func(db database.Store, check *expects) { app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{}) secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{ AppID: app.ID, }) - check.Args(secret.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionDelete) + check.Args(secret.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, policy.ActionDelete) })) } @@ -2454,7 +2455,7 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() { AppID: app.ID, UserID: user.ID, }) - check.Args(code.ID).Asserts(code, rbac.ActionRead).Returns(code) + check.Args(code.ID).Asserts(code, policy.ActionRead).Returns(code) })) s.Run("GetOAuth2ProviderAppCodeByPrefix", s.Subtest(func(db database.Store, check *expects) { user := dbgen.User(s.T(), db, database.User{}) @@ -2463,7 +2464,7 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() { AppID: app.ID, UserID: user.ID, }) - check.Args(code.SecretPrefix).Asserts(code, rbac.ActionRead).Returns(code) + check.Args(code.SecretPrefix).Asserts(code, policy.ActionRead).Returns(code) })) s.Run("InsertOAuth2ProviderAppCode", s.Subtest(func(db database.Store, check *expects) { user := dbgen.User(s.T(), db, database.User{}) @@ -2471,7 +2472,7 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() { check.Args(database.InsertOAuth2ProviderAppCodeParams{ AppID: app.ID, UserID: user.ID, - }).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionCreate) + }).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), policy.ActionCreate) })) s.Run("DeleteOAuth2ProviderAppCodeByID", s.Subtest(func(db database.Store, check *expects) { user := dbgen.User(s.T(), db, database.User{}) @@ -2480,7 +2481,7 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() { AppID: app.ID, UserID: user.ID, }) - check.Args(code.ID).Asserts(code, rbac.ActionDelete) + check.Args(code.ID).Asserts(code, policy.ActionDelete) })) s.Run("DeleteOAuth2ProviderAppCodesByAppAndUserID", s.Subtest(func(db database.Store, check *expects) { user := dbgen.User(s.T(), db, database.User{}) @@ -2494,7 +2495,7 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() { check.Args(database.DeleteOAuth2ProviderAppCodesByAppAndUserIDParams{ AppID: app.ID, UserID: user.ID, - }).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionDelete) + }).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), policy.ActionDelete) })) } @@ -2511,7 +2512,7 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() { check.Args(database.InsertOAuth2ProviderAppTokenParams{ AppSecretID: secret.ID, APIKeyID: key.ID, - }).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionCreate) + }).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), policy.ActionCreate) })) s.Run("GetOAuth2ProviderAppTokenByPrefix", s.Subtest(func(db database.Store, check *expects) { user := dbgen.User(s.T(), db, database.User{}) @@ -2526,7 +2527,7 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() { AppSecretID: secret.ID, APIKeyID: key.ID, }) - check.Args(token.HashPrefix).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionRead) + check.Args(token.HashPrefix).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), policy.ActionRead) })) s.Run("DeleteOAuth2ProviderAppTokensByAppAndUserID", s.Subtest(func(db database.Store, check *expects) { user := dbgen.User(s.T(), db, database.User{}) @@ -2546,6 +2547,6 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() { check.Args(database.DeleteOAuth2ProviderAppTokensByAppAndUserIDParams{ AppID: app.ID, UserID: user.ID, - }).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionDelete) + }).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), policy.ActionDelete) })) } diff --git a/coderd/database/dbauthz/setup_test.go b/coderd/database/dbauthz/setup_test.go index d3a8ae6b378eb..16829cdef669e 100644 --- a/coderd/database/dbauthz/setup_test.go +++ b/coderd/database/dbauthz/setup_test.go @@ -17,6 +17,7 @@ import ( "golang.org/x/xerrors" "cdr.dev/slog" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/database" @@ -338,7 +339,7 @@ func (m *expects) Errors(err error) *expects { // AssertRBAC contains the object and actions to be asserted. type AssertRBAC struct { Object rbac.Object - Actions []rbac.Action + Actions []policy.Action } // values is a convenience method for creating []reflect.Value. @@ -368,15 +369,15 @@ func values(ins ...any) []reflect.Value { // // Even-numbered inputs are the objects, and odd-numbered inputs are the actions. // Objects must implement rbac.Objecter. -// Inputs can be a single rbac.Action, or a slice of rbac.Action. +// Inputs can be a single policy.Action, or a slice of policy.Action. // -// asserts(workspace, rbac.ActionRead, template, slice(rbac.ActionRead, rbac.ActionWrite), ...) +// asserts(workspace, policy.ActionRead, template, slice(policy.ActionRead, policy.ActionWrite), ...) // // is equivalent to // // []AssertRBAC{ -// {Object: workspace, Actions: []rbac.Action{rbac.ActionRead}}, -// {Object: template, Actions: []rbac.Action{rbac.ActionRead, rbac.ActionWrite)}}, +// {Object: workspace, Actions: []policy.Action{policy.ActionRead}}, +// {Object: template, Actions: []policy.Action{policy.ActionRead, policy.ActionWrite)}}, // ... // } func asserts(inputs ...any) []AssertRBAC { @@ -392,19 +393,19 @@ func asserts(inputs ...any) []AssertRBAC { } rbacObj := obj.RBACObject() - var actions []rbac.Action - actions, ok = inputs[i+1].([]rbac.Action) + var actions []policy.Action + actions, ok = inputs[i+1].([]policy.Action) if !ok { - action, ok := inputs[i+1].(rbac.Action) + action, ok := inputs[i+1].(policy.Action) if !ok { // Could be the string type. actionAsString, ok := inputs[i+1].(string) if !ok { panic(fmt.Sprintf("action '%q' not a supported action", actionAsString)) } - action = rbac.Action(actionAsString) + action = policy.Action(actionAsString) } - actions = []rbac.Action{action} + actions = []policy.Action{action} } out = append(out, AssertRBAC{ diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index 596885c9d282d..fe660e7e8fa93 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -22,6 +22,7 @@ import ( "github.com/coder/coder/v2/coderd/database/provisionerjobs" "github.com/coder/coder/v2/coderd/database/pubsub" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/cryptorand" ) @@ -69,7 +70,7 @@ func Template(t testing.TB, db database.Store, seed database.Template) database. if seed.GroupACL == nil { // By default, all users in the organization can read the template. seed.GroupACL = database.TemplateACL{ - seed.OrganizationID.String(): []rbac.Action{rbac.ActionRead}, + seed.OrganizationID.String(): []policy.Action{policy.ActionRead}, } } if seed.UserACL == nil { diff --git a/coderd/database/dbmetrics/dbmetrics.go b/coderd/database/dbmetrics/dbmetrics.go index d92c60e8db09a..77ebfd6718757 100644 --- a/coderd/database/dbmetrics/dbmetrics.go +++ b/coderd/database/dbmetrics/dbmetrics.go @@ -14,12 +14,14 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" ) var ( // Force these imports, for some reason the autogen does not include them. _ uuid.UUID - _ rbac.Action + _ policy.Action + _ rbac.Objecter ) const wrapname = "dbmetrics.metricsStore" diff --git a/coderd/database/types.go b/coderd/database/types.go index b9f195e541c20..497446b25abfa 100644 --- a/coderd/database/types.go +++ b/coderd/database/types.go @@ -8,7 +8,7 @@ import ( "github.com/google/uuid" "golang.org/x/xerrors" - "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk/healthsdk" ) @@ -29,7 +29,7 @@ type HealthSettings struct { DismissedHealthchecks []healthsdk.HealthSection `db:"dismissed_healthchecks" json:"dismissed_healthchecks"` } -type Actions []rbac.Action +type Actions []policy.Action func (a *Actions) Scan(src interface{}) error { switch v := src.(type) { @@ -46,7 +46,7 @@ func (a *Actions) Value() (driver.Value, error) { } // TemplateACL is a map of ids to permissions. -type TemplateACL map[string][]rbac.Action +type TemplateACL map[string][]policy.Action func (t *TemplateACL) Scan(src interface{}) error { switch v := src.(type) { diff --git a/coderd/debug.go b/coderd/debug.go index d97edfe0b73fe..0e98539a71f75 100644 --- a/coderd/debug.go +++ b/coderd/debug.go @@ -19,6 +19,7 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/healthsdk" ) @@ -193,7 +194,7 @@ func (api *API) deploymentHealthSettings(rw http.ResponseWriter, r *http.Request func (api *API) putDeploymentHealthSettings(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() - if !api.Authorize(r, rbac.ActionUpdate, rbac.ResourceDeploymentValues) { + if !api.Authorize(r, policy.ActionUpdate, rbac.ResourceDeploymentValues) { httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{ Message: "Insufficient permissions to update health settings.", }) diff --git a/coderd/deployment.go b/coderd/deployment.go index d96d6d4388c9b..572bf9076bb59 100644 --- a/coderd/deployment.go +++ b/coderd/deployment.go @@ -5,6 +5,7 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" ) @@ -16,7 +17,7 @@ import ( // @Success 200 {object} codersdk.DeploymentConfig // @Router /deployment/config [get] func (api *API) deploymentValues(rw http.ResponseWriter, r *http.Request) { - if !api.Authorize(r, rbac.ActionRead, rbac.ResourceDeploymentValues) { + if !api.Authorize(r, policy.ActionRead, rbac.ResourceDeploymentValues) { httpapi.Forbidden(rw) return } @@ -44,7 +45,7 @@ func (api *API) deploymentValues(rw http.ResponseWriter, r *http.Request) { // @Success 200 {object} codersdk.DeploymentStats // @Router /deployment/stats [get] func (api *API) deploymentStats(rw http.ResponseWriter, r *http.Request) { - if !api.Authorize(r, rbac.ActionRead, rbac.ResourceDeploymentStats) { + if !api.Authorize(r, policy.ActionRead, rbac.ResourceDeploymentStats) { httpapi.Forbidden(rw) return } diff --git a/coderd/insights.go b/coderd/insights.go index fbd313247302d..85b4ec8661d9c 100644 --- a/coderd/insights.go +++ b/coderd/insights.go @@ -17,6 +17,7 @@ import ( "github.com/coder/coder/v2/coderd/database/db2sdk" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/util/slice" "github.com/coder/coder/v2/codersdk" ) @@ -32,7 +33,7 @@ const insightsTimeLayout = time.RFC3339 // @Success 200 {object} codersdk.DAUsResponse // @Router /insights/daus [get] func (api *API) deploymentDAUs(rw http.ResponseWriter, r *http.Request) { - if !api.Authorize(r, rbac.ActionRead, rbac.ResourceDeploymentValues) { + if !api.Authorize(r, policy.ActionRead, rbac.ResourceDeploymentValues) { httpapi.Forbidden(rw) return } diff --git a/coderd/insights_test.go b/coderd/insights_test.go index 83be460dbdd8e..b6a28f7b0c59b 100644 --- a/coderd/insights_test.go +++ b/coderd/insights_test.go @@ -29,6 +29,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbrollup" "github.com/coder/coder/v2/coderd/database/dbtestutil" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/workspaceapps" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" @@ -655,7 +656,7 @@ func TestTemplateInsights_Golden(t *testing.T) { OrganizationID: firstUser.OrganizationID, CreatedBy: firstUser.UserID, GroupACL: database.TemplateACL{ - firstUser.OrganizationID.String(): []rbac.Action{rbac.ActionRead}, + firstUser.OrganizationID.String(): []policy.Action{policy.ActionRead}, }, }) err := db.UpdateTemplateVersionByID(context.Background(), database.UpdateTemplateVersionByIDParams{ @@ -1551,7 +1552,7 @@ func TestUserActivityInsights_Golden(t *testing.T) { OrganizationID: firstUser.OrganizationID, CreatedBy: firstUser.UserID, GroupACL: database.TemplateACL{ - firstUser.OrganizationID.String(): []rbac.Action{rbac.ActionRead}, + firstUser.OrganizationID.String(): []policy.Action{policy.ActionRead}, }, }) err := db.UpdateTemplateVersionByID(context.Background(), database.UpdateTemplateVersionByIDParams{ diff --git a/coderd/rbac/astvalue.go b/coderd/rbac/astvalue.go index 954f20cfeea53..9549eb1ed7be8 100644 --- a/coderd/rbac/astvalue.go +++ b/coderd/rbac/astvalue.go @@ -3,12 +3,14 @@ package rbac import ( "github.com/open-policy-agent/opa/ast" "golang.org/x/xerrors" + + "github.com/coder/coder/v2/coderd/rbac/policy" ) // regoInputValue returns a rego input value for the given subject, action, and // object. This rego input is already parsed and can be used directly in a // rego query. -func regoInputValue(subject Subject, action Action, object Object) (ast.Value, error) { +func regoInputValue(subject Subject, action policy.Action, object Object) (ast.Value, error) { regoSubj, err := subject.regoValue() if err != nil { return nil, xerrors.Errorf("subject: %w", err) @@ -34,7 +36,7 @@ func regoInputValue(subject Subject, action Action, object Object) (ast.Value, e // regoPartialInputValue is the same as regoInputValue but only includes the // object type. This is for partial evaluations. -func regoPartialInputValue(subject Subject, action Action, objectType string) (ast.Value, error) { +func regoPartialInputValue(subject Subject, action policy.Action, objectType string) (ast.Value, error) { regoSubj, err := subject.regoValue() if err != nil { return nil, xerrors.Errorf("subject: %w", err) @@ -103,11 +105,11 @@ func (s Subject) regoValue() (ast.Value, error) { func (z Object) regoValue() ast.Value { userACL := ast.NewObject() for k, v := range z.ACLUserList { - userACL.Insert(ast.StringTerm(k), ast.NewTerm(regoSlice(v))) + userACL.Insert(ast.StringTerm(k), ast.NewTerm(regoSliceString(v...))) } grpACL := ast.NewObject() for k, v := range z.ACLGroupList { - grpACL.Insert(ast.StringTerm(k), ast.NewTerm(regoSlice(v))) + grpACL.Insert(ast.StringTerm(k), ast.NewTerm(regoSliceString(v...))) } return ast.NewObject( [2]*ast.Term{ @@ -200,10 +202,6 @@ func (perm Permission) regoValue() ast.Value { ) } -func (act Action) regoValue() ast.Value { - return ast.StringTerm(string(act)).Value -} - type regoValue interface { regoValue() ast.Value } @@ -218,10 +216,10 @@ func regoSlice[T regoValue](slice []T) *ast.Array { return ast.NewArray(terms...) } -func regoSliceString(slice ...string) *ast.Array { +func regoSliceString[T ~string](slice ...T) *ast.Array { terms := make([]*ast.Term, len(slice)) for i, v := range slice { - terms[i] = ast.StringTerm(v) + terms[i] = ast.StringTerm(string(v)) } return ast.NewArray(terms...) } diff --git a/coderd/rbac/authz.go b/coderd/rbac/authz.go index 08ff61da1372c..c647bb09f89a0 100644 --- a/coderd/rbac/authz.go +++ b/coderd/rbac/authz.go @@ -19,30 +19,21 @@ import ( "go.opentelemetry.io/otel/trace" "golang.org/x/xerrors" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/rbac/regosql" "github.com/coder/coder/v2/coderd/rbac/regosql/sqltypes" "github.com/coder/coder/v2/coderd/tracing" "github.com/coder/coder/v2/coderd/util/slice" ) -// Action represents the allowed actions to be done on an object. -type Action string - -const ( - ActionCreate Action = "create" - ActionRead Action = "read" - 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} +func AllActions() []policy.Action { + return []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete} } type AuthCall struct { Actor Subject - Action Action + Action policy.Action Object Object } @@ -52,7 +43,7 @@ type AuthCall struct { // // Note that this ignores some fields such as the permissions within a given // role, as this assumes all roles are static to a given role name. -func hashAuthorizeCall(actor Subject, action Action, object Object) [32]byte { +func hashAuthorizeCall(actor Subject, action policy.Action, object Object) [32]byte { var hashOut [32]byte hash := sha256.New() @@ -139,8 +130,8 @@ type Authorizer interface { // Authorize will authorize the given subject to perform the given action // on the given object. Authorize is pure and deterministic with respect to // its arguments and the surrounding object. - Authorize(ctx context.Context, subject Subject, action Action, object Object) error - Prepare(ctx context.Context, subject Subject, action Action, objectType string) (PreparedAuthorized, error) + Authorize(ctx context.Context, subject Subject, action policy.Action, object Object) error + Prepare(ctx context.Context, subject Subject, action policy.Action, objectType string) (PreparedAuthorized, error) } type PreparedAuthorized interface { @@ -154,7 +145,7 @@ type PreparedAuthorized interface { // // Ideally the 'CompileToSQL' is used instead for large sets. This cost scales // linearly with the number of objects passed in. -func Filter[O Objecter](ctx context.Context, auth Authorizer, subject Subject, action Action, objects []O) ([]O, error) { +func Filter[O Objecter](ctx context.Context, auth Authorizer, subject Subject, action policy.Action, objects []O) ([]O, error) { if len(objects) == 0 { // Nothing to filter return objects, nil @@ -236,7 +227,7 @@ var ( // Load the policy from policy.rego in this directory. // //go:embed policy.rego - policy string + regoPolicy string queryOnce sync.Once query rego.PreparedEvalQuery partialQuery rego.PreparedPartialQuery @@ -254,7 +245,7 @@ func NewAuthorizer(registry prometheus.Registerer) *RegoAuthorizer { var err error query, err = rego.New( rego.Query("data.authz.allow"), - rego.Module("policy.rego", policy), + rego.Module("policy.rego", regoPolicy), ).PrepareForEval(context.Background()) if err != nil { panic(xerrors.Errorf("compile rego: %w", err)) @@ -269,7 +260,7 @@ func NewAuthorizer(registry prometheus.Registerer) *RegoAuthorizer { "input.object.acl_group_list", }), rego.Query("data.authz.allow = true"), - rego.Module("policy.rego", policy), + rego.Module("policy.rego", regoPolicy), ).PrepareForPartial(context.Background()) if err != nil { panic(xerrors.Errorf("compile partial rego: %w", err)) @@ -334,7 +325,7 @@ type authSubject struct { // It returns `nil` if the subject is authorized to perform the action on // the object. // If an error is returned, the authorization is denied. -func (a RegoAuthorizer) Authorize(ctx context.Context, subject Subject, action Action, object Object) error { +func (a RegoAuthorizer) Authorize(ctx context.Context, subject Subject, action policy.Action, object Object) error { start := time.Now() ctx, span := tracing.StartSpan(ctx, trace.WithTimestamp(start), // Reuse the time.Now for metric and trace @@ -365,7 +356,7 @@ func (a RegoAuthorizer) Authorize(ctx context.Context, subject Subject, action A // It is a different function so the exported one can add tracing + metrics. // That code tends to clutter up the actual logic, so it's separated out. // nolint:revive -func (a RegoAuthorizer) authorize(ctx context.Context, subject Subject, action Action, object Object) error { +func (a RegoAuthorizer) authorize(ctx context.Context, subject Subject, action policy.Action, object Object) error { if subject.Roles == nil { return xerrors.Errorf("subject must have roles") } @@ -392,7 +383,7 @@ func (a RegoAuthorizer) authorize(ctx context.Context, subject Subject, action A // Prepare will partially execute the rego policy leaving the object fields unknown (except for the type). // This will vastly speed up performance if batch authorization on the same type of objects is needed. -func (a RegoAuthorizer) Prepare(ctx context.Context, subject Subject, action Action, objectType string) (PreparedAuthorized, error) { +func (a RegoAuthorizer) Prepare(ctx context.Context, subject Subject, action policy.Action, objectType string) (PreparedAuthorized, error) { start := time.Now() ctx, span := tracing.StartSpan(ctx, trace.WithTimestamp(start), @@ -428,7 +419,7 @@ type PartialAuthorizer struct { // input is used purely for debugging and logging. subjectInput Subject - subjectAction Action + subjectAction policy.Action subjectResourceType Object // preparedQueries are the compiled set of queries after partial evaluation. @@ -537,7 +528,7 @@ EachQueryLoop: pa.subjectInput, pa.subjectAction, pa.subjectResourceType, nil) } -func (a RegoAuthorizer) newPartialAuthorizer(ctx context.Context, subject Subject, action Action, objectType string) (*PartialAuthorizer, error) { +func (a RegoAuthorizer) newPartialAuthorizer(ctx context.Context, subject Subject, action policy.Action, objectType string) (*PartialAuthorizer, error) { if subject.Roles == nil { return nil, xerrors.Errorf("subject must have roles") } @@ -676,7 +667,7 @@ func Cacher(authz Authorizer) Authorizer { } } -func (c *authCache) Authorize(ctx context.Context, subject Subject, action Action, object Object) error { +func (c *authCache) Authorize(ctx context.Context, subject Subject, action policy.Action, object Object) error { authorizeCacheKey := hashAuthorizeCall(subject, action, object) var err error @@ -697,13 +688,13 @@ func (c *authCache) Authorize(ctx context.Context, subject Subject, action Actio // Prepare returns the underlying PreparedAuthorized. The cache does not apply // to prepared authorizations. These should be using a SQL filter, and // therefore the cache is not needed. -func (c *authCache) Prepare(ctx context.Context, subject Subject, action Action, objectType string) (PreparedAuthorized, error) { +func (c *authCache) Prepare(ctx context.Context, subject Subject, action policy.Action, objectType string) (PreparedAuthorized, error) { return c.authz.Prepare(ctx, subject, action, objectType) } // rbacTraceAttributes are the attributes that are added to all spans created by // the rbac package. These attributes should help to debug slow spans. -func rbacTraceAttributes(actor Subject, action Action, objectType string, extra ...attribute.KeyValue) trace.SpanStartOption { +func rbacTraceAttributes(actor Subject, action policy.Action, objectType string, extra ...attribute.KeyValue) trace.SpanStartOption { return trace.WithAttributes( append(extra, attribute.StringSlice("subject_roles", actor.SafeRoleNames()), diff --git a/coderd/rbac/authz_internal_test.go b/coderd/rbac/authz_internal_test.go index e264e31c73a8c..cba69952ea481 100644 --- a/coderd/rbac/authz_internal_test.go +++ b/coderd/rbac/authz_internal_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/xerrors" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/rbac/regosql" "github.com/coder/coder/v2/testutil" ) @@ -59,7 +60,7 @@ func TestFilterError(t *testing.T) { Scope: ScopeAll, } - _, err := Filter(context.Background(), auth, subject, ActionRead, []Object{ResourceUser, ResourceWorkspace}) + _, err := Filter(context.Background(), auth, subject, policy.ActionRead, []Object{ResourceUser, ResourceWorkspace}) require.ErrorContains(t, err, "object types must be uniform") }) @@ -67,7 +68,7 @@ func TestFilterError(t *testing.T) { t.Parallel() auth := &MockAuthorizer{ - AuthorizeFunc: func(ctx context.Context, subject Subject, action Action, object Object) error { + AuthorizeFunc: func(ctx context.Context, subject Subject, action policy.Action, object Object) error { // Authorize func always returns nil, unless the context is canceled. return ctx.Err() }, @@ -97,7 +98,7 @@ func TestFilterError(t *testing.T) { ResourceUser, } - _, err := Filter(ctx, auth, subject, ActionRead, objects) + _, err := Filter(ctx, auth, subject, policy.ActionRead, objects) require.ErrorIs(t, err, context.Canceled) }) @@ -117,7 +118,7 @@ func TestFilterError(t *testing.T) { bomb: cancel, } - _, err := Filter(ctx, auth, subject, ActionRead, objects) + _, err := Filter(ctx, auth, subject, policy.ActionRead, objects) require.ErrorIs(t, err, context.Canceled) }) }) @@ -150,7 +151,7 @@ func TestFilter(t *testing.T) { testCases := []struct { Name string Actor Subject - Action Action + Action policy.Action ObjectType string }{ { @@ -160,7 +161,7 @@ func TestFilter(t *testing.T) { Roles: RoleNames{}, }, ObjectType: ResourceWorkspace.Type, - Action: ActionRead, + Action: policy.ActionRead, }, { Name: "Admin", @@ -169,7 +170,7 @@ func TestFilter(t *testing.T) { Roles: RoleNames{RoleOrgMember(orgIDs[0]), "auditor", RoleOwner(), RoleMember()}, }, ObjectType: ResourceWorkspace.Type, - Action: ActionRead, + Action: policy.ActionRead, }, { Name: "OrgAdmin", @@ -178,7 +179,7 @@ func TestFilter(t *testing.T) { Roles: RoleNames{RoleOrgMember(orgIDs[0]), RoleOrgAdmin(orgIDs[0]), RoleMember()}, }, ObjectType: ResourceWorkspace.Type, - Action: ActionRead, + Action: policy.ActionRead, }, { Name: "OrgMember", @@ -187,7 +188,7 @@ func TestFilter(t *testing.T) { Roles: RoleNames{RoleOrgMember(orgIDs[0]), RoleOrgMember(orgIDs[1]), RoleMember()}, }, ObjectType: ResourceWorkspace.Type, - Action: ActionRead, + Action: policy.ActionRead, }, { Name: "ManyRoles", @@ -203,7 +204,7 @@ func TestFilter(t *testing.T) { }, }, ObjectType: ResourceWorkspace.Type, - Action: ActionRead, + Action: policy.ActionRead, }, { Name: "SiteMember", @@ -212,7 +213,7 @@ func TestFilter(t *testing.T) { Roles: RoleNames{RoleMember()}, }, ObjectType: ResourceUser.Type, - Action: ActionRead, + Action: policy.ActionRead, }, { Name: "ReadOrgs", @@ -227,7 +228,7 @@ func TestFilter(t *testing.T) { }, }, ObjectType: ResourceOrganization.Type, - Action: ActionRead, + Action: policy.ActionRead, }, { Name: "ScopeApplicationConnect", @@ -236,7 +237,7 @@ func TestFilter(t *testing.T) { Roles: RoleNames{RoleOrgMember(orgIDs[0]), "auditor", RoleOwner(), RoleMember()}, }, ObjectType: ResourceWorkspace.Type, - Action: ActionRead, + Action: policy.ActionRead, }, } @@ -263,7 +264,7 @@ func TestFilter(t *testing.T) { var allowedCount int for i, obj := range localObjects { obj.Type = tc.ObjectType - err := auth.Authorize(ctx, actor, ActionRead, obj.RBACObject()) + err := auth.Authorize(ctx, actor, policy.ActionRead, obj.RBACObject()) obj.Allowed = err == nil if err == nil { allowedCount++ @@ -301,64 +302,64 @@ func TestAuthorizeDomain(t *testing.T) { testAuthorize(t, "UserACLList", user, []authTestCase{ { - resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(unuseID).WithACLUserList(map[string][]Action{ + resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(unuseID).WithACLUserList(map[string][]policy.Action{ user.ID: AllActions(), }), actions: AllActions(), allow: true, }, { - resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(unuseID).WithACLUserList(map[string][]Action{ + resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(unuseID).WithACLUserList(map[string][]policy.Action{ user.ID: {WildcardSymbol}, }), actions: AllActions(), allow: true, }, { - resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(unuseID).WithACLUserList(map[string][]Action{ - user.ID: {ActionRead, ActionUpdate}, + resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(unuseID).WithACLUserList(map[string][]policy.Action{ + user.ID: {policy.ActionRead, policy.ActionUpdate}, }), - actions: []Action{ActionCreate, ActionDelete}, + actions: []policy.Action{policy.ActionCreate, policy.ActionDelete}, allow: false, }, { // By default users cannot update templates - resource: ResourceTemplate.InOrg(defOrg).WithACLUserList(map[string][]Action{ - user.ID: {ActionUpdate}, + resource: ResourceTemplate.InOrg(defOrg).WithACLUserList(map[string][]policy.Action{ + user.ID: {policy.ActionUpdate}, }), - actions: []Action{ActionUpdate}, + actions: []policy.Action{policy.ActionUpdate}, allow: true, }, }) testAuthorize(t, "GroupACLList", user, []authTestCase{ { - resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(defOrg).WithGroupACL(map[string][]Action{ + resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(defOrg).WithGroupACL(map[string][]policy.Action{ allUsersGroup: AllActions(), }), actions: AllActions(), allow: true, }, { - resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(defOrg).WithGroupACL(map[string][]Action{ + resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(defOrg).WithGroupACL(map[string][]policy.Action{ allUsersGroup: {WildcardSymbol}, }), actions: AllActions(), allow: true, }, { - resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(defOrg).WithGroupACL(map[string][]Action{ - allUsersGroup: {ActionRead, ActionUpdate}, + resource: ResourceWorkspace.WithOwner(unuseID.String()).InOrg(defOrg).WithGroupACL(map[string][]policy.Action{ + allUsersGroup: {policy.ActionRead, policy.ActionUpdate}, }), - actions: []Action{ActionCreate, ActionDelete}, + actions: []policy.Action{policy.ActionCreate, policy.ActionDelete}, allow: false, }, { // By default users cannot update templates - resource: ResourceTemplate.InOrg(defOrg).WithGroupACL(map[string][]Action{ - allUsersGroup: {ActionUpdate}, + resource: ResourceTemplate.InOrg(defOrg).WithGroupACL(map[string][]policy.Action{ + allUsersGroup: {policy.ActionUpdate}, }), - actions: []Action{ActionUpdate}, + actions: []policy.Action{policy.ActionUpdate}, allow: true, }, }) @@ -509,7 +510,7 @@ func TestAuthorizeDomain(t *testing.T) { testAuthorize(t, "ApplicationToken", user, // Create (connect) Actions cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionCreate} + c.actions = []policy.Action{policy.ActionCreate} return c }, []authTestCase{ // Org + me @@ -537,7 +538,7 @@ func TestAuthorizeDomain(t *testing.T) { }), // Not create actions cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionRead, ActionUpdate, ActionDelete} + c.actions = []policy.Action{policy.ActionRead, policy.ActionUpdate, policy.ActionDelete} c.allow = false return c }, []authTestCase{ @@ -566,7 +567,7 @@ func TestAuthorizeDomain(t *testing.T) { }), // Other Objects cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionCreate, ActionRead, ActionUpdate, ActionDelete} + c.actions = []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete} c.allow = false return c }, []authTestCase{ @@ -607,14 +608,14 @@ func TestAuthorizeDomain(t *testing.T) { defOrg.String(): {{ Negate: false, ResourceType: "*", - Action: ActionRead, + Action: policy.ActionRead, }}, }, User: []Permission{ { Negate: false, ResourceType: "*", - Action: ActionRead, + Action: policy.ActionRead, }, }, }, @@ -623,7 +624,7 @@ func TestAuthorizeDomain(t *testing.T) { testAuthorize(t, "ReadOnly", user, cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionRead} + c.actions = []policy.Action{policy.ActionRead} return c }, []authTestCase{ // Read @@ -653,7 +654,7 @@ func TestAuthorizeDomain(t *testing.T) { // Pass non-read actions cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionCreate, ActionUpdate, ActionDelete} + c.actions = []policy.Action{policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete} c.allow = false return c }, []authTestCase{ @@ -822,7 +823,7 @@ func TestAuthorizeScope(t *testing.T) { testAuthorize(t, "Admin_ScopeApplicationConnect", user, cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionRead, ActionUpdate, ActionDelete} + c.actions = []policy.Action{policy.ActionRead, policy.ActionUpdate, policy.ActionDelete} return c }, []authTestCase{ {resource: ResourceWorkspace.InOrg(defOrg).WithOwner(user.ID), allow: false}, @@ -839,9 +840,9 @@ func TestAuthorizeScope(t *testing.T) { }), // Allowed by scope: []authTestCase{ - {resource: ResourceWorkspaceApplicationConnect.InOrg(defOrg).WithOwner("not-me"), actions: []Action{ActionCreate}, allow: true}, - {resource: ResourceWorkspaceApplicationConnect.InOrg(defOrg).WithOwner(user.ID), actions: []Action{ActionCreate}, allow: true}, - {resource: ResourceWorkspaceApplicationConnect.InOrg(unusedID).WithOwner("not-me"), actions: []Action{ActionCreate}, allow: true}, + {resource: ResourceWorkspaceApplicationConnect.InOrg(defOrg).WithOwner("not-me"), actions: []policy.Action{policy.ActionCreate}, allow: true}, + {resource: ResourceWorkspaceApplicationConnect.InOrg(defOrg).WithOwner(user.ID), actions: []policy.Action{policy.ActionCreate}, allow: true}, + {resource: ResourceWorkspaceApplicationConnect.InOrg(unusedID).WithOwner("not-me"), actions: []policy.Action{policy.ActionCreate}, allow: true}, }, ) @@ -856,7 +857,7 @@ func TestAuthorizeScope(t *testing.T) { testAuthorize(t, "User_ScopeApplicationConnect", user, cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionRead, ActionUpdate, ActionDelete} + c.actions = []policy.Action{policy.ActionRead, policy.ActionUpdate, policy.ActionDelete} c.allow = false return c }, []authTestCase{ @@ -874,9 +875,9 @@ func TestAuthorizeScope(t *testing.T) { }), // Allowed by scope: []authTestCase{ - {resource: ResourceWorkspaceApplicationConnect.InOrg(defOrg).WithOwner(user.ID), actions: []Action{ActionCreate}, allow: true}, - {resource: ResourceWorkspaceApplicationConnect.InOrg(defOrg).WithOwner("not-me"), actions: []Action{ActionCreate}, allow: false}, - {resource: ResourceWorkspaceApplicationConnect.InOrg(unusedID).WithOwner("not-me"), actions: []Action{ActionCreate}, allow: false}, + {resource: ResourceWorkspaceApplicationConnect.InOrg(defOrg).WithOwner(user.ID), actions: []policy.Action{policy.ActionCreate}, allow: true}, + {resource: ResourceWorkspaceApplicationConnect.InOrg(defOrg).WithOwner("not-me"), actions: []policy.Action{policy.ActionCreate}, allow: false}, + {resource: ResourceWorkspaceApplicationConnect.InOrg(unusedID).WithOwner("not-me"), actions: []policy.Action{policy.ActionCreate}, allow: false}, }, ) @@ -891,9 +892,9 @@ func TestAuthorizeScope(t *testing.T) { Role: Role{ Name: "workspace_agent", DisplayName: "Workspace Agent", - Site: Permissions(map[string][]Action{ + Site: Permissions(map[string][]policy.Action{ // Only read access for workspaces. - ResourceWorkspace.Type: {ActionRead}, + ResourceWorkspace.Type: {policy.ActionRead}, }), Org: map[string][]Permission{}, User: []Permission{}, @@ -905,7 +906,7 @@ func TestAuthorizeScope(t *testing.T) { testAuthorize(t, "User_WorkspaceAgent", user, // Test cases without ID cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionCreate, ActionUpdate, ActionDelete} + c.actions = []policy.Action{policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete} c.allow = false return c }, []authTestCase{ @@ -924,7 +925,7 @@ func TestAuthorizeScope(t *testing.T) { // Test all cases with the workspace id cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionCreate, ActionUpdate, ActionDelete} + c.actions = []policy.Action{policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete} c.allow = false c.resource.WithID(workspaceID) return c @@ -943,7 +944,7 @@ func TestAuthorizeScope(t *testing.T) { }), // Test cases with random ids. These should always fail from the scope. cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionRead, ActionCreate, ActionUpdate, ActionDelete} + c.actions = []policy.Action{policy.ActionRead, policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete} c.allow = false c.resource.WithID(uuid.New()) return c @@ -962,10 +963,10 @@ func TestAuthorizeScope(t *testing.T) { }), // Allowed by scope: []authTestCase{ - {resource: ResourceWorkspace.WithID(workspaceID).InOrg(defOrg).WithOwner(user.ID), actions: []Action{ActionRead}, allow: true}, + {resource: ResourceWorkspace.WithID(workspaceID).InOrg(defOrg).WithOwner(user.ID), actions: []policy.Action{policy.ActionRead}, allow: true}, // The scope will return true, but the user perms return false for resources not owned by the user. - {resource: ResourceWorkspace.WithID(workspaceID).InOrg(defOrg).WithOwner("not-me"), actions: []Action{ActionRead}, allow: false}, - {resource: ResourceWorkspace.WithID(workspaceID).InOrg(unusedID).WithOwner("not-me"), actions: []Action{ActionRead}, allow: false}, + {resource: ResourceWorkspace.WithID(workspaceID).InOrg(defOrg).WithOwner("not-me"), actions: []policy.Action{policy.ActionRead}, allow: false}, + {resource: ResourceWorkspace.WithID(workspaceID).InOrg(unusedID).WithOwner("not-me"), actions: []policy.Action{policy.ActionRead}, allow: false}, }, ) @@ -980,9 +981,9 @@ func TestAuthorizeScope(t *testing.T) { Role: Role{ Name: "create_workspace", DisplayName: "Create Workspace", - Site: Permissions(map[string][]Action{ + Site: Permissions(map[string][]policy.Action{ // Only read access for workspaces. - ResourceWorkspace.Type: {ActionCreate}, + ResourceWorkspace.Type: {policy.ActionCreate}, }), Org: map[string][]Permission{}, User: []Permission{}, @@ -995,7 +996,7 @@ func TestAuthorizeScope(t *testing.T) { testAuthorize(t, "CreatWorkspaceScope", user, // All these cases will fail because a resource ID is set. cases(func(c authTestCase) authTestCase { - c.actions = []Action{ActionCreate, ActionRead, ActionUpdate, ActionDelete} + c.actions = []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete} c.allow = false c.resource.ID = uuid.NewString() return c @@ -1015,10 +1016,10 @@ func TestAuthorizeScope(t *testing.T) { // Test create allowed by scope: []authTestCase{ - {resource: ResourceWorkspace.InOrg(defOrg).WithOwner(user.ID), actions: []Action{ActionCreate}, allow: true}, + {resource: ResourceWorkspace.InOrg(defOrg).WithOwner(user.ID), actions: []policy.Action{policy.ActionCreate}, allow: true}, // The scope will return true, but the user perms return false for resources not owned by the user. - {resource: ResourceWorkspace.InOrg(defOrg).WithOwner("not-me"), actions: []Action{ActionCreate}, allow: false}, - {resource: ResourceWorkspace.InOrg(unusedID).WithOwner("not-me"), actions: []Action{ActionCreate}, allow: false}, + {resource: ResourceWorkspace.InOrg(defOrg).WithOwner("not-me"), actions: []policy.Action{policy.ActionCreate}, allow: false}, + {resource: ResourceWorkspace.InOrg(unusedID).WithOwner("not-me"), actions: []policy.Action{policy.ActionCreate}, allow: false}, }, ) } @@ -1036,7 +1037,7 @@ func cases(opt func(c authTestCase) authTestCase, cases []authTestCase) []authTe type authTestCase struct { resource Object - actions []Action + actions []policy.Action allow bool } @@ -1127,16 +1128,16 @@ func must[T any](value T, err error) T { } type MockAuthorizer struct { - AuthorizeFunc func(context.Context, Subject, Action, Object) error + AuthorizeFunc func(context.Context, Subject, policy.Action, Object) error } var _ Authorizer = (*MockAuthorizer)(nil) -func (d *MockAuthorizer) Authorize(ctx context.Context, s Subject, a Action, o Object) error { +func (d *MockAuthorizer) Authorize(ctx context.Context, s Subject, a policy.Action, o Object) error { return d.AuthorizeFunc(ctx, s, a, o) } -func (d *MockAuthorizer) Prepare(_ context.Context, subject Subject, action Action, _ string) (PreparedAuthorized, error) { +func (d *MockAuthorizer) Prepare(_ context.Context, subject Subject, action policy.Action, _ string) (PreparedAuthorized, error) { return &mockPreparedAuthorizer{ Original: d, Subject: subject, @@ -1152,7 +1153,7 @@ type mockPreparedAuthorizer struct { sync.RWMutex Original *MockAuthorizer Subject Subject - Action Action + Action policy.Action } func (f *mockPreparedAuthorizer) Authorize(ctx context.Context, object Object) error { diff --git a/coderd/rbac/authz_test.go b/coderd/rbac/authz_test.go index 9a38c94e33033..4ac8f20d94506 100644 --- a/coderd/rbac/authz_test.go +++ b/coderd/rbac/authz_test.go @@ -12,6 +12,7 @@ import ( "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/testutil" ) @@ -167,7 +168,7 @@ func BenchmarkRBACAuthorize(b *testing.B) { objects := benchmarkSetup(orgs, users, b.N) b.ResetTimer() for i := 0; i < b.N; i++ { - allowed := authorizer.Authorize(context.Background(), c.Actor, rbac.ActionRead, objects[b.N%len(objects)]) + allowed := authorizer.Authorize(context.Background(), c.Actor, policy.ActionRead, objects[b.N%len(objects)]) _ = allowed } }) @@ -191,30 +192,30 @@ func BenchmarkRBACAuthorizeGroups(b *testing.B) { // Same benchmark cases, but this time groups will be used to match. // Some '*' permissions will still match, but using a fake action reduces // the chance. - neverMatchAction := rbac.Action("never-match-action") + neverMatchAction := policy.Action("never-match-action") for _, c := range benchCases { b.Run(c.Name+"GroupACL", func(b *testing.B) { userGroupAllow := uuid.NewString() c.Actor.Groups = append(c.Actor.Groups, userGroupAllow) c.Actor.Scope = rbac.ScopeAll objects := benchmarkSetup(orgs, users, b.N, func(object rbac.Object) rbac.Object { - m := map[string][]rbac.Action{ + m := map[string][]policy.Action{ // Add the user's group // Noise - uuid.NewString(): {rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, - uuid.NewString(): {rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate}, - uuid.NewString(): {rbac.ActionCreate, rbac.ActionRead}, - uuid.NewString(): {rbac.ActionCreate}, - uuid.NewString(): {rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, - uuid.NewString(): {rbac.ActionRead, rbac.ActionUpdate}, + uuid.NewString(): {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + uuid.NewString(): {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate}, + uuid.NewString(): {policy.ActionCreate, policy.ActionRead}, + uuid.NewString(): {policy.ActionCreate}, + uuid.NewString(): {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + uuid.NewString(): {policy.ActionRead, policy.ActionUpdate}, } for _, g := range c.Actor.Groups { // Every group the user is in will be added, but it will not match the perms. This makes the // authorizer look at many groups before finding the one that matches. - m[g] = []rbac.Action{rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete} + m[g] = []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete} } // This is the only group that will give permission. - m[userGroupAllow] = []rbac.Action{neverMatchAction} + m[userGroupAllow] = []policy.Action{neverMatchAction} return object.WithGroupACL(m) }) b.ResetTimer() @@ -244,7 +245,7 @@ func BenchmarkRBACFilter(b *testing.B) { b.Run("PrepareOnly-"+c.Name, func(b *testing.B) { obType := rbac.ResourceWorkspace.Type for i := 0; i < b.N; i++ { - _, err := authorizer.Prepare(context.Background(), c.Actor, rbac.ActionRead, obType) + _, err := authorizer.Prepare(context.Background(), c.Actor, policy.ActionRead, obType) require.NoError(b, err) } }) @@ -254,7 +255,7 @@ func BenchmarkRBACFilter(b *testing.B) { b.Run(c.Name, func(b *testing.B) { objects := benchmarkSetup(orgs, users, b.N) b.ResetTimer() - allowed, err := rbac.Filter(context.Background(), authorizer, c.Actor, rbac.ActionRead, objects) + allowed, err := rbac.Filter(context.Background(), authorizer, c.Actor, policy.ActionRead, objects) require.NoError(b, err) _ = allowed }) @@ -263,9 +264,9 @@ func BenchmarkRBACFilter(b *testing.B) { func benchmarkSetup(orgs []uuid.UUID, users []uuid.UUID, size int, opts ...func(object rbac.Object) rbac.Object) []rbac.Object { // Create a "random" but deterministic set of objects. - aclList := map[string][]rbac.Action{ - uuid.NewString(): {rbac.ActionRead, rbac.ActionUpdate}, - uuid.NewString(): {rbac.ActionCreate}, + aclList := map[string][]policy.Action{ + uuid.NewString(): {policy.ActionRead, policy.ActionUpdate}, + uuid.NewString(): {policy.ActionCreate}, } objectList := make([]rbac.Object, size) for i := range objectList { @@ -297,7 +298,7 @@ func BenchmarkCacher(b *testing.B) { var ( subj rbac.Subject obj rbac.Object - action rbac.Action + action policy.Action ) for i := 0; i < b.N; i++ { if i%rat == 0 { @@ -359,7 +360,7 @@ func TestCacher(t *testing.T) { var ( ctx = testutil.Context(t, testutil.WaitShort) authOut = make(chan error, 1) // buffered to not block - authorizeFunc = func(ctx context.Context, subject rbac.Subject, action rbac.Action, object rbac.Object) error { + authorizeFunc = func(ctx context.Context, subject rbac.Subject, action policy.Action, object rbac.Object) error { // Just return what you're told. return testutil.RequireRecvCtx(ctx, t, authOut) } diff --git a/coderd/rbac/error.go b/coderd/rbac/error.go index 37c83f759efa3..98735ade322c4 100644 --- a/coderd/rbac/error.go +++ b/coderd/rbac/error.go @@ -11,6 +11,7 @@ import ( "golang.org/x/xerrors" "github.com/coder/coder/v2/coderd/httpapi/httpapiconstraints" + "github.com/coder/coder/v2/coderd/rbac/policy" ) const ( @@ -28,7 +29,7 @@ type UnauthorizedError struct { // These fields are for debugging purposes. subject Subject - action Action + action policy.Action // Note only the object type is set for partial execution. object Object @@ -52,7 +53,7 @@ func IsUnauthorizedError(err error) bool { // ForbiddenWithInternal creates a new error that will return a simple // "forbidden" to the client, logging internally the more detailed message // provided. -func ForbiddenWithInternal(internal error, subject Subject, action Action, object Object, output rego.ResultSet) *UnauthorizedError { +func ForbiddenWithInternal(internal error, subject Subject, action policy.Action, object Object, output rego.ResultSet) *UnauthorizedError { return &UnauthorizedError{ internal: internal, subject: subject, diff --git a/coderd/rbac/object.go b/coderd/rbac/object.go index 51b6da339c6ee..bac8b90fe90c4 100644 --- a/coderd/rbac/object.go +++ b/coderd/rbac/object.go @@ -2,6 +2,8 @@ package rbac import ( "github.com/google/uuid" + + "github.com/coder/coder/v2/coderd/rbac/policy" ) const WildcardSymbol = "*" @@ -250,8 +252,8 @@ type Object struct { // Type is "workspace", "project", "app", etc Type string `json:"type"` - ACLUserList map[string][]Action ` json:"acl_user_list"` - ACLGroupList map[string][]Action ` json:"acl_group_list"` + ACLUserList map[string][]policy.Action ` json:"acl_user_list"` + ACLGroupList map[string][]policy.Action ` json:"acl_group_list"` } func (z Object) Equal(b Object) bool { @@ -279,7 +281,7 @@ func (z Object) Equal(b Object) bool { return true } -func equalACLLists(a, b map[string][]Action) bool { +func equalACLLists(a, b map[string][]policy.Action) bool { if len(a) != len(b) { return false } @@ -307,8 +309,8 @@ func (z Object) All() Object { Owner: "", OrgID: "", Type: z.Type, - ACLUserList: map[string][]Action{}, - ACLGroupList: map[string][]Action{}, + ACLUserList: map[string][]policy.Action{}, + ACLGroupList: map[string][]policy.Action{}, } } @@ -359,7 +361,7 @@ func (z Object) WithOwner(ownerID string) Object { } // WithACLUserList adds an ACL list to a given object -func (z Object) WithACLUserList(acl map[string][]Action) Object { +func (z Object) WithACLUserList(acl map[string][]policy.Action) Object { return Object{ ID: z.ID, Owner: z.Owner, @@ -370,7 +372,7 @@ func (z Object) WithACLUserList(acl map[string][]Action) Object { } } -func (z Object) WithGroupACL(groups map[string][]Action) Object { +func (z Object) WithGroupACL(groups map[string][]policy.Action) Object { return Object{ ID: z.ID, Owner: z.Owner, diff --git a/coderd/rbac/object_test.go b/coderd/rbac/object_test.go index 505f12b8cc7b0..373119f7f0e57 100644 --- a/coderd/rbac/object_test.go +++ b/coderd/rbac/object_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/util/slice" ) @@ -24,8 +25,8 @@ func TestObjectEqual(t *testing.T) { { Name: "NilVs0", A: rbac.Object{ - ACLGroupList: map[string][]rbac.Action{}, - ACLUserList: map[string][]rbac.Action{}, + ACLGroupList: map[string][]policy.Action{}, + ACLUserList: map[string][]policy.Action{}, }, B: rbac.Object{}, Expected: true, @@ -37,16 +38,16 @@ func TestObjectEqual(t *testing.T) { Owner: "owner", OrgID: "orgID", Type: "type", - ACLUserList: map[string][]rbac.Action{}, - ACLGroupList: map[string][]rbac.Action{}, + ACLUserList: map[string][]policy.Action{}, + ACLGroupList: map[string][]policy.Action{}, }, B: rbac.Object{ ID: "id", Owner: "owner", OrgID: "orgID", Type: "type", - ACLUserList: map[string][]rbac.Action{}, - ACLGroupList: map[string][]rbac.Action{}, + ACLUserList: map[string][]policy.Action{}, + ACLGroupList: map[string][]policy.Action{}, }, Expected: true, }, @@ -93,13 +94,13 @@ func TestObjectEqual(t *testing.T) { { Name: "DifferentACLUserList", A: rbac.Object{ - ACLUserList: map[string][]rbac.Action{ - "user1": {rbac.ActionRead}, + ACLUserList: map[string][]policy.Action{ + "user1": {policy.ActionRead}, }, }, B: rbac.Object{ - ACLUserList: map[string][]rbac.Action{ - "user2": {rbac.ActionRead}, + ACLUserList: map[string][]policy.Action{ + "user2": {policy.ActionRead}, }, }, Expected: false, @@ -107,13 +108,13 @@ func TestObjectEqual(t *testing.T) { { Name: "ACLUserDiff#Actions", A: rbac.Object{ - ACLUserList: map[string][]rbac.Action{ - "user1": {rbac.ActionRead}, + ACLUserList: map[string][]policy.Action{ + "user1": {policy.ActionRead}, }, }, B: rbac.Object{ - ACLUserList: map[string][]rbac.Action{ - "user1": {rbac.ActionRead, rbac.ActionUpdate}, + ACLUserList: map[string][]policy.Action{ + "user1": {policy.ActionRead, policy.ActionUpdate}, }, }, Expected: false, @@ -121,13 +122,13 @@ func TestObjectEqual(t *testing.T) { { Name: "ACLUserDiffAction", A: rbac.Object{ - ACLUserList: map[string][]rbac.Action{ - "user1": {rbac.ActionRead}, + ACLUserList: map[string][]policy.Action{ + "user1": {policy.ActionRead}, }, }, B: rbac.Object{ - ACLUserList: map[string][]rbac.Action{ - "user1": {rbac.ActionUpdate}, + ACLUserList: map[string][]policy.Action{ + "user1": {policy.ActionUpdate}, }, }, Expected: false, @@ -135,14 +136,14 @@ func TestObjectEqual(t *testing.T) { { Name: "ACLUserDiff#Users", A: rbac.Object{ - ACLUserList: map[string][]rbac.Action{ - "user1": {rbac.ActionRead}, + ACLUserList: map[string][]policy.Action{ + "user1": {policy.ActionRead}, }, }, B: rbac.Object{ - ACLUserList: map[string][]rbac.Action{ - "user1": {rbac.ActionRead}, - "user2": {rbac.ActionRead}, + ACLUserList: map[string][]policy.Action{ + "user1": {policy.ActionRead}, + "user2": {policy.ActionRead}, }, }, Expected: false, @@ -150,13 +151,13 @@ func TestObjectEqual(t *testing.T) { { Name: "DifferentACLGroupList", A: rbac.Object{ - ACLGroupList: map[string][]rbac.Action{ - "group1": {rbac.ActionRead}, + ACLGroupList: map[string][]policy.Action{ + "group1": {policy.ActionRead}, }, }, B: rbac.Object{ - ACLGroupList: map[string][]rbac.Action{ - "group2": {rbac.ActionRead}, + ACLGroupList: map[string][]policy.Action{ + "group2": {policy.ActionRead}, }, }, Expected: false, diff --git a/coderd/rbac/policy/policy.go b/coderd/rbac/policy/policy.go new file mode 100644 index 0000000000000..a3c0dc9f3436b --- /dev/null +++ b/coderd/rbac/policy/policy.go @@ -0,0 +1,11 @@ +package policy + +// Action represents the allowed actions to be done on an object. +type Action string + +const ( + ActionCreate Action = "create" + ActionRead Action = "read" + ActionUpdate Action = "update" + ActionDelete Action = "delete" +) diff --git a/coderd/rbac/roles.go b/coderd/rbac/roles.go index ebe122386fb99..f69cf49174f60 100644 --- a/coderd/rbac/roles.go +++ b/coderd/rbac/roles.go @@ -8,6 +8,8 @@ import ( "github.com/open-policy-agent/opa/ast" "golang.org/x/xerrors" + + "github.com/coder/coder/v2/coderd/rbac/policy" ) const ( @@ -144,22 +146,22 @@ func ReloadBuiltinRoles(opts *RoleOptions) { memberRole := Role{ Name: member, DisplayName: "Member", - Site: Permissions(map[string][]Action{ - ResourceRoleAssignment.Type: {ActionRead}, + Site: Permissions(map[string][]policy.Action{ + ResourceRoleAssignment.Type: {policy.ActionRead}, // All users can see the provisioner daemons. - ResourceProvisionerDaemon.Type: {ActionRead}, + ResourceProvisionerDaemon.Type: {policy.ActionRead}, // All users can see OAuth2 provider applications. - ResourceOAuth2ProviderApp.Type: {ActionRead}, + ResourceOAuth2ProviderApp.Type: {policy.ActionRead}, }), Org: map[string][]Permission{}, User: append(allPermsExcept(ResourceWorkspaceDormant, ResourceUser, ResourceOrganizationMember), - Permissions(map[string][]Action{ + Permissions(map[string][]policy.Action{ // Users cannot do create/update/delete on themselves, but they // can read their own details. - ResourceUser.Type: {ActionRead}, - ResourceUserWorkspaceBuildParameters.Type: {ActionRead}, + ResourceUser.Type: {policy.ActionRead}, + ResourceUserWorkspaceBuildParameters.Type: {policy.ActionRead}, // Users can create provisioner daemons scoped to themselves. - ResourceProvisionerDaemon.Type: {ActionCreate, ActionRead, ActionUpdate}, + ResourceProvisionerDaemon.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate}, })..., ), }.withCachedRegoValue() @@ -167,19 +169,19 @@ func ReloadBuiltinRoles(opts *RoleOptions) { auditorRole := Role{ Name: auditor, DisplayName: "Auditor", - Site: Permissions(map[string][]Action{ + Site: Permissions(map[string][]policy.Action{ // Should be able to read all template details, even in orgs they // are not in. - ResourceTemplate.Type: {ActionRead}, - ResourceTemplateInsights.Type: {ActionRead}, - ResourceAuditLog.Type: {ActionRead}, - ResourceUser.Type: {ActionRead}, - ResourceGroup.Type: {ActionRead}, + ResourceTemplate.Type: {policy.ActionRead}, + ResourceTemplateInsights.Type: {policy.ActionRead}, + ResourceAuditLog.Type: {policy.ActionRead}, + ResourceUser.Type: {policy.ActionRead}, + ResourceGroup.Type: {policy.ActionRead}, // Allow auditors to query deployment stats and insights. - ResourceDeploymentStats.Type: {ActionRead}, - ResourceDeploymentValues.Type: {ActionRead}, + ResourceDeploymentStats.Type: {policy.ActionRead}, + ResourceDeploymentValues.Type: {policy.ActionRead}, // Org roles are not really used yet, so grant the perm at the site level. - ResourceOrganizationMember.Type: {ActionRead}, + ResourceOrganizationMember.Type: {policy.ActionRead}, }), Org: map[string][]Permission{}, User: []Permission{}, @@ -188,21 +190,21 @@ func ReloadBuiltinRoles(opts *RoleOptions) { templateAdminRole := Role{ Name: templateAdmin, DisplayName: "Template Admin", - Site: Permissions(map[string][]Action{ - ResourceTemplate.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete}, + Site: Permissions(map[string][]policy.Action{ + ResourceTemplate.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, // CRUD all files, even those they did not upload. - ResourceFile.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete}, - ResourceWorkspace.Type: {ActionRead}, + ResourceFile.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + ResourceWorkspace.Type: {policy.ActionRead}, // CRUD to provisioner daemons for now. - ResourceProvisionerDaemon.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete}, + ResourceProvisionerDaemon.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, // Needs to read all organizations since - ResourceOrganization.Type: {ActionRead}, - ResourceUser.Type: {ActionRead}, - ResourceGroup.Type: {ActionRead}, + ResourceOrganization.Type: {policy.ActionRead}, + ResourceUser.Type: {policy.ActionRead}, + ResourceGroup.Type: {policy.ActionRead}, // Org roles are not really used yet, so grant the perm at the site level. - ResourceOrganizationMember.Type: {ActionRead}, + ResourceOrganizationMember.Type: {policy.ActionRead}, // Template admins can read all template insights data - ResourceTemplateInsights.Type: {ActionRead}, + ResourceTemplateInsights.Type: {policy.ActionRead}, }), Org: map[string][]Permission{}, User: []Permission{}, @@ -211,14 +213,14 @@ func ReloadBuiltinRoles(opts *RoleOptions) { userAdminRole := Role{ Name: userAdmin, DisplayName: "User Admin", - Site: Permissions(map[string][]Action{ - ResourceRoleAssignment.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete}, - ResourceUser.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete}, - ResourceUserData.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete}, - ResourceUserWorkspaceBuildParameters.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete}, + Site: Permissions(map[string][]policy.Action{ + ResourceRoleAssignment.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + ResourceUser.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + ResourceUserData.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + ResourceUserWorkspaceBuildParameters.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, // Full perms to manage org members - ResourceOrganizationMember.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete}, - ResourceGroup.Type: {ActionCreate, ActionRead, ActionUpdate, ActionDelete}, + ResourceOrganizationMember.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, + ResourceGroup.Type: {policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, }), Org: map[string][]Permission{}, User: []Permission{}, @@ -277,19 +279,19 @@ func ReloadBuiltinRoles(opts *RoleOptions) { { // All org members can read the organization ResourceType: ResourceOrganization.Type, - Action: ActionRead, + Action: policy.ActionRead, }, { // Can read available roles. ResourceType: ResourceOrgRoleAssignment.Type, - Action: ActionRead, + Action: policy.ActionRead, }, }, }, User: []Permission{ { ResourceType: ResourceOrganizationMember.Type, - Action: ActionRead, + Action: policy.ActionRead, }, }, } @@ -349,9 +351,9 @@ type ExpandableRoles interface { // Permission is the format passed into the rego. type Permission struct { // Negate makes this a negative permission - Negate bool `json:"negate"` - ResourceType string `json:"resource_type"` - Action Action `json:"action"` + Negate bool `json:"negate"` + ResourceType string `json:"resource_type"` + Action policy.Action `json:"action"` } // Role is a set of permissions at multiple levels: @@ -521,7 +523,7 @@ func SiteRoles() []Role { // ChangeRoleSet is a helper function that finds the difference of 2 sets of // roles. When setting a user's new roles, it is equivalent to adding and // removing roles. This set determines the changes, so that the appropriate -// RBAC checks can be applied using "ActionCreate" and "ActionDelete" for +// RBAC checks can be applied using "policy.ActionCreate" and "policy.ActionDelete" for // "added" and "removed" roles respectively. func ChangeRoleSet(from []string, to []string) (added []string, removed []string) { has := make(map[string]struct{}) @@ -579,7 +581,7 @@ func roleSplit(role string) (name string, orgID string, err error) { // Permissions is just a helper function to make building roles that list out resources // and actions a bit easier. -func Permissions(perms map[string][]Action) []Permission { +func Permissions(perms map[string][]policy.Action) []Permission { list := make([]Permission, 0, len(perms)) for k, actions := range perms { for _, act := range actions { diff --git a/coderd/rbac/roles_internal_test.go b/coderd/rbac/roles_internal_test.go index 2055cfaafe42c..07126981081d8 100644 --- a/coderd/rbac/roles_internal_test.go +++ b/coderd/rbac/roles_internal_test.go @@ -6,6 +6,8 @@ import ( "github.com/google/uuid" "github.com/open-policy-agent/opa/ast" "github.com/stretchr/testify/require" + + "github.com/coder/coder/v2/coderd/rbac/policy" ) // BenchmarkRBACValueAllocation benchmarks the cost of allocating a rego input @@ -27,13 +29,13 @@ func BenchmarkRBACValueAllocation(b *testing.B) { WithID(uuid.New()). InOrg(uuid.New()). WithOwner(uuid.NewString()). - WithGroupACL(map[string][]Action{ - uuid.NewString(): {ActionRead, ActionCreate}, - uuid.NewString(): {ActionRead, ActionCreate}, - uuid.NewString(): {ActionRead, ActionCreate}, - }).WithACLUserList(map[string][]Action{ - uuid.NewString(): {ActionRead, ActionCreate}, - uuid.NewString(): {ActionRead, ActionCreate}, + WithGroupACL(map[string][]policy.Action{ + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, + }).WithACLUserList(map[string][]policy.Action{ + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, }) jsonSubject := authSubject{ @@ -45,7 +47,7 @@ func BenchmarkRBACValueAllocation(b *testing.B) { b.Run("ManualRegoValue", func(b *testing.B) { for i := 0; i < b.N; i++ { - _, err := regoInputValue(actor, ActionRead, obj) + _, err := regoInputValue(actor, policy.ActionRead, obj) require.NoError(b, err) } }) @@ -53,7 +55,7 @@ func BenchmarkRBACValueAllocation(b *testing.B) { for i := 0; i < b.N; i++ { _, err := ast.InterfaceToValue(map[string]interface{}{ "subject": jsonSubject, - "action": ActionRead, + "action": policy.ActionRead, "object": obj, }) require.NoError(b, err) @@ -90,16 +92,16 @@ func TestRegoInputValue(t *testing.T) { WithID(uuid.New()). InOrg(uuid.New()). WithOwner(uuid.NewString()). - WithGroupACL(map[string][]Action{ - uuid.NewString(): {ActionRead, ActionCreate}, - uuid.NewString(): {ActionRead, ActionCreate}, - uuid.NewString(): {ActionRead, ActionCreate}, - }).WithACLUserList(map[string][]Action{ - uuid.NewString(): {ActionRead, ActionCreate}, - uuid.NewString(): {ActionRead, ActionCreate}, + WithGroupACL(map[string][]policy.Action{ + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, + }).WithACLUserList(map[string][]policy.Action{ + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, + uuid.NewString(): {policy.ActionRead, policy.ActionCreate}, }) - action := ActionRead + action := policy.ActionRead t.Run("InputValue", func(t *testing.T) { t.Parallel() diff --git a/coderd/rbac/roles_test.go b/coderd/rbac/roles_test.go index 7ef98a7f3d46e..b5e78e606b8d4 100644 --- a/coderd/rbac/roles_test.go +++ b/coderd/rbac/roles_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" ) type authSubject struct { @@ -35,7 +36,7 @@ func TestOwnerExec(t *testing.T) { auth := rbac.NewCachingAuthorizer(prometheus.NewRegistry()) // Exec a random workspace - err := auth.Authorize(context.Background(), owner, rbac.ActionCreate, + err := auth.Authorize(context.Background(), owner, policy.ActionCreate, rbac.ResourceWorkspaceExecution.WithID(uuid.New()).InOrg(uuid.New()).WithOwner(uuid.NewString())) require.ErrorAsf(t, err, &rbac.UnauthorizedError{}, "expected unauthorized error") }) @@ -49,7 +50,7 @@ func TestOwnerExec(t *testing.T) { auth := rbac.NewCachingAuthorizer(prometheus.NewRegistry()) // Exec a random workspace - err := auth.Authorize(context.Background(), owner, rbac.ActionCreate, + err := auth.Authorize(context.Background(), owner, policy.ActionCreate, rbac.ResourceWorkspaceExecution.WithID(uuid.New()).InOrg(uuid.New()).WithOwner(uuid.NewString())) require.NoError(t, err, "expected owner can") }) @@ -94,7 +95,7 @@ func TestRolePermissions(t *testing.T) { // Name the test case to better locate the failing test case. Name string Resource rbac.Object - Actions []rbac.Action + Actions []policy.Action // AuthorizeMap must cover all subjects in 'requiredSubjects'. // This map will run an Authorize() check with the resource, action, // and subjects. The subjects are split into 2 categories, "true" and @@ -105,7 +106,7 @@ func TestRolePermissions(t *testing.T) { }{ { Name: "MyUser", - Actions: []rbac.Action{rbac.ActionRead}, + Actions: []policy.Action{policy.ActionRead}, Resource: rbac.ResourceUserObject(currentUser), AuthorizeMap: map[bool][]authSubject{ true: {orgMemberMe, owner, memberMe, templateAdmin, userAdmin}, @@ -114,7 +115,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "AUser", - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceUser, AuthorizeMap: map[bool][]authSubject{ true: {owner, userAdmin}, @@ -124,7 +125,7 @@ func TestRolePermissions(t *testing.T) { { Name: "ReadMyWorkspaceInOrg", // When creating the WithID won't be set, but it does not change the result. - Actions: []rbac.Action{rbac.ActionRead}, + Actions: []policy.Action{policy.ActionRead}, Resource: rbac.ResourceWorkspace.WithID(workspaceID).InOrg(orgID).WithOwner(currentUser.String()), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgMemberMe, orgAdmin, templateAdmin}, @@ -134,7 +135,7 @@ func TestRolePermissions(t *testing.T) { { Name: "C_RDMyWorkspaceInOrg", // When creating the WithID won't be set, but it does not change the result. - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceWorkspace.WithID(workspaceID).InOrg(orgID).WithOwner(currentUser.String()), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgMemberMe, orgAdmin}, @@ -144,7 +145,7 @@ func TestRolePermissions(t *testing.T) { { Name: "MyWorkspaceInOrgExecution", // When creating the WithID won't be set, but it does not change the result. - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceWorkspaceExecution.WithID(workspaceID).InOrg(orgID).WithOwner(currentUser.String()), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgMemberMe}, @@ -154,7 +155,7 @@ func TestRolePermissions(t *testing.T) { { Name: "MyWorkspaceInOrgAppConnect", // When creating the WithID won't be set, but it does not change the result. - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceWorkspaceApplicationConnect.WithID(workspaceID).InOrg(orgID).WithOwner(currentUser.String()), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin, orgMemberMe}, @@ -163,7 +164,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "Templates", - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceTemplate.WithID(templateID).InOrg(orgID), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin, templateAdmin}, @@ -172,7 +173,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "ReadTemplates", - Actions: []rbac.Action{rbac.ActionRead}, + Actions: []policy.Action{policy.ActionRead}, Resource: rbac.ResourceTemplate.InOrg(orgID), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin, templateAdmin}, @@ -181,7 +182,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "Files", - Actions: []rbac.Action{rbac.ActionCreate}, + Actions: []policy.Action{policy.ActionCreate}, Resource: rbac.ResourceFile.WithID(fileID), AuthorizeMap: map[bool][]authSubject{ true: {owner, templateAdmin}, @@ -190,7 +191,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "MyFile", - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceFile.WithID(fileID).WithOwner(currentUser.String()), AuthorizeMap: map[bool][]authSubject{ true: {owner, memberMe, orgMemberMe, templateAdmin}, @@ -199,7 +200,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "CreateOrganizations", - Actions: []rbac.Action{rbac.ActionCreate}, + Actions: []policy.Action{policy.ActionCreate}, Resource: rbac.ResourceOrganization, AuthorizeMap: map[bool][]authSubject{ true: {owner}, @@ -208,7 +209,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "Organizations", - Actions: []rbac.Action{rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceOrganization.WithID(orgID).InOrg(orgID), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin}, @@ -217,7 +218,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "ReadOrganizations", - Actions: []rbac.Action{rbac.ActionRead}, + Actions: []policy.Action{policy.ActionRead}, Resource: rbac.ResourceOrganization.WithID(orgID).InOrg(orgID), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin, orgMemberMe, templateAdmin}, @@ -226,7 +227,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "RoleAssignment", - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceRoleAssignment, AuthorizeMap: map[bool][]authSubject{ true: {owner, userAdmin}, @@ -235,7 +236,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "ReadRoleAssignment", - Actions: []rbac.Action{rbac.ActionRead}, + Actions: []policy.Action{policy.ActionRead}, Resource: rbac.ResourceRoleAssignment, AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin, orgMemberMe, otherOrgAdmin, otherOrgMember, memberMe, templateAdmin, userAdmin}, @@ -244,7 +245,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "OrgRoleAssignment", - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceOrgRoleAssignment.InOrg(orgID), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin}, @@ -253,7 +254,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "ReadOrgRoleAssignment", - Actions: []rbac.Action{rbac.ActionRead}, + Actions: []policy.Action{policy.ActionRead}, Resource: rbac.ResourceOrgRoleAssignment.InOrg(orgID), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin, orgMemberMe}, @@ -262,7 +263,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "APIKey", - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceAPIKey.WithID(apiKeyID).WithOwner(currentUser.String()), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgMemberMe, memberMe}, @@ -271,7 +272,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "UserData", - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionRead, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionRead, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceUserData.WithID(currentUser).WithOwner(currentUser.String()), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgMemberMe, memberMe, userAdmin}, @@ -280,7 +281,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "ManageOrgMember", - Actions: []rbac.Action{rbac.ActionCreate, rbac.ActionUpdate, rbac.ActionDelete}, + Actions: []policy.Action{policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, Resource: rbac.ResourceOrganizationMember.WithID(currentUser).InOrg(orgID).WithOwner(currentUser.String()), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin, userAdmin}, @@ -289,7 +290,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "ReadOrgMember", - Actions: []rbac.Action{rbac.ActionRead}, + Actions: []policy.Action{policy.ActionRead}, Resource: rbac.ResourceOrganizationMember.WithID(currentUser).InOrg(orgID).WithOwner(currentUser.String()), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin, userAdmin, orgMemberMe, templateAdmin}, @@ -298,10 +299,10 @@ func TestRolePermissions(t *testing.T) { }, { Name: "AllUsersGroupACL", - Actions: []rbac.Action{rbac.ActionRead}, + Actions: []policy.Action{policy.ActionRead}, Resource: rbac.ResourceTemplate.WithID(templateID).InOrg(orgID).WithGroupACL( - map[string][]rbac.Action{ - orgID.String(): {rbac.ActionRead}, + map[string][]policy.Action{ + orgID.String(): {policy.ActionRead}, }), AuthorizeMap: map[bool][]authSubject{ @@ -311,7 +312,7 @@ func TestRolePermissions(t *testing.T) { }, { Name: "Groups", - Actions: []rbac.Action{rbac.ActionRead}, + Actions: []policy.Action{policy.ActionRead}, Resource: rbac.ResourceGroup.WithID(groupID).InOrg(orgID), AuthorizeMap: map[bool][]authSubject{ true: {owner, orgAdmin, userAdmin, templateAdmin}, diff --git a/coderd/rbac/scopes.go b/coderd/rbac/scopes.go index fe85be67632c5..6353ca3c67919 100644 --- a/coderd/rbac/scopes.go +++ b/coderd/rbac/scopes.go @@ -6,6 +6,8 @@ import ( "github.com/google/uuid" "golang.org/x/xerrors" + + "github.com/coder/coder/v2/coderd/rbac/policy" ) type WorkspaceAgentScopeParams struct { @@ -58,7 +60,7 @@ var builtinScopes = map[ScopeName]Scope{ Role: Role{ Name: fmt.Sprintf("Scope_%s", ScopeAll), DisplayName: "All operations", - Site: Permissions(map[string][]Action{ + Site: Permissions(map[string][]policy.Action{ ResourceWildcard.Type: {WildcardSymbol}, }), Org: map[string][]Permission{}, @@ -71,8 +73,8 @@ var builtinScopes = map[ScopeName]Scope{ Role: Role{ Name: fmt.Sprintf("Scope_%s", ScopeApplicationConnect), DisplayName: "Ability to connect to applications", - Site: Permissions(map[string][]Action{ - ResourceWorkspaceApplicationConnect.Type: {ActionCreate}, + Site: Permissions(map[string][]policy.Action{ + ResourceWorkspaceApplicationConnect.Type: {policy.ActionCreate}, }), Org: map[string][]Permission{}, User: []Permission{}, diff --git a/coderd/roles.go b/coderd/roles.go index 7d49eadba7222..1cc74535119e3 100644 --- a/coderd/roles.go +++ b/coderd/roles.go @@ -4,6 +4,7 @@ import ( "net/http" "github.com/coder/coder/v2/coderd/httpmw" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/coderd/httpapi" @@ -22,7 +23,7 @@ import ( func (api *API) assignableSiteRoles(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() actorRoles := httpmw.UserAuthorization(r) - if !api.Authorize(r, rbac.ActionRead, rbac.ResourceRoleAssignment) { + if !api.Authorize(r, policy.ActionRead, rbac.ResourceRoleAssignment) { httpapi.Forbidden(rw) return } @@ -46,7 +47,7 @@ func (api *API) assignableOrgRoles(rw http.ResponseWriter, r *http.Request) { organization := httpmw.OrganizationParam(r) actorRoles := httpmw.UserAuthorization(r) - if !api.Authorize(r, rbac.ActionRead, rbac.ResourceOrgRoleAssignment.InOrg(organization.ID)) { + if !api.Authorize(r, policy.ActionRead, rbac.ResourceOrgRoleAssignment.InOrg(organization.ID)) { httpapi.ResourceNotFound(rw) return } diff --git a/coderd/templates.go b/coderd/templates.go index 59537b962c21e..94601ba2cc35b 100644 --- a/coderd/templates.go +++ b/coderd/templates.go @@ -19,6 +19,7 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/schedule" "github.com/coder/coder/v2/coderd/telemetry" "github.com/coder/coder/v2/coderd/util/ptr" @@ -322,7 +323,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque if !createTemplate.DisableEveryoneGroupAccess { // The organization ID is used as the group ID for the everyone group // in this organization. - defaultsGroups[organization.ID.String()] = []rbac.Action{rbac.ActionRead} + defaultsGroups[organization.ID.String()] = []policy.Action{policy.ActionRead} } err = api.Database.InTx(func(tx database.Store) error { now := dbtime.Now() @@ -455,7 +456,7 @@ func (api *API) templatesByOrganization(rw http.ResponseWriter, r *http.Request) return } - prepared, err := api.HTTPAuth.AuthorizeSQLFilter(r, rbac.ActionRead, rbac.ResourceTemplate.Type) + prepared, err := api.HTTPAuth.AuthorizeSQLFilter(r, policy.ActionRead, rbac.ResourceTemplate.Type) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Internal error preparing sql filter.", @@ -807,7 +808,7 @@ func (api *API) templateExamples(rw http.ResponseWriter, r *http.Request) { organization = httpmw.OrganizationParam(r) ) - if !api.Authorize(r, rbac.ActionRead, rbac.ResourceTemplate.InOrg(organization.ID)) { + if !api.Authorize(r, policy.ActionRead, rbac.ResourceTemplate.InOrg(organization.ID)) { httpapi.ResourceNotFound(rw) return } diff --git a/coderd/templateversions.go b/coderd/templateversions.go index ca8f660454ea8..788a01ba353b1 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -17,6 +17,7 @@ import ( "golang.org/x/xerrors" "cdr.dev/slog" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/audit" "github.com/coder/coder/v2/coderd/database" @@ -430,7 +431,7 @@ func (api *API) postTemplateVersionDryRun(rw http.ResponseWriter, r *http.Reques // We use the workspace RBAC check since we don't want to allow dry runs if // the user can't create workspaces. - if !api.Authorize(r, rbac.ActionCreate, + if !api.Authorize(r, policy.ActionCreate, rbac.ResourceWorkspace.InOrg(templateVersion.OrganizationID).WithOwner(apiKey.UserID.String())) { httpapi.ResourceNotFound(rw) return @@ -603,7 +604,7 @@ func (api *API) patchTemplateVersionDryRunCancel(rw http.ResponseWriter, r *http if !ok { return } - if !api.Authorize(r, rbac.ActionUpdate, + if !api.Authorize(r, policy.ActionUpdate, rbac.ResourceWorkspace.InOrg(templateVersion.OrganizationID).WithOwner(job.ProvisionerJob.InitiatorID.String())) { httpapi.ResourceNotFound(rw) return @@ -684,7 +685,7 @@ func (api *API) fetchTemplateVersionDryRunJob(rw http.ResponseWriter, r *http.Re } // Do a workspace resource check since it's basically a workspace dry-run. - if !api.Authorize(r, rbac.ActionRead, + if !api.Authorize(r, policy.ActionRead, rbac.ResourceWorkspace.InOrg(templateVersion.OrganizationID).WithOwner(job.ProvisionerJob.InitiatorID.String())) { httpapi.Forbidden(rw) return database.GetProvisionerJobsByIDsWithQueuePositionRow{}, false @@ -1359,12 +1360,12 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht var err error // if example id is specified we need to copy the embedded tar into a new file in the database if req.ExampleID != "" { - if !api.Authorize(r, rbac.ActionCreate, rbac.ResourceFile.WithOwner(apiKey.UserID.String())) { + if !api.Authorize(r, policy.ActionCreate, rbac.ResourceFile.WithOwner(apiKey.UserID.String())) { httpapi.Forbidden(rw) return } // ensure we can read the file that either already exists or will be created - if !api.Authorize(r, rbac.ActionRead, rbac.ResourceFile.WithOwner(apiKey.UserID.String())) { + if !api.Authorize(r, policy.ActionRead, rbac.ResourceFile.WithOwner(apiKey.UserID.String())) { httpapi.Forbidden(rw) return } diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index 3089b4eecf3e1..1267213932649 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -18,6 +18,7 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/examples" "github.com/coder/coder/v2/provisioner/echo" @@ -38,14 +39,14 @@ func TestTemplateVersion(t *testing.T) { req.Name = "bananas" req.Message = "first try" }) - authz.AssertChecked(t, rbac.ActionCreate, rbac.ResourceTemplate.InOrg(user.OrganizationID)) + authz.AssertChecked(t, policy.ActionCreate, rbac.ResourceTemplate.InOrg(user.OrganizationID)) ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) defer cancel() authz.Reset() tv, err := client.TemplateVersion(ctx, version.ID) - authz.AssertChecked(t, rbac.ActionRead, tv) + authz.AssertChecked(t, policy.ActionRead, tv) require.NoError(t, err) assert.Equal(t, "bananas", tv.Name) diff --git a/coderd/users.go b/coderd/users.go index 47cb6e1cd3be3..c698661d71429 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -21,6 +21,7 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/searchquery" "github.com/coder/coder/v2/coderd/telemetry" "github.com/coder/coder/v2/coderd/userpassword" @@ -1021,7 +1022,7 @@ func (api *API) userRoles(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() user := httpmw.UserParam(r) - if !api.Authorize(r, rbac.ActionRead, user.UserDataRBACObject()) { + if !api.Authorize(r, policy.ActionRead, user.UserDataRBACObject()) { httpapi.ResourceNotFound(rw) return } @@ -1171,7 +1172,7 @@ func (api *API) organizationsByUser(rw http.ResponseWriter, r *http.Request) { } // Only return orgs the user can read. - organizations, err = AuthorizeFilter(api.HTTPAuth, r, rbac.ActionRead, organizations) + organizations, err = AuthorizeFilter(api.HTTPAuth, r, policy.ActionRead, organizations) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Internal error fetching organizations.", diff --git a/coderd/users_test.go b/coderd/users_test.go index bc48632975eb2..588a2e107566b 100644 --- a/coderd/users_test.go +++ b/coderd/users_test.go @@ -10,6 +10,7 @@ import ( "github.com/coder/coder/v2/coderd" "github.com/coder/coder/v2/coderd/coderdtest/oidctest" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/serpent" "github.com/golang-jwt/jwt/v4" @@ -325,8 +326,8 @@ func TestDeleteUser(t *testing.T) { require.Equal(t, http.StatusUnauthorized, apiErr.StatusCode()) // RBAC checks - authz.AssertChecked(t, rbac.ActionCreate, rbac.ResourceUser) - authz.AssertChecked(t, rbac.ActionDelete, another) + authz.AssertChecked(t, policy.ActionCreate, rbac.ResourceUser) + authz.AssertChecked(t, policy.ActionDelete, another) }) t.Run("NoPermission", func(t *testing.T) { t.Parallel() diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go index 03ca23dcc1162..d79d191af9ce5 100644 --- a/coderd/workspaceagents.go +++ b/coderd/workspaceagents.go @@ -35,7 +35,7 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/prometheusmetrics" - "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/schedule" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" @@ -1030,7 +1030,7 @@ func (api *API) workspaceAgentClientCoordinate(rw http.ResponseWriter, r *http.R // This route accepts user API key auth and workspace proxy auth. The moon actor has // full permissions so should be able to pass this authz check. workspace := httpmw.WorkspaceParam(r) - if !api.Authorize(r, rbac.ActionCreate, workspace.ExecutionRBAC()) { + if !api.Authorize(r, policy.ActionCreate, workspace.ExecutionRBAC()) { httpapi.ResourceNotFound(rw) return } diff --git a/coderd/workspaceapps.go b/coderd/workspaceapps.go index 8c6ffdb62e34a..d2fa11b9ea2ea 100644 --- a/coderd/workspaceapps.go +++ b/coderd/workspaceapps.go @@ -16,7 +16,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" - "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/workspaceapps" "github.com/coder/coder/v2/coderd/workspaceapps/appurl" "github.com/coder/coder/v2/codersdk" @@ -53,7 +53,7 @@ func (api *API) appHost(rw http.ResponseWriter, r *http.Request) { func (api *API) workspaceApplicationAuth(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() apiKey := httpmw.APIKey(r) - if !api.Authorize(r, rbac.ActionCreate, apiKey) { + if !api.Authorize(r, policy.ActionCreate, apiKey) { httpapi.ResourceNotFound(rw) return } diff --git a/coderd/workspaceapps/db.go b/coderd/workspaceapps/db.go index 619bdd95ba165..144de2f2573f9 100644 --- a/coderd/workspaceapps/db.go +++ b/coderd/workspaceapps/db.go @@ -19,6 +19,7 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" ) @@ -281,8 +282,8 @@ func (p *DBTokenProvider) authorizeRequest(ctx context.Context, roles *rbac.Subj // Figure out which RBAC resource to check. For terminals we use execution // instead of application connect. var ( - rbacAction rbac.Action = rbac.ActionCreate - rbacResource rbac.Object = dbReq.Workspace.ApplicationConnectRBAC() + rbacAction policy.Action = policy.ActionCreate + rbacResource rbac.Object = dbReq.Workspace.ApplicationConnectRBAC() // rbacResourceOwned is for the level "authenticated". We still need to // make sure the API key has permissions to connect to the actor's own // workspace. Scopes would prevent this. diff --git a/coderd/workspacebuilds.go b/coderd/workspacebuilds.go index 40514cb913d86..ef5b63a1e5b19 100644 --- a/coderd/workspacebuilds.go +++ b/coderd/workspacebuilds.go @@ -28,6 +28,7 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/wsbuilder" "github.com/coder/coder/v2/codersdk" ) @@ -374,7 +375,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) { workspaceBuild, provisionerJob, err := builder.Build( ctx, api.Database, - func(action rbac.Action, object rbac.Objecter) bool { + func(action policy.Action, object rbac.Objecter) bool { return api.Authorize(r, action, object) }, audit.WorkspaceBuildBaggageFromRequest(r), @@ -636,7 +637,7 @@ func (api *API) workspaceBuildState(rw http.ResponseWriter, r *http.Request) { // You must have update permissions on the template to get the state. // This matches a push! - if !api.Authorize(r, rbac.ActionUpdate, template.RBACObject()) { + if !api.Authorize(r, policy.ActionUpdate, template.RBACObject()) { httpapi.ResourceNotFound(rw) return } diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 6f398b34488d6..7d0344be4e321 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -24,6 +24,7 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/schedule/cron" "github.com/coder/coder/v2/coderd/searchquery" "github.com/coder/coder/v2/coderd/telemetry" @@ -160,7 +161,7 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) { } // Workspaces do not have ACL columns. - prepared, err := api.HTTPAuth.AuthorizeSQLFilter(r, rbac.ActionRead, rbac.ResourceWorkspace.Type) + prepared, err := api.HTTPAuth.AuthorizeSQLFilter(r, policy.ActionRead, rbac.ResourceWorkspace.Type) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Internal error preparing sql filter.", @@ -375,7 +376,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req defer commitAudit() // Do this upfront to save work. - if !api.Authorize(r, rbac.ActionCreate, + if !api.Authorize(r, policy.ActionCreate, rbac.ResourceWorkspace.InOrg(organization.ID).WithOwner(member.UserID.String())) { httpapi.ResourceNotFound(rw) return @@ -570,7 +571,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req workspaceBuild, provisionerJob, err = builder.Build( ctx, db, - func(action rbac.Action, object rbac.Objecter) bool { + func(action policy.Action, object rbac.Objecter) bool { return api.Authorize(r, action, object) }, audit.WorkspaceBuildBaggageFromRequest(r), @@ -1109,7 +1110,7 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) { // @Router /workspaces/{workspace}/usage [post] func (api *API) postWorkspaceUsage(rw http.ResponseWriter, r *http.Request) { workspace := httpmw.WorkspaceParam(r) - if !api.Authorize(r, rbac.ActionUpdate, workspace) { + if !api.Authorize(r, policy.ActionUpdate, workspace) { httpapi.Forbidden(rw) return } diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index c01f9689d6ace..d91de4a5e26a1 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -31,6 +31,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/parameter" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/schedule" "github.com/coder/coder/v2/coderd/schedule/cron" "github.com/coder/coder/v2/coderd/util/ptr" @@ -59,7 +60,7 @@ func TestWorkspace(t *testing.T) { authz.Reset() // Reset all previous checks done in setup. ws, err := client.Workspace(ctx, workspace.ID) - authz.AssertChecked(t, rbac.ActionRead, ws) + authz.AssertChecked(t, policy.ActionRead, ws) require.NoError(t, err) require.Equal(t, user.UserID, ws.LatestBuild.InitiatorID) require.Equal(t, codersdk.BuildReasonInitiator, ws.LatestBuild.Reason) diff --git a/coderd/wsbuilder/wsbuilder.go b/coderd/wsbuilder/wsbuilder.go index 810f52502c6f8..3959c0e55a428 100644 --- a/coderd/wsbuilder/wsbuilder.go +++ b/coderd/wsbuilder/wsbuilder.go @@ -10,6 +10,7 @@ import ( "net/http" "time" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/provisionersdk" "github.com/google/uuid" @@ -202,7 +203,7 @@ func (e BuildError) Unwrap() error { func (b *Builder) Build( ctx context.Context, store database.Store, - authFunc func(action rbac.Action, object rbac.Objecter) bool, + authFunc func(action policy.Action, object rbac.Objecter) bool, auditBaggage audit.WorkspaceBuildBaggage, ) ( *database.WorkspaceBuild, *database.ProvisionerJob, error, @@ -237,7 +238,7 @@ func (b *Builder) Build( // the calculation of multiple attributes. // // In order to utilize this cache, the functions that compute build attributes use a pointer receiver type. -func (b *Builder) buildTx(authFunc func(action rbac.Action, object rbac.Objecter) bool) ( +func (b *Builder) buildTx(authFunc func(action policy.Action, object rbac.Objecter) bool) ( *database.WorkspaceBuild, *database.ProvisionerJob, error, ) { if authFunc != nil { @@ -632,16 +633,16 @@ func (b *Builder) getLastBuildJob() (*database.ProvisionerJob, error) { } // authorize performs build authorization pre-checks using the provided authFunc -func (b *Builder) authorize(authFunc func(action rbac.Action, object rbac.Objecter) bool) error { +func (b *Builder) authorize(authFunc func(action policy.Action, object rbac.Objecter) bool) error { // Doing this up front saves a lot of work if the user doesn't have permission. // This is checked again in the dbauthz layer, but the check is cached // and will be a noop later. - var action rbac.Action + var action policy.Action switch b.trans { case database.WorkspaceTransitionDelete: - action = rbac.ActionDelete + action = policy.ActionDelete case database.WorkspaceTransitionStart, database.WorkspaceTransitionStop: - action = rbac.ActionUpdate + action = policy.ActionUpdate default: msg := fmt.Sprintf("Transition %q not supported.", b.trans) return BuildError{http.StatusBadRequest, msg, xerrors.New(msg)} @@ -659,12 +660,12 @@ func (b *Builder) authorize(authFunc func(action rbac.Action, object rbac.Object // If custom state, deny request since user could be corrupting or leaking // cloud state. if b.state.explicit != nil || b.state.orphan { - if !authFunc(rbac.ActionUpdate, template.RBACObject()) { + if !authFunc(policy.ActionUpdate, template.RBACObject()) { return BuildError{http.StatusForbidden, "Only template managers may provide custom state", xerrors.New("Only template managers may provide custom state")} } } - if b.logLevel != "" && !authFunc(rbac.ActionRead, rbac.ResourceDeploymentValues) { + if b.logLevel != "" && !authFunc(policy.ActionRead, rbac.ResourceDeploymentValues) { return BuildError{ http.StatusBadRequest, "Workspace builds with a custom log level are restricted to administrators only.", diff --git a/enterprise/coderd/appearance.go b/enterprise/coderd/appearance.go index 7029340672b6e..5104936ac62a4 100644 --- a/enterprise/coderd/appearance.go +++ b/enterprise/coderd/appearance.go @@ -16,6 +16,7 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" ) @@ -136,7 +137,7 @@ func validateHexColor(color string) error { func (api *API) putAppearance(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() - if !api.Authorize(r, rbac.ActionUpdate, rbac.ResourceDeploymentValues) { + if !api.Authorize(r, policy.ActionUpdate, rbac.ResourceDeploymentValues) { httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{ Message: "Insufficient permissions to update appearance", }) diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index 722cc3631ed05..56c774911018b 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -15,6 +15,7 @@ import ( "github.com/coder/coder/v2/coderd/appearance" "github.com/coder/coder/v2/coderd/database" agplportsharing "github.com/coder/coder/v2/coderd/portsharing" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/enterprise/coderd/portsharing" "golang.org/x/xerrors" @@ -132,7 +133,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { // If the user can read the workspace proxy resource, return that. // If not, always default to the regions. actor, ok := agpldbauthz.ActorFromContext(ctx) - if ok && api.Authorizer.Authorize(ctx, actor, rbac.ActionRead, rbac.ResourceWorkspaceProxy) == nil { + if ok && api.Authorizer.Authorize(ctx, actor, policy.ActionRead, rbac.ResourceWorkspaceProxy) == nil { return api.fetchWorkspaceProxies(ctx) } return api.fetchRegions(ctx) @@ -1016,6 +1017,6 @@ func (api *API) runEntitlementsLoop(ctx context.Context) { } } -func (api *API) Authorize(r *http.Request, action rbac.Action, object rbac.Objecter) bool { +func (api *API) Authorize(r *http.Request, action policy.Action, object rbac.Objecter) bool { return api.AGPL.HTTPAuth.Authorize(r, action, object) } diff --git a/enterprise/coderd/coderd_test.go b/enterprise/coderd/coderd_test.go index 1b156a4355c89..e53b714b3fe22 100644 --- a/enterprise/coderd/coderd_test.go +++ b/enterprise/coderd/coderd_test.go @@ -15,6 +15,7 @@ import ( "go.uber.org/goleak" "cdr.dev/slog/sloggers/slogtest" + "github.com/coder/coder/v2/coderd/rbac/policy" agplaudit "github.com/coder/coder/v2/coderd/audit" "github.com/coder/coder/v2/coderd/coderdtest" @@ -498,7 +499,7 @@ func testDBAuthzRole(ctx context.Context) context.Context { { Name: "testing", DisplayName: "Unit Tests", - Site: rbac.Permissions(map[string][]rbac.Action{ + Site: rbac.Permissions(map[string][]policy.Action{ rbac.ResourceWildcard.Type: {rbac.WildcardSymbol}, }), Org: map[string][]rbac.Permission{}, diff --git a/enterprise/coderd/groups.go b/enterprise/coderd/groups.go index fa5da3f7827c3..dea135f683fb8 100644 --- a/enterprise/coderd/groups.go +++ b/enterprise/coderd/groups.go @@ -14,7 +14,7 @@ import ( "github.com/coder/coder/v2/coderd/database/db2sdk" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" - "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" ) @@ -397,7 +397,7 @@ func (api *API) groups(rw http.ResponseWriter, r *http.Request) { } // Filter groups based on rbac permissions - groups, err = coderd.AuthorizeFilter(api.AGPL.HTTPAuth, r, rbac.ActionRead, groups) + groups, err = coderd.AuthorizeFilter(api.AGPL.HTTPAuth, r, policy.ActionRead, groups) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Internal error fetching groups.", diff --git a/enterprise/coderd/licenses.go b/enterprise/coderd/licenses.go index 2808bc4920e93..54bc57b649f62 100644 --- a/enterprise/coderd/licenses.go +++ b/enterprise/coderd/licenses.go @@ -27,6 +27,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/enterprise/coderd/license" ) @@ -75,7 +76,7 @@ func (api *API) postLicense(rw http.ResponseWriter, r *http.Request) { ) defer commitAudit() - if !api.AGPL.Authorize(r, rbac.ActionCreate, rbac.ResourceLicense) { + if !api.AGPL.Authorize(r, policy.ActionCreate, rbac.ResourceLicense) { httpapi.Forbidden(rw) return } @@ -181,7 +182,7 @@ func (api *API) postRefreshEntitlements(rw http.ResponseWriter, r *http.Request) // If the user cannot create a new license, then they cannot refresh entitlements. // Refreshing entitlements is a way to force a refresh of the license, so it is // equivalent to creating a new license. - if !api.AGPL.Authorize(r, rbac.ActionCreate, rbac.ResourceLicense) { + if !api.AGPL.Authorize(r, policy.ActionCreate, rbac.ResourceLicense) { httpapi.Forbidden(rw) return } @@ -258,7 +259,7 @@ func (api *API) licenses(rw http.ResponseWriter, r *http.Request) { return } - licenses, err = coderd.AuthorizeFilter(api.AGPL.HTTPAuth, r, rbac.ActionRead, licenses) + licenses, err = coderd.AuthorizeFilter(api.AGPL.HTTPAuth, r, policy.ActionRead, licenses) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Internal error fetching licenses.", @@ -315,7 +316,7 @@ func (api *API) deleteLicense(rw http.ResponseWriter, r *http.Request) { defer commitAudit() aReq.Old = dl - if !api.AGPL.Authorize(r, rbac.ActionDelete, rbac.ResourceLicense) { + if !api.AGPL.Authorize(r, policy.ActionDelete, rbac.ResourceLicense) { httpapi.Forbidden(rw) return } diff --git a/enterprise/coderd/provisionerdaemons.go b/enterprise/coderd/provisionerdaemons.go index 0161e7a265d60..827ecfffe46a6 100644 --- a/enterprise/coderd/provisionerdaemons.go +++ b/enterprise/coderd/provisionerdaemons.go @@ -29,6 +29,7 @@ import ( "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/provisionerdserver" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/telemetry" "github.com/coder/coder/v2/coderd/util/ptr" "github.com/coder/coder/v2/codersdk" @@ -77,7 +78,7 @@ func (api *API) provisionerDaemons(rw http.ResponseWriter, r *http.Request) { if daemons == nil { daemons = []database.ProvisionerDaemon{} } - daemons, err = coderd.AuthorizeFilter(api.AGPL.HTTPAuth, r, rbac.ActionRead, daemons) + daemons, err = coderd.AuthorizeFilter(api.AGPL.HTTPAuth, r, policy.ActionRead, daemons) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Internal error fetching provisioner daemons.", @@ -107,7 +108,7 @@ func (p *provisionerDaemonAuth) authorize(r *http.Request, tags map[string]strin return tags, true } ua := httpmw.UserAuthorization(r) - if err := p.authorizer.Authorize(ctx, ua, rbac.ActionCreate, rbac.ResourceProvisionerDaemon); err == nil { + if err := p.authorizer.Authorize(ctx, ua, policy.ActionCreate, rbac.ResourceProvisionerDaemon); err == nil { // User is allowed to create provisioner daemons return tags, true } diff --git a/enterprise/coderd/replicas.go b/enterprise/coderd/replicas.go index 536048aaac84a..75b6c36fdde17 100644 --- a/enterprise/coderd/replicas.go +++ b/enterprise/coderd/replicas.go @@ -6,6 +6,7 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" ) @@ -19,7 +20,7 @@ import ( // @Success 200 {array} codersdk.Replica // @Router /replicas [get] func (api *API) replicas(rw http.ResponseWriter, r *http.Request) { - if !api.AGPL.Authorize(r, rbac.ActionRead, rbac.ResourceReplicas) { + if !api.AGPL.Authorize(r, policy.ActionRead, rbac.ResourceReplicas) { httpapi.ResourceNotFound(rw) return } diff --git a/enterprise/coderd/templates.go b/enterprise/coderd/templates.go index f7ad7b12ed155..feddcce4d8372 100644 --- a/enterprise/coderd/templates.go +++ b/enterprise/coderd/templates.go @@ -16,6 +16,7 @@ import ( "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" ) @@ -35,7 +36,7 @@ func (api *API) templateAvailablePermissions(rw http.ResponseWriter, r *http.Req // Requires update permission on the template to list all avail users/groups // for assignment. - if !api.Authorize(r, rbac.ActionUpdate, template) { + if !api.Authorize(r, policy.ActionUpdate, template) { httpapi.ResourceNotFound(rw) return } @@ -305,9 +306,9 @@ func validateTemplateRole(role codersdk.TemplateRole) error { return nil } -func convertToTemplateRole(actions []rbac.Action) codersdk.TemplateRole { +func convertToTemplateRole(actions []policy.Action) codersdk.TemplateRole { switch { - case len(actions) == 1 && actions[0] == rbac.ActionRead: + case len(actions) == 1 && actions[0] == policy.ActionRead: return codersdk.TemplateRoleUse case len(actions) == 1 && actions[0] == rbac.WildcardSymbol: return codersdk.TemplateRoleAdmin @@ -316,12 +317,12 @@ func convertToTemplateRole(actions []rbac.Action) codersdk.TemplateRole { return "" } -func convertSDKTemplateRole(role codersdk.TemplateRole) []rbac.Action { +func convertSDKTemplateRole(role codersdk.TemplateRole) []policy.Action { switch role { case codersdk.TemplateRoleAdmin: - return []rbac.Action{rbac.WildcardSymbol} + return []policy.Action{rbac.WildcardSymbol} case codersdk.TemplateRoleUse: - return []rbac.Action{rbac.ActionRead} + return []policy.Action{policy.ActionRead} } return nil diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index 234212f479cfd..22fe1bc747cbe 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -21,7 +21,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" - "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/coderd/telemetry" "github.com/coder/coder/v2/coderd/workspaceapps" "github.com/coder/coder/v2/coderd/workspaceapps/appurl" @@ -799,7 +799,7 @@ func (api *API) workspaceProxyDeregister(rw http.ResponseWriter, r *http.Request func (api *API) reconnectingPTYSignedToken(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() apiKey := httpmw.APIKey(r) - if !api.Authorize(r, rbac.ActionCreate, apiKey) { + if !api.Authorize(r, policy.ActionCreate, apiKey) { httpapi.ResourceNotFound(rw) return } diff --git a/enterprise/coderd/workspacequota.go b/enterprise/coderd/workspacequota.go index 44ea3f302ff37..d11111edac388 100644 --- a/enterprise/coderd/workspacequota.go +++ b/enterprise/coderd/workspacequota.go @@ -13,7 +13,7 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" - "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/provisionerd/proto" ) @@ -123,7 +123,7 @@ func (c *committer) CommitQuota( func (api *API) workspaceQuota(rw http.ResponseWriter, r *http.Request) { user := httpmw.UserParam(r) - if !api.AGPL.Authorize(r, rbac.ActionRead, user) { + if !api.AGPL.Authorize(r, policy.ActionRead, user) { httpapi.ResourceNotFound(rw) return } diff --git a/enterprise/tailnet/pgcoord.go b/enterprise/tailnet/pgcoord.go index 1a9dc88378b03..8cb9595492feb 100644 --- a/enterprise/tailnet/pgcoord.go +++ b/enterprise/tailnet/pgcoord.go @@ -19,6 +19,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbauthz" "github.com/coder/coder/v2/coderd/database/pubsub" "github.com/coder/coder/v2/coderd/rbac" + "github.com/coder/coder/v2/coderd/rbac/policy" agpl "github.com/coder/coder/v2/tailnet" "github.com/coder/coder/v2/tailnet/proto" ) @@ -101,7 +102,7 @@ var pgCoordSubject = rbac.Subject{ { Name: "tailnetcoordinator", DisplayName: "Tailnet Coordinator", - Site: rbac.Permissions(map[string][]rbac.Action{ + Site: rbac.Permissions(map[string][]policy.Action{ rbac.ResourceTailnetCoordinator.Type: {rbac.WildcardSymbol}, }), Org: map[string][]rbac.Permission{}, diff --git a/support/support.go b/support/support.go index 341e01e1862bb..e49f95e38d045 100644 --- a/support/support.go +++ b/support/support.go @@ -16,12 +16,12 @@ import ( "tailscale.com/net/netcheck" "github.com/coder/coder/v2/coderd/healthcheck/derphealth" + "github.com/coder/coder/v2/coderd/rbac/policy" "github.com/google/uuid" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" - "github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" "github.com/coder/coder/v2/codersdk/healthsdk" @@ -462,7 +462,7 @@ func Run(ctx context.Context, d *Deps) (*Bundle, error) { Object: codersdk.AuthorizationObject{ ResourceType: codersdk.ResourceDeploymentValues, }, - Action: string(rbac.ActionRead), + Action: string(policy.ActionRead), }, }