@@ -417,6 +417,35 @@ var (
417
417
rbac .ResourceProvisionerJobs .Type : {policy .ActionRead , policy .ActionUpdate , policy .ActionCreate },
418
418
rbac .ResourceOauth2App .Type : {policy .ActionCreate , policy .ActionRead , policy .ActionUpdate , policy .ActionDelete },
419
419
rbac .ResourceOauth2AppSecret .Type : {policy .ActionCreate , policy .ActionRead , policy .ActionUpdate , policy .ActionDelete },
420
+ rbac .ResourceOauth2AppCodeToken .Type : {policy .ActionCreate , policy .ActionRead , policy .ActionUpdate , policy .ActionDelete },
421
+ }),
422
+ Org : map [string ][]rbac.Permission {},
423
+ User : []rbac.Permission {},
424
+ },
425
+ }),
426
+ Scope : rbac .ScopeAll ,
427
+ }.WithCachedASTValue ()
428
+
429
+ subjectSystemOAuth2 = rbac.Subject {
430
+ Type : rbac .SubjectTypeSystemRestricted ,
431
+ FriendlyName : "System OAuth2" ,
432
+ ID : uuid .Nil .String (),
433
+ Roles : rbac .Roles ([]rbac.Role {
434
+ {
435
+ Identifier : rbac.RoleIdentifier {Name : "system-oauth2" },
436
+ DisplayName : "System OAuth2" ,
437
+ Site : rbac .Permissions (map [string ][]policy.Action {
438
+ // OAuth2 resources - full CRUD permissions
439
+ rbac .ResourceOauth2App .Type : rbac .ResourceOauth2App .AvailableActions (),
440
+ rbac .ResourceOauth2AppSecret .Type : rbac .ResourceOauth2AppSecret .AvailableActions (),
441
+ rbac .ResourceOauth2AppCodeToken .Type : rbac .ResourceOauth2AppCodeToken .AvailableActions (),
442
+
443
+ // API key permissions needed for OAuth2 token revocation
444
+ rbac .ResourceApiKey .Type : {policy .ActionRead , policy .ActionDelete },
445
+
446
+ // Minimal read permissions that might be needed for OAuth2 operations
447
+ rbac .ResourceUser .Type : {policy .ActionRead },
448
+ rbac .ResourceOrganization .Type : {policy .ActionRead },
420
449
}),
421
450
Org : map [string ][]rbac.Permission {},
422
451
User : []rbac.Permission {},
@@ -567,6 +596,12 @@ func AsSystemRestricted(ctx context.Context) context.Context {
567
596
return As (ctx , subjectSystemRestricted )
568
597
}
569
598
599
+ // AsSystemOAuth2 returns a context with an actor that has permissions
600
+ // required for OAuth2 provider operations (token revocation, device codes, registration).
601
+ func AsSystemOAuth2 (ctx context.Context ) context.Context {
602
+ return As (ctx , subjectSystemOAuth2 )
603
+ }
604
+
570
605
// AsSystemReadProvisionerDaemons returns a context with an actor that has permissions
571
606
// to read provisioner daemons.
572
607
func AsSystemReadProvisionerDaemons (ctx context.Context ) context.Context {
@@ -1346,6 +1381,14 @@ func (q *querier) CleanTailnetTunnels(ctx context.Context) error {
1346
1381
return q .db .CleanTailnetTunnels (ctx )
1347
1382
}
1348
1383
1384
+ func (q * querier ) ConsumeOAuth2ProviderAppCodeByPrefix (ctx context.Context , secretPrefix []byte ) (database.OAuth2ProviderAppCode , error ) {
1385
+ return updateWithReturn (q .log , q .auth , q .db .GetOAuth2ProviderAppCodeByPrefix , q .db .ConsumeOAuth2ProviderAppCodeByPrefix )(ctx , secretPrefix )
1386
+ }
1387
+
1388
+ func (q * querier ) ConsumeOAuth2ProviderDeviceCodeByPrefix (ctx context.Context , deviceCodePrefix string ) (database.OAuth2ProviderDeviceCode , error ) {
1389
+ return updateWithReturn (q .log , q .auth , q .db .GetOAuth2ProviderDeviceCodeByPrefix , q .db .ConsumeOAuth2ProviderDeviceCodeByPrefix )(ctx , deviceCodePrefix )
1390
+ }
1391
+
1349
1392
func (q * querier ) CountAuditLogs (ctx context.Context , arg database.CountAuditLogsParams ) (int64 , error ) {
1350
1393
// Shortcut if the user is an owner. The SQL filter is noticeable,
1351
1394
// and this is an easy win for owners. Which is the common case.
@@ -1481,7 +1524,7 @@ func (q *querier) DeleteExpiredOAuth2ProviderDeviceCodes(ctx context.Context) er
1481
1524
func (q * querier ) DeleteExternalAuthLink (ctx context.Context , arg database.DeleteExternalAuthLinkParams ) error {
1482
1525
return fetchAndExec (q .log , q .auth , policy .ActionUpdatePersonal , func (ctx context.Context , arg database.DeleteExternalAuthLinkParams ) (database.ExternalAuthLink , error ) {
1483
1526
//nolint:gosimple
1484
- return q .db .GetExternalAuthLink (ctx , database.GetExternalAuthLinkParams { UserID : arg . UserID , ProviderID : arg . ProviderID } )
1527
+ return q .db .GetExternalAuthLink (ctx , database .GetExternalAuthLinkParams ( arg ) )
1485
1528
}, q .db .DeleteExternalAuthLink )(ctx , arg )
1486
1529
}
1487
1530
@@ -1560,27 +1603,30 @@ func (q *querier) DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx context.Contex
1560
1603
return q .db .DeleteOAuth2ProviderAppTokensByAppAndUserID (ctx , arg )
1561
1604
}
1562
1605
1563
- func (q * querier ) DeleteOldAuditLogConnectionEvents (ctx context.Context , threshold database.DeleteOldAuditLogConnectionEventsParams ) error {
1564
- // `ResourceSystem` is deprecated, but it doesn't make sense to add
1565
- // `policy.ActionDelete` to `ResourceAuditLog`, since this is the one and
1566
- // only time we'll be deleting from the audit log.
1567
- if err := q .authorizeContext (ctx , policy .ActionDelete , rbac .ResourceSystem ); err != nil {
1568
- return err
1569
- }
1570
- return q .db .DeleteOldAuditLogConnectionEvents (ctx , threshold )
1571
- }
1572
-
1573
1606
func (q * querier ) DeleteOAuth2ProviderDeviceCodeByID (ctx context.Context , id uuid.UUID ) error {
1574
1607
// Fetch the device code first to check authorization
1575
1608
deviceCode , err := q .db .GetOAuth2ProviderDeviceCodeByID (ctx , id )
1576
1609
if err != nil {
1577
- return err
1610
+ return xerrors . Errorf ( "get oauth2 provider device code: %w" , err )
1578
1611
}
1579
1612
if err := q .authorizeContext (ctx , policy .ActionDelete , deviceCode ); err != nil {
1580
- return err
1613
+ return xerrors . Errorf ( "authorize oauth2 provider device code deletion: %w" , err )
1581
1614
}
1582
1615
1583
- return q .db .DeleteOAuth2ProviderDeviceCodeByID (ctx , id )
1616
+ if err := q .db .DeleteOAuth2ProviderDeviceCodeByID (ctx , id ); err != nil {
1617
+ return xerrors .Errorf ("delete oauth2 provider device code: %w" , err )
1618
+ }
1619
+ return nil
1620
+ }
1621
+
1622
+ func (q * querier ) DeleteOldAuditLogConnectionEvents (ctx context.Context , threshold database.DeleteOldAuditLogConnectionEventsParams ) error {
1623
+ // `ResourceSystem` is deprecated, but it doesn't make sense to add
1624
+ // `policy.ActionDelete` to `ResourceAuditLog`, since this is the one and
1625
+ // only time we'll be deleting from the audit log.
1626
+ if err := q .authorizeContext (ctx , policy .ActionDelete , rbac .ResourceSystem ); err != nil {
1627
+ return err
1628
+ }
1629
+ return q .db .DeleteOldAuditLogConnectionEvents (ctx , threshold )
1584
1630
}
1585
1631
1586
1632
func (q * querier ) DeleteOldNotificationMessages (ctx context.Context ) error {
@@ -1612,7 +1658,7 @@ func (q *querier) DeleteOldWorkspaceAgentStats(ctx context.Context) error {
1612
1658
}
1613
1659
1614
1660
func (q * querier ) DeleteOrganizationMember (ctx context.Context , arg database.DeleteOrganizationMemberParams ) error {
1615
- return deleteQ [database. OrganizationMember ] (q .log , q .auth , func (ctx context.Context , arg database.DeleteOrganizationMemberParams ) (database.OrganizationMember , error ) {
1661
+ return deleteQ (q .log , q .auth , func (ctx context.Context , arg database.DeleteOrganizationMemberParams ) (database.OrganizationMember , error ) {
1616
1662
member , err := database .ExpectOne (q .OrganizationMembers (ctx , database.OrganizationMembersParams {
1617
1663
OrganizationID : arg .OrganizationID ,
1618
1664
UserID : arg .UserID ,
@@ -2203,7 +2249,7 @@ func (q *querier) GetLicenseByID(ctx context.Context, id int32) (database.Licens
2203
2249
}
2204
2250
2205
2251
func (q * querier ) GetLicenses (ctx context.Context ) ([]database.License , error ) {
2206
- fetch := func (ctx context.Context , _ interface {} ) ([]database.License , error ) {
2252
+ fetch := func (ctx context.Context , _ any ) ([]database.License , error ) {
2207
2253
return q .db .GetLicenses (ctx )
2208
2254
}
2209
2255
return fetchWithPostFilter (q .auth , policy .ActionRead , fetch )(ctx , nil )
@@ -2367,8 +2413,8 @@ func (q *querier) GetOAuth2ProviderDeviceCodeByUserCode(ctx context.Context, use
2367
2413
}
2368
2414
2369
2415
func (q * querier ) GetOAuth2ProviderDeviceCodesByClientID (ctx context.Context , clientID uuid.UUID ) ([]database.OAuth2ProviderDeviceCode , error ) {
2370
- // This requires access to read the OAuth2 app
2371
- if err := q .authorizeContext (ctx , policy .ActionRead , rbac .ResourceOauth2App ); err != nil {
2416
+ // This requires access to read OAuth2 app code tokens
2417
+ if err := q .authorizeContext (ctx , policy .ActionRead , rbac .ResourceOauth2AppCodeToken ); err != nil {
2372
2418
return []database.OAuth2ProviderDeviceCode {}, err
2373
2419
}
2374
2420
return q .db .GetOAuth2ProviderDeviceCodesByClientID (ctx , clientID )
@@ -2425,7 +2471,7 @@ func (q *querier) GetOrganizationResourceCountByID(ctx context.Context, organiza
2425
2471
}
2426
2472
2427
2473
func (q * querier ) GetOrganizations (ctx context.Context , args database.GetOrganizationsParams ) ([]database.Organization , error ) {
2428
- fetch := func (ctx context.Context , _ interface {} ) ([]database.Organization , error ) {
2474
+ fetch := func (ctx context.Context , _ any ) ([]database.Organization , error ) {
2429
2475
return q .db .GetOrganizations (ctx , args )
2430
2476
}
2431
2477
return fetchWithPostFilter (q .auth , policy .ActionRead , fetch )(ctx , nil )
@@ -2553,7 +2599,7 @@ func (q *querier) GetPreviousTemplateVersion(ctx context.Context, arg database.G
2553
2599
}
2554
2600
2555
2601
func (q * querier ) GetProvisionerDaemons (ctx context.Context ) ([]database.ProvisionerDaemon , error ) {
2556
- fetch := func (ctx context.Context , _ interface {} ) ([]database.ProvisionerDaemon , error ) {
2602
+ fetch := func (ctx context.Context , _ any ) ([]database.ProvisionerDaemon , error ) {
2557
2603
return q .db .GetProvisionerDaemons (ctx )
2558
2604
}
2559
2605
return fetchWithPostFilter (q .auth , policy .ActionRead , fetch )(ctx , nil )
@@ -3511,7 +3557,7 @@ func (q *querier) GetWorkspaceModulesCreatedAfter(ctx context.Context, createdAt
3511
3557
}
3512
3558
3513
3559
func (q * querier ) GetWorkspaceProxies (ctx context.Context ) ([]database.WorkspaceProxy , error ) {
3514
- return fetchWithPostFilter (q .auth , policy .ActionRead , func (ctx context.Context , _ interface {} ) ([]database.WorkspaceProxy , error ) {
3560
+ return fetchWithPostFilter (q .auth , policy .ActionRead , func (ctx context.Context , _ any ) ([]database.WorkspaceProxy , error ) {
3515
3561
return q .db .GetWorkspaceProxies (ctx )
3516
3562
})(ctx , nil )
3517
3563
}
@@ -3810,8 +3856,8 @@ func (q *querier) InsertOAuth2ProviderAppToken(ctx context.Context, arg database
3810
3856
}
3811
3857
3812
3858
func (q * querier ) InsertOAuth2ProviderDeviceCode (ctx context.Context , arg database.InsertOAuth2ProviderDeviceCodeParams ) (database.OAuth2ProviderDeviceCode , error ) {
3813
- // Creating device codes requires OAuth2 app access
3814
- if err := q .authorizeContext (ctx , policy .ActionCreate , rbac .ResourceOauth2App ); err != nil {
3859
+ // Creating device codes requires OAuth2 app code token creation access
3860
+ if err := q .authorizeContext (ctx , policy .ActionCreate , rbac .ResourceOauth2AppCodeToken ); err != nil {
3815
3861
return database.OAuth2ProviderDeviceCode {}, err
3816
3862
}
3817
3863
return q .db .InsertOAuth2ProviderDeviceCode (ctx , arg )
@@ -4118,10 +4164,11 @@ func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertW
4118
4164
return xerrors .Errorf ("get workspace by id: %w" , err )
4119
4165
}
4120
4166
4121
- var action policy.Action = policy .ActionWorkspaceStart
4122
- if arg .Transition == database .WorkspaceTransitionDelete {
4167
+ action := policy .ActionWorkspaceStart
4168
+ switch arg .Transition {
4169
+ case database .WorkspaceTransitionDelete :
4123
4170
action = policy .ActionDelete
4124
- } else if arg . Transition == database .WorkspaceTransitionStop {
4171
+ case database .WorkspaceTransitionStop :
4125
4172
action = policy .ActionWorkspaceStop
4126
4173
}
4127
4174
@@ -4490,13 +4537,10 @@ func (q *querier) UpdateOAuth2ProviderAppSecretByID(ctx context.Context, arg dat
4490
4537
}
4491
4538
4492
4539
func (q * querier ) UpdateOAuth2ProviderDeviceCodeAuthorization (ctx context.Context , arg database.UpdateOAuth2ProviderDeviceCodeAuthorizationParams ) (database.OAuth2ProviderDeviceCode , error ) {
4493
- // Verify the user is authenticated for device code authorization
4494
- _ , ok := ActorFromContext (ctx )
4495
- if ! ok {
4496
- return database.OAuth2ProviderDeviceCode {}, ErrNoActor
4540
+ fetch := func (ctx context.Context , arg database.UpdateOAuth2ProviderDeviceCodeAuthorizationParams ) (database.OAuth2ProviderDeviceCode , error ) {
4541
+ return q .db .GetOAuth2ProviderDeviceCodeByID (ctx , arg .ID )
4497
4542
}
4498
-
4499
- return q .db .UpdateOAuth2ProviderDeviceCodeAuthorization (ctx , arg )
4543
+ return updateWithReturn (q .log , q .auth , fetch , q .db .UpdateOAuth2ProviderDeviceCodeAuthorization )(ctx , arg )
4500
4544
}
4501
4545
4502
4546
func (q * querier ) UpdateOrganization (ctx context.Context , arg database.UpdateOrganizationParams ) (database.Organization , error ) {
0 commit comments