feat: add workspace agent connect and app open audit types (#16493)

This commit adds new audit resource types for workspace agents and
workspace apps, as well as connect/disconnect and open/close actions.

The idea is that we will log new audit events for connecting to the
agent via SSH/editor.

Likewise, we will log openings of `coder_app`s.

This change also introduces support for filtering by `request_id`.

Updates #15139
This commit is contained in:
Mathias Fredriksson
2025-02-17 13:02:30 +00:00
committed by GitHub
parent 42f6b716f2
commit b5329ae1cd
21 changed files with 411 additions and 43 deletions
+4 -1
View File
@@ -12433,10 +12433,13 @@ func (q *FakeQuerier) GetAuthorizedAuditLogsOffset(ctx context.Context, arg data
arg.OffsetOpt--
continue
}
if arg.RequestID != uuid.Nil && arg.RequestID != alog.RequestID {
continue
}
if arg.OrganizationID != uuid.Nil && arg.OrganizationID != alog.OrganizationID {
continue
}
if arg.Action != "" && !strings.Contains(string(alog.Action), arg.Action) {
if arg.Action != "" && string(alog.Action) != arg.Action {
continue
}
if arg.ResourceType != "" && !strings.Contains(string(alog.ResourceType), arg.ResourceType) {
+8 -2
View File
@@ -25,7 +25,11 @@ CREATE TYPE audit_action AS ENUM (
'login',
'logout',
'register',
'request_password_reset'
'request_password_reset',
'connect',
'disconnect',
'open',
'close'
);
CREATE TYPE automatic_updates AS ENUM (
@@ -201,7 +205,9 @@ CREATE TYPE resource_type AS ENUM (
'notification_template',
'idp_sync_settings_organization',
'idp_sync_settings_group',
'idp_sync_settings_role'
'idp_sync_settings_role',
'workspace_agent',
'workspace_app'
);
CREATE TYPE startup_script_behavior AS ENUM (
@@ -0,0 +1 @@
-- No-op, enum values can't be dropped.
@@ -0,0 +1,13 @@
-- Add new audit types for connect and open actions.
ALTER TYPE audit_action
ADD VALUE IF NOT EXISTS 'connect';
ALTER TYPE audit_action
ADD VALUE IF NOT EXISTS 'disconnect';
ALTER TYPE resource_type
ADD VALUE IF NOT EXISTS 'workspace_agent';
ALTER TYPE audit_action
ADD VALUE IF NOT EXISTS 'open';
ALTER TYPE audit_action
ADD VALUE IF NOT EXISTS 'close';
ALTER TYPE resource_type
ADD VALUE IF NOT EXISTS 'workspace_app';
+1
View File
@@ -467,6 +467,7 @@ func (q *sqlQuerier) GetAuthorizedAuditLogsOffset(ctx context.Context, arg GetAu
arg.DateFrom,
arg.DateTo,
arg.BuildReason,
arg.RequestID,
arg.OffsetOpt,
arg.LimitOpt,
)
+20 -2
View File
@@ -147,6 +147,10 @@ const (
AuditActionLogout AuditAction = "logout"
AuditActionRegister AuditAction = "register"
AuditActionRequestPasswordReset AuditAction = "request_password_reset"
AuditActionConnect AuditAction = "connect"
AuditActionDisconnect AuditAction = "disconnect"
AuditActionOpen AuditAction = "open"
AuditActionClose AuditAction = "close"
)
func (e *AuditAction) Scan(src interface{}) error {
@@ -194,7 +198,11 @@ func (e AuditAction) Valid() bool {
AuditActionLogin,
AuditActionLogout,
AuditActionRegister,
AuditActionRequestPasswordReset:
AuditActionRequestPasswordReset,
AuditActionConnect,
AuditActionDisconnect,
AuditActionOpen,
AuditActionClose:
return true
}
return false
@@ -211,6 +219,10 @@ func AllAuditActionValues() []AuditAction {
AuditActionLogout,
AuditActionRegister,
AuditActionRequestPasswordReset,
AuditActionConnect,
AuditActionDisconnect,
AuditActionOpen,
AuditActionClose,
}
}
@@ -1608,6 +1620,8 @@ const (
ResourceTypeIdpSyncSettingsOrganization ResourceType = "idp_sync_settings_organization"
ResourceTypeIdpSyncSettingsGroup ResourceType = "idp_sync_settings_group"
ResourceTypeIdpSyncSettingsRole ResourceType = "idp_sync_settings_role"
ResourceTypeWorkspaceAgent ResourceType = "workspace_agent"
ResourceTypeWorkspaceApp ResourceType = "workspace_app"
)
func (e *ResourceType) Scan(src interface{}) error {
@@ -1668,7 +1682,9 @@ func (e ResourceType) Valid() bool {
ResourceTypeNotificationTemplate,
ResourceTypeIdpSyncSettingsOrganization,
ResourceTypeIdpSyncSettingsGroup,
ResourceTypeIdpSyncSettingsRole:
ResourceTypeIdpSyncSettingsRole,
ResourceTypeWorkspaceAgent,
ResourceTypeWorkspaceApp:
return true
}
return false
@@ -1698,6 +1714,8 @@ func AllResourceTypeValues() []ResourceType {
ResourceTypeIdpSyncSettingsOrganization,
ResourceTypeIdpSyncSettingsGroup,
ResourceTypeIdpSyncSettingsRole,
ResourceTypeWorkspaceAgent,
ResourceTypeWorkspaceApp,
}
}
+10 -2
View File
@@ -558,6 +558,12 @@ WHERE
workspace_builds.reason::text = $11
ELSE true
END
-- Filter request_id
AND CASE
WHEN $12 :: uuid != '00000000-0000-0000-0000-000000000000'::uuid THEN
audit_logs.request_id = $12
ELSE true
END
-- Authorize Filter clause will be injected below in GetAuthorizedAuditLogsOffset
-- @authorize_filter
@@ -567,9 +573,9 @@ LIMIT
-- a limit of 0 means "no limit". The audit log table is unbounded
-- in size, and is expected to be quite large. Implement a default
-- limit of 100 to prevent accidental excessively large queries.
COALESCE(NULLIF($13 :: int, 0), 100)
COALESCE(NULLIF($14 :: int, 0), 100)
OFFSET
$12
$13
`
type GetAuditLogsOffsetParams struct {
@@ -584,6 +590,7 @@ type GetAuditLogsOffsetParams struct {
DateFrom time.Time `db:"date_from" json:"date_from"`
DateTo time.Time `db:"date_to" json:"date_to"`
BuildReason string `db:"build_reason" json:"build_reason"`
RequestID uuid.UUID `db:"request_id" json:"request_id"`
OffsetOpt int32 `db:"offset_opt" json:"offset_opt"`
LimitOpt int32 `db:"limit_opt" json:"limit_opt"`
}
@@ -624,6 +631,7 @@ func (q *sqlQuerier) GetAuditLogsOffset(ctx context.Context, arg GetAuditLogsOff
arg.DateFrom,
arg.DateTo,
arg.BuildReason,
arg.RequestID,
arg.OffsetOpt,
arg.LimitOpt,
)
+6
View File
@@ -117,6 +117,12 @@ WHERE
workspace_builds.reason::text = @build_reason
ELSE true
END
-- Filter request_id
AND CASE
WHEN @request_id :: uuid != '00000000-0000-0000-0000-000000000000'::uuid THEN
audit_logs.request_id = @request_id
ELSE true
END
-- Authorize Filter clause will be injected below in GetAuthorizedAuditLogsOffset
-- @authorize_filter