Skip to content

Commit cdf7c51

Browse files
Add upload event struct and log execution events (#35)
* add new santa event upload and request types * use new type and log upload events to stdout * remove deprecated use of ioutil * update go mod * bump circleci config to go 1.20 --------- Co-authored-by: Brandon Friess <[email protected]>
1 parent 7b53542 commit cdf7c51

File tree

8 files changed

+88
-34
lines changed

8 files changed

+88
-34
lines changed

.circleci/config.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
version: 2
22
jobs:
3-
build-go1.11:
3+
build-go1.20:
44
docker:
5-
- image: golang:1.11
5+
- image: golang:1.20
66

77
working_directory: /go/src/github.com/groob/moroz
88
steps:
@@ -15,5 +15,5 @@ workflows:
1515
version: 2
1616
build:
1717
jobs:
18-
- build-go1.11
18+
- build-go1.20
1919

configs/global.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ client_mode = "MONITOR"
22
# blocked_path_regex = "^(?:/Users)/.*"
33
# allowed_path_regex = "^(?:/Users)/.*"
44
batch_size = 100
5+
enable_all_event_upload = true
56
enable_bundles = false
67
enable_transitive_rules = true
78
clean_sync = true

go.mod

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
module github.com/groob/moroz
22

3+
go 1.20
4+
35
require (
46
github.com/BurntSushi/toml v0.2.0
57
github.com/go-kit/kit v0.4.0
6-
github.com/go-logfmt/logfmt v0.3.0 // indirect
7-
github.com/go-stack/stack v1.7.0 // indirect
8-
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f // indirect
98
github.com/gorilla/mux v1.6.1
109
github.com/kolide/kit v0.0.0-20180912215818-0c28f72eb2b0
11-
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect
1210
github.com/oklog/run v1.0.0
1311
github.com/pkg/errors v0.8.0
12+
)
13+
14+
require (
15+
github.com/go-logfmt/logfmt v0.3.0 // indirect
16+
github.com/go-stack/stack v1.7.0 // indirect
17+
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f // indirect
18+
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect
1419
golang.org/x/net v0.0.0-20180124060956-0ed95abb35c4 // indirect
1520
)

moroz/svc_upload_event.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"context"
66
"encoding/json"
77
"fmt"
8-
"io/ioutil"
98
"net/http"
109
"os"
1110
"path/filepath"
@@ -25,7 +24,13 @@ func (svc *SantaService) UploadEvent(ctx context.Context, machineID string, even
2524
}
2625

2726
eventPath := filepath.Join(eventDir, fmt.Sprintf("%f.json", ev.UnixTime))
28-
if err := ioutil.WriteFile(eventPath, ev.Content, 0644); err != nil {
27+
28+
eventInfoJSON, err := json.Marshal(ev.EventInfo)
29+
if err != nil {
30+
return errors.Wrap(err, "marshal event info to json")
31+
}
32+
33+
if err := os.WriteFile(eventPath, eventInfoJSON, 0644); err != nil {
2934
return errors.Wrapf(err, "write event to path %s", eventPath)
3035
}
3136
}
@@ -65,9 +70,7 @@ func decodeEventUpload(ctx context.Context, r *http.Request) (interface{}, error
6570
}
6671

6772
// decode the JSON into individual log events.
68-
var eventPayload = struct {
69-
Events []json.RawMessage `json:"events"`
70-
}{}
73+
var eventPayload santa.EventUploadRequest
7174

7275
if err := json.NewDecoder(zr).Decode(&eventPayload); err != nil {
7376
return nil, errors.Wrap(err, "decoding event upload request json")
@@ -76,10 +79,9 @@ func decodeEventUpload(ctx context.Context, r *http.Request) (interface{}, error
7679
var events []santa.EventPayload
7780
for _, ev := range eventPayload.Events {
7881
var payload santa.EventPayload
79-
if err := json.Unmarshal(ev, &payload); err != nil {
80-
return nil, errors.Wrap(err, "decoding file sha from event upload json")
81-
}
82-
payload.Content = ev
82+
payload.EventInfo = ev
83+
payload.FileSHA = ev.FileSHA256
84+
payload.UnixTime = ev.ExecutionTime
8385
events = append(events, payload)
8486
}
8587

@@ -89,13 +91,15 @@ func decodeEventUpload(ctx context.Context, r *http.Request) (interface{}, error
8991

9092
func (mw logmw) UploadEvent(ctx context.Context, machineID string, events []santa.EventPayload) (err error) {
9193
defer func(begin time.Time) {
92-
_ = mw.logger.Log(
93-
"method", "UploadEvent",
94-
"machine_id", machineID,
95-
"event_count", len(events),
96-
"err", err,
97-
"took", time.Since(begin),
98-
)
94+
for _, ev := range events {
95+
_ = mw.logger.Log(
96+
"method", "UploadEvent",
97+
"machine_id", machineID,
98+
"event", ev.EventInfo,
99+
"err", err,
100+
"took", time.Since(begin),
101+
)
102+
}
99103
}(time.Now())
100104

101105
err = mw.next.UploadEvent(ctx, machineID, events)

santa/santa.go

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
package santa
33

44
import (
5-
"encoding/json"
6-
75
"github.com/pkg/errors"
86
)
97

@@ -24,12 +22,13 @@ type Rule struct {
2422
CustomMessage string `json:"custom_msg,omitempty" toml:"custom_msg,omitempty"`
2523
}
2624

27-
// Preflight representssync response sent to a Santa client by the sync server.
25+
// Preflight represents sync response sent to a Santa client by the sync server.
2826
type Preflight struct {
2927
ClientMode ClientMode `json:"client_mode" toml:"client_mode"`
3028
BlockedPathRegex string `json:"blocked_path_regex" toml:"blocked_path_regex"`
3129
AllowedPathRegex string `json:"allowed_path_regex" toml:"allowed_path_regex"`
3230
BatchSize int `json:"batch_size" toml:"batch_size"`
31+
EnableAllEventUpload bool `json:"enable_all_event_upload" toml:"enable_all_event_upload"`
3332
EnableBundles bool `json:"enable_bundles" toml:"enable_bundles"`
3433
EnableTransitiveRules bool `json:"enable_transitive_rules" toml:"enable_transitive_rules"`
3534
CleanSync bool `json:"clean_sync" toml:"clean_sync"`
@@ -51,9 +50,55 @@ type PreflightPayload struct {
5150

5251
// EventPayload represents derived metadata for events uploaded with the UploadEvent endpoint.
5352
type EventPayload struct {
54-
FileSHA string `json:"file_sha256"`
55-
UnixTime float64 `json:"execution_time"`
56-
Content json.RawMessage `json:"-"`
53+
FileSHA string `json:"file_sha256"`
54+
UnixTime float64 `json:"execution_time"`
55+
EventInfo EventUploadEvent
56+
}
57+
58+
// EventUploadRequest encapsulation of an /eventupload POST body sent by a Santa client
59+
type EventUploadRequest struct {
60+
Events []EventUploadEvent `json:"events"`
61+
}
62+
63+
// EventUploadEvent is a single event entry
64+
type EventUploadEvent struct {
65+
CurrentSessions []string `json:"current_sessions"`
66+
Decision string `json:"decision"`
67+
ExecutingUser string `json:"executing_user"`
68+
ExecutionTime float64 `json:"execution_time"`
69+
FileBundleBinaryCount int64 `json:"file_bundle_binary_count"`
70+
FileBundleExecutableRelPath string `json:"file_bundle_executable_rel_path"`
71+
FileBundleHash string `json:"file_bundle_hash"`
72+
FileBundleHashMilliseconds float64 `json:"file_bundle_hash_millis"`
73+
FileBundleID string `json:"file_bundle_id"`
74+
FileBundleName string `json:"file_bundle_name"`
75+
FileBundlePath string `json:"file_bundle_path"`
76+
FileBundleShortVersionString string `json:"file_bundle_version_string"`
77+
FileBundleVersion string `json:"file_bundle_version"`
78+
FileName string `json:"file_name"`
79+
FilePath string `json:"file_path"`
80+
FileSHA256 string `json:"file_sha256"`
81+
LoggedInUsers []string `json:"logged_in_users"`
82+
ParentName string `json:"parent_name"`
83+
ParentProcessID int `json:"ppid"`
84+
ProcessID int `json:"pid"`
85+
QuarantineAgentBundleID string `json:"quarantine_agent_bundle_id"`
86+
QuarantineDataUrl string `json:"quarantine_data_url"`
87+
QuarantineRefererUrl string `json:"quarantine_referer_url"`
88+
QuarantineTimestamp float64 `json:"quarantine_timestamp"`
89+
SigningChain []SigningEntry `json:"signing_chain"`
90+
SigningID string `json:"signing_id"`
91+
TeamID string `json:"team_id"`
92+
}
93+
94+
// SigningEntry is optionally present when an event includes a binary that is signed
95+
type SigningEntry struct {
96+
CertificateName string `json:"cn"`
97+
Organization string `json:"org"`
98+
OrganizationalUnit string `json:"ou"`
99+
SHA256 string `json:"sha256"`
100+
ValidFrom int `json:"valid_from"`
101+
ValidUntil int `json:"valid_until"`
57102
}
58103

59104
// RuleType represents a Santa rule type.

santa/santa_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package santa
22

33
import (
44
"bytes"
5-
"io/ioutil"
65
"os"
76
"testing"
87

@@ -64,7 +63,7 @@ func TestConfigMarshalUnmarshal(t *testing.T) {
6463
func testConfig(t *testing.T, path string, replace bool) Config {
6564
t.Helper()
6665

67-
file, err := ioutil.ReadFile(path)
66+
file, err := os.ReadFile(path)
6867
if err != nil {
6968
t.Fatalf("loading config from path %q, err = %q\n", path, err)
7069
}
@@ -80,7 +79,7 @@ func testConfig(t *testing.T, path string, replace bool) Config {
8079
}
8180

8281
if replace {
83-
if err := ioutil.WriteFile(path, buf.Bytes(), os.ModePerm); err != nil {
82+
if err := os.WriteFile(path, buf.Bytes(), os.ModePerm); err != nil {
8483
t.Fatalf("replace config at path %q, err = %q\n", path, err)
8584
}
8685
return testConfig(t, path, false)

santa/testdata/config_a_toml.golden

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ client_mode = "LOCKDOWN"
22
blocked_path_regex = "^(?:/Users)/.*"
33
allowed_path_regex = "^(?:/Users)/.*"
44
batch_size = 100
5+
enable_all_event_upload = true
56
enable_bundles = false
67
enable_transitive_rules = true
78
clean_sync = true

santaconfig/config.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package santaconfig
22

33
import (
44
"context"
5-
"io/ioutil"
65
"os"
76
"path/filepath"
87
"strings"
@@ -72,7 +71,7 @@ func loadConfigs(path string) ([]santa.Config, error) {
7271
if filepath.Ext(info.Name()) != ".toml" {
7372
return nil
7473
}
75-
file, err := ioutil.ReadFile(path)
74+
file, err := os.ReadFile(path)
7675
if err != nil {
7776
return err
7877
}

0 commit comments

Comments
 (0)