refactor: replace AsSystemRestricted with narrower actors (#23712)

Replace overly-broad `AsSystemRestricted` with purpose-built actors:

- **OAuth2 provider paths** → `AsSystemOAuth2` (13 call sites across
`tokens.go`, `registration.go`, `apikey.go`)
- **Provisioner daemon health read** → `AsSystemReadProvisionerDaemons`
(1 site in `healthcheck/provisioner.go`)
- **Provisionerd file cache paths** → `AsProvisionerd` (2 sites in
`provisionerdserver.go`, matching existing usage nearby)

<details>
<summary>Implementation notes</summary>

Each replacement actor is a strict subset of `AsSystemRestricted`. Every
DB method
at each call site is already covered by the narrower actor's
permissions:

- `subjectSystemOAuth2`: OAuth2App/Secret/CodeToken (all), ApiKey (Read,
Delete), User (Read), Organization (Read)
- `subjectSystemReadProvisionerDaemons`: ProvisionerDaemon (Read)
- `subjectProvisionerd`: File (Create, Read) plus provisionerd-scoped
resources

No new permissions added. `nolint:gocritic` comments updated to reflect
the new actors.
</details>

> 🤖 Created by a Coder Agent, reviewed by me.
This commit is contained in:
Cian Johnston
2026-03-27 15:08:30 +00:00
committed by GitHub
parent 97a27d3c09
commit 3f55b35f68
5 changed files with 32 additions and 32 deletions
+16 -16
View File
@@ -73,8 +73,8 @@ func CreateDynamicClientRegistration(db database.Store, accessURL *url.URL, audi
// Store in database - use system context since this is a public endpoint
now := dbtime.Now()
clientName := req.GenerateClientName()
//nolint:gocritic // Dynamic client registration is a public endpoint, system access required
app, err := db.InsertOAuth2ProviderApp(dbauthz.AsSystemRestricted(ctx), database.InsertOAuth2ProviderAppParams{
//nolint:gocritic // OAuth2 system context — dynamic registration is a public endpoint
app, err := db.InsertOAuth2ProviderApp(dbauthz.AsSystemOAuth2(ctx), database.InsertOAuth2ProviderAppParams{
ID: clientID,
CreatedAt: now,
UpdatedAt: now,
@@ -121,8 +121,8 @@ func CreateDynamicClientRegistration(db database.Store, accessURL *url.URL, audi
return
}
//nolint:gocritic // Dynamic client registration is a public endpoint, system access required
_, err = db.InsertOAuth2ProviderAppSecret(dbauthz.AsSystemRestricted(ctx), database.InsertOAuth2ProviderAppSecretParams{
//nolint:gocritic // OAuth2 system context — dynamic registration is a public endpoint
_, err = db.InsertOAuth2ProviderAppSecret(dbauthz.AsSystemOAuth2(ctx), database.InsertOAuth2ProviderAppSecretParams{
ID: uuid.New(),
CreatedAt: now,
SecretPrefix: []byte(parsedSecret.Prefix),
@@ -183,8 +183,8 @@ func GetClientConfiguration(db database.Store) http.HandlerFunc {
}
// Get app by client ID
//nolint:gocritic // RFC 7592 endpoints need system access to retrieve dynamically registered clients
app, err := db.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemRestricted(ctx), clientID)
//nolint:gocritic // OAuth2 system context — RFC 7592 client configuration endpoint
app, err := db.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemOAuth2(ctx), clientID)
if err != nil {
if xerrors.Is(err, sql.ErrNoRows) {
writeOAuth2RegistrationError(ctx, rw, http.StatusUnauthorized,
@@ -269,8 +269,8 @@ func UpdateClientConfiguration(db database.Store, auditor *audit.Auditor, logger
req = req.ApplyDefaults()
// Get existing app to verify it exists and is dynamically registered
//nolint:gocritic // RFC 7592 endpoints need system access to retrieve dynamically registered clients
existingApp, err := db.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemRestricted(ctx), clientID)
//nolint:gocritic // OAuth2 system context — RFC 7592 client configuration endpoint
existingApp, err := db.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemOAuth2(ctx), clientID)
if err == nil {
aReq.Old = existingApp
}
@@ -294,8 +294,8 @@ func UpdateClientConfiguration(db database.Store, auditor *audit.Auditor, logger
// Update app in database
now := dbtime.Now()
//nolint:gocritic // RFC 7592 endpoints need system access to update dynamically registered clients
updatedApp, err := db.UpdateOAuth2ProviderAppByClientID(dbauthz.AsSystemRestricted(ctx), database.UpdateOAuth2ProviderAppByClientIDParams{
//nolint:gocritic // OAuth2 system context — RFC 7592 client configuration endpoint
updatedApp, err := db.UpdateOAuth2ProviderAppByClientID(dbauthz.AsSystemOAuth2(ctx), database.UpdateOAuth2ProviderAppByClientIDParams{
ID: clientID,
UpdatedAt: now,
Name: req.GenerateClientName(),
@@ -377,8 +377,8 @@ func DeleteClientConfiguration(db database.Store, auditor *audit.Auditor, logger
}
// Get existing app to verify it exists and is dynamically registered
//nolint:gocritic // RFC 7592 endpoints need system access to retrieve dynamically registered clients
existingApp, err := db.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemRestricted(ctx), clientID)
//nolint:gocritic // OAuth2 system context — RFC 7592 client configuration endpoint
existingApp, err := db.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemOAuth2(ctx), clientID)
if err == nil {
aReq.Old = existingApp
}
@@ -401,8 +401,8 @@ func DeleteClientConfiguration(db database.Store, auditor *audit.Auditor, logger
}
// Delete the client and all associated data (tokens, secrets, etc.)
//nolint:gocritic // RFC 7592 endpoints need system access to delete dynamically registered clients
err = db.DeleteOAuth2ProviderAppByClientID(dbauthz.AsSystemRestricted(ctx), clientID)
//nolint:gocritic // OAuth2 system context — RFC 7592 client configuration endpoint
err = db.DeleteOAuth2ProviderAppByClientID(dbauthz.AsSystemOAuth2(ctx), clientID)
if err != nil {
writeOAuth2RegistrationError(ctx, rw, http.StatusInternalServerError,
"server_error", "Failed to delete client")
@@ -453,8 +453,8 @@ func RequireRegistrationAccessToken(db database.Store) func(http.Handler) http.H
}
// Get the client and verify the registration access token
//nolint:gocritic // RFC 7592 endpoints need system access to validate dynamically registered clients
app, err := db.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemRestricted(ctx), clientID)
//nolint:gocritic // OAuth2 system context — RFC 7592 registration access token validation
app, err := db.GetOAuth2ProviderAppByClientID(dbauthz.AsSystemOAuth2(ctx), clientID)
if err != nil {
if xerrors.Is(err, sql.ErrNoRows) {
// Return 401 for authentication-related issues, not 404
+8 -8
View File
@@ -217,8 +217,8 @@ func authorizationCodeGrant(ctx context.Context, db database.Store, app database
if err != nil {
return codersdk.OAuth2TokenResponse{}, errBadSecret
}
//nolint:gocritic // Users cannot read secrets so we must use the system.
dbSecret, err := db.GetOAuth2ProviderAppSecretByPrefix(dbauthz.AsSystemRestricted(ctx), []byte(secret.Prefix))
//nolint:gocritic // OAuth2 system context — users cannot read secrets
dbSecret, err := db.GetOAuth2ProviderAppSecretByPrefix(dbauthz.AsSystemOAuth2(ctx), []byte(secret.Prefix))
if errors.Is(err, sql.ErrNoRows) {
return codersdk.OAuth2TokenResponse{}, errBadSecret
}
@@ -236,8 +236,8 @@ func authorizationCodeGrant(ctx context.Context, db database.Store, app database
if err != nil {
return codersdk.OAuth2TokenResponse{}, errBadCode
}
//nolint:gocritic // There is no user yet so we must use the system.
dbCode, err := db.GetOAuth2ProviderAppCodeByPrefix(dbauthz.AsSystemRestricted(ctx), []byte(code.Prefix))
//nolint:gocritic // OAuth2 system context — no authenticated user during token exchange
dbCode, err := db.GetOAuth2ProviderAppCodeByPrefix(dbauthz.AsSystemOAuth2(ctx), []byte(code.Prefix))
if errors.Is(err, sql.ErrNoRows) {
return codersdk.OAuth2TokenResponse{}, errBadCode
}
@@ -384,8 +384,8 @@ func refreshTokenGrant(ctx context.Context, db database.Store, app database.OAut
if err != nil {
return codersdk.OAuth2TokenResponse{}, errBadToken
}
//nolint:gocritic // There is no user yet so we must use the system.
dbToken, err := db.GetOAuth2ProviderAppTokenByPrefix(dbauthz.AsSystemRestricted(ctx), []byte(token.Prefix))
//nolint:gocritic // OAuth2 system context — no authenticated user during refresh
dbToken, err := db.GetOAuth2ProviderAppTokenByPrefix(dbauthz.AsSystemOAuth2(ctx), []byte(token.Prefix))
if errors.Is(err, sql.ErrNoRows) {
return codersdk.OAuth2TokenResponse{}, errBadToken
}
@@ -411,8 +411,8 @@ func refreshTokenGrant(ctx context.Context, db database.Store, app database.OAut
}
// Grab the user roles so we can perform the refresh as the user.
//nolint:gocritic // There is no user yet so we must use the system.
prevKey, err := db.GetAPIKeyByID(dbauthz.AsSystemRestricted(ctx), dbToken.APIKeyID)
//nolint:gocritic // OAuth2 system context — need to read the previous API key
prevKey, err := db.GetAPIKeyByID(dbauthz.AsSystemOAuth2(ctx), dbToken.APIKeyID)
if err != nil {
return codersdk.OAuth2TokenResponse{}, err
}