Skip to content

Commit

Permalink
Merge pull request #30 from valllabh/29-provide-json-for-enum-values-…
Browse files Browse the repository at this point in the history
…for-mapping

29-provide-json-for-enum-values-for-mapping completed
  • Loading branch information
valllabh authored Jan 3, 2024
2 parents 0580af9 + ef5c814 commit d8a2540
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ test-compile-proto: clean-output-java clean-output-golang
test-create-proto: clean-output-proto
# ./bin/ocsf-tool config extensions linux
# ./bin/ocsf-tool config profiles cloud container
./bin/ocsf-tool generate-proto file_activity
./bin/ocsf-tool generate-proto file_activity security_finding

run: build-docs build-project test-create-proto test-compile-proto
2 changes: 2 additions & 0 deletions commands/generate_proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ func runGenerateProtoCmd(cmd *cobra.Command, args []string) {
// Produce Output
mapper.Marshal(events)

mapper.WriteEnumValueMap(protoOutput)

// Print a console message indicating where the output is generated
fmt.Printf("Proto files are generated in %s\n", protoOutput)
}
Expand Down
2 changes: 1 addition & 1 deletion docs/ocsf-tool.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
* [ocsf-tool generate-proto](ocsf-tool_generate-proto.md) - Generate a Proto file
* [ocsf-tool schema-class-list](ocsf-tool_schema-class-list.md) - List all classes in the OCSF schema

###### Auto generated by spf13/cobra on 22-Dec-2023
###### Auto generated by spf13/cobra on 3-Jan-2024
2 changes: 1 addition & 1 deletion docs/ocsf-tool_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ ocsf-tool config <extensions|profiles> values... [flags]

* [ocsf-tool](ocsf-tool.md) -

###### Auto generated by spf13/cobra on 22-Dec-2023
###### Auto generated by spf13/cobra on 3-Jan-2024
2 changes: 1 addition & 1 deletion docs/ocsf-tool_generate-proto.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ ocsf-tool generate-proto file_activity process_activity

* [ocsf-tool](ocsf-tool.md) -

###### Auto generated by spf13/cobra on 22-Dec-2023
###### Auto generated by spf13/cobra on 3-Jan-2024
2 changes: 1 addition & 1 deletion docs/ocsf-tool_schema-class-list.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ ocsf-tool schema-class-list [flags]

* [ocsf-tool](ocsf-tool.md) -

###### Auto generated by spf13/cobra on 22-Dec-2023
###### Auto generated by spf13/cobra on 3-Jan-2024
32 changes: 31 additions & 1 deletion ocsf/mappers/protobuff_v3/mapper.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package protobuff_v3

import (
"encoding/json"
"fmt"
"strconv"
"strings"
Expand Down Expand Up @@ -62,6 +63,34 @@ func (mapper *mapper) Marshal(events []schema.Event) {
}

mapper.RootPackage.Marshal()

}

func (mapper *mapper) WriteEnumValueMap(path string) {

enumValueMap := make(map[string]EnumValue)

for _, enum := range mapper.Enums {
for _, ev := range enum.values {
enumValueMap[ToEnumValueName(ev.enum.Name+" "+ev.Name)] = EnumValue{
Name: ev.Name,
Value: ev.Value,
}
}
}

filePath := commons.PathPrepare(path + "/enum-value-map.json")

json, jsonError := json.Marshal(enumValueMap)

if jsonError != nil {
fmt.Println(jsonError.Error())
return
}

println("Writing enum value map to " + filePath)
commons.CreateFile(filePath, json)

}

func (mapper *mapper) populateFieldsFromAttributes(message *Message, attributes map[string]schema.Attribute) {
Expand Down Expand Up @@ -138,7 +167,8 @@ func (mapper *mapper) populateFieldsFromAttributes(message *Message, attributes
Name: aev.Caption,
Value: v,
Comment: Comment{
"Type": "OCSF_VALUE",
"Type": "OCSF_VALUE",
"EnumValue": fmt.Sprintf("%d", v),
},
}
}
Expand Down
2 changes: 1 addition & 1 deletion ocsf/mappers/protobuff_v3/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (p *Pkg) GetEnums() []*Enum {
msgs := maps.Values(GetMapper().Enums)

filterFunc := func(e *Enum) bool {
return e.Package.GetName() == p.GetName()
return e.Package.GetFullName() == p.GetFullName()
}

return commons.Filter(msgs, filterFunc)
Expand Down
6 changes: 3 additions & 3 deletions ocsf/mappers/protobuff_v3/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ type Enum struct {
}

type EnumValue struct {
Name string
Value int64
Comment Comment
Name string `json:"name"`
Value int64 `json:"value"`
Comment Comment `json:",omitempty"`
enum *Enum
}

Expand Down
160 changes: 153 additions & 7 deletions ocsf/schema/loader-repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package schema
import (
"encoding/json"
"errors"
"fmt"
"os"
"strconv"
"strings"

"github.com/jinzhu/copier"
Expand Down Expand Up @@ -60,6 +62,9 @@ func (sl *SchemaRepositorySchemaLoader) Load() (*OCSFSchema, error) {

sl.processExtensions(ocsfSchema)

jsonOcsfSchema, _ := json.Marshal(ocsfSchema)
commons.CreateFile("./schema.json", jsonOcsfSchema)

return ocsfSchema, nil
}

Expand Down Expand Up @@ -248,6 +253,7 @@ func (sl *SchemaRepositorySchemaLoader) loadSchemaFromDirectory(directory string
return nil, schemaVersionError
}

println("\nLoading repo dictionary")
dictionary := Dictionary{}
objectMap := make(map[string]Object)
eventMap := make(map[string]Event)
Expand All @@ -260,6 +266,14 @@ func (sl *SchemaRepositorySchemaLoader) loadSchemaFromDirectory(directory string
return nil, dictionaryLoadingError
}

println("\nLoading repo categories")
categoriesFile := repoPath("/categories.json")
categories, categoriesLoadingError := sl.loadCategories(categoriesFile)

if categoriesLoadingError != nil {
return nil, categoriesLoadingError
}

println("\nLoading repo objects")

// Load objects defined in json files in the map from /objects directory using schema.Object struct
Expand All @@ -280,7 +294,7 @@ func (sl *SchemaRepositorySchemaLoader) loadSchemaFromDirectory(directory string
// Load events defined in json files in the map from /events directory using schema.Event struct
eventsDirectory := repoPath("/events")

eventLoadingError := sl.loadEvents(eventsDirectory, &eventMap, &dictionary)
eventLoadingError := sl.loadEvents(eventsDirectory, &eventMap, &dictionary, &categories)

if eventLoadingError != nil {
return nil, eventLoadingError
Expand All @@ -298,6 +312,7 @@ func (sl *SchemaRepositorySchemaLoader) loadSchemaFromDirectory(directory string
Version: schemaVersion.Version,
Types: dictionary.Types.Attributes,
Dictionary: dictionary,
Categories: categories,
}

return &schema, nil
Expand Down Expand Up @@ -391,7 +406,7 @@ func (sl *SchemaRepositorySchemaLoader) loadExtensionFromDirectory(path string,

// Load events defined in json files in the map from /events directory using schema.Event struct
eventsDirectory := commons.CleanPath(path + "/" + "events")
eventLoadingError := sl.loadEvents(eventsDirectory, &schema.Classes, &schema.Dictionary)
eventLoadingError := sl.loadEvents(eventsDirectory, &schema.Classes, &schema.Dictionary, &schema.Categories)

if eventLoadingError != nil {
return eventLoadingError
Expand Down Expand Up @@ -433,6 +448,30 @@ func (sl *SchemaRepositorySchemaLoader) loadVersionFromDirectory() (Version, err
return version, nil
}

// func to load categories from categories.json
func (sl *SchemaRepositorySchemaLoader) loadCategories(path string) (Categories, error) {

// Declare categories
var categories Categories

// Categories file path
categoriesFile := commons.CleanPath(path)

// Load data from file []byte
data, loadDataError := os.ReadFile(categoriesFile)

if loadDataError != nil {
return categories, loadDataError
}

// Unmarshal data into categories
if err := json.Unmarshal(data, &categories); err != nil {
return categories, err
}

return categories, nil
}

// function to load objects from directory
func (sl *SchemaRepositorySchemaLoader) loadObjects(directory string, objects *(map[string]Object), dictionary *Dictionary) error {

Expand Down Expand Up @@ -501,7 +540,7 @@ func (sl *SchemaRepositorySchemaLoader) loadObjects(directory string, objects *(
}

// function to load events from directory
func (sl *SchemaRepositorySchemaLoader) loadEvents(directory string, events *(map[string]Event), dictionary *Dictionary) error {
func (sl *SchemaRepositorySchemaLoader) loadEvents(directory string, events *(map[string]Event), dictionary *Dictionary, categories *Categories) error {

rootDir := commons.Dir(directory)

Expand Down Expand Up @@ -563,6 +602,58 @@ func (sl *SchemaRepositorySchemaLoader) loadEvents(directory string, events *(ma
// extend event
sl.extendEvent(&event, events)

// event schema enrichments
category, categoryExists := categories.Attributes[event.Category]

if categoryExists {
categoryUid, categoryUidExists := event.Attributes["category_uid"]
if categoryUidExists {

// add category_uid to event
categoryUid.Enum = map[string]EnumAttribute{}
categoryUidString := fmt.Sprintf("%d", category.Uid)
categoryUid.Enum[categoryUidString] = EnumAttribute{
Caption: category.Caption,
Uid: category.Uid,
Description: category.Description,
}
event.Attributes["category_uid"] = categoryUid

// add class_uid to event
classUid := fmt.Sprintf("%d%d", (100 * category.Uid), event.Uid)
attributeClassUid := event.Attributes["class_uid"]
attributeClassUid.Enum = Enum{}
attributeClassUid.Enum[classUid] = EnumAttribute{
Caption: event.Caption,
Description: event.Description,
}
event.Attributes["class_uid"] = attributeClassUid

// add uid to event
classUidAsInt, classUidConversionError := strconv.Atoi(classUid)
if classUidConversionError == nil {
event.Uid = classUidAsInt
}

// add type_uid to event
if event.Attributes["activity_id"].Enum != nil {
typeUid, typeUidExists := event.Attributes["type_uid"]
if typeUidExists {
typeUid.Enum = Enum{}
for activityKey, activity := range event.Attributes["activity_id"].Enum {
typeUidKey := fmt.Sprintf("%d%02s", event.Uid, activityKey)
typeUid.Enum[typeUidKey] = EnumAttribute{
Caption: event.Caption + ": " + activity.Caption,
Description: activity.Description,
}
}
event.Attributes["type_uid"] = typeUid
}
}

}
}

}

return err
Expand Down Expand Up @@ -629,7 +720,10 @@ func (sl *SchemaRepositorySchemaLoader) extendEvent(item *Event, items *map[stri

// set attributes
for key, value := range parentItem.Attributes {
item.Attributes[key] = value
_, exists := item.Attributes[key]
if !exists {
item.Attributes[key] = value
}
}

// if item category is not null then use parent
Expand Down Expand Up @@ -809,21 +903,52 @@ func (sl *SchemaRepositorySchemaLoader) loadEventFromFile(path string, includeRo
event.Extends = e.Extends
event.Name = e.Name
event.Category = e.Category
event.CategoryName = e.CategoryName
if e.CategoryName != nil {
event.CategoryName = string(e.CategoryName.(string))
}
event.Profiles = e.Profiles
event.Uid = e.Uid

// iterate over attributes and copy each attribute to object
event.Attributes = make(map[string]Attribute)
for key, value := range e.Attributes {
event.Attributes[key] = value.(Attribute)

attr := value.(Attribute)

if attr.Include != "" {

enumFilePath := commons.CleanPath(includeRootPath + "/" + attr.Include)

println("Loading enum from " + enumFilePath)
loadAttributeEnum, loadAttributeEnumError := sl.loadAttributeEnumFromFile(enumFilePath)

if loadAttributeEnumError != nil {
println(loadAttributeEnumError.Error())
}

// Try loading enum from repo if not found in rootPath
if loadAttributeEnumError != nil {
repoEnumFilePath := repoPath(attr.Include)
println("Loading enum from " + repoEnumFilePath)
loadAttributeEnum, loadAttributeEnumError = sl.loadAttributeEnumFromFile(repoEnumFilePath)
}

if loadAttributeEnumError == nil {
attr.Enum = loadAttributeEnum.Enum
}
}

attr.Include = ""

event.Attributes[key] = attr

}

return event, nil

}

// func detectAndLoadInclude which accepts include file path and loads it using diffrent function based on path. Possible paths are /includes, /profiles
// func detectAndLoadInclude which accepts include file path and loads it using different function based on path. Possible paths are /includes, /profiles
func (sl *SchemaRepositorySchemaLoader) includeFile(path string) (map[string]Attribute, error) {

// switch based on path prefix
Expand All @@ -840,6 +965,27 @@ func (sl *SchemaRepositorySchemaLoader) includeFile(path string) (map[string]Att

}

// func includeEnum which accepts include file path
func (sl *SchemaRepositorySchemaLoader) loadAttributeEnumFromFile(path string) (Attribute, error) {

// declare include
var attribute Attribute

data, loadDataError := os.ReadFile(path)

if loadDataError != nil {
return attribute, loadDataError
}

// unmarshal data into include
if err := json.Unmarshal(data, &attribute); err != nil {
return attribute, err
}

return attribute, nil

}

// function to load include from file returns Include struct and error. It accepts include file path as string and loads json file from repo Directory and returns Include struct and error
func (sl *SchemaRepositorySchemaLoader) loadIncludeFromFile(path string) (Include, error) {

Expand Down
Loading

0 comments on commit d8a2540

Please sign in to comment.