refactor: Event log use audit event as SSOT (#350)

This commit is contained in:
Abhisek Datta
2026-06-24 15:43:20 +05:30
committed by GitHub
parent 25dd12d7a4
commit 7ee4187d50
4 changed files with 32 additions and 82 deletions
+1 -34
View File
@@ -20,7 +20,7 @@ func (s *eventlogSink) Handle(_ context.Context, event AuditEvent) error {
elEvent := eventlog.Event{ elEvent := eventlog.Event{
Timestamp: event.Timestamp, Timestamp: event.Timestamp,
EventType: mapEventType(event.Type), EventType: string(event.Type),
Message: event.Message, Message: event.Message,
PackageName: pkgName(event.PackageVersion), PackageName: pkgName(event.PackageVersion),
Version: pkgVersion(event.PackageVersion), Version: pkgVersion(event.PackageVersion),
@@ -48,36 +48,3 @@ func sessionDataToDetails(sd *SessionData) map[string]interface{} {
func (s *eventlogSink) Close() error { func (s *eventlogSink) Close() error {
return nil return nil
} }
func mapEventType(t EventType) eventlog.EventType {
switch t {
case EventTypeMalwareBlocked:
return eventlog.EventTypeMalwareBlocked
case EventTypeMalwareConfirmed:
return eventlog.EventTypeMalwareConfirmed
case EventTypeInstallAllowed:
return eventlog.EventTypeInstallAllowed
case EventTypeInstallTrustedAllowed:
return eventlog.EventTypeInstallTrustedAllowed
case EventTypeInstallStarted:
return eventlog.EventTypeInstallStarted
case EventTypeDependencyResolved:
return eventlog.EventTypeDependencyResolved
case EventTypeInstallInsecureBypass:
return eventlog.EventTypeInstallInsecureBypass
case EventTypeProxyHostObserved:
return eventlog.EventTypeProxyHostObserved
case EventTypeDependencyCooldown:
return eventlog.EventTypeDependencyCooldown
case EventTypeCooldownSkipped:
return eventlog.EventTypeCooldownSkipped
case EventTypeSandboxOverride:
return eventlog.EventTypeSandboxOverride
case EventTypeError:
return eventlog.EventTypeError
case EventTypeSessionComplete:
return eventlog.EventType("session_complete")
default:
return eventlog.EventType(string(t))
}
}
+21 -21
View File
@@ -3,36 +3,36 @@ package audit
import ( import (
"testing" "testing"
"github.com/safedep/pmg/internal/eventlog"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestEventlogSinkTranslatesAllEventTypes(t *testing.T) { // TestEventTypeOnDiskValues pins the event_type strings written to the on-disk
// event log. The audit package is the single owner of this vocabulary; the
// eventlog sink writes string(event.Type) verbatim, so these values are the
// file-format contract and must not change without a migration.
func TestEventTypeOnDiskValues(t *testing.T) {
tests := []struct { tests := []struct {
name string
input EventType input EventType
expected eventlog.EventType expected string
}{ }{
{"malware_blocked", EventTypeMalwareBlocked, eventlog.EventTypeMalwareBlocked}, {EventTypeMalwareBlocked, "malware_blocked"},
{"malware_confirmed", EventTypeMalwareConfirmed, eventlog.EventTypeMalwareConfirmed}, {EventTypeMalwareConfirmed, "malware_confirmed"},
{"install_allowed", EventTypeInstallAllowed, eventlog.EventTypeInstallAllowed}, {EventTypeInstallAllowed, "install_allowed"},
{"install_trusted_allowed", EventTypeInstallTrustedAllowed, eventlog.EventTypeInstallTrustedAllowed}, {EventTypeInstallTrustedAllowed, "install_trusted_allowed"},
{"install_started", EventTypeInstallStarted, eventlog.EventTypeInstallStarted}, {EventTypeInstallStarted, "install_started"},
{"dependency_resolved", EventTypeDependencyResolved, eventlog.EventTypeDependencyResolved}, {EventTypeDependencyResolved, "dependency_resolved"},
{"install_insecure_bypass", EventTypeInstallInsecureBypass, eventlog.EventTypeInstallInsecureBypass}, {EventTypeInstallInsecureBypass, "install_insecure_bypass"},
{"proxy_host_observed", EventTypeProxyHostObserved, eventlog.EventTypeProxyHostObserved}, {EventTypeProxyHostObserved, "proxy_host_observed"},
{"dependency_cooldown", EventTypeDependencyCooldown, eventlog.EventTypeDependencyCooldown}, {EventTypeDependencyCooldown, "dependency_cooldown"},
{"dependency_cooldown_skipped", EventTypeCooldownSkipped, eventlog.EventTypeCooldownSkipped}, {EventTypeCooldownSkipped, "dependency_cooldown_skipped"},
{"sandbox_override", EventTypeSandboxOverride, eventlog.EventTypeSandboxOverride}, {EventTypeSandboxOverride, "sandbox_override"},
{"error", EventTypeError, eventlog.EventTypeError}, {EventTypeError, "error"},
{"session_complete", EventTypeSessionComplete, eventlog.EventType("session_complete")}, {EventTypeSessionComplete, "session_complete"},
{"unknown_type", EventType("custom_event"), eventlog.EventType("custom_event")},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.expected, func(t *testing.T) {
result := mapEventType(tt.input) assert.Equal(t, tt.expected, string(tt.input))
assert.Equal(t, tt.expected, result)
}) })
} }
} }
+3 -20
View File
@@ -13,28 +13,11 @@ import (
"github.com/safedep/pmg/config" "github.com/safedep/pmg/config"
) )
// EventType represents the type of event being logged // Event is the on-disk DTO for a logged security event. The event vocabulary is
type EventType string // owned by the audit package; here event_type is just a JSON string column.
const (
EventTypeMalwareBlocked EventType = "malware_blocked"
EventTypeMalwareConfirmed EventType = "malware_confirmed"
EventTypeInstallAllowed EventType = "install_allowed"
EventTypeInstallTrustedAllowed EventType = "install_trusted_allowed"
EventTypeInstallStarted EventType = "install_started"
EventTypeDependencyResolved EventType = "dependency_resolved"
EventTypeInstallInsecureBypass EventType = "install_insecure_bypass"
EventTypeProxyHostObserved EventType = "proxy_host_observed"
EventTypeDependencyCooldown EventType = "dependency_cooldown"
EventTypeCooldownSkipped EventType = "dependency_cooldown_skipped"
EventTypeSandboxOverride EventType = "sandbox_override"
EventTypeError EventType = "error"
)
// Event represents a security event
type Event struct { type Event struct {
Timestamp time.Time `json:"timestamp"` Timestamp time.Time `json:"timestamp"`
EventType EventType `json:"event_type"` EventType string `json:"event_type"`
Message string `json:"message"` Message string `json:"message"`
PackageName string `json:"package_name,omitempty"` PackageName string `json:"package_name,omitempty"`
Version string `json:"version,omitempty"` Version string `json:"version,omitempty"`
+7 -7
View File
@@ -57,7 +57,7 @@ func TestLogEvent(t *testing.T) {
// Log an event // Log an event
event := Event{ event := Event{
EventType: EventTypeMalwareBlocked, EventType: "malware_blocked",
Message: "Test malware blocked", Message: "Test malware blocked",
PackageName: "evil-package", PackageName: "evil-package",
Version: "1.0.0", Version: "1.0.0",
@@ -81,7 +81,7 @@ func TestLogEvent(t *testing.T) {
assert.NoError(t, err, "Failed to parse logged event") assert.NoError(t, err, "Failed to parse logged event")
// Verify the event // Verify the event
assert.Equal(t, EventTypeMalwareBlocked, loggedEvent.EventType) assert.Equal(t, "malware_blocked", loggedEvent.EventType)
assert.Equal(t, "evil-package", loggedEvent.PackageName) assert.Equal(t, "evil-package", loggedEvent.PackageName)
} }
@@ -97,7 +97,7 @@ func TestLogEventMalwareBlocked(t *testing.T) {
}() }()
err = LogEvent(Event{ err = LogEvent(Event{
EventType: EventTypeMalwareBlocked, EventType: "malware_blocked",
Message: "Blocked installation of malicious package: malicious-pkg@2.0.0", Message: "Blocked installation of malicious package: malicious-pkg@2.0.0",
PackageName: "malicious-pkg", PackageName: "malicious-pkg",
Version: "2.0.0", Version: "2.0.0",
@@ -114,7 +114,7 @@ func TestLogEventMalwareBlocked(t *testing.T) {
err = json.Unmarshal(data, &event) err = json.Unmarshal(data, &event)
assert.NoError(t, err, "Failed to parse event") assert.NoError(t, err, "Failed to parse event")
assert.Equal(t, EventTypeMalwareBlocked, event.EventType) assert.Equal(t, "malware_blocked", event.EventType)
assert.Equal(t, "malicious-pkg", event.PackageName) assert.Equal(t, "malicious-pkg", event.PackageName)
assert.Equal(t, "pypi", event.Ecosystem) assert.Equal(t, "pypi", event.Ecosystem)
} }
@@ -131,7 +131,7 @@ func TestLogEventProxyHostObserved(t *testing.T) {
}() }()
err = LogEvent(Event{ err = LogEvent(Event{
EventType: EventTypeProxyHostObserved, EventType: "proxy_host_observed",
Message: "Proxy observed outbound host: example.com", Message: "Proxy observed outbound host: example.com",
Details: map[string]interface{}{ Details: map[string]interface{}{
"hostname": "example.com", "hostname": "example.com",
@@ -150,7 +150,7 @@ func TestLogEventProxyHostObserved(t *testing.T) {
err = json.Unmarshal(data, &event) err = json.Unmarshal(data, &event)
assert.NoError(t, err, "Failed to parse event") assert.NoError(t, err, "Failed to parse event")
assert.Equal(t, EventTypeProxyHostObserved, event.EventType) assert.Equal(t, "proxy_host_observed", event.EventType)
assert.Equal(t, "example.com", event.Details["hostname"]) assert.Equal(t, "example.com", event.Details["hostname"])
assert.Equal(t, "CONNECT", event.Details["method"]) assert.Equal(t, "CONNECT", event.Details["method"])
assert.Equal(t, "connect_tunnel_no_interceptor", event.Details["reason"]) assert.Equal(t, "connect_tunnel_no_interceptor", event.Details["reason"])
@@ -179,7 +179,7 @@ func TestInitializeWithFile(t *testing.T) {
// Log an event // Log an event
event := Event{ event := Event{
EventType: EventTypeMalwareBlocked, EventType: "malware_blocked",
Message: "Test custom file logging", Message: "Test custom file logging",
PackageName: "test-package", PackageName: "test-package",
Version: "1.0.0", Version: "1.0.0",