libddwaf 1.24.1.2.1 → 1.25.1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '029b3d9c81bc6161f7080edb546d4de3820769540747788f766638dd28472776'
4
- data.tar.gz: 336fa61a91724299d961cbb03f12347cf51c6cf4f72a05e72f9368e077045c60
3
+ metadata.gz: 01670d4445892bdf889e3a2e00bbaa9b59931ff385f3f503ec529f0fc83a6837
4
+ data.tar.gz: 020d15ce0f7452a568a6307183358cbb74de49fda3ebd2cd0da120340de686ad
5
5
  SHA512:
6
- metadata.gz: a658fc7175a4e87599844a60712284743d4a765d700c3584f9a84acb15f2f230613085be8b7a563090fdffe150640cf5af18d547e08880d68b99bf93259f5e95
7
- data.tar.gz: a7616a7818f46cdb402fe0e7b111b927e990e4f5e274a191877685070facf0df85ff91f292b7a88b75272905a7069f7b2e285c17099e8fac0911d3b192baf2c8
6
+ metadata.gz: 6a9f480d301dd36765d9865f491adc0d158d7486fc44b52c949a916b6096369dfdea69895d1ac23a64b85af4deea95a66325e2cc500eccfe9075ece3607aee13
7
+ data.tar.gz: 2166ec0d0898e7b543cc0c9759f1d1ec9f4368f9b34c4731c6ef8525c7382a58e59904b012b923dc5df5ee614c8eac8744d90b5479fdb7aadab25cb162fd61b4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Unreleased
2
2
 
3
+ # 2025-09-24 v1.25.1.1.0
4
+
5
+ ## Changed
6
+
7
+ - Change coersion of the values in WAF rules to use `libddwaf` primitives
8
+
9
+ # 2025-09-18 v1.25.1.0.1
10
+
11
+ ## Fixed
12
+
13
+ - Fix handling of unsuccessful `ddwaf_run` call and result conversion
14
+
15
+ # 2025-09-16 v1.25.1.0.0
16
+
17
+ ## Added
18
+
19
+ - Add `Result#keep?` method
20
+
21
+ ## Changed
22
+
23
+ - Change `LibDDWAF::Object#input_truncated?` to `LibDDWAF::Object#truncated?` method
24
+ - Change `LibDDWAF::Object#mark_as_input_truncated?` to `LibDDWAF::Object#mark_truncated?` method
25
+ - Change `Result#timeout` to `Result#timeout?` method
26
+ - Change `Result#derivatives` to `Result#attributes` method
27
+ - Change `Result#total_runtime` to `Result#duration` method
28
+
3
29
  # 2025-09-15 v1.24.1.2.1
4
30
 
5
31
  ## Fixed
@@ -6,7 +6,16 @@ module Datadog
6
6
  # Ruby representation of the ddwaf_context in libddwaf
7
7
  # See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/BINDING_IMPL_NOTES.md?plain=1#L125-L158
8
8
  class Context
9
- RESULT_CODE = {
9
+ EMPTY_RESULT = {
10
+ "events" => [], #: WAF::events
11
+ "actions" => {}, #: WAF::actions
12
+ "attributes" => {}, #: WAF::attributes
13
+ "duration" => 0,
14
+ "timeout" => false,
15
+ "keep" => false
16
+ }.freeze
17
+ SUCCESS_RESULT_CODES = %i[ddwaf_ok ddwaf_match].freeze
18
+ RESULT_CODE_TO_STATUS = {
10
19
  ddwaf_ok: :ok,
11
20
  ddwaf_match: :match,
12
21
  ddwaf_err_internal: :err_internal,
@@ -69,18 +78,28 @@ module Datadog
69
78
  raise ConversionError, "Could not convert ephemeral data: #{ephemeral_data.inspect}"
70
79
  end
71
80
 
72
- result_obj = LibDDWAF::Result.new
81
+ result_obj = LibDDWAF::Object.new
73
82
  raise LibDDWAFError, "Could not create result object" if result_obj.null?
74
83
 
75
84
  code = LibDDWAF.ddwaf_run(@context_ptr, persistent_data_obj, ephemeral_data_obj, result_obj, timeout)
85
+ result = Converter.object_to_ruby(result_obj)
86
+
87
+ # NOTE: In case of the error, `libddwaf` will not "fill" the result
88
+ # object, so it will be empty and the conversion of it will return
89
+ # `nil`, but that is not a conversion issue.
90
+ if SUCCESS_RESULT_CODES.include?(code) && result.nil?
91
+ raise ConversionError, "Could not convert result into object: #{code}"
92
+ end
76
93
 
94
+ result ||= EMPTY_RESULT
77
95
  result = Result.new(
78
- RESULT_CODE[code],
79
- Converter.object_to_ruby(result_obj[:events]),
80
- result_obj[:total_runtime],
81
- result_obj[:timeout],
82
- Converter.object_to_ruby(result_obj[:actions]),
83
- Converter.object_to_ruby(result_obj[:derivatives])
96
+ status: RESULT_CODE_TO_STATUS[code],
97
+ events: result["events"],
98
+ actions: result["actions"],
99
+ attributes: result["attributes"],
100
+ duration: result["duration"],
101
+ timeout: result["timeout"],
102
+ keep: result["keep"]
84
103
  )
85
104
 
86
105
  if persistent_data_obj.truncated? || ephemeral_data_obj.truncated?
@@ -89,7 +108,7 @@ module Datadog
89
108
 
90
109
  result
91
110
  ensure
92
- LibDDWAF.ddwaf_result_free(result_obj) if result_obj
111
+ LibDDWAF.ddwaf_object_free(result_obj) if result_obj
93
112
  LibDDWAF.ddwaf_object_free(ephemeral_data_obj) if ephemeral_data_obj
94
113
  end
95
114
 
@@ -164,19 +164,19 @@ module Datadog
164
164
  when :ddwaf_obj_float
165
165
  obj[:valueUnion][:f64]
166
166
  when :ddwaf_obj_array
167
- (0...obj[:nbEntries]).each.with_object([]) do |i, a|
167
+ (0...obj[:nbEntries]).each.with_object([]) do |i, a| #$ ::Array[WAF::opaque]
168
168
  ptr = obj[:valueUnion][:array] + i * LibDDWAF::Object.size
169
169
  e = Converter.object_to_ruby(LibDDWAF::Object.new(ptr))
170
- a << e # steep:ignore
170
+ a << e
171
171
  end
172
172
  when :ddwaf_obj_map
173
- (0...obj[:nbEntries]).each.with_object({}) do |i, h|
173
+ (0...obj[:nbEntries]).each.with_object({}) do |i, h| #$ ::Hash[::String, WAF::opaque]
174
174
  ptr = obj[:valueUnion][:array] + i * Datadog::AppSec::WAF::LibDDWAF::Object.size
175
175
  o = Datadog::AppSec::WAF::LibDDWAF::Object.new(ptr)
176
176
  l = o[:parameterNameLength]
177
177
  k = o[:parameterName].read_bytes(l)
178
178
  v = Converter.object_to_ruby(LibDDWAF::Object.new(ptr))
179
- h[k] = v # steep:ignore
179
+ h[k] = v
180
180
  end
181
181
  end
182
182
  end
@@ -58,7 +58,7 @@ module Datadog
58
58
  def add_or_update_config(config, path:)
59
59
  ensure_pointer_presence!
60
60
 
61
- config_obj = Converter.ruby_to_object(config)
61
+ config_obj = Converter.ruby_to_object(config, coerce: false)
62
62
  diagnostics_obj = LibDDWAF::Object.new
63
63
 
64
64
  LibDDWAF.ddwaf_builder_add_or_update_config(@builder_ptr, path, path.length, config_obj, diagnostics_obj)
@@ -253,21 +253,9 @@ module Datadog
253
253
  attach_function :ddwaf_context_init, [:ddwaf_handle], :ddwaf_context
254
254
  attach_function :ddwaf_context_destroy, [:ddwaf_context], :void
255
255
 
256
- # Ruby representation of ddwaf_result
257
- # See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L154-L173
258
- class Result < ::FFI::Struct
259
- layout :timeout, :bool,
260
- :events, Object,
261
- :actions, Object,
262
- :derivatives, Object,
263
- :total_runtime, :uint64
264
- end
265
-
266
- typedef Result.by_ref, :ddwaf_result
267
256
  typedef :uint64, :timeout_us
268
257
 
269
- attach_function :ddwaf_run, [:ddwaf_context, :ddwaf_object, :ddwaf_object, :ddwaf_result, :timeout_us], :ddwaf_ret_code, blocking: true
270
- attach_function :ddwaf_result_free, [:ddwaf_result], :void
258
+ attach_function :ddwaf_run, [:ddwaf_context, :ddwaf_object, :ddwaf_object, :ddwaf_object, :timeout_us], :ddwaf_ret_code, blocking: true
271
259
 
272
260
  # logging
273
261
 
@@ -4,17 +4,19 @@ module Datadog
4
4
  module AppSec
5
5
  module WAF
6
6
  # Ruby representation of the ddwaf_result of a libddwaf run.
7
- # See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L159-L173
7
+ # See https://github.com/DataDog/libddwaf/blob/8dbee187ff74a0aa25e1bcbdde51677f77930e1b/include/ddwaf.h#L277-L290
8
8
  class Result
9
- attr_reader :status, :events, :total_runtime, :timeout, :actions, :derivatives
9
+ attr_reader :status, :events, :actions, :attributes, :duration
10
10
 
11
- def initialize(status, events, total_runtime, timeout, actions, derivatives)
11
+ def initialize(status:, events:, actions:, attributes:, duration:, timeout:, keep:)
12
12
  @status = status
13
13
  @events = events
14
- @total_runtime = total_runtime
15
- @timeout = timeout
16
14
  @actions = actions
17
- @derivatives = derivatives
15
+ @attributes = attributes
16
+ @duration = duration
17
+
18
+ @keep = !!keep
19
+ @timeout = !!timeout
18
20
  @input_truncated = false
19
21
  end
20
22
 
@@ -22,6 +24,14 @@ module Datadog
22
24
  @input_truncated = true
23
25
  end
24
26
 
27
+ def timeout?
28
+ @timeout
29
+ end
30
+
31
+ def keep?
32
+ @keep
33
+ end
34
+
25
35
  def input_truncated?
26
36
  @input_truncated
27
37
  end
@@ -30,10 +40,12 @@ module Datadog
30
40
  {
31
41
  status: @status,
32
42
  events: @events,
33
- total_runtime: @total_runtime,
34
- timeout: @timeout,
35
43
  actions: @actions,
36
- derivatives: @derivatives
44
+ attributes: @attributes,
45
+ duration: @duration,
46
+ keep: @keep,
47
+ timeout: @timeout,
48
+ input_truncated: @input_truncated
37
49
  }
38
50
  end
39
51
  end
@@ -2,10 +2,10 @@ module Datadog
2
2
  module AppSec
3
3
  module WAF
4
4
  module VERSION
5
- BASE_STRING = "1.24.1"
5
+ BASE_STRING = "1.25.1"
6
6
  # NOTE: Every change to the `BASE_STRING` should be accompanied
7
7
  # by a reset of the patch version in the `STRING` below.
8
- STRING = "#{BASE_STRING}.2.1"
8
+ STRING = "#{BASE_STRING}.1.0"
9
9
  MINIMUM_RUBY_VERSION = "2.5"
10
10
  end
11
11
  end
@@ -6,13 +6,24 @@ module Datadog
6
6
 
7
7
  @retained: Array[untyped]
8
8
 
9
- RESULT_CODE: ::Hash[::Symbol, ::Symbol]
9
+ EMPTY_RESULT: {
10
+ "events" => WAF::events,
11
+ "actions" => WAF::actions,
12
+ "attributes" => WAF::attributes,
13
+ "duration" => ::Integer,
14
+ "timeout" => bool,
15
+ "keep" => bool
16
+ }
17
+
18
+ SUCCESS_RESULT_CODES: ::Array[::Symbol]
19
+
20
+ RESULT_CODE_TO_STATUS: ::Hash[::Symbol, ::Symbol]
10
21
 
11
22
  def initialize: (::FFI::Pointer context_ptr) -> void
12
23
 
13
24
  def finalize!: () -> void
14
25
 
15
- def run: (WAF::data persistent_data, WAF::data ephemeral_data, ?::Integer timeout) -> Result
26
+ def run: (WAF::input persistent_data, WAF::input ephemeral_data, ?::Integer timeout) -> Result
16
27
 
17
28
  private
18
29
 
@@ -2,9 +2,16 @@ module Datadog
2
2
  module AppSec
3
3
  module WAF
4
4
  module Converter
5
- def self.ruby_to_object: (top val, ?max_container_size: ::Integer?, ?max_container_depth: ::Integer?, ?max_string_length: ::Integer?, ?top_obj: LibDDWAF::Object?, ?coerce: bool?) -> LibDDWAF::Object
5
+ def self?.ruby_to_object: (
6
+ top val,
7
+ ?max_container_size: ::Integer?,
8
+ ?max_container_depth: ::Integer?,
9
+ ?max_string_length: ::Integer?,
10
+ ?top_obj: LibDDWAF::Object?,
11
+ ?coerce: bool?
12
+ ) -> LibDDWAF::Object
6
13
 
7
- def self.object_to_ruby: (LibDDWAF::Object obj) -> WAF::data
14
+ def self?.object_to_ruby: (LibDDWAF::Object obj) -> WAF::opaque
8
15
  end
9
16
  end
10
17
  end
@@ -11,9 +11,9 @@ module Datadog
11
11
  end
12
12
 
13
13
  class LibDDWAFError < Error
14
- attr_reader diagnostics: WAF::data
14
+ attr_reader diagnostics: WAF::opaque
15
15
 
16
- def initialize: (::String msg, ?diagnostics: WAF::data?) -> void
16
+ def initialize: (::String msg, ?diagnostics: WAF::opaque?) -> void
17
17
  end
18
18
  end
19
19
  end
@@ -10,7 +10,7 @@ module Datadog
10
10
 
11
11
  def build_handle: () -> Handle
12
12
 
13
- def add_or_update_config: (data config, path: ::String) -> data
13
+ def add_or_update_config: (WAF::input config, path: ::String) -> WAF::opaque
14
14
 
15
15
  def remove_config_at_path: (::String path) -> bool
16
16
 
@@ -58,6 +58,8 @@ module Datadog
58
58
  end
59
59
 
60
60
  class Object < ::FFI::Struct[::FFI::AbstractMemory, untyped]
61
+ @truncated: bool
62
+
61
63
  def truncated?: () -> bool
62
64
 
63
65
  def mark_truncated!: () -> bool
@@ -139,11 +141,7 @@ module Datadog
139
141
  def self.ddwaf_context_init: (::FFI::Pointer) -> ::FFI::Pointer
140
142
  def self.ddwaf_context_destroy: (::FFI::Pointer) -> void
141
143
 
142
- class Result < ::FFI::Struct[::FFI::AbstractMemory, untyped]
143
- end
144
-
145
- def self.ddwaf_run: (::FFI::Pointer, Object, Object, Result, ::Integer) -> ::Symbol
146
- def self.ddwaf_result_free: (Result) -> void
144
+ def self.ddwaf_run: (::FFI::Pointer, Object, Object, Object, ::Integer) -> ::Symbol
147
145
 
148
146
  # logging
149
147
 
@@ -4,35 +4,49 @@ module Datadog
4
4
  class Result
5
5
  @status: ::Symbol
6
6
 
7
- @events: WAF::data
7
+ @events: WAF::events
8
8
 
9
- @total_runtime: ::Float
9
+ @actions: WAF::actions
10
10
 
11
- @timeout: bool
11
+ @attributes: WAF::attributes
12
+
13
+ @duration: ::Integer
12
14
 
13
- @actions: WAF::data
15
+ @timeout: bool
14
16
 
15
- @derivatives: WAF::data
17
+ @keep: bool
16
18
 
17
19
  @input_truncated: bool
18
20
 
19
21
  attr_reader status: ::Symbol
20
22
 
21
- attr_reader events: WAF::data
22
-
23
- attr_reader total_runtime: ::Float
23
+ attr_reader events: WAF::events
24
24
 
25
- attr_reader timeout: bool
25
+ attr_reader actions: WAF::actions
26
26
 
27
- attr_reader actions: WAF::data
27
+ attr_reader attributes: WAF::attributes
28
28
 
29
- attr_reader derivatives: WAF::data
29
+ attr_reader duration: ::Integer
30
30
 
31
- def initialize: (::Symbol status, WAF::data events, ::Float total_runtime, bool timeout, WAF::data actions, WAF::data derivatives) -> void
31
+ def initialize: (
32
+ status: ::Symbol,
33
+ events: WAF::events,
34
+ actions: WAF::actions,
35
+ attributes: WAF::attributes,
36
+ duration: ::Integer,
37
+ timeout: bool,
38
+ keep: bool
39
+ ) -> void
32
40
 
33
41
  def mark_input_truncated!: () -> bool
34
42
 
43
+ def timeout?: () -> bool
44
+
45
+ def keep?: () -> bool
46
+
35
47
  def input_truncated?: () -> bool
48
+
49
+ def to_h: () -> ::Hash[::Symbol, (::Symbol | WAF::opaque)]
36
50
  end
37
51
  end
38
52
  end
@@ -1,18 +1,58 @@
1
1
  module Datadog
2
2
  module AppSec
3
3
  module WAF
4
- type data = String | Symbol | Integer | Float | TrueClass | FalseClass | Array[data] | Hash[(String | Symbol | nil), data] | nil
4
+ type input = nil | bool | ::String | ::Symbol | ::Integer | ::Float | ::Array[input] | ::Hash[input, input]
5
5
  type known_addresses = ::Array[::String]
6
- type diagnostics = ::Hash[::String, untyped]
7
-
8
- def self.version: () -> ::String
6
+ type result = {
7
+ "keep" => bool,
8
+ "events" => events,
9
+ "actions" => actions,
10
+ "attributes" => attributes,
11
+ "timeout" => bool,
12
+ # NOTE: Schema defines it as a `number`, but we alway get it as `Integer`
13
+ # That will be fixed in the libddwaf specs
14
+ "duration" => ::Integer
15
+ }
16
+ type events = ::Array[event]
17
+ type event = {"rule" => rule, "rule_matches" => ::Array[rule_match]}
18
+ type rule = {
19
+ "id" => ::String,
20
+ "name" => ::String,
21
+ "tags" => {
22
+ "type" => ::String,
23
+ # optional key
24
+ "category" => ::String?
25
+ },
26
+ # optional key
27
+ "on_match" => ::Array[::String]?
28
+ }
29
+ type rule_match = {
30
+ "operator" => ::String,
31
+ "operator_value" => ::String,
32
+ "parameters" => ::Array[rule_match_parameter]
33
+ }
34
+ type rule_match_parameter = {
35
+ "address" => ::String,
36
+ "key_path" => ::Array[::String | ::Integer],
37
+ "value" => ::String,
38
+ "highlight" => ::Array[::String]
39
+ }
40
+ type actions = ::Hash[::String, action]
41
+ type action = ::Hash[::String, ::String]
42
+ type attributes = ::Hash[::String, opaque]
43
+ type opaque = nil | bool | ::String | ::Integer | ::Float | ::Array[opaque] | ::Hash[::String, opaque]
9
44
 
10
45
  self.@logger: ::Logger
46
+
11
47
  self.@log_callback: LibDDWAF::ddwaf_log_cb
12
48
 
13
- def self.log_callback: (LibDDWAF::ddwaf_log_level, ::String, ::String, ::Integer, ::FFI::Pointer, ::Integer) -> void
14
- def self.logger: () -> ::Logger
15
- def self.logger=: (::Logger logger) -> void
49
+ def self?.version: () -> ::String
50
+
51
+ def self?.log_callback: (LibDDWAF::ddwaf_log_level, ::String, ::String, ::Integer, ::FFI::Pointer, ::Integer) -> void
52
+
53
+ def self?.logger: () -> ::Logger
54
+
55
+ def self?.logger=: (::Logger logger) -> void
16
56
  end
17
57
  end
18
58
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libddwaf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.24.1.2.1
4
+ version: 1.25.1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Datadog, Inc.
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 2025-09-15 00:00:00.000000000 Z
11
+ date: 2025-09-24 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: ffi
@@ -60,10 +61,10 @@ files:
60
61
  - sig/datadog/appsec/waf/result.rbs
61
62
  - sig/datadog/appsec/waf/version.rbs
62
63
  - sig/libddwaf.rbs
63
- - vendor/libddwaf/libddwaf-1.24.1-darwin-arm64/lib/libddwaf.dylib
64
- - vendor/libddwaf/libddwaf-1.24.1-darwin-x86_64/lib/libddwaf.dylib
65
- - vendor/libddwaf/libddwaf-1.24.1-linux-aarch64/lib/libddwaf.so
66
- - vendor/libddwaf/libddwaf-1.24.1-linux-x86_64/lib/libddwaf.so
64
+ - vendor/libddwaf/libddwaf-1.25.1-darwin-arm64/lib/libddwaf.dylib
65
+ - vendor/libddwaf/libddwaf-1.25.1-darwin-x86_64/lib/libddwaf.dylib
66
+ - vendor/libddwaf/libddwaf-1.25.1-linux-aarch64/lib/libddwaf.so
67
+ - vendor/libddwaf/libddwaf-1.25.1-linux-x86_64/lib/libddwaf.so
67
68
  - vendor/rbs/gem/0/gem.rbs
68
69
  - vendor/rbs/jruby/0/jruby.rbs
69
70
  homepage: https://github.com/DataDog/libddwaf-rb
@@ -71,6 +72,7 @@ licenses:
71
72
  - BSD-3-Clause
72
73
  metadata:
73
74
  allowed_push_host: https://rubygems.org
75
+ post_install_message:
74
76
  rdoc_options: []
75
77
  require_paths:
76
78
  - lib
@@ -85,7 +87,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
87
  - !ruby/object:Gem::Version
86
88
  version: 2.0.0
87
89
  requirements: []
88
- rubygems_version: 3.6.2
90
+ rubygems_version: 3.5.21
91
+ signing_key:
89
92
  specification_version: 4
90
93
  summary: Datadog WAF
91
94
  test_files: []