mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
refactor(dbauthz): add authz for system-level functions (#6513)
- Introduces rbac.ResourceSystem - Grants system.* to system and provisionerd rbac subjects - Updates dbauthz system queries where applicable - coderd: Avoid index out of bounds in api.workspaceBuilds - dbauthz: move GetUsersByIDs out of system, modify RBAC check to ResourceUser - workspaceapps: Add test case for when owner of app is not found
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"cdr.dev/slog"
|
||||
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/database/dbauthz"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
@@ -39,12 +40,14 @@ func Entitlements(
|
||||
}
|
||||
}
|
||||
|
||||
licenses, err := db.GetUnexpiredLicenses(ctx)
|
||||
// nolint:gocritic // Getting unexpired licenses is a system function.
|
||||
licenses, err := db.GetUnexpiredLicenses(dbauthz.AsSystemRestricted(ctx))
|
||||
if err != nil {
|
||||
return entitlements, err
|
||||
}
|
||||
|
||||
activeUserCount, err := db.GetActiveUserCount(ctx)
|
||||
// nolint:gocritic // Getting active user count is a system function.
|
||||
activeUserCount, err := db.GetActiveUserCount(dbauthz.AsSystemRestricted(ctx))
|
||||
if err != nil {
|
||||
return entitlements, xerrors.Errorf("query active user count: %w", err)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
"github.com/coder/coder/coderd/provisionerdserver"
|
||||
"github.com/coder/coder/coderd/rbac"
|
||||
"github.com/coder/coder/codersdk"
|
||||
"github.com/coder/coder/enterprise/coderd/coderdenttest"
|
||||
"github.com/coder/coder/enterprise/coderd/license"
|
||||
@@ -20,6 +21,22 @@ import (
|
||||
|
||||
func TestProvisionerDaemonServe(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdenttest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
coderdenttest.AddLicense(t, client, coderdenttest.LicenseOptions{
|
||||
Features: license.Features{
|
||||
codersdk.FeatureExternalProvisionerDaemons: 1,
|
||||
},
|
||||
})
|
||||
srv, err := client.ServeProvisionerDaemon(context.Background(), user.OrganizationID, []codersdk.ProvisionerType{
|
||||
codersdk.ProvisionerTypeEcho,
|
||||
}, map[string]string{})
|
||||
require.NoError(t, err)
|
||||
srv.DRPCConn().Close()
|
||||
})
|
||||
|
||||
t.Run("NoLicense", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdenttest.New(t, nil)
|
||||
@@ -42,11 +59,16 @@ func TestProvisionerDaemonServe(t *testing.T) {
|
||||
codersdk.FeatureExternalProvisionerDaemons: 1,
|
||||
},
|
||||
})
|
||||
srv, err := client.ServeProvisionerDaemon(context.Background(), user.OrganizationID, []codersdk.ProvisionerType{
|
||||
another, _ := coderdtest.CreateAnotherUser(t, client, user.OrganizationID, rbac.RoleOrgAdmin(user.OrganizationID))
|
||||
_, err := another.ServeProvisionerDaemon(context.Background(), user.OrganizationID, []codersdk.ProvisionerType{
|
||||
codersdk.ProvisionerTypeEcho,
|
||||
}, map[string]string{})
|
||||
require.NoError(t, err)
|
||||
srv.DRPCConn().Close()
|
||||
}, map[string]string{
|
||||
provisionerdserver.TagScope: provisionerdserver.ScopeOrganization,
|
||||
})
|
||||
require.Error(t, err)
|
||||
var apiError *codersdk.Error
|
||||
require.ErrorAs(t, err, &apiError)
|
||||
require.Equal(t, http.StatusForbidden, apiError.StatusCode())
|
||||
})
|
||||
|
||||
t.Run("OrganizationNoPerms", func(t *testing.T) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
"github.com/coder/coder/buildinfo"
|
||||
"github.com/coder/coder/coderd/database"
|
||||
"github.com/coder/coder/coderd/database/dbauthz"
|
||||
)
|
||||
|
||||
var PubsubEvent = "replica"
|
||||
@@ -61,7 +62,8 @@ func New(ctx context.Context, logger slog.Logger, db database.Store, pubsub data
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("ping database: %w", err)
|
||||
}
|
||||
replica, err := db.InsertReplica(ctx, database.InsertReplicaParams{
|
||||
// nolint:gocritic // Inserting a replica is a system function.
|
||||
replica, err := db.InsertReplica(dbauthz.AsSystemRestricted(ctx), database.InsertReplicaParams{
|
||||
ID: options.ID,
|
||||
CreatedAt: database.Now(),
|
||||
StartedAt: database.Now(),
|
||||
@@ -141,7 +143,8 @@ func (m *Manager) loop(ctx context.Context) {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-deleteTicker.C:
|
||||
err := m.db.DeleteReplicasUpdatedBefore(ctx, m.updateInterval())
|
||||
// nolint:gocritic // Deleting a replica is a system function
|
||||
err := m.db.DeleteReplicasUpdatedBefore(dbauthz.AsSystemRestricted(ctx), m.updateInterval())
|
||||
if err != nil {
|
||||
m.logger.Warn(ctx, "delete old replicas", slog.Error(err))
|
||||
}
|
||||
@@ -218,7 +221,8 @@ func (m *Manager) syncReplicas(ctx context.Context) error {
|
||||
defer m.closeWait.Done()
|
||||
// Expect replicas to update once every three times the interval...
|
||||
// If they don't, assume death!
|
||||
replicas, err := m.db.GetReplicasUpdatedAfter(ctx, m.updateInterval())
|
||||
// nolint:gocritic // Reading replicas is a system function
|
||||
replicas, err := m.db.GetReplicasUpdatedAfter(dbauthz.AsSystemRestricted(ctx), m.updateInterval())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("get replicas: %w", err)
|
||||
}
|
||||
@@ -276,7 +280,8 @@ func (m *Manager) syncReplicas(ctx context.Context) error {
|
||||
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
replica, err := m.db.UpdateReplica(ctx, database.UpdateReplicaParams{
|
||||
// nolint:gocritic // Updating a replica is a system function.
|
||||
replica, err := m.db.UpdateReplica(dbauthz.AsSystemRestricted(ctx), database.UpdateReplicaParams{
|
||||
ID: m.self.ID,
|
||||
UpdatedAt: database.Now(),
|
||||
StartedAt: m.self.StartedAt,
|
||||
@@ -366,7 +371,8 @@ func (m *Manager) Close() error {
|
||||
defer m.mutex.Unlock()
|
||||
ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancelFunc()
|
||||
_, err := m.db.UpdateReplica(ctx, database.UpdateReplicaParams{
|
||||
// nolint:gocritic // Updating a replica is a sytsem function.
|
||||
_, err := m.db.UpdateReplica(dbauthz.AsSystemRestricted(ctx), database.UpdateReplicaParams{
|
||||
ID: m.self.ID,
|
||||
UpdatedAt: database.Now(),
|
||||
StartedAt: m.self.StartedAt,
|
||||
|
||||
Reference in New Issue
Block a user