Skip to content

Commit

Permalink
added support for repository based schema loading
Browse files Browse the repository at this point in the history
  • Loading branch information
valllabh committed Dec 17, 2023
1 parent 007ac52 commit 0bc4608
Show file tree
Hide file tree
Showing 29 changed files with 1,661 additions and 203 deletions.
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
output
bin
/output
/bin
ocsf-schema.json
ocsf-schema-*.json
download/ocsf-tool/
config.yaml
config.yaml
/schema
/schema/*
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ test-compile-proto: clean-output-java clean-output-golang
find ./output/proto -type f -name "*.proto" | xargs protoc --proto_path=./output/proto --java_out=./output/java --go_opt=paths=source_relative --go_out=./output/golang

test-create-proto: clean-output-proto
./bin/ocsf-tool config extensions linux
./bin/ocsf-tool config profiles cloud container
# ./bin/ocsf-tool config extensions linux
# ./bin/ocsf-tool config profiles cloud container
./bin/ocsf-tool generate-proto file_activity

run: build-docs build-project test-create-proto test-compile-proto
69 changes: 65 additions & 4 deletions commands/config.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,50 @@
package commands

import (
"errors"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/valllabh/ocsf-tool/commons"
"github.com/valllabh/ocsf-tool/config"
)

type ConfigVariable struct {
variable string
help string
example string
type_ string
}

var CONFIGURATIONS map[string]ConfigVariable = map[string]ConfigVariable{
"extensions": ConfigVariable{
variable: "extensions",
help: "OCSF Extensions",
example: "linux win",
type_: "[]string",
},
"profiles": ConfigVariable{
variable: "profiles",
help: "OCSF Profiles",
example: "cloud linux/linux_users",
type_: "[]string",
},
"schema.loading.strategy": ConfigVariable{
variable: "schema.loading.strategy",
help: "Schema Loading Strategy. Possible values: server, repository",
example: "repository",
type_: "string",
},
}

// Define the setConfig command
var configCmd = &cobra.Command{
Use: `config <extensions|profiles> values...`,
Short: `Set configuration values for extensions and profiles`,
Example: `
ocsf-tool config extensions linux win
ocsf-tool config profiles cloud linux/linux_users
ocfs-tool config schema.loading.strategy repository
`,
Long: `
Set configuration values for extensions and profiles
Expand All @@ -31,20 +63,49 @@ var configCmd = &cobra.Command{
// Extract the variable and values from the args
variable, values := args[0], args[1:]

configMeta, configError := getConfig(variable)

// validate variable
if variable != "extensions" && variable != "profiles" {
println("Invalid variable name. Possible values are [extensions, profiles].")
if configError != nil {
println("Invalid config variable:", variable)
// print help
cmd.Help()
return
}

// set the config value
viper.Set(variable, values)
// switch on the type of the config variable and set the value
switch configMeta.type_ {
case "[]string":
viper.Set(variable, values)
case "string":
viper.Set(variable, values[0])
}

// Write the config file to disk
config.WriteConfig()
},
}

// getConfig returns ConfigVariable of the given config variable or error if the config variable is invalid
func getConfig(variable string) (ConfigVariable, error) {
// validate variable
if !isValidConfigVariable(variable) {
return ConfigVariable{}, errors.New("Invalid config variable: " + variable)
}

return CONFIGURATIONS[variable], nil
}

// getValidConfigVariables returns a list of valid config variables
func getValidConfigVariables() []string {
return commons.GetMapKeys(CONFIGURATIONS)
}

// isValidConfigVariable checks if the given variable is a valid config variable
func isValidConfigVariable(variable string) bool {
return commons.Contains(getValidConfigVariables(), variable)
}

func init() {
// Add the setConfig command to the root command
rootCmd.AddCommand(configCmd)
Expand Down
2 changes: 1 addition & 1 deletion commands/generate_proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func runGenerateProtoCmd(cmd *cobra.Command, args []string) {
golangPackageName, _ := cmd.Flags().GetString("golang-root-package")
javaPackageName, _ := cmd.Flags().GetString("java-root-package")

ocsfSchema, _ := schema.LoadOCSFSchema()
ocsfSchema := schema.LoadOCSFSchema()
events := []schema.Event{}
mapper := protobuff_v3.NewMapper(ocsfSchema)

Expand Down
4 changes: 4 additions & 0 deletions commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ import (
// Define the root command
var rootCmd = &cobra.Command{
Use: "ocsf-tool",

PostRun: func(cmd *cobra.Command, args []string) {
// Write the config file to disk
config.WriteConfig()
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
println("--")
},
}

// Initialize the root command
Expand Down
2 changes: 1 addition & 1 deletion commands/schema_class_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var SchemaClassListCmd = &cobra.Command{
// Define the run function for the SchemaClassListCmd command
func runSchemaClassListCmd(cmd *cobra.Command, args []string) {

ocsfSchema, _ := schema.LoadOCSFSchema()
ocsfSchema := schema.LoadOCSFSchema()
classes := ocsfSchema.Classes

// Group classes by Category
Expand Down
20 changes: 20 additions & 0 deletions commons/arrays.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,23 @@ func Filter[T any](arr []T, filter func(T) bool) []T {
}
return filtered
}

// function to check if an element exists in a slice
// Example: Contains([]string{"a", "b", "c"}, "b") -> true
func Contains[T comparable](arr []T, element T) bool {

// check if arr is not nil and empty
if len(arr) == 0 {
return false
}

// iterate over the array and check if the element exists
for _, a := range arr {
if a == element {
return true
}
}

// return false if the element does not exist
return false
}
101 changes: 101 additions & 0 deletions commons/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package commons

import (
"os"
"path/filepath"
"strings"
)

// EnsureDirExists checks if a directory exists at the given path, and creates it if it doesn't exist.
func EnsureDirExists(path string) error {

path = CleanPath(path)
path = Dir(path)

if !PathExists(path) {
err := os.MkdirAll(path, 0755)
if err != nil {
return err
}
}
return nil
}

// Extract Dir path from file path
func Dir(filePath string) string {
return filepath.Dir(filePath)
}

// Path Exists
func PathExists(path string) bool {
if _, err := os.Stat(path); os.IsNotExist(err) {
return false
}
return true
}

// CreateFile creates a file at the given path and writes the contents to the file.
// It overwrites the file if it already exists.
func CreateFile(path string, contents []byte) error {

// Ensure the directory exists
err := EnsureDirExists(path)
if err != nil {
return err
}

// Write contents to the file
err = os.WriteFile(path, contents, 0644)
if err != nil {
return err
}

return nil
}

// PathPrepare replaces $HOME, $TMP, $CWD with their respective paths
func PathPrepare(path string) string {

// replace $HOME with Home path if path contains $HOME is present
if strings.HasPrefix(path, "$HOME") {
path = strings.Replace(path, "$HOME", os.Getenv("HOME"), 1)
}

// replace $TMP with Temp path if path contains $TMP is present
if strings.HasPrefix(path, "$TMP") {
path = strings.Replace(path, "$TMP", os.Getenv("TMP"), 1)
}

// replace $CWD with current working path if path contains $CWD is present
if strings.HasPrefix(path, "$CWD") {
path = strings.Replace(path, "$CWD", os.Getenv("PWD"), 1)
}

// remove double slashes
path = CleanPath(path)

return path
}

// clean Path string
func CleanPath(path string) string {
// remove double slashes
path = strings.Replace(path, "//", "/", 1)

return path
}

// Walk walks the file tree rooted at root, calling walkFn for each file or directory in the tree, including root.
func Walk(root string, walkFn filepath.WalkFunc) error {
return filepath.Walk(root, walkFn)
}

// FileName from path
func FileName(path string) string {
return filepath.Base(path)
}

// FilenameWithoutExtension from path
func FilenameWithoutExtension(path string) string {
return strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))
}
46 changes: 46 additions & 0 deletions commons/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package commons

import (
"os"
"testing"
)

func TestPathPrepare(t *testing.T) {
tests := []struct {
name string
path string
expected string
}{
{
name: "Replace $HOME",
path: "$HOME/test",
expected: os.Getenv("HOME") + "/test",
},
{
name: "Replace $TMP",
path: "$TMP/test",
expected: os.Getenv("TMP") + "/test",
},
{
name: "Replace $CWD",
path: "$CWD/test",
expected: os.Getenv("PWD") + "/test",
},
{
name: "No replacements",
path: "/test/path",
expected: "/test/path",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result := PathPrepare(test.path)
if result != test.expected {
t.Errorf("Expected %s, but got %s", test.expected, result)
} else {
t.Logf("Passed Test %s, Input %s, Expected %s, Result %s", test.name, test.path, test.expected, result)
}
})
}
}
36 changes: 0 additions & 36 deletions commons/fileutils.go

This file was deleted.

Loading

0 comments on commit 0bc4608

Please sign in to comment.