Skip to content

Commit

Permalink
feat(processor): added key-value and CEF processor (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfizzle authored Apr 13, 2022
1 parent 807e2cc commit 9bbce68
Show file tree
Hide file tree
Showing 7 changed files with 521 additions and 23 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ require (
cloud.google.com/go/pubsub v1.19.0
cloud.google.com/go/storage v1.10.0
github.com/aws/aws-sdk-go v1.43.18
github.com/dlclark/regexp2 v1.4.0
github.com/go-resty/resty/v2 v2.7.0
github.com/golang/protobuf v1.5.2
github.com/google/cel-go v0.10.1
github.com/google/uuid v1.3.0
github.com/gookit/validate v1.3.1
github.com/influxdata/go-syslog/v3 v3.0.0
github.com/jjeffery/kv v0.8.1
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down Expand Up @@ -268,6 +270,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/go-syslog/v3 v3.0.0 h1:jichmjSZlYK0VMmlz+k4WeOQd7z745YLsvGMqwtYt4I=
github.com/influxdata/go-syslog/v3 v3.0.0/go.mod h1:tulsOp+CecTAYC27u9miMgq21GqXRW6VdKbOG+QSP4Q=
github.com/jjeffery/kv v0.8.1 h1:S4/KbfPVNTGM/YCt5F+Za93o09119VNtOT+rLL4Gls0=
github.com/jjeffery/kv v0.8.1/go.mod h1:iHA3uy+umBqxcJFr+e+gaGAv1OcyHlU6rSo3TcR61yQ=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
Expand Down Expand Up @@ -541,6 +545,7 @@ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
51 changes: 28 additions & 23 deletions internal/app/builtin.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,49 @@
package app

import (
filein "github.com/ThoronicLLC/collector/internal/input/file"
"github.com/ThoronicLLC/collector/internal/input/msgraph"
pubsubin "github.com/ThoronicLLC/collector/internal/input/pubsub"
"github.com/ThoronicLLC/collector/internal/input/syslog"
fileout "github.com/ThoronicLLC/collector/internal/output/file"
"github.com/ThoronicLLC/collector/internal/output/gcs"
"github.com/ThoronicLLC/collector/internal/output/log_analytics"
pubsubout "github.com/ThoronicLLC/collector/internal/output/pubsub"
"github.com/ThoronicLLC/collector/internal/output/s3"
"github.com/ThoronicLLC/collector/internal/output/stdout"
"github.com/ThoronicLLC/collector/internal/processor/cel"
syslog_processor "github.com/ThoronicLLC/collector/internal/processor/syslog"
"github.com/ThoronicLLC/collector/pkg/core"

file_input "github.com/ThoronicLLC/collector/internal/input/file"
msgraph_input "github.com/ThoronicLLC/collector/internal/input/msgraph"
pubsub_input "github.com/ThoronicLLC/collector/internal/input/pubsub"
syslog_input "github.com/ThoronicLLC/collector/internal/input/syslog"

cel_processor "github.com/ThoronicLLC/collector/internal/processor/cel"
kv_processor "github.com/ThoronicLLC/collector/internal/processor/kv"
syslog_processor "github.com/ThoronicLLC/collector/internal/processor/syslog"

file_output "github.com/ThoronicLLC/collector/internal/output/file"
gcs_output "github.com/ThoronicLLC/collector/internal/output/gcs"
log_analytics_output "github.com/ThoronicLLC/collector/internal/output/log_analytics"
pubsub_output "github.com/ThoronicLLC/collector/internal/output/pubsub"
s3_output "github.com/ThoronicLLC/collector/internal/output/s3"
stdout_output "github.com/ThoronicLLC/collector/internal/output/stdout"
)

func AddInternalInputs() map[string]core.InputHandler {
return map[string]core.InputHandler{
filein.InputName: filein.Handler(),
pubsubin.InputName: pubsubin.Handler(),
syslog.InputName: syslog.Handler(),
msgraph.InputName: msgraph.Handler(),
file_input.InputName: file_input.Handler(),
pubsub_input.InputName: pubsub_input.Handler(),
syslog_input.InputName: syslog_input.Handler(),
msgraph_input.InputName: msgraph_input.Handler(),
}
}

func AddInternalProcessors() map[string]core.ProcessHandler {
return map[string]core.ProcessHandler{
cel.ProcessorName: cel.Handler(),
cel_processor.ProcessorName: cel_processor.Handler(),
syslog_processor.ProcessorName: syslog_processor.Handler(),
kv_processor.ProcessorName: kv_processor.Handler(),
}
}

func AddInternalOutputs() map[string]core.OutputHandler {
return map[string]core.OutputHandler{
fileout.OutputName: fileout.Handler(),
stdout.OutputName: stdout.Handler(),
s3.OutputName: s3.Handler(),
gcs.OutputName: gcs.Handler(),
log_analytics.OutputName: log_analytics.Handler(),
pubsubout.OutputName: pubsubout.Handler(),
file_output.OutputName: file_output.Handler(),
stdout_output.OutputName: stdout_output.Handler(),
s3_output.OutputName: s3_output.Handler(),
gcs_output.OutputName: gcs_output.Handler(),
log_analytics_output.OutputName: log_analytics_output.Handler(),
pubsub_output.OutputName: pubsub_output.Handler(),
}
}
143 changes: 143 additions & 0 deletions internal/processor/kv/cef.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package kv

import (
"encoding/json"
"fmt"
"strconv"
"strings"

"github.com/dlclark/regexp2"
)

type cefEvent struct {
Version string
DeviceVendor string
DeviceProduct string
DeviceVersion string
DeviceEventClassId string
Name string
Severity string
Extensions map[string]string
}

func parseCef(event string) ([]byte, error) {
cefMsg, err := cefStringToObject(event)

if err != nil {
return nil, err
}

// Marshal JSON string
jsonString, err := json.Marshal(cefMsg)

// Handle errors
if err != nil {
fmt.Println(3)
return nil, err
}

return jsonString, nil
}

func cefStringToObject(cefString string) (*cefEvent, error) {
// Split by CEF separator
arr := strings.Split(cefString, "|")

if len(arr) < 7 {
return nil, fmt.Errorf("invalid CEF format")
}

version := ""

if strings.Contains(arr[0], ":") {
// Split first field to validate CEF
validate := strings.Split(arr[0], ":")

// Validate that it is a valid CEF message
if validate[0] != "CEF" {
return nil, fmt.Errorf("invalid CEF format")
}

version = validate[1]
} else {
if _, err := strconv.Atoi(arr[0]); err != nil {
return nil, fmt.Errorf("invalid CEF format")
}
version = arr[0]
}

// Get extensions
extensions := strings.Join(arr[7:], "|")

// Replace colons with {{COLON}}
safeExtensions := strings.ReplaceAll(extensions, ":", "{{COLON}}")
safeExtensions = strings.ReplaceAll(safeExtensions, `\\=`, "{{EQUAL_ESCAPE_2}}")
safeExtensions = strings.ReplaceAll(safeExtensions, `\=`, "{{EQUAL_ESCAPE_1}}")

// Replace non KV spaces with {{SPACE}}
re := regexp2.MustCompile(`\s(?!([\w\-]+)\=)`, 0)
safeExtensions2, err := re.Replace(safeExtensions, "{{SPACE}}", -1, -1)

// Parse extensions in key value format
keyValueMap, err := parseKeyValue(safeExtensions2, true)

// Handle error
if err != nil {
return nil, err
}

// Restore colons
newKeyValueMap := make(map[string]string, 0)
for k, v := range keyValueMap {
newKey := strings.ReplaceAll(k, `{{SPACE}}`, " ")
newKey = strings.ReplaceAll(newKey, `{{EQUAL_ESCAPE_1}}`, `\=`)
newKey = strings.ReplaceAll(newKey, `{{EQUAL_ESCAPE_2}}`, `\\=`)
newKey = strings.ReplaceAll(newKey, `{{COLON}}`, ":")

newValue := strings.ReplaceAll(v, `{{SPACE}}`, " ")
newValue = strings.ReplaceAll(newValue, `{{EQUAL_ESCAPE_1}}`, `\=`)
newValue = strings.ReplaceAll(newValue, `{{EQUAL_ESCAPE_2}}`, `\\=`)
newValue = strings.ReplaceAll(newValue, `{{COLON}}`, ":")
newValue = strings.TrimSpace(newValue)

newKeyValueMap[newKey] = newValue
}

// Build CEF event
cefEvent := &cefEvent{
Version: version,
DeviceVendor: cefEscapeField(arr[1]),
DeviceProduct: cefEscapeField(arr[2]),
DeviceVersion: cefEscapeField(arr[3]),
DeviceEventClassId: cefEscapeField(arr[4]),
Name: cefEscapeField(arr[5]),
Severity: cefEscapeField(arr[6]),
Extensions: newKeyValueMap,
}

return cefEvent, nil
}

// Unescape CEF fields
func cefEscapeField(field string) string {

replacer := strings.NewReplacer(
"\\\\", "\\",
"\\|", "|",
"\\n", "\n",
)

return replacer.Replace(field)
}

// Unescape CEF extensions
func cefEscapeExtension(field string) string {

replacer := strings.NewReplacer(
"\\\\", "\\",
"\\n", "\n",
"\\=", "=",
)

return replacer.Replace(field)
}
Loading

0 comments on commit 9bbce68

Please sign in to comment.