mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: audit user secret create, update, and delete (#24756)
Emit user secret audit log entries for create/update/delete operations. Reads stay un-audited, matching every other resource. Audit log entries record changes in user secret name, environment variable name, file path, and value. The secret value column is marked `ActionSecret` so the diff records the change without showing the ciphertext or plaintext. Closes a TOCTOU window on delete to ensure no phantom audit logs for a delete of a non-existent secret. Secret update accepts a small TOCTOU window matching the other audited resources (templates, workspaces, chats). The two-query pattern is wrapped in a transaction so audit state can't leak from a failed mutation.
This commit is contained in:
@@ -445,6 +445,18 @@ func (api *API) auditLogIsResourceDeleted(ctx context.Context, alog database.Get
|
||||
api.Logger.Error(ctx, "unable to fetch chat", slog.Error(err))
|
||||
}
|
||||
return false
|
||||
case database.ResourceTypeUserSecret:
|
||||
_, err := api.Database.GetUserSecretByID(ctx, alog.AuditLog.ResourceID)
|
||||
if xerrors.Is(err, sql.ErrNoRows) {
|
||||
return true
|
||||
}
|
||||
// Only users have user_secret:read on their own secrets. If dbauthz returns
|
||||
// ErrUnauthorized, it's not an error worth logging because we have enough
|
||||
// information to know it's not deleted.
|
||||
if err != nil && !dbauthz.IsNotAuthorizedError(err) {
|
||||
api.Logger.Error(ctx, "unable to fetch user secret", slog.Error(err))
|
||||
}
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@@ -536,6 +548,10 @@ func (api *API) auditLogResourceLink(ctx context.Context, alog database.GetAudit
|
||||
// Chats are surfaced at /agents/{id}. They are owner-scoped but
|
||||
// not username-scoped in the URL like workspaces or tasks.
|
||||
return fmt.Sprintf("/agents/%s", alog.AuditLog.ResourceID)
|
||||
case database.ResourceTypeUserSecret:
|
||||
// TODO(PLAT-102): point at the user secrets management page once
|
||||
// it ships. Until then, the audit row links nowhere.
|
||||
return ""
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user