Skip to content

Commit c49c60c

Browse files
authored
Merge branch 'main' into phorcys420/fix-template-api-docs
2 parents 856d4b5 + 155c7bb commit c49c60c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2296
-404
lines changed

cli/server.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import (
5555

5656
"cdr.dev/slog"
5757
"cdr.dev/slog/sloggers/sloghuman"
58+
"github.com/coder/coder/v2/coderd/pproflabel"
5859
"github.com/coder/pretty"
5960
"github.com/coder/quartz"
6061
"github.com/coder/retry"
@@ -1459,14 +1460,14 @@ func newProvisionerDaemon(
14591460
tracer := coderAPI.TracerProvider.Tracer(tracing.TracerName)
14601461
terraformClient, terraformServer := drpcsdk.MemTransportPipe()
14611462
wg.Add(1)
1462-
go func() {
1463+
pproflabel.Go(ctx, pproflabel.Service(pproflabel.ServiceTerraformProvisioner), func(ctx context.Context) {
14631464
defer wg.Done()
14641465
<-ctx.Done()
14651466
_ = terraformClient.Close()
14661467
_ = terraformServer.Close()
1467-
}()
1468+
})
14681469
wg.Add(1)
1469-
go func() {
1470+
pproflabel.Go(ctx, pproflabel.Service(pproflabel.ServiceTerraformProvisioner), func(ctx context.Context) {
14701471
defer wg.Done()
14711472
defer cancel()
14721473

@@ -1485,7 +1486,7 @@ func newProvisionerDaemon(
14851486
default:
14861487
}
14871488
}
1488-
}()
1489+
})
14891490

14901491
connector[string(database.ProvisionerTypeTerraform)] = sdkproto.NewDRPCProvisionerClient(terraformClient)
14911492
default:

coderd/apidoc/docs.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/autobuild/lifecycle_executor.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"cdr.dev/slog"
2222
"github.com/coder/coder/v2/coderd/files"
23+
"github.com/coder/coder/v2/coderd/pproflabel"
2324

2425
"github.com/coder/coder/v2/coderd/audit"
2526
"github.com/coder/coder/v2/coderd/database"
@@ -107,10 +108,10 @@ func (e *Executor) WithStatsChannel(ch chan<- Stats) *Executor {
107108
// tick from its channel. It will stop when its context is Done, or when
108109
// its channel is closed.
109110
func (e *Executor) Run() {
110-
go func() {
111+
pproflabel.Go(e.ctx, pproflabel.Service(pproflabel.ServiceLifecycles), func(ctx context.Context) {
111112
for {
112113
select {
113-
case <-e.ctx.Done():
114+
case <-ctx.Done():
114115
return
115116
case t, ok := <-e.tick:
116117
if !ok {
@@ -120,15 +121,15 @@ func (e *Executor) Run() {
120121
e.metrics.autobuildExecutionDuration.Observe(stats.Elapsed.Seconds())
121122
if e.statsCh != nil {
122123
select {
123-
case <-e.ctx.Done():
124+
case <-ctx.Done():
124125
return
125126
case e.statsCh <- stats:
126127
}
127128
}
128-
e.log.Debug(e.ctx, "run stats", slog.F("elapsed", stats.Elapsed), slog.F("transitions", stats.Transitions))
129+
e.log.Debug(ctx, "run stats", slog.F("elapsed", stats.Elapsed), slog.F("transitions", stats.Transitions))
129130
}
130131
}
131-
}()
132+
})
132133
}
133134

134135
func (e *Executor) runOnce(t time.Time) Stats {

coderd/coderd.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ import (
1414
"net/url"
1515
"path/filepath"
1616
"regexp"
17+
"runtime/pprof"
1718
"strings"
1819
"sync"
1920
"sync/atomic"
2021
"time"
2122

2223
"github.com/coder/coder/v2/coderd/oauth2provider"
24+
"github.com/coder/coder/v2/coderd/pproflabel"
2325
"github.com/coder/coder/v2/coderd/prebuilds"
2426
"github.com/coder/coder/v2/coderd/wsbuilder"
2527

@@ -852,6 +854,7 @@ func New(options *Options) *API {
852854

853855
r.Use(
854856
httpmw.Recover(api.Logger),
857+
httpmw.WithProfilingLabels,
855858
tracing.StatusWriterMiddleware,
856859
tracing.Middleware(api.TracerProvider),
857860
httpmw.AttachRequestID,
@@ -1339,7 +1342,13 @@ func New(options *Options) *API {
13391342
).Get("/connection", api.workspaceAgentConnectionGeneric)
13401343
r.Route("/me", func(r chi.Router) {
13411344
r.Use(workspaceAgentInfo)
1342-
r.Get("/rpc", api.workspaceAgentRPC)
1345+
r.Group(func(r chi.Router) {
1346+
r.Use(
1347+
// Override the request_type for agent rpc traffic.
1348+
httpmw.WithStaticProfilingLabels(pprof.Labels(pproflabel.RequestTypeTag, "agent-rpc")),
1349+
)
1350+
r.Get("/rpc", api.workspaceAgentRPC)
1351+
})
13431352
r.Patch("/logs", api.patchWorkspaceAgentLogs)
13441353
r.Patch("/app-status", api.patchWorkspaceAgentAppStatus)
13451354
// Deprecated: Required to support legacy agents
@@ -1415,7 +1424,8 @@ func New(options *Options) *API {
14151424
r.Get("/timings", api.workspaceTimings)
14161425
r.Route("/acl", func(r chi.Router) {
14171426
r.Use(
1418-
httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentWorkspaceSharing))
1427+
httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentWorkspaceSharing),
1428+
)
14191429

14201430
r.Patch("/", api.patchWorkspaceACL)
14211431
})

coderd/database/dbauthz/dbauthz.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,14 @@ func (q *querier) CountUnreadInboxNotificationsByUserID(ctx context.Context, use
13871387
return q.db.CountUnreadInboxNotificationsByUserID(ctx, userID)
13881388
}
13891389

1390+
func (q *querier) CreateUserSecret(ctx context.Context, arg database.CreateUserSecretParams) (database.UserSecret, error) {
1391+
obj := rbac.ResourceUserSecret.WithOwner(arg.UserID.String())
1392+
if err := q.authorizeContext(ctx, policy.ActionCreate, obj); err != nil {
1393+
return database.UserSecret{}, err
1394+
}
1395+
return q.db.CreateUserSecret(ctx, arg)
1396+
}
1397+
13901398
// TODO: Handle org scoped lookups
13911399
func (q *querier) CustomRoles(ctx context.Context, arg database.CustomRolesParams) ([]database.CustomRole, error) {
13921400
roleObject := rbac.ResourceAssignRole
@@ -1657,6 +1665,19 @@ func (q *querier) DeleteTailnetTunnel(ctx context.Context, arg database.DeleteTa
16571665
return q.db.DeleteTailnetTunnel(ctx, arg)
16581666
}
16591667

1668+
func (q *querier) DeleteUserSecret(ctx context.Context, id uuid.UUID) error {
1669+
// First get the secret to check ownership
1670+
secret, err := q.GetUserSecret(ctx, id)
1671+
if err != nil {
1672+
return err
1673+
}
1674+
1675+
if err := q.authorizeContext(ctx, policy.ActionDelete, secret); err != nil {
1676+
return err
1677+
}
1678+
return q.db.DeleteUserSecret(ctx, id)
1679+
}
1680+
16601681
func (q *querier) DeleteWebpushSubscriptionByUserIDAndEndpoint(ctx context.Context, arg database.DeleteWebpushSubscriptionByUserIDAndEndpointParams) error {
16611682
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceWebpushSubscription.WithOwner(arg.UserID.String())); err != nil {
16621683
return err
@@ -3075,6 +3096,28 @@ func (q *querier) GetUserNotificationPreferences(ctx context.Context, userID uui
30753096
return q.db.GetUserNotificationPreferences(ctx, userID)
30763097
}
30773098

3099+
func (q *querier) GetUserSecret(ctx context.Context, id uuid.UUID) (database.UserSecret, error) {
3100+
// First get the secret to check ownership
3101+
secret, err := q.db.GetUserSecret(ctx, id)
3102+
if err != nil {
3103+
return database.UserSecret{}, err
3104+
}
3105+
3106+
if err := q.authorizeContext(ctx, policy.ActionRead, secret); err != nil {
3107+
return database.UserSecret{}, err
3108+
}
3109+
return secret, nil
3110+
}
3111+
3112+
func (q *querier) GetUserSecretByUserIDAndName(ctx context.Context, arg database.GetUserSecretByUserIDAndNameParams) (database.UserSecret, error) {
3113+
obj := rbac.ResourceUserSecret.WithOwner(arg.UserID.String())
3114+
if err := q.authorizeContext(ctx, policy.ActionRead, obj); err != nil {
3115+
return database.UserSecret{}, err
3116+
}
3117+
3118+
return q.db.GetUserSecretByUserIDAndName(ctx, arg)
3119+
}
3120+
30783121
func (q *querier) GetUserStatusCounts(ctx context.Context, arg database.GetUserStatusCountsParams) ([]database.GetUserStatusCountsRow, error) {
30793122
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceUser); err != nil {
30803123
return nil, err
@@ -4153,6 +4196,14 @@ func (q *querier) ListProvisionerKeysByOrganizationExcludeReserved(ctx context.C
41534196
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.ListProvisionerKeysByOrganizationExcludeReserved)(ctx, organizationID)
41544197
}
41554198

4199+
func (q *querier) ListUserSecrets(ctx context.Context, userID uuid.UUID) ([]database.UserSecret, error) {
4200+
obj := rbac.ResourceUserSecret.WithOwner(userID.String())
4201+
if err := q.authorizeContext(ctx, policy.ActionRead, obj); err != nil {
4202+
return nil, err
4203+
}
4204+
return q.db.ListUserSecrets(ctx, userID)
4205+
}
4206+
41564207
func (q *querier) ListWorkspaceAgentPortShares(ctx context.Context, workspaceID uuid.UUID) ([]database.WorkspaceAgentPortShare, error) {
41574208
workspace, err := q.db.GetWorkspaceByID(ctx, workspaceID)
41584209
if err != nil {
@@ -4866,6 +4917,19 @@ func (q *querier) UpdateUserRoles(ctx context.Context, arg database.UpdateUserRo
48664917
return q.db.UpdateUserRoles(ctx, arg)
48674918
}
48684919

4920+
func (q *querier) UpdateUserSecret(ctx context.Context, arg database.UpdateUserSecretParams) (database.UserSecret, error) {
4921+
// First get the secret to check ownership
4922+
secret, err := q.db.GetUserSecret(ctx, arg.ID)
4923+
if err != nil {
4924+
return database.UserSecret{}, err
4925+
}
4926+
4927+
if err := q.authorizeContext(ctx, policy.ActionUpdate, secret); err != nil {
4928+
return database.UserSecret{}, err
4929+
}
4930+
return q.db.UpdateUserSecret(ctx, arg)
4931+
}
4932+
48694933
func (q *querier) UpdateUserStatus(ctx context.Context, arg database.UpdateUserStatusParams) (database.User, error) {
48704934
fetch := func(ctx context.Context, arg database.UpdateUserStatusParams) (database.User, error) {
48714935
return q.db.GetUserByID(ctx, arg.ID)
@@ -5376,6 +5440,26 @@ func (q *querier) UpsertWorkspaceAppAuditSession(ctx context.Context, arg databa
53765440
return q.db.UpsertWorkspaceAppAuditSession(ctx, arg)
53775441
}
53785442

5443+
func (q *querier) ValidateGroupIDs(ctx context.Context, groupIDs []uuid.UUID) (database.ValidateGroupIDsRow, error) {
5444+
// This check is probably overly restrictive, but the "correct" check isn't
5445+
// necessarily obvious. It's only used as a verification check for ACLs right
5446+
// now, which are performed as system.
5447+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
5448+
return database.ValidateGroupIDsRow{}, err
5449+
}
5450+
return q.db.ValidateGroupIDs(ctx, groupIDs)
5451+
}
5452+
5453+
func (q *querier) ValidateUserIDs(ctx context.Context, userIDs []uuid.UUID) (database.ValidateUserIDsRow, error) {
5454+
// This check is probably overly restrictive, but the "correct" check isn't
5455+
// necessarily obvious. It's only used as a verification check for ACLs right
5456+
// now, which are performed as system.
5457+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
5458+
return database.ValidateUserIDsRow{}, err
5459+
}
5460+
return q.db.ValidateUserIDs(ctx, userIDs)
5461+
}
5462+
53795463
func (q *querier) GetAuthorizedTemplates(ctx context.Context, arg database.GetTemplatesWithFilterParams, _ rbac.PreparedAuthorized) ([]database.Template, error) {
53805464
// TODO Delete this function, all GetTemplates should be authorized. For now just call getTemplates on the authz querier.
53815465
return q.GetTemplatesWithFilter(ctx, arg)

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,11 @@ func (s *MethodTestSuite) TestGroup() {
623623
ID: g.ID,
624624
}).Asserts(g, policy.ActionUpdate)
625625
}))
626+
s.Run("ValidateGroupIDs", s.Subtest(func(db database.Store, check *expects) {
627+
o := dbgen.Organization(s.T(), db, database.Organization{})
628+
g := dbgen.Group(s.T(), db, database.Group{OrganizationID: o.ID})
629+
check.Args([]uuid.UUID{g.ID}).Asserts(rbac.ResourceSystem, policy.ActionRead)
630+
}))
626631
}
627632

628633
func (s *MethodTestSuite) TestProvisionerJob() {
@@ -2077,6 +2082,10 @@ func (s *MethodTestSuite) TestUser() {
20772082
Interval: int32((time.Hour * 24).Seconds()),
20782083
}).Asserts(rbac.ResourceUser, policy.ActionRead)
20792084
}))
2085+
s.Run("ValidateUserIDs", s.Subtest(func(db database.Store, check *expects) {
2086+
u := dbgen.User(s.T(), db, database.User{})
2087+
check.Args([]uuid.UUID{u.ID}).Asserts(rbac.ResourceSystem, policy.ActionRead)
2088+
}))
20802089
}
20812090

20822091
func (s *MethodTestSuite) TestWorkspace() {
@@ -5874,3 +5883,64 @@ func (s *MethodTestSuite) TestAuthorizePrebuiltWorkspace() {
58745883
}).Asserts(w, policy.ActionUpdate, w.AsPrebuild(), policy.ActionUpdate)
58755884
}))
58765885
}
5886+
5887+
func (s *MethodTestSuite) TestUserSecrets() {
5888+
s.Run("GetUserSecretByUserIDAndName", s.Subtest(func(db database.Store, check *expects) {
5889+
user := dbgen.User(s.T(), db, database.User{})
5890+
userSecret := dbgen.UserSecret(s.T(), db, database.UserSecret{
5891+
UserID: user.ID,
5892+
})
5893+
arg := database.GetUserSecretByUserIDAndNameParams{
5894+
UserID: user.ID,
5895+
Name: userSecret.Name,
5896+
}
5897+
check.Args(arg).
5898+
Asserts(rbac.ResourceUserSecret.WithOwner(arg.UserID.String()), policy.ActionRead).
5899+
Returns(userSecret)
5900+
}))
5901+
s.Run("GetUserSecret", s.Subtest(func(db database.Store, check *expects) {
5902+
user := dbgen.User(s.T(), db, database.User{})
5903+
userSecret := dbgen.UserSecret(s.T(), db, database.UserSecret{
5904+
UserID: user.ID,
5905+
})
5906+
check.Args(userSecret.ID).
5907+
Asserts(userSecret, policy.ActionRead).
5908+
Returns(userSecret)
5909+
}))
5910+
s.Run("ListUserSecrets", s.Subtest(func(db database.Store, check *expects) {
5911+
user := dbgen.User(s.T(), db, database.User{})
5912+
userSecret := dbgen.UserSecret(s.T(), db, database.UserSecret{
5913+
UserID: user.ID,
5914+
})
5915+
check.Args(user.ID).
5916+
Asserts(rbac.ResourceUserSecret.WithOwner(user.ID.String()), policy.ActionRead).
5917+
Returns([]database.UserSecret{userSecret})
5918+
}))
5919+
s.Run("CreateUserSecret", s.Subtest(func(db database.Store, check *expects) {
5920+
user := dbgen.User(s.T(), db, database.User{})
5921+
arg := database.CreateUserSecretParams{
5922+
UserID: user.ID,
5923+
}
5924+
check.Args(arg).
5925+
Asserts(rbac.ResourceUserSecret.WithOwner(arg.UserID.String()), policy.ActionCreate)
5926+
}))
5927+
s.Run("UpdateUserSecret", s.Subtest(func(db database.Store, check *expects) {
5928+
user := dbgen.User(s.T(), db, database.User{})
5929+
userSecret := dbgen.UserSecret(s.T(), db, database.UserSecret{
5930+
UserID: user.ID,
5931+
})
5932+
arg := database.UpdateUserSecretParams{
5933+
ID: userSecret.ID,
5934+
}
5935+
check.Args(arg).
5936+
Asserts(userSecret, policy.ActionUpdate)
5937+
}))
5938+
s.Run("DeleteUserSecret", s.Subtest(func(db database.Store, check *expects) {
5939+
user := dbgen.User(s.T(), db, database.User{})
5940+
userSecret := dbgen.UserSecret(s.T(), db, database.UserSecret{
5941+
UserID: user.ID,
5942+
})
5943+
check.Args(userSecret.ID).
5944+
Asserts(userSecret, policy.ActionRead, userSecret, policy.ActionDelete)
5945+
}))
5946+
}

coderd/database/dbgen/dbgen.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,20 @@ func PresetParameter(t testing.TB, db database.Store, seed database.InsertPreset
14221422
return parameters
14231423
}
14241424

1425+
func UserSecret(t testing.TB, db database.Store, seed database.UserSecret) database.UserSecret {
1426+
userSecret, err := db.CreateUserSecret(genCtx, database.CreateUserSecretParams{
1427+
ID: takeFirst(seed.ID, uuid.New()),
1428+
UserID: takeFirst(seed.UserID, uuid.New()),
1429+
Name: takeFirst(seed.Name, "secret-name"),
1430+
Description: takeFirst(seed.Description, "secret description"),
1431+
Value: takeFirst(seed.Value, "secret value"),
1432+
EnvName: takeFirst(seed.EnvName, "SECRET_ENV_NAME"),
1433+
FilePath: takeFirst(seed.FilePath, "~/secret/file/path"),
1434+
})
1435+
require.NoError(t, err, "failed to insert user secret")
1436+
return userSecret
1437+
}
1438+
14251439
func ClaimPrebuild(t testing.TB, db database.Store, newUserID uuid.UUID, newName string, presetID uuid.UUID) database.ClaimPrebuiltWorkspaceRow {
14261440
claimedWorkspace, err := db.ClaimPrebuiltWorkspace(genCtx, database.ClaimPrebuiltWorkspaceParams{
14271441
NewUserID: newUserID,

0 commit comments

Comments
 (0)