Audit build outcomes/kira pilot (#5143)

* auditing failed builds

* logging workspace build successes

* remove duplicate workspace build entry

* fixed workspacebuilds_test

* PR feedback

* lint and migrations

* fix nil auditors

* workspace_build test

* fixed workspaces_teest

Co-authored-by: Colin Adler <colin1adler@gmail.com>
This commit is contained in:
Kira Pilot
2022-11-22 13:22:56 -05:00
committed by GitHub
co-authored by Colin Adler
parent 1f20cab110
commit 6786ca2854
18 changed files with 184 additions and 85 deletions
+50 -1
View File
@@ -2,6 +2,7 @@ package audit
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"net"
@@ -32,6 +33,20 @@ type Request[T Auditable] struct {
New T
}
type BuildAuditParams[T Auditable] struct {
Audit Auditor
Log slog.Logger
UserID uuid.UUID
JobID uuid.UUID
Status int
Action database.AuditAction
AdditionalFields json.RawMessage
New T
Old T
}
func ResourceTarget[T Auditable](tgt T) string {
switch typed := any(tgt).(type) {
case database.Organization:
@@ -147,7 +162,7 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request
Time: database.Now(),
UserID: httpmw.APIKey(p.Request).UserID,
Ip: ip,
UserAgent: p.Request.UserAgent(),
UserAgent: sql.NullString{String: p.Request.UserAgent(), Valid: true},
ResourceType: either(req.Old, req.New, ResourceType[T]),
ResourceID: either(req.Old, req.New, ResourceID[T]),
ResourceTarget: either(req.Old, req.New, ResourceTarget[T]),
@@ -164,6 +179,40 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request
}
}
// BuildAudit creates an audit log for a workspace build.
// The audit log is committed upon invocation.
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("{}")
if p.AdditionalFields == nil {
p.AdditionalFields = json.RawMessage("{}")
}
err := p.Audit.Export(ctx, database.AuditLog{
ID: uuid.New(),
Time: database.Now(),
UserID: p.UserID,
Ip: ip,
UserAgent: sql.NullString{},
ResourceType: either(p.Old, p.New, ResourceType[T]),
ResourceID: either(p.Old, p.New, ResourceID[T]),
ResourceTarget: either(p.Old, p.New, ResourceTarget[T]),
Action: p.Action,
Diff: diffRaw,
StatusCode: int32(p.Status),
RequestID: p.JobID,
AdditionalFields: p.AdditionalFields,
})
if err != nil {
p.Log.Error(ctx, "export audit log", slog.Error(err))
return
}
}
func either[T Auditable, R any](old, new T, fn func(T) R) R {
if ResourceID(new) != uuid.Nil {
return fn(new)