diff --git a/coderd/audit/request.go b/coderd/audit/request.go index 4a389836b9fde..1b3dec96bf599 100644 --- a/coderd/audit/request.go +++ b/coderd/audit/request.go @@ -189,8 +189,14 @@ func BuildAudit[T Auditable](ctx context.Context, p *BuildAuditParams[T]) { // As the audit request has not been initiated directly by a user, we omit // certain user details. ip := parseIP("") - // We do not show diffs for build audit logs - var diffRaw = []byte("{}") + + diff := Diff(p.Audit, p.Old, p.New) + var err error + diffRaw, err := json.Marshal(diff) + if err != nil { + p.Log.Warn(ctx, "marshal diff", slog.Error(err)) + diffRaw = []byte("{}") + } if p.AdditionalFields == nil { p.AdditionalFields = json.RawMessage("{}") @@ -211,8 +217,8 @@ func BuildAudit[T Auditable](ctx context.Context, p *BuildAuditParams[T]) { RequestID: p.JobID, AdditionalFields: p.AdditionalFields, } - err := p.Audit.Export(ctx, auditLog) - if err != nil { + exportErr := p.Audit.Export(ctx, auditLog) + if exportErr != nil { p.Log.Error(ctx, "export audit log", slog.F("audit_log", auditLog), slog.Error(err), diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index 2aebc794b43a5..cc8bb604a26d0 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -545,6 +545,14 @@ func (server *Server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*p if err != nil { server.Logger.Error(ctx, "audit log - get workspace", slog.Error(err)) } else { + previousBuildNumber := build.BuildNumber - 1 + previousBuild, prevBuildErr := server.Database.GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx, database.GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams{ + WorkspaceID: workspace.ID, + BuildNumber: previousBuildNumber, + }) + if prevBuildErr != nil { + previousBuild = database.WorkspaceBuild{} + } // We pass the below information to the Auditor so that it // can form a friendly string for the user to view in the UI. buildResourceInfo := map[string]string{ @@ -564,6 +572,7 @@ func (server *Server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*p UserID: job.InitiatorID, JobID: job.ID, Action: auditAction, + Old: previousBuild, New: build, Status: http.StatusInternalServerError, AdditionalFields: wriBytes, @@ -796,6 +805,15 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete auditor := server.Auditor.Load() auditAction := auditActionFromTransition(workspaceBuild.Transition) + previousBuildNumber := workspaceBuild.BuildNumber - 1 + previousBuild, prevBuildErr := server.Database.GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx, database.GetWorkspaceBuildByWorkspaceIDAndBuildNumberParams{ + WorkspaceID: workspace.ID, + BuildNumber: previousBuildNumber, + }) + if prevBuildErr != nil { + previousBuild = database.WorkspaceBuild{} + } + // We pass the below information to the Auditor so that it // can form a friendly string for the user to view in the UI. buildResourceInfo := map[string]string{ @@ -815,6 +833,7 @@ func (server *Server) CompleteJob(ctx context.Context, completed *proto.Complete UserID: job.InitiatorID, JobID: job.ID, Action: auditAction, + Old: previousBuild, New: workspaceBuild, Status: http.StatusOK, AdditionalFields: wriBytes, diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go index cf1f08b64727b..842f90a20adc6 100644 --- a/enterprise/audit/table.go +++ b/enterprise/audit/table.go @@ -111,7 +111,7 @@ var AuditableResources = auditMap(map[any]map[string]Action{ "created_at": ActionIgnore, "updated_at": ActionIgnore, "workspace_id": ActionIgnore, - "template_version_id": ActionIgnore, + "template_version_id": ActionTrack, "build_number": ActionIgnore, "transition": ActionIgnore, "initiator_id": ActionIgnore,