mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: add support for workspace app audit (#16801)
This change adds support for workspace app auditing. To avoid audit log spam, we introduce the concept of app audit sessions. An audit session is unique per workspace app, user, ip, user agent and http status code. The sessions are stored in a separate table from audit logs to allow use-case specific optimizations. Sessions are ephemeral and the table does not function as a log. The logic for auditing is placed in the DBTokenProvider for workspace apps so that wsproxies are included. This is the final change affecting the API fo #15139. Updates #15139
This commit is contained in:
committed by
GitHub
parent
3ae55bbbf4
commit
de41bd6b95
@ -14635,6 +14635,79 @@ func (q *sqlQuerier) InsertWorkspaceAgentStats(ctx context.Context, arg InsertWo
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertWorkspaceAppAuditSession = `-- name: UpsertWorkspaceAppAuditSession :one
|
||||
INSERT INTO
|
||||
workspace_app_audit_sessions (
|
||||
agent_id,
|
||||
app_id,
|
||||
user_id,
|
||||
ip,
|
||||
user_agent,
|
||||
slug_or_port,
|
||||
status_code,
|
||||
started_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8,
|
||||
$9
|
||||
)
|
||||
ON CONFLICT
|
||||
(agent_id, app_id, user_id, ip, user_agent, slug_or_port, status_code)
|
||||
DO
|
||||
UPDATE
|
||||
SET
|
||||
started_at = CASE
|
||||
WHEN workspace_app_audit_sessions.updated_at > NOW() - ($10::bigint || ' ms')::interval
|
||||
THEN workspace_app_audit_sessions.started_at
|
||||
ELSE EXCLUDED.started_at
|
||||
END,
|
||||
updated_at = EXCLUDED.updated_at
|
||||
RETURNING
|
||||
started_at
|
||||
`
|
||||
|
||||
type UpsertWorkspaceAppAuditSessionParams struct {
|
||||
AgentID uuid.UUID `db:"agent_id" json:"agent_id"`
|
||||
AppID uuid.UUID `db:"app_id" json:"app_id"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
Ip string `db:"ip" json:"ip"`
|
||||
UserAgent string `db:"user_agent" json:"user_agent"`
|
||||
SlugOrPort string `db:"slug_or_port" json:"slug_or_port"`
|
||||
StatusCode int32 `db:"status_code" json:"status_code"`
|
||||
StartedAt time.Time `db:"started_at" json:"started_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
StaleIntervalMS int64 `db:"stale_interval_ms" json:"stale_interval_ms"`
|
||||
}
|
||||
|
||||
// Insert a new workspace app audit session or update an existing one, if
|
||||
// started_at is updated, it means the session has been restarted.
|
||||
func (q *sqlQuerier) UpsertWorkspaceAppAuditSession(ctx context.Context, arg UpsertWorkspaceAppAuditSessionParams) (time.Time, error) {
|
||||
row := q.db.QueryRowContext(ctx, upsertWorkspaceAppAuditSession,
|
||||
arg.AgentID,
|
||||
arg.AppID,
|
||||
arg.UserID,
|
||||
arg.Ip,
|
||||
arg.UserAgent,
|
||||
arg.SlugOrPort,
|
||||
arg.StatusCode,
|
||||
arg.StartedAt,
|
||||
arg.UpdatedAt,
|
||||
arg.StaleIntervalMS,
|
||||
)
|
||||
var started_at time.Time
|
||||
err := row.Scan(&started_at)
|
||||
return started_at, err
|
||||
}
|
||||
|
||||
const getWorkspaceAppByAgentIDAndSlug = `-- name: GetWorkspaceAppByAgentIDAndSlug :one
|
||||
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = $1 AND slug = $2
|
||||
`
|
||||
|
Reference in New Issue
Block a user