Skip to content

Commit

Permalink
Fix/add docstrings (#30)
Browse files Browse the repository at this point in the history
* Add docstrings

* Bump go version for testing
  • Loading branch information
pcktdmp authored Sep 22, 2024
1 parent 6ae03cf commit 4bb7093
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 10 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:
runs-on: ubuntu-latest
steps:

- name: Set up Go 1.14
- name: Set up Go 1.22
uses: actions/setup-go@v1
with:
go-version: 1.14
go-version: 1.22
id: go

- name: Check out code into the Go module directory
Expand Down
90 changes: 82 additions & 8 deletions cefevent/cefevent.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@ import (
"strings"
)

// CefEventer defines the interface for handling Common Event Format (CEF) events.
// It includes methods to generate, validate, read, and log CEF events.
type CefEventer interface {
Generate() (string, error)
Validate() bool
Read(line string) (CefEvent, error)
Log() (bool, error)
Generate() (string, error) // Generate constructs and returns a CEF message string if all the mandatory fields are set.
Validate() bool // Validate checks whether all mandatory fields in the CefEvent struct are set.
Read(line string) (CefEvent, error) // Read parses a CEF message string and populates the CefEvent struct with the extracted data.
Log() (bool, error) // Log attempts to generate a CEF message from the current CefEvent and logs it to the standard output.
}

// CefEvent represents a Common Event Format (CEF) event.
// It includes fields for CEF version, device vendor, device product, device version,
// device event class ID, event name, event severity, and additional extensions.
type CefEvent struct {
// defaults to 0 which is also the first CEF version.
Version int
Expand All @@ -30,6 +35,19 @@ type CefEvent struct {
Extensions map[string]string
}

// cefEscapeField escapes special characters in a given string that are used in CEF (Common Event Format) fields.
// It replaces backslashes, pipes, and newlines with their escaped counterparts.
//
// The following replacements are performed:
// - "\" becomes "\\"
// - "|" becomes "\\|"
// - "\n" becomes "\\n"
//
// Parameters:
// - field: A string that needs to be escaped.
//
// Returns:
// - A string with the special characters escaped to ensure proper formatting in CEF fields.
func cefEscapeField(field string) string {

replacer := strings.NewReplacer(
Expand All @@ -41,6 +59,19 @@ func cefEscapeField(field string) string {
return replacer.Replace(field)
}

// cefEscapeExtension escapes special characters in a given string that are used in CEF (Common Event Format) extensions.
// It replaces backslashes, newlines, and equals signs with their escaped counterparts.
//
// The following replacements are performed:
// - "\" becomes "\\"
// - "\n" becomes "\\n"
// - "=" becomes "\\="
//
// Parameters:
// - field: A string that needs to be escaped.
//
// Returns:
// - A string with the special characters escaped to ensure proper formatting in CEF extensions.
func cefEscapeExtension(field string) string {

replacer := strings.NewReplacer(
Expand All @@ -51,6 +82,15 @@ func cefEscapeExtension(field string) string {
return replacer.Replace(field)
}

// Validate verifies whether all mandatory fields in the CefEvent struct are set.
// It checks if the fields Version, DeviceVendor, DeviceProduct, DeviceVersion,
// DeviceEventClassId, Name, and Severity are populated and returns true if they are,
// otherwise, it returns false.
//
// This method uses reflection to loop over the mandatory fields and check their values.
//
// Returns:
// - A boolean indicating whether all mandatory fields are set (true) or not (false).
func (event *CefEvent) Validate() bool {

assertEvent := reflect.ValueOf(event).Elem()
Expand Down Expand Up @@ -81,10 +121,18 @@ func (event *CefEvent) Validate() bool {

}

// Log should be used as a stub in most cases, it either
// succeeds generating the CEF event and send it to stdout
// or doesn't and logs that to stderr. This function
// plays well inside containers.
// Log attempts to generate a CEF message from the current CefEvent
// and logs it to the standard output. If generation fails, it logs
// an error message to the standard error.
//
// The method works well within containerized environments by appropriately
// selecting output targets based on success or failure. If the generation
// of the event is successful, it logs the message to stdout, otherwise,
// it logs an error message to stderr.
//
// Returns:
// - A boolean indicating whether the logging operation succeeded (true) or failed (false).
// - An error if the logging operation could not be completed due to a failure in generating the CEF message.
func (event *CefEvent) Log() (bool, error) {

logMessage, err := event.Generate()
Expand All @@ -101,6 +149,17 @@ func (event *CefEvent) Log() (bool, error) {
return true, nil
}

// Generate constructs and returns a CEF (Common Event Format) message string if all the mandatory
// fields are set in the CefEvent. If any mandatory field is missing, it returns an error.
//
// A CEF message follows the format:
// CEF:Version|Device Vendor|Device Product|Device Version|Device Event Class ID|Name|Severity|Extensions
//
// Each field is escaped to ensure that special characters do not interfere with the CEF format.
//
// Returns:
// - A string representing the generated CEF message.
// - An error if any mandatory field is missing or if there are other issues during generation.
func (event CefEvent) Generate() (string, error) {

if !CefEventer.Validate(&event) {
Expand Down Expand Up @@ -146,6 +205,21 @@ func (event CefEvent) Generate() (string, error) {
return eventCef, nil
}

// Read parses a CEF (Common Event Format) message string and populates the CefEvent struct
// with the extracted data.
//
// The method checks if the provided string starts with the "CEF:" prefix and then splits
// the string into its constituent fields. It also extracts any key-value pairs present in the
// Extensions part of the CEF message.
//
// The format of a CEF message is:
// CEF:Version|Device Vendor|Device Product|Device Version|Device Event Class ID|Name|Severity|Extensions
//
// The method ensures that if any mandatory field is missing or improperly formatted, it returns an error.
//
// Returns:
// - A CefEvent struct populated with the parsed CEF message data.
// - An error if the CEF message is improperly formatted or if any mandatory field is missing.
func (event CefEvent) Read(eventLine string) (CefEvent, error) {
if strings.HasPrefix(eventLine, "CEF:") {
eventSlashed := strings.Split(strings.TrimPrefix(eventLine, "CEF:"), "|")
Expand Down

0 comments on commit 4bb7093

Please sign in to comment.