Skip to content

Commit fc8454b

Browse files
authored
feat: extend request logs with auth & DB info (#17498)
1 parent 550b81f commit fc8454b

File tree

19 files changed

+716
-94
lines changed

19 files changed

+716
-94
lines changed

Makefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,8 @@ GEN_FILES := \
564564
examples/examples.gen.json \
565565
$(TAILNETTEST_MOCKS) \
566566
coderd/database/pubsub/psmock/psmock.go \
567-
agent/agentcontainers/acmock/acmock.go
567+
agent/agentcontainers/acmock/acmock.go \
568+
coderd/httpmw/loggermw/loggermock/loggermock.go
568569

569570

570571
# all gen targets should be added here and to gen/mark-fresh
@@ -600,6 +601,7 @@ gen/mark-fresh:
600601
$(TAILNETTEST_MOCKS) \
601602
coderd/database/pubsub/psmock/psmock.go \
602603
agent/agentcontainers/acmock/acmock.go \
604+
coderd/httpmw/loggermw/loggermock/loggermock.go
603605
"
604606

605607
for file in $$files; do
@@ -634,6 +636,9 @@ coderd/database/pubsub/psmock/psmock.go: coderd/database/pubsub/pubsub.go
634636
agent/agentcontainers/acmock/acmock.go: agent/agentcontainers/containers.go
635637
go generate ./agent/agentcontainers/acmock/
636638

639+
coderd/httpmw/loggermw/loggermock/loggermock.go: coderd/httpmw/loggermw/logger.go
640+
go generate ./coderd/httpmw/loggermw/loggermock/
641+
637642
$(TAILNETTEST_MOCKS): tailnet/coordinator.go tailnet/service.go
638643
go generate ./tailnet/tailnettest/
639644

coderd/coderd.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import (
6363
"github.com/coder/coder/v2/coderd/healthcheck/derphealth"
6464
"github.com/coder/coder/v2/coderd/httpapi"
6565
"github.com/coder/coder/v2/coderd/httpmw"
66+
"github.com/coder/coder/v2/coderd/httpmw/loggermw"
6667
"github.com/coder/coder/v2/coderd/metricscache"
6768
"github.com/coder/coder/v2/coderd/notifications"
6869
"github.com/coder/coder/v2/coderd/portsharing"
@@ -788,7 +789,7 @@ func New(options *Options) *API {
788789
tracing.Middleware(api.TracerProvider),
789790
httpmw.AttachRequestID,
790791
httpmw.ExtractRealIP(api.RealIPConfig),
791-
httpmw.Logger(api.Logger),
792+
loggermw.Logger(api.Logger),
792793
singleSlashMW,
793794
rolestore.CustomRoleMW,
794795
prometheusMW,

coderd/database/dbauthz/dbauthz.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/coder/coder/v2/coderd/database"
2525
"github.com/coder/coder/v2/coderd/database/dbtime"
2626
"github.com/coder/coder/v2/coderd/httpapi/httpapiconstraints"
27+
"github.com/coder/coder/v2/coderd/httpmw/loggermw"
2728
"github.com/coder/coder/v2/coderd/rbac"
2829
"github.com/coder/coder/v2/coderd/util/slice"
2930
"github.com/coder/coder/v2/provisionersdk"
@@ -162,6 +163,7 @@ func ActorFromContext(ctx context.Context) (rbac.Subject, bool) {
162163

163164
var (
164165
subjectProvisionerd = rbac.Subject{
166+
Type: rbac.SubjectTypeProvisionerd,
165167
FriendlyName: "Provisioner Daemon",
166168
ID: uuid.Nil.String(),
167169
Roles: rbac.Roles([]rbac.Role{
@@ -195,6 +197,7 @@ var (
195197
}.WithCachedASTValue()
196198

197199
subjectAutostart = rbac.Subject{
200+
Type: rbac.SubjectTypeAutostart,
198201
FriendlyName: "Autostart",
199202
ID: uuid.Nil.String(),
200203
Roles: rbac.Roles([]rbac.Role{
@@ -218,6 +221,7 @@ var (
218221

219222
// See unhanger package.
220223
subjectHangDetector = rbac.Subject{
224+
Type: rbac.SubjectTypeHangDetector,
221225
FriendlyName: "Hang Detector",
222226
ID: uuid.Nil.String(),
223227
Roles: rbac.Roles([]rbac.Role{
@@ -238,6 +242,7 @@ var (
238242

239243
// See cryptokeys package.
240244
subjectCryptoKeyRotator = rbac.Subject{
245+
Type: rbac.SubjectTypeCryptoKeyRotator,
241246
FriendlyName: "Crypto Key Rotator",
242247
ID: uuid.Nil.String(),
243248
Roles: rbac.Roles([]rbac.Role{
@@ -256,6 +261,7 @@ var (
256261

257262
// See cryptokeys package.
258263
subjectCryptoKeyReader = rbac.Subject{
264+
Type: rbac.SubjectTypeCryptoKeyReader,
259265
FriendlyName: "Crypto Key Reader",
260266
ID: uuid.Nil.String(),
261267
Roles: rbac.Roles([]rbac.Role{
@@ -273,6 +279,7 @@ var (
273279
}.WithCachedASTValue()
274280

275281
subjectNotifier = rbac.Subject{
282+
Type: rbac.SubjectTypeNotifier,
276283
FriendlyName: "Notifier",
277284
ID: uuid.Nil.String(),
278285
Roles: rbac.Roles([]rbac.Role{
@@ -290,6 +297,7 @@ var (
290297
}.WithCachedASTValue()
291298

292299
subjectResourceMonitor = rbac.Subject{
300+
Type: rbac.SubjectTypeResourceMonitor,
293301
FriendlyName: "Resource Monitor",
294302
ID: uuid.Nil.String(),
295303
Roles: rbac.Roles([]rbac.Role{
@@ -308,6 +316,7 @@ var (
308316
}.WithCachedASTValue()
309317

310318
subjectSystemRestricted = rbac.Subject{
319+
Type: rbac.SubjectTypeSystemRestricted,
311320
FriendlyName: "System",
312321
ID: uuid.Nil.String(),
313322
Roles: rbac.Roles([]rbac.Role{
@@ -342,6 +351,7 @@ var (
342351
}.WithCachedASTValue()
343352

344353
subjectSystemReadProvisionerDaemons = rbac.Subject{
354+
Type: rbac.SubjectTypeSystemReadProvisionerDaemons,
345355
FriendlyName: "Provisioner Daemons Reader",
346356
ID: uuid.Nil.String(),
347357
Roles: rbac.Roles([]rbac.Role{
@@ -362,53 +372,53 @@ var (
362372
// AsProvisionerd returns a context with an actor that has permissions required
363373
// for provisionerd to function.
364374
func AsProvisionerd(ctx context.Context) context.Context {
365-
return context.WithValue(ctx, authContextKey{}, subjectProvisionerd)
375+
return As(ctx, subjectProvisionerd)
366376
}
367377

368378
// AsAutostart returns a context with an actor that has permissions required
369379
// for autostart to function.
370380
func AsAutostart(ctx context.Context) context.Context {
371-
return context.WithValue(ctx, authContextKey{}, subjectAutostart)
381+
return As(ctx, subjectAutostart)
372382
}
373383

374384
// AsHangDetector returns a context with an actor that has permissions required
375385
// for unhanger.Detector to function.
376386
func AsHangDetector(ctx context.Context) context.Context {
377-
return context.WithValue(ctx, authContextKey{}, subjectHangDetector)
387+
return As(ctx, subjectHangDetector)
378388
}
379389

380390
// AsKeyRotator returns a context with an actor that has permissions required for rotating crypto keys.
381391
func AsKeyRotator(ctx context.Context) context.Context {
382-
return context.WithValue(ctx, authContextKey{}, subjectCryptoKeyRotator)
392+
return As(ctx, subjectCryptoKeyRotator)
383393
}
384394

385395
// AsKeyReader returns a context with an actor that has permissions required for reading crypto keys.
386396
func AsKeyReader(ctx context.Context) context.Context {
387-
return context.WithValue(ctx, authContextKey{}, subjectCryptoKeyReader)
397+
return As(ctx, subjectCryptoKeyReader)
388398
}
389399

390400
// AsNotifier returns a context with an actor that has permissions required for
391401
// creating/reading/updating/deleting notifications.
392402
func AsNotifier(ctx context.Context) context.Context {
393-
return context.WithValue(ctx, authContextKey{}, subjectNotifier)
403+
return As(ctx, subjectNotifier)
394404
}
395405

396406
// AsResourceMonitor returns a context with an actor that has permissions required for
397407
// updating resource monitors.
398408
func AsResourceMonitor(ctx context.Context) context.Context {
399-
return context.WithValue(ctx, authContextKey{}, subjectResourceMonitor)
409+
return As(ctx, subjectResourceMonitor)
400410
}
401411

402412
// AsSystemRestricted returns a context with an actor that has permissions
403413
// required for various system operations (login, logout, metrics cache).
404414
func AsSystemRestricted(ctx context.Context) context.Context {
405-
return context.WithValue(ctx, authContextKey{}, subjectSystemRestricted)
415+
return As(ctx, subjectSystemRestricted)
406416
}
407417

408418
// AsSystemReadProvisionerDaemons returns a context with an actor that has permissions
409419
// to read provisioner daemons.
410420
func AsSystemReadProvisionerDaemons(ctx context.Context) context.Context {
411-
return context.WithValue(ctx, authContextKey{}, subjectSystemReadProvisionerDaemons)
421+
return As(ctx, subjectSystemReadProvisionerDaemons)
412422
}
413423

414424
var AsRemoveActor = rbac.Subject{
@@ -426,6 +436,9 @@ func As(ctx context.Context, actor rbac.Subject) context.Context {
426436
// should be removed from the context.
427437
return context.WithValue(ctx, authContextKey{}, nil)
428438
}
439+
if rlogger := loggermw.RequestLoggerFromContext(ctx); rlogger != nil {
440+
rlogger.WithAuthContext(actor)
441+
}
429442
return context.WithValue(ctx, authContextKey{}, actor)
430443
}
431444

coderd/database/queries.sql.go

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

coderd/database/queries/users.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,10 @@ WHERE
244244
-- This function returns roles for authorization purposes. Implied member roles
245245
-- are included.
246246
SELECT
247-
-- username is returned just to help for logging purposes
247+
-- username and email are returned just to help for logging purposes
248248
-- status is used to enforce 'suspended' users, as all roles are ignored
249249
-- when suspended.
250-
id, username, status,
250+
id, username, status, email,
251251
-- All user roles, including their org roles.
252252
array_cat(
253253
-- All users are members

coderd/httpmw/apikey.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,9 @@ func UserRBACSubject(ctx context.Context, db database.Store, userID uuid.UUID, s
465465
}
466466

467467
actor := rbac.Subject{
468+
Type: rbac.SubjectTypeUser,
468469
FriendlyName: roles.Username,
470+
Email: roles.Email,
469471
ID: userID.String(),
470472
Roles: rbacRoles,
471473
Groups: roles.Groups,

coderd/httpmw/logger.go

Lines changed: 0 additions & 76 deletions
This file was deleted.

0 commit comments

Comments
 (0)