sqreen 0.7.01461158029-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +22 -0
  3. data/README.md +77 -0
  4. data/Rakefile +40 -0
  5. data/lib/sqreen.rb +67 -0
  6. data/lib/sqreen/binding_accessor.rb +184 -0
  7. data/lib/sqreen/ca.crt +72 -0
  8. data/lib/sqreen/callback_tree.rb +78 -0
  9. data/lib/sqreen/callbacks.rb +120 -0
  10. data/lib/sqreen/capped_queue.rb +23 -0
  11. data/lib/sqreen/condition_evaluator.rb +169 -0
  12. data/lib/sqreen/conditionable.rb +50 -0
  13. data/lib/sqreen/configuration.rb +151 -0
  14. data/lib/sqreen/context.rb +22 -0
  15. data/lib/sqreen/deliveries/batch.rb +80 -0
  16. data/lib/sqreen/deliveries/simple.rb +36 -0
  17. data/lib/sqreen/detect.rb +14 -0
  18. data/lib/sqreen/detect/shell_injection.rb +61 -0
  19. data/lib/sqreen/detect/sql_injection.rb +115 -0
  20. data/lib/sqreen/event.rb +16 -0
  21. data/lib/sqreen/events/attack.rb +60 -0
  22. data/lib/sqreen/events/remote_exception.rb +53 -0
  23. data/lib/sqreen/exception.rb +31 -0
  24. data/lib/sqreen/frameworks.rb +40 -0
  25. data/lib/sqreen/frameworks/generic.rb +243 -0
  26. data/lib/sqreen/frameworks/rails.rb +155 -0
  27. data/lib/sqreen/frameworks/rails3.rb +36 -0
  28. data/lib/sqreen/frameworks/sinatra.rb +34 -0
  29. data/lib/sqreen/frameworks/sqreen_test.rb +26 -0
  30. data/lib/sqreen/instrumentation.rb +504 -0
  31. data/lib/sqreen/log.rb +116 -0
  32. data/lib/sqreen/metrics.rb +6 -0
  33. data/lib/sqreen/metrics/average.rb +39 -0
  34. data/lib/sqreen/metrics/base.rb +41 -0
  35. data/lib/sqreen/metrics/collect.rb +22 -0
  36. data/lib/sqreen/metrics/sum.rb +20 -0
  37. data/lib/sqreen/metrics_store.rb +94 -0
  38. data/lib/sqreen/parsers/sql.rb +98 -0
  39. data/lib/sqreen/parsers/sql_tokenizer.rb +266 -0
  40. data/lib/sqreen/parsers/unix.rb +110 -0
  41. data/lib/sqreen/payload_creator.rb +132 -0
  42. data/lib/sqreen/performance_notifications.rb +86 -0
  43. data/lib/sqreen/performance_notifications/log.rb +36 -0
  44. data/lib/sqreen/performance_notifications/metrics.rb +36 -0
  45. data/lib/sqreen/performance_notifications/newrelic.rb +36 -0
  46. data/lib/sqreen/remote_command.rb +82 -0
  47. data/lib/sqreen/rule_attributes.rb +25 -0
  48. data/lib/sqreen/rule_callback.rb +97 -0
  49. data/lib/sqreen/rules.rb +116 -0
  50. data/lib/sqreen/rules_callbacks.rb +29 -0
  51. data/lib/sqreen/rules_callbacks/binding_accessor_metrics.rb +79 -0
  52. data/lib/sqreen/rules_callbacks/count_http_codes.rb +18 -0
  53. data/lib/sqreen/rules_callbacks/crawler_user_agent_matches.rb +24 -0
  54. data/lib/sqreen/rules_callbacks/crawler_user_agent_matches_metrics.rb +25 -0
  55. data/lib/sqreen/rules_callbacks/execjs.rb +136 -0
  56. data/lib/sqreen/rules_callbacks/headers_insert.rb +20 -0
  57. data/lib/sqreen/rules_callbacks/inspect_rule.rb +20 -0
  58. data/lib/sqreen/rules_callbacks/matcher_rule.rb +103 -0
  59. data/lib/sqreen/rules_callbacks/rails_parameters.rb +14 -0
  60. data/lib/sqreen/rules_callbacks/record_request_context.rb +23 -0
  61. data/lib/sqreen/rules_callbacks/reflected_xss.rb +40 -0
  62. data/lib/sqreen/rules_callbacks/regexp_rule.rb +36 -0
  63. data/lib/sqreen/rules_callbacks/shell.rb +33 -0
  64. data/lib/sqreen/rules_callbacks/shell_env.rb +32 -0
  65. data/lib/sqreen/rules_callbacks/sql.rb +41 -0
  66. data/lib/sqreen/rules_callbacks/system_shell.rb +25 -0
  67. data/lib/sqreen/rules_callbacks/url_matches.rb +25 -0
  68. data/lib/sqreen/rules_callbacks/user_agent_matches.rb +22 -0
  69. data/lib/sqreen/rules_signature.rb +142 -0
  70. data/lib/sqreen/runner.rb +312 -0
  71. data/lib/sqreen/runtime_infos.rb +127 -0
  72. data/lib/sqreen/session.rb +340 -0
  73. data/lib/sqreen/stats.rb +18 -0
  74. data/lib/sqreen/version.rb +6 -0
  75. metadata +143 -0
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'sqreen/frameworks/rails'
5
+
6
+ module Sqreen
7
+ module Frameworks
8
+ # Handle Rails 3 specifics
9
+ class Rails3Framework < RailsFramework
10
+ def root
11
+ Rails.root
12
+ end
13
+
14
+ def prevent_startup
15
+ res = super
16
+ return res if res
17
+ return :rails_console if defined?(Rails::Console)
18
+ nil
19
+ end
20
+
21
+ def instrument_when_ready!(instrumentor, rules)
22
+ config = Rails.configuration
23
+ if config.cache_classes
24
+ instrumentor.instrument!(rules, self)
25
+ else
26
+ # FIXME: What needs to be done if no active_record?
27
+ # (probably related to SQREEN-219)
28
+ frm = self
29
+ ActiveSupport.on_load(:active_record) do
30
+ instrumentor.instrument!(rules, frm)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'sqreen/frameworks/generic'
5
+
6
+ module Sqreen
7
+ module Frameworks
8
+ # Handle Sinatra specific functions
9
+ class SinatraFramework < GenericFramework
10
+ def framework_infos
11
+ h = super
12
+ h[:framework_type] = 'Sinatra'
13
+ h[:framework_version] = Sinatra::VERSION
14
+ h
15
+ end
16
+
17
+ def db_settings(options = {})
18
+ adapter = options[:connection_adapter]
19
+ return nil unless adapter
20
+
21
+ begin
22
+ adapter_name = adapter.class.const_get 'ADAPTER_NAME'
23
+ rescue
24
+ # FIXME: we may want to log that
25
+ Sqreen.log.error 'cannot find ADAPTER_NAME'
26
+ return nil
27
+ end
28
+ db_type = DB_MAPPING[adapter_name]
29
+ db_infos = { :name => adapter_name }
30
+ [db_type, db_infos]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'sqreen/frameworks/generic'
5
+
6
+ module Sqreen
7
+ module Frameworks
8
+ # Rails related framework code
9
+ class SqreenTestFramework < GenericFramework
10
+ def framework_infos
11
+ {
12
+ :framework_type => 'SqreenTest',
13
+ :framework_version => '0.1',
14
+ }
15
+ end
16
+
17
+ def client_ip
18
+ '127.0.0.1'
19
+ end
20
+
21
+ def request_infos
22
+ {}
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,504 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'sqreen/callback_tree'
5
+ require 'sqreen/log'
6
+ require 'sqreen/stats'
7
+ require 'sqreen/exception'
8
+ require 'sqreen/performance_notifications'
9
+ require 'sqreen/events/remote_exception'
10
+ require 'sqreen/rules_signature'
11
+ require 'set'
12
+
13
+ # How to override a class method:
14
+ #
15
+ # class Cache
16
+ #
17
+ # def self.get3
18
+ # puts "GET3"
19
+ # end
20
+ # def self.get
21
+ # puts "GET"
22
+ # end
23
+ # end
24
+ #
25
+ # class << Cache # Change context to metaclass of Cache
26
+ # def get_modified
27
+ # puts "GET MODIFI"
28
+ # end
29
+ # alias_method :get_not_modified, :get
30
+ # alias_method :get, :get_modified
31
+ # end
32
+
33
+ module Sqreen
34
+ class Instrumentation
35
+ @@override_semaphore = Mutex.new
36
+
37
+ ## Overriden methods and callbacks globals
38
+ @@overriden_methods = []
39
+ @@registered_callbacks = CBTree.new
40
+
41
+ def self.semaphore
42
+ @@override_semaphore
43
+ end
44
+
45
+ def self.callbacks
46
+ @@registered_callbacks
47
+ end
48
+
49
+ def self.overriden
50
+ @@overriden_methods
51
+ end
52
+
53
+ def self.callback_wrapper_pre(klass, method, instance, *args, &block)
54
+ Instrumentation.guard_call(method, []) do
55
+ callbacks = @@registered_callbacks.get(klass, method, :pre)
56
+
57
+ returns = []
58
+ callbacks.each do |cb|
59
+ rule = cb.rule_name if cb.respond_to?(:rule_name)
60
+ Sqreen.log.debug { "running pre cb #{cb}" }
61
+ Sqreen::PerformanceNotifications.instrument("Callbacks/#{rule || cb.class.name}/pre") do
62
+ begin
63
+ res = cb.send(:pre, instance, *args, &block)
64
+ if !res.nil? && cb.respond_to?(:block) && (!cb.block && !Sqreen.config_get(:block_all_rules))
65
+ Sqreen.log.debug do
66
+ "#{cb} cannot block, overriding return value"
67
+ end
68
+ res = nil
69
+ elsif res.is_a?(Hash)
70
+ res[:rule_name] = rule
71
+ end
72
+ returns << res
73
+ rescue => e
74
+ Sqreen.log.error "we catch an exception: #{e.inspect}"
75
+ Sqreen.log.error e.backtrace
76
+ if cb.respond_to?(:record_exception)
77
+ cb.record_exception(e)
78
+ else
79
+ Sqreen::RemoteException.record(e)
80
+ end
81
+ next
82
+ end
83
+ end
84
+ end
85
+ returns
86
+ end
87
+ end
88
+
89
+ def self.callback_wrapper_post(klass, method, return_val, instance, *args, &block)
90
+ Instrumentation.guard_call(method, []) do
91
+ callbacks = @@registered_callbacks.get(klass, method, :post)
92
+
93
+ returns = []
94
+ callbacks.reverse_each do |cb|
95
+ rule = cb.rule_name if cb.respond_to?(:rule_name)
96
+ Sqreen.log.debug { "running post cb #{cb}" }
97
+ Sqreen::PerformanceNotifications.instrument("Callbacks/#{rule || cb.class.name}/post") do
98
+ begin
99
+ res = cb.send(:post, return_val, instance, *args, &block)
100
+ if !res.nil? && cb.respond_to?(:block) && (!cb.block && !Sqreen.config_get(:block_all_rules))
101
+ Sqreen.log.debug do
102
+ "#{cb} cannot block, overriding return value"
103
+ end
104
+ res = nil
105
+ elsif res.is_a?(Hash)
106
+ res[:rule_name] = rule
107
+ end
108
+ returns << res
109
+ rescue => e
110
+ Sqreen.log.error "we catch an exception: #{e.inspect}"
111
+ Sqreen.log.error e.backtrace
112
+ if cb.respond_to?(:record_exception)
113
+ cb.record_exception(e)
114
+ else
115
+ Sqreen::RemoteException.record(e)
116
+ end
117
+ next
118
+ end
119
+ end
120
+ end
121
+ returns
122
+ end
123
+ end
124
+
125
+ def self.callback_wrapper_failing(exception, klass, method, instance, *args, &block)
126
+ Instrumentation.guard_call(method, []) do
127
+ callbacks = @@registered_callbacks.get(klass, method, :failing)
128
+
129
+ returns = []
130
+ callbacks.each do |cb|
131
+ rule = cb.rule_name if cb.respond_to?(:rule_name)
132
+ Sqreen.log.debug { "running failing cb #{cb}" }
133
+ Sqreen::PerformanceNotifications.instrument("Callbacks/#{rule || cb.class.name}/failing") do
134
+ begin
135
+ res = cb.send(:failing, exception, instance, *args, &block)
136
+ if !res.nil? && cb.respond_to?(:block) && (!cb.block && !Sqreen.config_get(:block_all_rules))
137
+ Sqreen.log.debug do
138
+ "#{cb} cannot block, overriding return value"
139
+ end
140
+ res = nil
141
+ elsif res.is_a?(Hash)
142
+ res[:rule_name] = rule
143
+ end
144
+ returns << res
145
+ rescue => e
146
+ Sqreen.log.error "we catch an exception: #{e.inspect}"
147
+ Sqreen.log.error e.backtrace
148
+ if cb.respond_to?(:record_exception)
149
+ cb.record_exception(e)
150
+ else
151
+ Sqreen::RemoteException.record(e)
152
+ end
153
+ next
154
+ end
155
+ end
156
+ end
157
+ returns
158
+ end
159
+ end
160
+
161
+ def self.guard_call(method, retval)
162
+ if @sqreen_in_instr && @sqreen_in_instr.member?(method)
163
+ return retval
164
+ else
165
+ @sqreen_in_instr ||= Set.new
166
+ @sqreen_in_instr.add(method)
167
+ r = yield
168
+ @sqreen_in_instr.delete(method)
169
+ return r
170
+ end
171
+ rescue Exception => e
172
+ @sqreen_in_instr.delete(method)
173
+ raise e
174
+ end
175
+
176
+ def self.define_callback_method(meth, original_meth, klass_name)
177
+ proc do |*args, &block|
178
+ Sqreen.stats.callbacks_calls += 1
179
+
180
+ skip = false
181
+ result = nil
182
+
183
+ # pre callback
184
+ returns = Instrumentation.callback_wrapper_pre(klass_name,
185
+ meth,
186
+ self,
187
+ *args,
188
+ &block)
189
+ returns.each do |ret|
190
+ next unless ret.is_a? Hash
191
+ case ret[:status]
192
+ when :skip, 'skip'
193
+ skip = true
194
+ result = ret[:new_return_value] if ret.key? :new_return_value
195
+ next
196
+ when :raise, 'raise'
197
+ fail Sqreen::AttackBlocked, "Sqreen blocked a security threat (type: #{ret[:rule_name]}). No action is required."
198
+ end
199
+ end
200
+
201
+ return result if skip
202
+ begin
203
+ result = send(original_meth, *args, &block)
204
+ rescue => e
205
+ returns = Instrumentation.callback_wrapper_failing(e, klass_name,
206
+ meth,
207
+ self,
208
+ *args,
209
+ &block)
210
+ will_retry = false
211
+ will_raise = returns.empty?
212
+ returns.each do |ret|
213
+ will_raise = true if ret.nil?
214
+ next unless ret.is_a? Hash
215
+ case ret[:status]
216
+ when :override, 'override'
217
+ result = ret[:new_return_value] if ret.key? :new_return_value
218
+ when :retry, 'retry'
219
+ will_retry = true
220
+ else # :reraise, 'reraise'
221
+ will_raise = true
222
+ end
223
+ end
224
+ raise e if will_raise
225
+ retry if will_retry
226
+ result
227
+ else
228
+
229
+ # post callback
230
+ returns = Instrumentation.callback_wrapper_post(klass_name,
231
+ meth,
232
+ result,
233
+ self,
234
+ *args,
235
+ &block)
236
+ returns.each do |ret|
237
+ next unless ret.is_a? Hash
238
+ case ret[:status]
239
+ when :raise, 'raise'
240
+ fail Sqreen::AttackBlocked, "Sqreen blocked a security threat (type: #{ret[:rule_name]}). No action is required."
241
+ when :override, 'override'
242
+ result = ret[:new_return_value]
243
+ else
244
+ next
245
+ end
246
+ end
247
+ result
248
+ end
249
+ end
250
+ end
251
+
252
+ def override_class_method(klass, meth)
253
+ # FIXME: This is somehow ugly. We should reduce the amount of
254
+ # `evaled` code.
255
+ str = " class << #{klass}
256
+
257
+ original = '#{meth}'.to_sym
258
+ saved_meth_name = '#{get_saved_method_name(meth)}'.to_sym
259
+ new_method = '#{meth}_modified'.to_sym
260
+
261
+ alias_method saved_meth_name, original
262
+
263
+ p = Instrumentation.define_callback_method(original, saved_meth_name,
264
+ #{klass})
265
+ define_method(new_method, p)
266
+
267
+ private new_method
268
+
269
+ method_kind = nil
270
+ case
271
+ when public_method_defined?(original)
272
+ method_kind = :public
273
+ when protected_method_defined?(original)
274
+ method_kind = :protected
275
+ when private_method_defined?(original)
276
+ method_kind = :private
277
+ end
278
+ alias_method original, new_method
279
+ send(method_kind, original)
280
+ private saved_meth_name
281
+ end "
282
+ eval str
283
+ end
284
+
285
+ def unoverride_instance_method(obj, meth)
286
+ saved_meth_name = get_saved_method_name(meth)
287
+
288
+ method_kind = nil
289
+ obj.class_eval do
290
+ # Note: As a lambda the following will crash ruby 2.2.3p173
291
+ case
292
+ when public_method_defined?(meth)
293
+ method_kind = :public
294
+ when protected_method_defined?(meth)
295
+ method_kind = :protected
296
+ when private_method_defined?(meth)
297
+ method_kind = :private
298
+ end
299
+ alias_method meth, saved_meth_name
300
+ send(method_kind, meth)
301
+ end
302
+ end
303
+
304
+ def get_saved_method_name(meth)
305
+ "#{meth}_not_modified".to_sym
306
+ end
307
+
308
+ def override_instance_method(klass_name, meth)
309
+ saved_meth_name = get_saved_method_name(meth)
310
+ new_method = "#{meth}_modified".to_sym
311
+
312
+ p = Instrumentation.define_callback_method(meth, saved_meth_name,
313
+ klass_name)
314
+ method_kind = nil
315
+ klass_name.class_eval do
316
+ alias_method saved_meth_name, meth
317
+
318
+ define_method(new_method, p)
319
+
320
+ case
321
+ when public_method_defined?(meth)
322
+ method_kind = :public
323
+ when protected_method_defined?(meth)
324
+ method_kind = :protected
325
+ when private_method_defined?(meth)
326
+ method_kind = :private
327
+ end
328
+ alias_method meth, new_method
329
+ private saved_meth_name
330
+ private new_method
331
+ send(method_kind, meth)
332
+ end
333
+ saved_meth_name
334
+ end
335
+
336
+ # WARNING We do not actually remove `meth`
337
+ def unoverride_class_method(klass, meth)
338
+ saved_meth_name = get_saved_method_name(meth)
339
+
340
+ eval "method_kind = nil; class << #{klass}
341
+ new_method = '#{meth}_modified'.to_sym
342
+ case
343
+ when public_method_defined?(#{meth.to_sym.inspect})
344
+ method_kind = :public
345
+ when protected_method_defined?(original)
346
+ method_kind = :protected
347
+ when private_method_defined?(#{meth.to_sym.inspect})
348
+ method_kind = :private
349
+ end
350
+ alias_method #{meth.to_sym.inspect}, #{saved_meth_name.to_sym.inspect}
351
+ send(method_kind, #{meth.to_sym.inspect})
352
+ end "
353
+ end
354
+
355
+ if RUBY_VERSION < '1.9'
356
+ def adjust_method_name(method)
357
+ method.to_s
358
+ end
359
+ else
360
+ def adjust_method_name(method)
361
+ method
362
+ end
363
+ end
364
+
365
+ def is_instance_method?(klass, method)
366
+ method = adjust_method_name(method)
367
+ klass.instance_methods.include?(method) ||
368
+ klass.private_instance_methods.include?(method)
369
+ end
370
+
371
+ def is_class_method?(klass, method)
372
+ method = adjust_method_name(method)
373
+ klass.singleton_methods.include? method
374
+ end
375
+
376
+ def add_callback(cb)
377
+ @@override_semaphore.synchronize do
378
+ klass = cb.klass
379
+ method = cb.method
380
+ key = [klass, method]
381
+
382
+ already_overriden = @@overriden_methods.include? key
383
+
384
+ if !already_overriden
385
+ if is_class_method?(klass, method)
386
+ Sqreen.log.debug "overriding class method for #{cb}"
387
+ success = override_class_method(klass, method)
388
+ elsif is_instance_method?(klass, method)
389
+ Sqreen.log.debug "overriding instance method for #{cb}"
390
+ success = override_instance_method(klass, method)
391
+ else
392
+ # FIXME: Override define_method and other dynamic ways to
393
+ # The following should be monitored to make sure we
394
+ # don't forget dynamically added methods:
395
+ # - define_method
396
+ # - method_added
397
+ # - method_missing
398
+ # ...
399
+ #
400
+ msg = "#{cb} is neither singleton or instance"
401
+ raise Sqreen::NotImplementedYet, msg
402
+ end
403
+
404
+ @@overriden_methods += [key] if success
405
+ else
406
+ Sqreen.log.debug "#{key} was already overriden"
407
+ end
408
+
409
+ @@registered_callbacks.add(cb)
410
+ end
411
+ end
412
+
413
+ def remove_callback(cb)
414
+ @@override_semaphore.synchronize do
415
+ remove_callback_no_lock(cb)
416
+ end
417
+ end
418
+
419
+ def remove_callback_no_lock(cb)
420
+ klass = cb.klass
421
+ method = cb.method
422
+
423
+ key = [klass, method]
424
+
425
+ already_overriden = @@overriden_methods.include? key
426
+ unless already_overriden
427
+ Sqreen.log.debug "#{key} not overriden, returning"
428
+ return
429
+ end
430
+
431
+ defined_cbs = @@registered_callbacks.get(klass, method)
432
+
433
+ nb_removed = 0
434
+ defined_cbs.each do |found_cb|
435
+ if found_cb == cb
436
+ Sqreen.log.debug "Removing callback #{found_cb}"
437
+ @@registered_callbacks.remove(found_cb)
438
+ nb_removed += 1
439
+ else
440
+ Sqreen.log.debug "Not removing callback #{found_cb} (remains #{defined_cbs.size} cbs)"
441
+ end
442
+ end
443
+
444
+ return unless nb_removed == defined_cbs.size
445
+
446
+ Sqreen.log.debug "Removing overriden method #{key}"
447
+ @@overriden_methods.delete(key)
448
+
449
+ if is_class_method?(klass, method)
450
+ unoverride_class_method(klass, method)
451
+ elsif is_instance_method?(klass, method)
452
+ unoverride_instance_method(klass, method)
453
+ else
454
+ # FIXME: Override define_method and other dynamic ways to
455
+ # The following should be monitored to make sure we
456
+ # don't forget dynamically added methods:
457
+ # - define_method
458
+ # - method_added
459
+ # - method_missing
460
+ # ...
461
+ #
462
+ msg = "#{cb} is neither singleton or instance"
463
+ raise Sqreen::NotImplementedYet, msg
464
+ end
465
+ end
466
+
467
+ def remove_all_callbacks
468
+ @@override_semaphore.synchronize do
469
+ @@registered_callbacks.entries.each do |cb|
470
+ remove_callback_no_lock(cb)
471
+ end
472
+ Sqreen.instrumentation_ready = false
473
+ end
474
+ end
475
+
476
+ attr_accessor :metrics_engine
477
+
478
+ # Instrument the application code using the rules
479
+ # @param rules [Array<Hash>] Rules to instrument
480
+ # @param metrics_engine [MetricsStore] Metric storage facility
481
+ def instrument!(rules, framework)
482
+ verifier = nil
483
+ if Sqreen.features['rules_signature'] &&
484
+ Sqreen.config_get(:rules_verify_signature) &&
485
+ !defined?(::JRUBY_VERSION)
486
+ verifier = Sqreen::RulesSignature.new
487
+ else
488
+ Sqreen.log.debug('Rules signature is not enabled')
489
+ end
490
+ remove_all_callbacks # Force cb tree to be empty before instrumenting
491
+ rules.each do |rule|
492
+ rcb = Sqreen::Rules.cb_from_rule(rule, metrics_engine, verifier)
493
+ next unless rcb
494
+ rcb.framework = framework
495
+ add_callback(rcb)
496
+ end
497
+ Sqreen.instrumentation_ready = true
498
+ end
499
+
500
+ def initialize(metrics_engine = nil)
501
+ self.metrics_engine = metrics_engine
502
+ end
503
+ end
504
+ end