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), }, }