bradleyjkemp / sigma-go

A Go implementation and parser for Sigma rules.
MIT License
84 stars 18 forks source link

Add ability to save rules from memory to sigma #29

Closed calebstewart closed 1 year ago

calebstewart commented 1 year ago

This PR adds the ability to marshal a Sigma rule from memory back to a compliant YAML-formatted Sigma rule on disk. This allows users of the library to in theory modify or fully create rules in memory and then save them back to disk.

For the most part, this is straightforward. The only semi-complicated piece was marshalling the condition expression back properly. For this, I added a toString method to the AST objects to do context-aware construction of the expression, and then put the search expression and optional aggregation expression back together in the a Marshal implementation for Condition.

I added a test, but it's not great. The marshalling process produces a logically identical rule, but some of the fields end up with their default empty values being marshalled back out to the file, so a one-to-one comparison doesn't work. I used the Google cmp package to compare the re-loaded Detection representation in the test to ensure the detection was the same, since that is arguably the most important part of the rule itself. Anectdotally, the other fields seem to be marshalled properly during my testing.

As far as a use-case/motivation here, I am building a sort of rule "bundler" which puts a library of rules together into a single file for uploading to an engine. I'd like to load the rules, validate them, and then output a composite file with all the validated rules. If the Rule struct can completely implement the yaml.Marshaler interface, then this is super simple.

If you have an ideas for better improving the marshalling or the test case, let me know. I'm open to opinions here. This is just a first stab that seems to be working for me. :)

calebstewart commented 1 year ago

I added appropriate yaml:",omitempty" tags to relevant fields in the rule itself, and now doing a direct comparison between the sigma.Rule objects in the unit test works (instead of comparing the Detection field only). This is a better test which actually validates that all the fields are marshalled and then unmarshalled correctly.

calebstewart commented 1 year ago

I realized I missed the implementation of toString for the Near aggregation, so I've added that and all tests are currently passing.