@@ -11,6 +11,7 @@ import (
1111 "runtime"
1212
1313 "github.com/DataDog/go-libddwaf/v4/internal/bindings"
14+ "github.com/DataDog/go-libddwaf/v4/internal/ruleset"
1415)
1516
1617// Builder manages an evolving WAF configuration over time. Its lifecycle is
@@ -20,7 +21,8 @@ import (
2021// or similar when sharing it across multiple goroutines. All methods of this
2122// type are safe to call with a nil receiver.
2223type Builder struct {
23- handle bindings.WAFBuilder
24+ handle bindings.WAFBuilder
25+ defaultLoaded bool
2426}
2527
2628// NewBuilder creates a new [Builder] instance. Its lifecycle is typically tied
5860 errBuilderClosed = errors .New ("builder has already been closed" )
5961)
6062
63+ const defaultRecommendedRulesetPath = "::/go-libddwaf/default/recommended.json"
64+
65+ // AddDefaultRecommendedRuleset adds the default recommended ruleset to the
66+ // receiving [Builder], and returns the [Diagnostics] produced in the process.
67+ func (b * Builder ) AddDefaultRecommendedRuleset () (Diagnostics , error ) {
68+ var pinner runtime.Pinner
69+ defer pinner .Unpin ()
70+
71+ ruleset , err := ruleset .DefaultRuleset (& pinner )
72+ if err != nil {
73+ return Diagnostics {}, fmt .Errorf ("failed to load default recommended ruleset: %w" , err )
74+ }
75+
76+ diag , err := b .addOrUpdateConfig (defaultRecommendedRulesetPath , & ruleset )
77+ if err == nil {
78+ b .defaultLoaded = true
79+ }
80+ return diag , err
81+ }
82+
83+ // RemoveDefaultRecommendedRuleset removes the default recommended ruleset from
84+ // the receiving [Builder]. Returns true if the removal occurred (meaning the
85+ // default recommended ruleset was indeed present in the builder).
86+ func (b * Builder ) RemoveDefaultRecommendedRuleset () bool {
87+ if b .RemoveConfig (defaultRecommendedRulesetPath ) {
88+ b .defaultLoaded = false
89+ return true
90+ }
91+ return false
92+ }
93+
6194// AddOrUpdateConfig adds or updates a configuration fragment to this [Builder].
6295// Returns the [Diagnostics] produced by adding or updating this configuration.
6396func (b * Builder ) AddOrUpdateConfig (path string , fragment any ) (Diagnostics , error ) {
@@ -82,15 +115,22 @@ func (b *Builder) AddOrUpdateConfig(path string, fragment any) (Diagnostics, err
82115 return Diagnostics {}, fmt .Errorf ("could not encode the config fragment into a WAF object; %w" , err )
83116 }
84117
118+ return b .addOrUpdateConfig (path , frag )
119+ }
120+
121+ // addOrUpdateConfig adds or updates a configuration fragment to this [Builder].
122+ // Returns the [Diagnostics] produced by adding or updating this configuration.
123+ func (b * Builder ) addOrUpdateConfig (path string , cfg * bindings.WAFObject ) (Diagnostics , error ) {
85124 var diagnosticsWafObj bindings.WAFObject
86125 defer wafLib .ObjectFree (& diagnosticsWafObj )
87126
88- res := wafLib .BuilderAddOrUpdateConfig (b .handle , path , frag , & diagnosticsWafObj )
127+ res := wafLib .BuilderAddOrUpdateConfig (b .handle , path , cfg , & diagnosticsWafObj )
89128
90129 var diags Diagnostics
91130 if ! diagnosticsWafObj .IsInvalid () {
92131 // The Diagnostics object will be invalid if the config was completely
93132 // rejected.
133+ var err error
94134 diags , err = decodeDiagnostics (& diagnosticsWafObj )
95135 if err != nil {
96136 return diags , fmt .Errorf ("failed to decode WAF diagnostics: %w" , err )
0 commit comments