From 77df7e011c1c6619e4e6339a448fe01173f324f6 Mon Sep 17 00:00:00 2001 From: Tim Lee Date: Tue, 21 Oct 2025 08:26:12 -0600 Subject: [PATCH] bugfix: correct santa json status based on santa docs (#34561) --- orbit/pkg/table/santa/santa_status.go | 154 +++++++++++++-------- orbit/pkg/table/santa/santa_status_test.go | 100 +++++++------ 2 files changed, 147 insertions(+), 107 deletions(-) diff --git a/orbit/pkg/table/santa/santa_status.go b/orbit/pkg/table/santa/santa_status.go index cc0a0d1f84..2eeded6b72 100644 --- a/orbit/pkg/table/santa/santa_status.go +++ b/orbit/pkg/table/santa/santa_status.go @@ -22,19 +22,15 @@ import ( var execCommandContext = exec.CommandContext type santaStatus struct { - WatchItems struct { - Enabled bool `json:"enabled"` - } `json:"watch_items"` Daemon struct { FileLogging bool `json:"file_logging"` WatchdogRamEvents int `json:"watchdog_ram_events"` - DriverConnected bool `json:"driver_connected"` LogType string `json:"log_type"` WatchdogCpuEvents int `json:"watchdog_cpu_events"` Mode string `json:"mode"` WatchdogCpuPeak float64 `json:"watchdog_cpu_peak"` WatchdogRamPeak float64 `json:"watchdog_ram_peak"` - TransitiveRules bool `json:"transitive_rules"` + StaticRules int `json:"static_rules"` RemountUsbMode string `json:"remount_usb_mode"` BlockUsb bool `json:"block_usb"` OnStartUsbOptions string `json:"on_start_usb_options"` @@ -43,40 +39,49 @@ type santaStatus struct { RootCacheCount int `json:"root_cache_count"` NonRootCacheCount int `json:"non_root_cache_count"` } `json:"cache"` - StaticRules struct { - RuleCount int `json:"rule_count"` - } `json:"static_rules"` - Database struct { - CertificateRules int `json:"certificate_rules"` - CdhashRules int `json:"cdhash_rules"` - TransitiveRules int `json:"transitive_rules"` - TeamidRules int `json:"teamid_rules"` - SigningidRules int `json:"signingid_rules"` - CompilerRules int `json:"compiler_rules"` - BinaryRules int `json:"binary_rules"` - EventsPendingUpload int `json:"events_pending_upload"` - } `json:"database"` + RuleTypes struct { + CertificateRules int `json:"certificate_rules"` + CdhashRules int `json:"cdhash_rules"` + TeamidRules int `json:"teamid_rules"` + SigningidRules int `json:"signingid_rules"` + BinaryRules int `json:"binary_rules"` + } `json:"rule_types"` + TransitiveAllowlisting struct { + Enabled bool `json:"enabled"` + CompilerRules int `json:"compiler_rules"` + TransitiveRules int `json:"transitive_rules"` + } `json:"transitive_allowlisting"` Sync struct { - LastSuccessfulRule string `json:"last_successful_rule"` - PushNotifications string `json:"push_notifications"` - BundleScanning bool `json:"bundle_scanning"` - CleanRequired bool `json:"clean_required"` - Server string `json:"server"` - LastSuccessfulFull string `json:"last_successful_full"` + Enabled bool `json:"enabled"` + Server string `json:"server"` + CleanRequired bool `json:"clean_required"` + LastSuccessfulFull string `json:"last_successful_full"` + LastSuccessfulRule string `json:"last_successful_rule"` + PushNotifications string `json:"push_notifications"` + BundleScanning bool `json:"bundle_scanning"` + EventsPendingUpload int `json:"events_pending_upload"` + ExecutionRulesHash string `json:"execution_rules_hash"` + FileAccessRulesHash string `json:"file_access_rules_hash"` } `json:"sync"` + WatchItems struct { + Enabled bool `json:"enabled"` + DataSource string `json:"data_source"` + RuleCount int `json:"rule_count"` + LastPolicyUpdate string `json:"last_policy_update"` + PolicyVersion string `json:"policy_version"` + ConfigPath string `json:"config_path"` + } `json:"watch_items"` + Metrics struct { + Enabled bool `json:"enabled"` + Server string `json:"server"` + ExportIntervalSeconds int `json:"export_interval_seconds"` + } `json:"metrics"` } func StatusColumns() []table.ColumnDefinition { return []table.ColumnDefinition{ - table.TextColumn("last_successful_rule"), - table.TextColumn("push_notifications"), - table.IntegerColumn("bundle_scanning"), - table.IntegerColumn("clean_required"), - table.TextColumn("server"), - table.TextColumn("last_successful_full"), table.IntegerColumn("file_logging"), table.IntegerColumn("watchdog_ram_events"), - table.IntegerColumn("driver_connected"), table.TextColumn("log_type"), table.IntegerColumn("watchdog_cpu_events"), table.TextColumn("mode"), @@ -98,6 +103,23 @@ func StatusColumns() []table.ColumnDefinition { table.IntegerColumn("binary_rules"), table.IntegerColumn("events_pending_upload"), table.IntegerColumn("watch_items_enabled"), + table.IntegerColumn("sync_enabled"), + table.TextColumn("sync_server"), + table.IntegerColumn("sync_clean_required"), + table.TextColumn("sync_last_successful_full"), + table.TextColumn("sync_last_successful_rule"), + table.TextColumn("sync_push_notifications"), + table.IntegerColumn("sync_bundle_scanning"), + table.TextColumn("sync_execution_rules_hash"), + table.TextColumn("sync_file_access_rules_hash"), + table.TextColumn("watch_items_data_source"), + table.IntegerColumn("watch_items_rule_count"), + table.TextColumn("watch_items_last_policy_update"), + table.TextColumn("watch_items_policy_version"), + table.TextColumn("watch_items_config_path"), + table.IntegerColumn("metrics_enabled"), + table.TextColumn("metrics_server"), + table.IntegerColumn("metrics_export_interval_seconds"), } } @@ -116,36 +138,46 @@ func GenerateStatus(ctx context.Context, _ table.QueryContext) ([]map[string]str } row := map[string]string{ - "last_successful_rule": status.Sync.LastSuccessfulRule, - "push_notifications": status.Sync.PushNotifications, - "bundle_scanning": boolToIntString(status.Sync.BundleScanning), - "clean_required": boolToIntString(status.Sync.CleanRequired), - "server": status.Sync.Server, - "last_successful_full": status.Sync.LastSuccessfulFull, - "file_logging": boolToIntString(status.Daemon.FileLogging), - "watchdog_ram_events": strconv.Itoa(status.Daemon.WatchdogRamEvents), - "driver_connected": boolToIntString(status.Daemon.DriverConnected), - "log_type": status.Daemon.LogType, - "watchdog_cpu_events": strconv.Itoa(status.Daemon.WatchdogCpuEvents), - "mode": status.Daemon.Mode, - "watchdog_cpu_peak": floatToString(status.Daemon.WatchdogCpuPeak), - "watchdog_ram_peak": floatToString(status.Daemon.WatchdogRamPeak), - "transitive_rules_enabled": boolToIntString(status.Daemon.TransitiveRules), - "remount_usb_mode": status.Daemon.RemountUsbMode, - "block_usb": boolToIntString(status.Daemon.BlockUsb), - "on_start_usb_options": status.Daemon.OnStartUsbOptions, - "root_cache_count": strconv.Itoa(status.Cache.RootCacheCount), - "non_root_cache_count": strconv.Itoa(status.Cache.NonRootCacheCount), - "static_rule_count": strconv.Itoa(status.StaticRules.RuleCount), - "certificate_rules": strconv.Itoa(status.Database.CertificateRules), - "cdhash_rules": strconv.Itoa(status.Database.CdhashRules), - "transitive_rules_count": strconv.Itoa(status.Database.TransitiveRules), - "teamid_rules": strconv.Itoa(status.Database.TeamidRules), - "signingid_rules": strconv.Itoa(status.Database.SigningidRules), - "compiler_rules": strconv.Itoa(status.Database.CompilerRules), - "binary_rules": strconv.Itoa(status.Database.BinaryRules), - "events_pending_upload": strconv.Itoa(status.Database.EventsPendingUpload), - "watch_items_enabled": boolToIntString(status.WatchItems.Enabled), + "file_logging": boolToIntString(status.Daemon.FileLogging), + "watchdog_ram_events": strconv.Itoa(status.Daemon.WatchdogRamEvents), + "log_type": status.Daemon.LogType, + "watchdog_cpu_events": strconv.Itoa(status.Daemon.WatchdogCpuEvents), + "mode": status.Daemon.Mode, + "watchdog_cpu_peak": floatToString(status.Daemon.WatchdogCpuPeak), + "watchdog_ram_peak": floatToString(status.Daemon.WatchdogRamPeak), + "transitive_rules_enabled": boolToIntString(status.TransitiveAllowlisting.Enabled), + "remount_usb_mode": status.Daemon.RemountUsbMode, + "block_usb": boolToIntString(status.Daemon.BlockUsb), + "on_start_usb_options": status.Daemon.OnStartUsbOptions, + "root_cache_count": strconv.Itoa(status.Cache.RootCacheCount), + "non_root_cache_count": strconv.Itoa(status.Cache.NonRootCacheCount), + "static_rule_count": strconv.Itoa(status.Daemon.StaticRules), + "certificate_rules": strconv.Itoa(status.RuleTypes.CertificateRules), + "cdhash_rules": strconv.Itoa(status.RuleTypes.CdhashRules), + "transitive_rules_count": strconv.Itoa(status.TransitiveAllowlisting.TransitiveRules), + "teamid_rules": strconv.Itoa(status.RuleTypes.TeamidRules), + "signingid_rules": strconv.Itoa(status.RuleTypes.SigningidRules), + "compiler_rules": strconv.Itoa(status.TransitiveAllowlisting.CompilerRules), + "binary_rules": strconv.Itoa(status.RuleTypes.BinaryRules), + "events_pending_upload": strconv.Itoa(status.Sync.EventsPendingUpload), + "watch_items_enabled": boolToIntString(status.WatchItems.Enabled), + "sync_enabled": boolToIntString(status.Sync.Enabled), + "sync_server": status.Sync.Server, + "sync_clean_required": boolToIntString(status.Sync.CleanRequired), + "sync_last_successful_full": status.Sync.LastSuccessfulFull, + "sync_last_successful_rule": status.Sync.LastSuccessfulRule, + "sync_push_notifications": status.Sync.PushNotifications, + "sync_bundle_scanning": boolToIntString(status.Sync.BundleScanning), + "sync_execution_rules_hash": status.Sync.ExecutionRulesHash, + "sync_file_access_rules_hash": status.Sync.FileAccessRulesHash, + "watch_items_data_source": status.WatchItems.DataSource, + "watch_items_rule_count": strconv.Itoa(status.WatchItems.RuleCount), + "watch_items_last_policy_update": status.WatchItems.LastPolicyUpdate, + "watch_items_policy_version": status.WatchItems.PolicyVersion, + "watch_items_config_path": status.WatchItems.ConfigPath, + "metrics_enabled": boolToIntString(status.Metrics.Enabled), + "metrics_server": status.Metrics.Server, + "metrics_export_interval_seconds": strconv.Itoa(status.Metrics.ExportIntervalSeconds), } return []map[string]string{row}, nil diff --git a/orbit/pkg/table/santa/santa_status_test.go b/orbit/pkg/table/santa/santa_status_test.go index 168c846bdf..6835f2dccb 100644 --- a/orbit/pkg/table/santa/santa_status_test.go +++ b/orbit/pkg/table/santa/santa_status_test.go @@ -25,16 +25,21 @@ func TestGenerateStatus_HappyPath(t *testing.T) { row := rows[0] // spot check a few fields and types - require.Equal(t, "2025-09-01T12:34:56Z", row["last_successful_rule"]) - require.Equal(t, "apns", row["push_notifications"]) - require.Equal(t, "1", row["bundle_scanning"]) // bool → "1" - require.Equal(t, "0", row["clean_required"]) - require.Equal(t, "monitor", row["mode"]) - require.Equal(t, "3", row["watchdog_cpu_events"]) - require.Equal(t, "42", row["root_cache_count"]) - require.Equal(t, "1", row["watch_items_enabled"]) + require.Equal(t, "Monitor", row["mode"]) + require.Equal(t, "0", row["watchdog_cpu_events"]) + require.Equal(t, "3", row["watchdog_ram_events"]) + require.Equal(t, "175", row["root_cache_count"]) + require.Equal(t, "0", row["watch_items_enabled"]) + require.Equal(t, "1", row["file_logging"]) + require.Equal(t, "file", row["log_type"]) + require.Equal(t, "6", row["static_rule_count"]) + require.Equal(t, "rdonly", row["remount_usb_mode"]) + require.Equal(t, "0", row["sync_enabled"]) + require.Equal(t, "0", row["metrics_enabled"]) + require.Equal(t, "0", row["events_pending_upload"]) // float formatting should be plain (no trailing zeros or scientific unless big) - require.True(t, strings.Contains(row["watchdog_ram_peak"], "1024")) + require.True(t, strings.Contains(row["watchdog_ram_peak"], "252.453125")) + require.True(t, strings.Contains(row["watchdog_cpu_peak"], "4.759")) } func TestGenerateStatus_CommandErrorReturnsEmptyNoError(t *testing.T) { @@ -77,8 +82,8 @@ func TestStatusColumns_Contract(t *testing.T) { } // a few key columns to lock contract for _, name := range []string{ - "last_successful_rule", "push_notifications", "bundle_scanning", "file_logging", "mode", "watchdog_cpu_events", "watch_items_enabled", + "sync_enabled", "metrics_enabled", "events_pending_upload", } { if _, ok := names[name]; !ok { t.Fatalf("missing column %q", name) @@ -157,40 +162,43 @@ func TestHelperProcess(t *testing.T) { func sampleStatusJSON() string { return `{ - "watch_items": { "enabled": true }, - "daemon": { - "file_logging": true, - "watchdog_ram_events": 5, - "driver_connected": true, - "log_type": "file", - "watchdog_cpu_events": 3, - "mode": "monitor", - "watchdog_cpu_peak": 1.25, - "watchdog_ram_peak": 1024, - "transitive_rules": true, - "remount_usb_mode": "ro", - "block_usb": false, - "on_start_usb_options": "block" - }, - "cache": { "root_cache_count": 42, "non_root_cache_count": 7 }, - "static_rules": { "rule_count": 9 }, - "database": { - "certificate_rules": 1, - "cdhash_rules": 2, - "transitive_rules": 3, - "teamid_rules": 4, - "signingid_rules": 5, - "compiler_rules": 6, - "binary_rules": 7, - "events_pending_upload": 8 - }, - "sync": { - "last_successful_rule": "2025-09-01T12:34:56Z", - "push_notifications": "apns", - "bundle_scanning": true, - "clean_required": false, - "server": "https://example.test", - "last_successful_full": "2025-09-01T12:34:56Z" - } - }` + "daemon" : { + "watchdog_ram_events" : 3, + "block_usb" : false, + "log_type" : "file", + "mode" : "Monitor", + "watchdog_cpu_events" : 0, + "static_rules" : 6, + "watchdog_ram_peak" : 252.453125, + "watchdog_cpu_peak" : 4.7590483333333333, + "file_logging" : true, + "remount_usb_mode" : "rdonly", + "on_start_usb_options" : "None" + }, + "sync" : { + "enabled" : false + }, + "rule_types" : { + "cdhash_rules" : 0, + "teamid_rules" : 4, + "certificate_rules" : 0, + "signingid_rules" : 1, + "binary_rules" : 1 + }, + "cache" : { + "root_cache_count" : 175, + "non_root_cache_count" : 5 + }, + "watch_items" : { + "enabled" : false + }, + "metrics" : { + "enabled" : false + }, + "transitive_allowlisting" : { + "enabled" : false, + "compiler_rules" : 0, + "transitive_rules" : 0 + } +}` }