mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
refactor: Event log use audit event as SSOT (#350)
This commit is contained in:
@@ -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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user