libddwaf 1.22.0.0.2-x86_64-linux → 1.24.1.0.0-x86_64-linux
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 +4 -4
- data/CHANGELOG.md +21 -2
- data/lib/datadog/appsec/waf/context.rb +24 -38
- data/lib/datadog/appsec/waf/converter.rb +62 -69
- data/lib/datadog/appsec/waf/errors.rb +19 -0
- data/lib/datadog/appsec/waf/handle.rb +30 -77
- data/lib/datadog/appsec/waf/handle_builder.rb +91 -0
- data/lib/datadog/appsec/waf/lib_ddwaf.rb +94 -94
- data/lib/datadog/appsec/waf/version.rb +3 -3
- data/lib/datadog/appsec/waf.rb +9 -7
- data/lib/libddwaf.rb +1 -1
- data/vendor/libddwaf/libddwaf-1.24.1-linux-x86_64/lib/libddwaf.so +0 -0
- metadata +6 -7
- data/vendor/libddwaf/libddwaf-1.22.0-linux-x86_64/lib/libddwaf.so +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1973e8e5005a0c2a06f6fb1f479ccdb405fc935a73641dfe26f623cd0eae2f3
|
4
|
+
data.tar.gz: 0b9fc7a24984318b544ca933100d9169577b6c131cebf3db8ffd29141f90b285
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d78fef9052216d6be2e5ef65e6c683df7fbd50943014164744f2530acb28f852515f1c7079b5a9a139f8ee07788543fd15e2104f7f654d5fe34d0eebc4ed5846
|
7
|
+
data.tar.gz: c313fd77f70b3d250b5fe6d62eb3544b4c5c27d3bb5faa14446ad1c3497b34a02700f126b582988703280b0f907861b9021958557227a75ad9399b2d6f57d174
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
# Unreleased v1.23.0.0.0
|
2
|
+
|
3
|
+
## Added
|
4
|
+
|
5
|
+
- Add `HandleBuilder` class for managing libddwaf configuration and building WAF handles
|
6
|
+
- Add Error classes:
|
7
|
+
- `LibDDWAFError` for libddwaf errors
|
8
|
+
- `ConversionError` for conversion errors
|
9
|
+
- `InstanceFinalizedError` that is raised when attempting to run methods on finalized instances
|
10
|
+
|
11
|
+
## Changed
|
12
|
+
|
13
|
+
- Change `Handle` instantiation - now it should be done using `HandleBuilder#build_handle` method
|
14
|
+
- Change `Context` instantiation - now is should be done using `Handle#build_context` method
|
15
|
+
- Change configuration of Limits and obfuscation - it is now done when initializing `HandleBuilder`
|
16
|
+
- Change `Context#run` to return a `Result` object instead of an tuple with code and result
|
17
|
+
|
18
|
+
## Removed
|
19
|
+
|
20
|
+
- Remove `WAF::Handle#merge` method - the configuration is now handled by `HandleBuilder`
|
21
|
+
|
1
22
|
# 2025-02-20 v.1.18.0.0.1
|
2
23
|
|
3
24
|
- Fixed memory-leak in `Datadog::AppSec::WAF::Context#run` when non-empty ephemeral data passed
|
@@ -12,7 +33,6 @@
|
|
12
33
|
- Update to libddwaf 1.14.0
|
13
34
|
- Add support for `Float` and `Nil` scalar values when converting from ruby to WAF Object and vice versa.
|
14
35
|
|
15
|
-
|
16
36
|
# 2023-08-29 v.1.11.0.0.0
|
17
37
|
|
18
38
|
- Update to libddwaf 1.11.0
|
@@ -21,7 +41,6 @@
|
|
21
41
|
- Changed `Datadog::AppSec::WAF::Result#data` to `Datadog::AppSec::WAF::Result#events`. (Breaking change)
|
22
42
|
The schema of the events variable can be found [here](https://github.com/DataDog/libddwaf/blob/master/schema/events.json)
|
23
43
|
|
24
|
-
|
25
44
|
# 2023-08-28 v.1.10.0.0.0
|
26
45
|
|
27
46
|
- Update to libddwaf 1.10.0
|
@@ -14,20 +14,16 @@ module Datadog
|
|
14
14
|
ddwaf_err_invalid_argument: :err_invalid_argument
|
15
15
|
}.freeze
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
def initialize(handle)
|
20
|
-
handle_obj = handle.handle_obj
|
21
|
-
retain(handle)
|
22
|
-
|
23
|
-
@context_obj = LibDDWAF.ddwaf_context_init(handle_obj)
|
24
|
-
raise LibDDWAF::Error, 'Could not create context' if @context_obj.null?
|
25
|
-
|
26
|
-
validate!
|
17
|
+
def initialize(context_ptr)
|
18
|
+
@context_ptr = context_ptr
|
27
19
|
end
|
28
20
|
|
29
|
-
|
30
|
-
|
21
|
+
# Destroys the WAF context and sets the pointer to nil.
|
22
|
+
#
|
23
|
+
# The instance becomes unusable after this method is called.
|
24
|
+
def finalize!
|
25
|
+
context_ptr_to_destroy = @context_ptr
|
26
|
+
@context_ptr = nil
|
31
27
|
|
32
28
|
retained.each do |retained_obj|
|
33
29
|
next unless retained_obj.is_a?(LibDDWAF::Object)
|
@@ -36,11 +32,17 @@ module Datadog
|
|
36
32
|
end
|
37
33
|
|
38
34
|
retained.clear
|
39
|
-
LibDDWAF.ddwaf_context_destroy(
|
35
|
+
LibDDWAF.ddwaf_context_destroy(context_ptr_to_destroy)
|
40
36
|
end
|
41
37
|
|
38
|
+
# Runs the WAF context with the given persistent and ephemeral data.
|
39
|
+
#
|
40
|
+
# @raise [ConversionError] if the conversion of persistent or ephemeral data fails
|
41
|
+
# @raise [LibDDWAFError] if libddwaf could not create the result object
|
42
|
+
#
|
43
|
+
# @return [Result] the result of the WAF run
|
42
44
|
def run(persistent_data, ephemeral_data, timeout = LibDDWAF::DDWAF_RUN_TIMEOUT)
|
43
|
-
|
45
|
+
ensure_pointer_presence!
|
44
46
|
|
45
47
|
persistent_data_obj = Converter.ruby_to_object(
|
46
48
|
persistent_data,
|
@@ -50,7 +52,7 @@ module Datadog
|
|
50
52
|
coerce: false
|
51
53
|
)
|
52
54
|
if persistent_data_obj.null?
|
53
|
-
raise
|
55
|
+
raise ConversionError, "Could not convert persistent data: #{persistent_data.inspect}"
|
54
56
|
end
|
55
57
|
|
56
58
|
# retain C objects in memory for subsequent calls to run
|
@@ -64,15 +66,15 @@ module Datadog
|
|
64
66
|
coerce: false
|
65
67
|
)
|
66
68
|
if ephemeral_data_obj.null?
|
67
|
-
raise
|
69
|
+
raise ConversionError, "Could not convert ephemeral data: #{ephemeral_data.inspect}"
|
68
70
|
end
|
69
71
|
|
70
72
|
result_obj = LibDDWAF::Result.new
|
71
|
-
raise
|
73
|
+
raise LibDDWAFError, "Could not create result object" if result_obj.null?
|
72
74
|
|
73
|
-
code = LibDDWAF.ddwaf_run(@
|
75
|
+
code = LibDDWAF.ddwaf_run(@context_ptr, persistent_data_obj, ephemeral_data_obj, result_obj, timeout)
|
74
76
|
|
75
|
-
|
77
|
+
Result.new(
|
76
78
|
RESULT_CODE[code],
|
77
79
|
Converter.object_to_ruby(result_obj[:events]),
|
78
80
|
result_obj[:total_runtime],
|
@@ -80,8 +82,6 @@ module Datadog
|
|
80
82
|
Converter.object_to_ruby(result_obj[:actions]),
|
81
83
|
Converter.object_to_ruby(result_obj[:derivatives])
|
82
84
|
)
|
83
|
-
|
84
|
-
[RESULT_CODE[code], result]
|
85
85
|
ensure
|
86
86
|
LibDDWAF.ddwaf_result_free(result_obj) if result_obj
|
87
87
|
LibDDWAF.ddwaf_object_free(ephemeral_data_obj) if ephemeral_data_obj
|
@@ -89,24 +89,10 @@ module Datadog
|
|
89
89
|
|
90
90
|
private
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
def validate!
|
95
|
-
@valid = true
|
96
|
-
end
|
97
|
-
|
98
|
-
def invalidate!
|
99
|
-
@valid = false
|
100
|
-
end
|
101
|
-
|
102
|
-
def valid?
|
103
|
-
@valid
|
104
|
-
end
|
105
|
-
|
106
|
-
def valid!
|
107
|
-
return if valid?
|
92
|
+
def ensure_pointer_presence!
|
93
|
+
return if @context_ptr
|
108
94
|
|
109
|
-
raise
|
95
|
+
raise InstanceFinalizedError, "Cannot use WAF context after it has been finalized"
|
110
96
|
end
|
111
97
|
|
112
98
|
def retained
|
@@ -7,66 +7,67 @@ module Datadog
|
|
7
7
|
module Converter
|
8
8
|
module_function
|
9
9
|
|
10
|
-
#
|
10
|
+
# standard:disable Metrics/MethodLength,Metrics/CyclomaticComplexity
|
11
11
|
def ruby_to_object(val, max_container_size: nil, max_container_depth: nil, max_string_length: nil, coerce: true)
|
12
12
|
case val
|
13
13
|
when Array
|
14
14
|
obj = LibDDWAF::Object.new
|
15
15
|
res = LibDDWAF.ddwaf_object_array(obj)
|
16
|
-
if res.null?
|
17
|
-
raise LibDDWAF::Error, "Could not convert into object: #{val}"
|
18
|
-
end
|
16
|
+
raise ConversionError, "Could not convert into object: #{val}" if res.null?
|
19
17
|
|
20
18
|
max_index = max_container_size - 1 if max_container_size
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
19
|
+
unless max_container_depth == 0
|
20
|
+
val.each.with_index do |e, i|
|
21
|
+
member = Converter.ruby_to_object(
|
22
|
+
e,
|
23
|
+
max_container_size: max_container_size,
|
24
|
+
max_container_depth: (max_container_depth - 1 if max_container_depth),
|
25
|
+
max_string_length: max_string_length,
|
26
|
+
coerce: coerce
|
27
|
+
)
|
28
|
+
e_res = LibDDWAF.ddwaf_object_array_add(obj, member)
|
29
|
+
raise ConversionError, "Could not add to array object: #{e.inspect}" unless e_res
|
30
|
+
|
31
|
+
break val if max_index && i >= max_index
|
32
|
+
end
|
33
|
+
end
|
32
34
|
|
33
35
|
obj
|
34
36
|
when Hash
|
35
37
|
obj = LibDDWAF::Object.new
|
36
38
|
res = LibDDWAF.ddwaf_object_map(obj)
|
37
|
-
if res.null?
|
38
|
-
raise LibDDWAF::Error, "Could not convert into object: #{val}"
|
39
|
-
end
|
39
|
+
raise ConversionError, "Could not convert into object: #{val}" if res.null?
|
40
40
|
|
41
41
|
max_index = max_container_size - 1 if max_container_size
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
42
|
+
unless max_container_depth == 0
|
43
|
+
val.each.with_index do |e, i|
|
44
|
+
# for Steep, which doesn't handle |(k, v), i|
|
45
|
+
k = e[0]
|
46
|
+
v = e[1]
|
47
|
+
|
48
|
+
k = k.to_s[0, max_string_length] if max_string_length
|
49
|
+
member = Converter.ruby_to_object(
|
50
|
+
v,
|
51
|
+
max_container_size: max_container_size,
|
52
|
+
max_container_depth: (max_container_depth - 1 if max_container_depth),
|
53
|
+
max_string_length: max_string_length,
|
54
|
+
coerce: coerce
|
55
|
+
)
|
56
|
+
kv_res = LibDDWAF.ddwaf_object_map_addl(obj, k.to_s, k.to_s.bytesize, member)
|
57
|
+
raise ConversionError, "Could not add to map object: #{k.inspect} => #{v.inspect}" unless kv_res
|
58
|
+
|
59
|
+
break val if max_index && i >= max_index
|
55
60
|
end
|
56
|
-
|
57
|
-
break val if max_index && i >= max_index
|
58
|
-
end unless max_container_depth == 0
|
61
|
+
end
|
59
62
|
|
60
63
|
obj
|
61
64
|
when String
|
62
65
|
obj = LibDDWAF::Object.new
|
63
|
-
encoded_val = val.to_s.encode(
|
66
|
+
encoded_val = val.to_s.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
|
64
67
|
val = encoded_val[0, max_string_length] if max_string_length
|
65
68
|
str = val.to_s
|
66
69
|
res = LibDDWAF.ddwaf_object_stringl(obj, str, str.bytesize)
|
67
|
-
if res.null?
|
68
|
-
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
69
|
-
end
|
70
|
+
raise ConversionError, "Could not convert into object: #{val.inspect}" if res.null?
|
70
71
|
|
71
72
|
obj
|
72
73
|
when Symbol
|
@@ -74,67 +75,58 @@ module Datadog
|
|
74
75
|
val = val.to_s[0, max_string_length] if max_string_length
|
75
76
|
str = val.to_s
|
76
77
|
res = LibDDWAF.ddwaf_object_stringl(obj, str, str.bytesize)
|
77
|
-
if res.null?
|
78
|
-
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
79
|
-
end
|
78
|
+
raise ConversionError, "Could not convert into object: #{val.inspect}" if res.null?
|
80
79
|
|
81
80
|
obj
|
82
81
|
when Integer
|
83
82
|
obj = LibDDWAF::Object.new
|
84
83
|
res = if coerce
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
91
|
-
if res.null?
|
92
|
-
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
84
|
+
LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
85
|
+
elsif val < 0
|
86
|
+
LibDDWAF.ddwaf_object_signed(obj, val)
|
87
|
+
else
|
88
|
+
LibDDWAF.ddwaf_object_unsigned(obj, val)
|
93
89
|
end
|
90
|
+
raise ConversionError, "Could not convert into object: #{val.inspect}" if res.null?
|
94
91
|
|
95
92
|
obj
|
96
93
|
when Float
|
97
94
|
obj = LibDDWAF::Object.new
|
98
95
|
res = if coerce
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
103
|
-
if res.null?
|
104
|
-
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
96
|
+
LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
97
|
+
else
|
98
|
+
LibDDWAF.ddwaf_object_float(obj, val)
|
105
99
|
end
|
100
|
+
raise ConversionError, "Could not convert into object: #{val.inspect}" if res.null?
|
106
101
|
|
107
102
|
obj
|
108
103
|
when TrueClass, FalseClass
|
109
104
|
obj = LibDDWAF::Object.new
|
110
105
|
res = if coerce
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
end
|
115
|
-
if res.null?
|
116
|
-
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
106
|
+
LibDDWAF.ddwaf_object_string(obj, val.to_s)
|
107
|
+
else
|
108
|
+
LibDDWAF.ddwaf_object_bool(obj, val)
|
117
109
|
end
|
110
|
+
raise ConversionError, "Could not convert into object: #{val.inspect}" if res.null?
|
118
111
|
|
119
112
|
obj
|
120
113
|
when NilClass
|
121
114
|
obj = LibDDWAF::Object.new
|
122
115
|
res = if coerce
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
127
|
-
if res.null?
|
128
|
-
raise LibDDWAF::Error, "Could not convert into object: #{val.inspect}"
|
116
|
+
LibDDWAF.ddwaf_object_string(obj, "")
|
117
|
+
else
|
118
|
+
LibDDWAF.ddwaf_object_null(obj)
|
129
119
|
end
|
120
|
+
raise ConversionError, "Could not convert into object: #{val.inspect}" if res.null?
|
130
121
|
|
131
122
|
obj
|
132
123
|
else
|
133
|
-
Converter.ruby_to_object(
|
124
|
+
Converter.ruby_to_object("")
|
134
125
|
end
|
135
126
|
end
|
136
|
-
#
|
127
|
+
# standard:enable Metrics/MethodLength,Metrics/CyclomaticComplexity
|
137
128
|
|
129
|
+
# standard:disable Metrics/MethodLength,Metrics/CyclomaticComplexity
|
138
130
|
def object_to_ruby(obj)
|
139
131
|
case obj[:type]
|
140
132
|
when :ddwaf_obj_invalid, :ddwaf_obj_null
|
@@ -170,6 +162,7 @@ module Datadog
|
|
170
162
|
end
|
171
163
|
end
|
172
164
|
end
|
165
|
+
# standard:enable Metrics/MethodLength,Metrics/CyclomaticComplexity
|
173
166
|
end
|
174
167
|
end
|
175
168
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Datadog
|
2
|
+
module AppSec
|
3
|
+
module WAF
|
4
|
+
Error = Class.new(StandardError)
|
5
|
+
InstanceFinalizedError = Class.new(Error)
|
6
|
+
ConversionError = Class.new(Error)
|
7
|
+
|
8
|
+
class LibDDWAFError < Error
|
9
|
+
attr_reader :diagnostics
|
10
|
+
|
11
|
+
def initialize(msg, diagnostics: nil)
|
12
|
+
@diagnostics = diagnostics
|
13
|
+
|
14
|
+
super(msg)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -6,101 +6,54 @@ module Datadog
|
|
6
6
|
# Ruby representation of the ddwaf_handle in libddwaf
|
7
7
|
# See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/BINDING_IMPL_NOTES.md?plain=1#L4-L19
|
8
8
|
class Handle
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
rule_obj = Converter.ruby_to_object(rule)
|
13
|
-
if rule_obj.null? || rule_obj[:type] == :ddwaf_object_invalid
|
14
|
-
raise LibDDWAF::Error, "Could not convert object #{rule.inspect}"
|
15
|
-
end
|
16
|
-
|
17
|
-
config_obj = Datadog::AppSec::WAF::LibDDWAF::Config.new
|
18
|
-
if config_obj.null?
|
19
|
-
raise LibDDWAF::Error, 'Could not create config struct'
|
20
|
-
end
|
21
|
-
|
22
|
-
config_obj[:limits][:max_container_size] = limits[:max_container_size] || LibDDWAF::DEFAULT_MAX_CONTAINER_SIZE
|
23
|
-
config_obj[:limits][:max_container_depth] = limits[:max_container_depth] || LibDDWAF::DEFAULT_MAX_CONTAINER_DEPTH
|
24
|
-
config_obj[:limits][:max_string_length] = limits[:max_string_length] || LibDDWAF::DEFAULT_MAX_STRING_LENGTH
|
25
|
-
config_obj[:obfuscator][:key_regex] = FFI::MemoryPointer.from_string(obfuscator[:key_regex]) if obfuscator[:key_regex]
|
26
|
-
config_obj[:obfuscator][:value_regex] = FFI::MemoryPointer.from_string(obfuscator[:value_regex]) if obfuscator[:value_regex]
|
27
|
-
config_obj[:free_fn] = LibDDWAF::ObjectNoFree
|
28
|
-
|
29
|
-
@config = config_obj
|
30
|
-
|
31
|
-
diagnostics_obj = LibDDWAF::Object.new
|
32
|
-
|
33
|
-
@handle_obj = LibDDWAF.ddwaf_init(rule_obj, config_obj, diagnostics_obj)
|
34
|
-
|
35
|
-
@diagnostics = Converter.object_to_ruby(diagnostics_obj)
|
9
|
+
def initialize(handle_ptr)
|
10
|
+
@handle_ptr = handle_ptr
|
11
|
+
end
|
36
12
|
|
37
|
-
|
38
|
-
|
39
|
-
|
13
|
+
# Destroys the WAF handle and sets the pointer to nil.
|
14
|
+
#
|
15
|
+
# The instance becomes unusable after this method is called.
|
16
|
+
def finalize!
|
17
|
+
handle_ptr_to_destroy = @handle_ptr
|
18
|
+
@handle_ptr = nil
|
40
19
|
|
41
|
-
|
42
|
-
ensure
|
43
|
-
LibDDWAF.ddwaf_object_free(diagnostics_obj) if diagnostics_obj
|
44
|
-
LibDDWAF.ddwaf_object_free(rule_obj) if rule_obj
|
20
|
+
LibDDWAF.ddwaf_destroy(handle_ptr_to_destroy)
|
45
21
|
end
|
46
22
|
|
47
|
-
|
48
|
-
|
23
|
+
# Builds a WAF context.
|
24
|
+
#
|
25
|
+
# @raise [LibDDWAFError] if libddwaf could not create the context.
|
26
|
+
# @return [Handle] the WAF handle
|
27
|
+
def build_context
|
28
|
+
ensure_pointer_presence!
|
29
|
+
|
30
|
+
context_obj = LibDDWAF.ddwaf_context_init(@handle_ptr)
|
31
|
+
raise LibDDWAFError, "Could not create context" if context_obj.null?
|
49
32
|
|
50
|
-
|
33
|
+
Context.new(context_obj)
|
51
34
|
end
|
52
35
|
|
53
|
-
|
54
|
-
|
36
|
+
# Returns the list of known addresses in the WAF handle.
|
37
|
+
#
|
38
|
+
# @return [Array<String>] the list of known addresses
|
39
|
+
def known_addresses
|
40
|
+
ensure_pointer_presence!
|
55
41
|
|
56
42
|
count = LibDDWAF::UInt32Ptr.new
|
57
|
-
list = LibDDWAF.ddwaf_known_addresses(
|
43
|
+
list = LibDDWAF.ddwaf_known_addresses(@handle_ptr, count)
|
58
44
|
|
59
45
|
return [] if count == 0 # list is null
|
60
46
|
|
61
47
|
list.get_array_of_string(0, count[:value])
|
62
|
-
|
63
|
-
|
64
|
-
def merge(data)
|
65
|
-
data_obj = Converter.ruby_to_object(data, coerce: false)
|
66
|
-
diagnostics_obj = LibDDWAF::Object.new
|
67
|
-
new_handle = LibDDWAF.ddwaf_update(handle_obj, data_obj, diagnostics_obj)
|
68
|
-
|
69
|
-
return if new_handle.null?
|
70
|
-
|
71
|
-
diagnostics = Converter.object_to_ruby(diagnostics_obj)
|
72
|
-
new_from_handle(new_handle, diagnostics, config)
|
73
|
-
ensure
|
74
|
-
LibDDWAF.ddwaf_object_free(data_obj) if data_obj
|
75
|
-
LibDDWAF.ddwaf_object_free(diagnostics_obj) if diagnostics_obj
|
48
|
+
# TODO: garbage collect the count?
|
76
49
|
end
|
77
50
|
|
78
51
|
private
|
79
52
|
|
80
|
-
def
|
81
|
-
|
82
|
-
obj.instance_variable_set(:@handle_obj, handle_object)
|
83
|
-
obj.instance_variable_set(:@diagnostics, diagnostics)
|
84
|
-
obj.instance_variable_set(:@config, config)
|
85
|
-
obj
|
86
|
-
end
|
87
|
-
|
88
|
-
def validate!
|
89
|
-
@valid = true
|
90
|
-
end
|
91
|
-
|
92
|
-
def invalidate!
|
93
|
-
@valid = false
|
94
|
-
end
|
95
|
-
|
96
|
-
def valid?
|
97
|
-
@valid
|
98
|
-
end
|
99
|
-
|
100
|
-
def valid!
|
101
|
-
return if valid?
|
53
|
+
def ensure_pointer_presence!
|
54
|
+
return if @handle_ptr
|
102
55
|
|
103
|
-
raise
|
56
|
+
raise InstanceFinalizedError, "Cannot use WAF handle after it has been finalized"
|
104
57
|
end
|
105
58
|
end
|
106
59
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module AppSec
|
5
|
+
module WAF
|
6
|
+
# This class represents the libddwaf WAF builder, which is used to generate WAF handles.
|
7
|
+
#
|
8
|
+
# It handles merging of potentially overlapping configurations.
|
9
|
+
class HandleBuilder
|
10
|
+
def initialize(limits: {}, obfuscator: {})
|
11
|
+
handle_config_obj = LibDDWAF::HandleBuilderConfig.new
|
12
|
+
if handle_config_obj.null?
|
13
|
+
raise LibDDWAFError, "Could not create config struct"
|
14
|
+
end
|
15
|
+
|
16
|
+
handle_config_obj[:limits][:max_container_size] = limits[:max_container_size] || LibDDWAF::DEFAULT_MAX_CONTAINER_SIZE
|
17
|
+
handle_config_obj[:limits][:max_container_depth] = limits[:max_container_depth] || LibDDWAF::DEFAULT_MAX_CONTAINER_DEPTH
|
18
|
+
handle_config_obj[:limits][:max_string_length] = limits[:max_string_length] || LibDDWAF::DEFAULT_MAX_STRING_LENGTH
|
19
|
+
|
20
|
+
handle_config_obj[:obfuscator][:key_regex] = FFI::MemoryPointer.from_string(obfuscator[:key_regex]) if obfuscator[:key_regex]
|
21
|
+
handle_config_obj[:obfuscator][:value_regex] = FFI::MemoryPointer.from_string(obfuscator[:value_regex]) if obfuscator[:value_regex]
|
22
|
+
handle_config_obj[:free_fn] = LibDDWAF::ObjectNoFree
|
23
|
+
|
24
|
+
@builder_ptr = LibDDWAF.ddwaf_builder_init(handle_config_obj)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Destroys the WAF builder and sets the pointer to nil.
|
28
|
+
#
|
29
|
+
# The instance becomes unusable after this method is called.
|
30
|
+
def finalize!
|
31
|
+
builder_ptr_to_destroy = @builder_ptr
|
32
|
+
@builder_ptr = nil
|
33
|
+
|
34
|
+
LibDDWAF.ddwaf_builder_destroy(builder_ptr_to_destroy)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Builds a WAF handle from the current state of the builder.
|
38
|
+
#
|
39
|
+
# @raise [LibDDWAFError] if no rules were added to the builder before building the handle
|
40
|
+
# @return [Handle] the WAF handle
|
41
|
+
def build_handle
|
42
|
+
ensure_pointer_presence!
|
43
|
+
|
44
|
+
handle_obj = LibDDWAF.ddwaf_builder_build_instance(@builder_ptr)
|
45
|
+
raise LibDDWAFError, "Could not create handle" if handle_obj.null?
|
46
|
+
|
47
|
+
Handle.new(handle_obj)
|
48
|
+
end
|
49
|
+
|
50
|
+
# :section: Configuration management methods
|
51
|
+
# methods for adding, updating, and removing configurations from the WAF handle builder.
|
52
|
+
|
53
|
+
# Adds or updates a configuration in the WAF handle builder for the given path.
|
54
|
+
#
|
55
|
+
# @return [Hash] diagnostics object
|
56
|
+
# NOTE: default config that was read from file at application startup
|
57
|
+
# has to be removed before adding configurations obtained through Remote Configuration.
|
58
|
+
def add_or_update_config(config, path:)
|
59
|
+
ensure_pointer_presence!
|
60
|
+
|
61
|
+
config_obj = Converter.ruby_to_object(config)
|
62
|
+
diagnostics_obj = LibDDWAF::Object.new
|
63
|
+
|
64
|
+
LibDDWAF.ddwaf_builder_add_or_update_config(@builder_ptr, path, path.length, config_obj, diagnostics_obj)
|
65
|
+
|
66
|
+
Converter.object_to_ruby(diagnostics_obj)
|
67
|
+
ensure
|
68
|
+
LibDDWAF.ddwaf_object_free(config_obj) if config_obj
|
69
|
+
LibDDWAF.ddwaf_object_free(diagnostics_obj) if diagnostics_obj
|
70
|
+
end
|
71
|
+
|
72
|
+
# Removes a configuration from the WAF handle builder for the given path.
|
73
|
+
#
|
74
|
+
# @return [Boolean] true if the configuration was removed, false otherwise
|
75
|
+
def remove_config_at_path(path)
|
76
|
+
ensure_pointer_presence!
|
77
|
+
|
78
|
+
LibDDWAF.ddwaf_builder_remove_config(@builder_ptr, path, path.length)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def ensure_pointer_presence!
|
84
|
+
return if @builder_ptr
|
85
|
+
|
86
|
+
raise InstanceFinalizedError, "Cannot use WAF handle builder after it has been finalized"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "ffi"
|
4
|
+
require "datadog/appsec/waf/version"
|
5
5
|
|
6
6
|
module Datadog
|
7
7
|
module AppSec
|
@@ -9,28 +9,27 @@ module Datadog
|
|
9
9
|
# FFI-binding for C-libddwaf
|
10
10
|
# See https://github.com/DataDog/libddwaf
|
11
11
|
module LibDDWAF
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
DEFAULT_MAX_CONTAINER_SIZE = 256
|
13
|
+
DEFAULT_MAX_CONTAINER_DEPTH = 20
|
14
|
+
DEFAULT_MAX_STRING_LENGTH = 16_384 # in bytes, UTF-8 worst case being 4x size in terms of code point
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
DDWAF_MAX_CONTAINER_SIZE = 256
|
17
|
+
DDWAF_MAX_CONTAINER_DEPTH = 20
|
18
|
+
DDWAF_MAX_STRING_LENGTH = 4096
|
18
19
|
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
20
|
+
DDWAF_RUN_TIMEOUT = 5000
|
22
21
|
|
23
22
|
extend ::FFI::Library
|
24
23
|
|
25
24
|
def self.local_os
|
26
|
-
if RUBY_ENGINE ==
|
27
|
-
os_name = java.lang.System.get_property(
|
25
|
+
if RUBY_ENGINE == "jruby"
|
26
|
+
os_name = java.lang.System.get_property("os.name")
|
28
27
|
|
29
28
|
os = case os_name
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
when /linux/i then "linux"
|
30
|
+
when /mac/i then "darwin"
|
31
|
+
else raise Error, "unsupported JRuby os.name: #{os_name.inspect}"
|
32
|
+
end
|
34
33
|
|
35
34
|
return os
|
36
35
|
end
|
@@ -39,23 +38,23 @@ module Datadog
|
|
39
38
|
end
|
40
39
|
|
41
40
|
def self.local_version
|
42
|
-
return nil unless local_os ==
|
41
|
+
return nil unless local_os == "linux"
|
43
42
|
|
44
43
|
# Old rubygems don't handle non-gnu linux correctly
|
45
44
|
return ::Regexp.last_match(1) if RUBY_PLATFORM =~ /linux-(.+)$/
|
46
45
|
|
47
|
-
|
46
|
+
"gnu"
|
48
47
|
end
|
49
48
|
|
50
49
|
def self.local_cpu
|
51
|
-
if RUBY_ENGINE ==
|
52
|
-
os_arch = java.lang.System.get_property(
|
50
|
+
if RUBY_ENGINE == "jruby"
|
51
|
+
os_arch = java.lang.System.get_property("os.arch")
|
53
52
|
|
54
53
|
cpu = case os_arch
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
54
|
+
when "amd64" then "x86_64"
|
55
|
+
when "aarch64" then (local_os == "darwin") ? "arm64" : "aarch64"
|
56
|
+
else raise Error, "unsupported JRuby os.arch: #{os_arch.inspect}"
|
57
|
+
end
|
59
58
|
|
60
59
|
return cpu
|
61
60
|
end
|
@@ -64,15 +63,15 @@ module Datadog
|
|
64
63
|
end
|
65
64
|
|
66
65
|
def self.source_dir
|
67
|
-
__dir__ || raise(
|
66
|
+
__dir__ || raise("__dir__ is nil: eval?")
|
68
67
|
end
|
69
68
|
|
70
69
|
def self.vendor_dir
|
71
|
-
File.join(source_dir,
|
70
|
+
File.join(source_dir, "../../../../vendor")
|
72
71
|
end
|
73
72
|
|
74
73
|
def self.libddwaf_vendor_dir
|
75
|
-
File.join(vendor_dir,
|
74
|
+
File.join(vendor_dir, "libddwaf")
|
76
75
|
end
|
77
76
|
|
78
77
|
def self.shared_lib_triplet(version: local_version)
|
@@ -81,31 +80,31 @@ module Datadog
|
|
81
80
|
|
82
81
|
def self.libddwaf_dir
|
83
82
|
default = File.join(libddwaf_vendor_dir,
|
84
|
-
|
83
|
+
"libddwaf-#{Datadog::AppSec::WAF::VERSION::BASE_STRING}-#{shared_lib_triplet}")
|
85
84
|
candidates = [
|
86
85
|
default
|
87
86
|
]
|
88
87
|
|
89
|
-
if local_os ==
|
88
|
+
if local_os == "linux"
|
90
89
|
candidates << File.join(libddwaf_vendor_dir,
|
91
|
-
|
90
|
+
"libddwaf-#{Datadog::AppSec::WAF::VERSION::BASE_STRING}-#{shared_lib_triplet(version: nil)}")
|
92
91
|
end
|
93
92
|
|
94
93
|
candidates.find { |d| Dir.exist?(d) } || default
|
95
94
|
end
|
96
95
|
|
97
96
|
def self.shared_lib_extname
|
98
|
-
if Gem::Platform.local.os ==
|
99
|
-
|
100
|
-
elsif Gem::Platform.local.os ==
|
101
|
-
|
97
|
+
if Gem::Platform.local.os == "darwin"
|
98
|
+
".dylib"
|
99
|
+
elsif Gem::Platform.local.os == "java" && java.lang.System.get_property("os.name").match(/mac/i)
|
100
|
+
".dylib"
|
102
101
|
else
|
103
|
-
|
102
|
+
".so"
|
104
103
|
end
|
105
104
|
end
|
106
105
|
|
107
106
|
def self.shared_lib_path
|
108
|
-
File.join(libddwaf_dir,
|
107
|
+
File.join(libddwaf_dir, "lib", "libddwaf#{shared_lib_extname}")
|
109
108
|
end
|
110
109
|
|
111
110
|
ffi_lib [shared_lib_path]
|
@@ -116,15 +115,15 @@ module Datadog
|
|
116
115
|
|
117
116
|
# ddwaf::object data structure
|
118
117
|
|
119
|
-
DDWAF_OBJ_TYPE = enum :ddwaf_obj_invalid,
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
118
|
+
DDWAF_OBJ_TYPE = enum :ddwaf_obj_invalid, 0,
|
119
|
+
:ddwaf_obj_signed, 1 << 0,
|
120
|
+
:ddwaf_obj_unsigned, 1 << 1,
|
121
|
+
:ddwaf_obj_string, 1 << 2,
|
122
|
+
:ddwaf_obj_array, 1 << 3,
|
123
|
+
:ddwaf_obj_map, 1 << 4,
|
124
|
+
:ddwaf_obj_bool, 1 << 5,
|
125
|
+
:ddwaf_obj_float, 1 << 6,
|
126
|
+
:ddwaf_obj_null, 1 << 7
|
128
127
|
|
129
128
|
typedef DDWAF_OBJ_TYPE, :ddwaf_obj_type
|
130
129
|
|
@@ -155,21 +154,21 @@ module Datadog
|
|
155
154
|
# Ruby representation of C union
|
156
155
|
class ObjectValueUnion < ::FFI::Union
|
157
156
|
layout :stringValue, :charptr,
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
157
|
+
:uintValue, :uint64,
|
158
|
+
:intValue, :int64,
|
159
|
+
:array, :pointer,
|
160
|
+
:boolean, :bool,
|
161
|
+
:f64, :double
|
163
162
|
end
|
164
163
|
|
165
164
|
# Ruby representation of ddwaf_object
|
166
165
|
# See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L94C1-L115C3
|
167
166
|
class Object < ::FFI::Struct
|
168
|
-
layout :parameterName,
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
167
|
+
layout :parameterName, :charptr,
|
168
|
+
:parameterNameLength, :uint64,
|
169
|
+
:valueUnion, ObjectValueUnion,
|
170
|
+
:nbEntries, :uint64,
|
171
|
+
:type, :ddwaf_obj_type
|
173
172
|
end
|
174
173
|
|
175
174
|
typedef Object.by_ref, :ddwaf_object
|
@@ -214,51 +213,62 @@ module Datadog
|
|
214
213
|
ObjectFree = attach_function :ddwaf_object_free, [:ddwaf_object], :void
|
215
214
|
ObjectNoFree = ::FFI::Pointer::NULL
|
216
215
|
|
217
|
-
#
|
216
|
+
# handle builder
|
218
217
|
|
218
|
+
typedef :pointer, :ddwaf_builder
|
219
219
|
typedef :pointer, :ddwaf_handle
|
220
|
-
typedef
|
220
|
+
typedef :pointer, :ddwaf_diagnostics
|
221
221
|
|
222
222
|
callback :ddwaf_object_free_fn, [:ddwaf_object], :void
|
223
223
|
|
224
224
|
# Ruby representation of ddwaf_config
|
225
225
|
# https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L129-L152
|
226
|
-
class
|
226
|
+
class HandleBuilderConfig < ::FFI::Struct
|
227
227
|
# Ruby representation of ddwaf_config_limits
|
228
228
|
# https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L131-L138
|
229
229
|
class Limits < ::FFI::Struct
|
230
|
-
layout :max_container_size,
|
231
|
-
|
232
|
-
|
230
|
+
layout :max_container_size, :uint32,
|
231
|
+
:max_container_depth, :uint32,
|
232
|
+
:max_string_length, :uint32
|
233
233
|
end
|
234
234
|
|
235
235
|
# Ruby representation of ddwaf_config_obfuscator
|
236
236
|
# https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L141-L146
|
237
237
|
class Obfuscator < ::FFI::Struct
|
238
|
-
layout :key_regex,
|
239
|
-
|
238
|
+
layout :key_regex, :pointer, # should be :charptr
|
239
|
+
:value_regex, :pointer # should be :charptr
|
240
240
|
end
|
241
241
|
|
242
|
-
layout :limits,
|
243
|
-
|
244
|
-
|
242
|
+
layout :limits, Limits,
|
243
|
+
:obfuscator, Obfuscator,
|
244
|
+
:free_fn, :pointer # :ddwaf_object_free_fn
|
245
245
|
end
|
246
246
|
|
247
|
-
typedef
|
247
|
+
typedef HandleBuilderConfig.by_ref, :ddwaf_config
|
248
|
+
|
249
|
+
attach_function :ddwaf_builder_init, [:ddwaf_config], :ddwaf_builder
|
250
|
+
attach_function :ddwaf_builder_destroy, [:ddwaf_builder], :void
|
251
|
+
|
252
|
+
attach_function :ddwaf_builder_add_or_update_config, [:ddwaf_builder, :string, :size_t, :ddwaf_object, :ddwaf_diagnostics], :bool
|
253
|
+
attach_function :ddwaf_builder_remove_config, [:ddwaf_builder, :string, :size_t], :bool
|
254
|
+
|
255
|
+
attach_function :ddwaf_builder_build_instance, [:ddwaf_builder], :ddwaf_handle
|
256
|
+
|
257
|
+
# handle
|
258
|
+
|
259
|
+
callback :ddwaf_object_free_fn, [:ddwaf_object], :void
|
248
260
|
|
249
|
-
attach_function :ddwaf_init, [:ddwaf_rule, :ddwaf_config, :ddwaf_object], :ddwaf_handle
|
250
|
-
attach_function :ddwaf_update, [:ddwaf_handle, :ddwaf_object, :ddwaf_object], :ddwaf_handle
|
251
261
|
attach_function :ddwaf_destroy, [:ddwaf_handle], :void
|
252
262
|
|
253
263
|
attach_function :ddwaf_known_addresses, [:ddwaf_handle, UInt32Ptr], :charptrptr
|
254
264
|
|
255
265
|
# updating
|
256
266
|
|
257
|
-
DDWAF_RET_CODE = enum :ddwaf_err_internal,
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
267
|
+
DDWAF_RET_CODE = enum :ddwaf_err_internal, -3,
|
268
|
+
:ddwaf_err_invalid_object, -2,
|
269
|
+
:ddwaf_err_invalid_argument, -1,
|
270
|
+
:ddwaf_ok, 0,
|
271
|
+
:ddwaf_match, 1
|
262
272
|
typedef DDWAF_RET_CODE, :ddwaf_ret_code
|
263
273
|
|
264
274
|
# running
|
@@ -271,11 +281,11 @@ module Datadog
|
|
271
281
|
# Ruby representation of ddwaf_result
|
272
282
|
# See https://github.com/DataDog/libddwaf/blob/10e3a1dfc7bc9bb8ab11a09a9f8b6b339eaf3271/include/ddwaf.h#L154-L173
|
273
283
|
class Result < ::FFI::Struct
|
274
|
-
layout :timeout,
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
284
|
+
layout :timeout, :bool,
|
285
|
+
:events, Object,
|
286
|
+
:actions, Object,
|
287
|
+
:derivatives, Object,
|
288
|
+
:total_runtime, :uint64
|
279
289
|
end
|
280
290
|
|
281
291
|
typedef Result.by_ref, :ddwaf_result
|
@@ -287,26 +297,16 @@ module Datadog
|
|
287
297
|
# logging
|
288
298
|
|
289
299
|
DDWAF_LOG_LEVEL = enum :ddwaf_log_trace,
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
300
|
+
:ddwaf_log_debug,
|
301
|
+
:ddwaf_log_info,
|
302
|
+
:ddwaf_log_warn,
|
303
|
+
:ddwaf_log_error,
|
304
|
+
:ddwaf_log_off
|
295
305
|
typedef DDWAF_LOG_LEVEL, :ddwaf_log_level
|
296
306
|
|
297
307
|
callback :ddwaf_log_cb, [:ddwaf_log_level, :string, :string, :uint, :charptr, :uint64], :void
|
298
308
|
|
299
309
|
attach_function :ddwaf_set_log_cb, [:ddwaf_log_cb, :ddwaf_log_level], :bool
|
300
|
-
|
301
|
-
DEFAULT_MAX_CONTAINER_SIZE = 256
|
302
|
-
DEFAULT_MAX_CONTAINER_DEPTH = 20
|
303
|
-
DEFAULT_MAX_STRING_LENGTH = 16_384 # in bytes, UTF-8 worst case being 4x size in terms of code point)
|
304
|
-
|
305
|
-
DDWAF_MAX_CONTAINER_SIZE = 256
|
306
|
-
DDWAF_MAX_CONTAINER_DEPTH = 20
|
307
|
-
DDWAF_MAX_STRING_LENGTH = 4096
|
308
|
-
|
309
|
-
DDWAF_RUN_TIMEOUT = 5000
|
310
310
|
end
|
311
311
|
end
|
312
312
|
end
|
@@ -2,11 +2,11 @@ module Datadog
|
|
2
2
|
module AppSec
|
3
3
|
module WAF
|
4
4
|
module VERSION
|
5
|
-
BASE_STRING =
|
5
|
+
BASE_STRING = "1.24.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}.0.
|
9
|
-
MINIMUM_RUBY_VERSION =
|
8
|
+
STRING = "#{BASE_STRING}.0.0"
|
9
|
+
MINIMUM_RUBY_VERSION = "2.5"
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
data/lib/datadog/appsec/waf.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
3
|
+
require "datadog/appsec/waf/lib_ddwaf"
|
4
|
+
|
5
|
+
require "datadog/appsec/waf/handle_builder"
|
6
|
+
require "datadog/appsec/waf/handle"
|
7
|
+
require "datadog/appsec/waf/converter"
|
8
|
+
require "datadog/appsec/waf/errors"
|
9
|
+
require "datadog/appsec/waf/result"
|
10
|
+
require "datadog/appsec/waf/context"
|
11
|
+
require "datadog/appsec/waf/version"
|
10
12
|
|
11
13
|
module Datadog
|
12
14
|
module AppSec
|
data/lib/libddwaf.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require "datadog/appsec/waf"
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libddwaf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.24.1.0.0
|
5
5
|
platform: x86_64-linux
|
6
6
|
authors:
|
7
7
|
- Datadog, Inc.
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date: 2025-
|
10
|
+
date: 2025-05-20 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: ffi
|
@@ -42,18 +41,19 @@ files:
|
|
42
41
|
- lib/datadog/appsec/waf.rb
|
43
42
|
- lib/datadog/appsec/waf/context.rb
|
44
43
|
- lib/datadog/appsec/waf/converter.rb
|
44
|
+
- lib/datadog/appsec/waf/errors.rb
|
45
45
|
- lib/datadog/appsec/waf/handle.rb
|
46
|
+
- lib/datadog/appsec/waf/handle_builder.rb
|
46
47
|
- lib/datadog/appsec/waf/lib_ddwaf.rb
|
47
48
|
- lib/datadog/appsec/waf/result.rb
|
48
49
|
- lib/datadog/appsec/waf/version.rb
|
49
50
|
- lib/libddwaf.rb
|
50
|
-
- vendor/libddwaf/libddwaf-1.
|
51
|
+
- vendor/libddwaf/libddwaf-1.24.1-linux-x86_64/lib/libddwaf.so
|
51
52
|
homepage: https://github.com/DataDog/libddwaf-rb
|
52
53
|
licenses:
|
53
54
|
- BSD-3-Clause
|
54
55
|
metadata:
|
55
56
|
allowed_push_host: https://rubygems.org
|
56
|
-
post_install_message:
|
57
57
|
rdoc_options: []
|
58
58
|
require_paths:
|
59
59
|
- lib
|
@@ -68,8 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: 2.0.0
|
70
70
|
requirements: []
|
71
|
-
rubygems_version: 3.
|
72
|
-
signing_key:
|
71
|
+
rubygems_version: 3.6.2
|
73
72
|
specification_version: 4
|
74
73
|
summary: Datadog WAF
|
75
74
|
test_files: []
|
Binary file
|