lib/sqreen/instrumentation.rb in sqreen-alt-1.12.0 vs lib/sqreen/instrumentation.rb in sqreen-alt-1.13.0
- old
+ new
@@ -9,10 +9,11 @@
require 'sqreen/events/remote_exception'
require 'sqreen/rules_signature'
require 'sqreen/shared_storage'
require 'sqreen/rules_callbacks/record_request_context'
require 'sqreen/rules_callbacks/run_req_start_actions'
+require 'sqreen/rules_callbacks/run_block_user_actions'
require 'set'
# How to override a class method:
#
# class Cache
@@ -243,10 +244,14 @@
end
def self.define_callback_method(meth, original_meth, klass_name)
@sqreen_multi_instr ||= nil
proc do |*args, &block|
+ record_req_hp = @@record_request_hookpoints.include?([klass_name, meth]) &&
+ Sqreen::PerformanceNotifications.listen_for?
+ Sqreen::PerformanceNotifications::BinnedMetrics.start_request if record_req_hp
+
budget = nil
skip_call = Thread.current[:sqreen_in_use]
begin
if !skip_call && Sqreen.performance_budget
# Not using framework here to try to get a bit more perf by not loading cbs
@@ -368,23 +373,25 @@
&block)
returns.each do |ret|
next unless ret.is_a? Hash
case ret[:status]
when :raise, 'raise'
+ raise ret[:exception] if ret.key?(:exception)
raise Sqreen::AttackBlocked, "Sqreen blocked a security threat (type: #{ret[:rule_name]}). No action is required."
when :override, 'override'
result = ret[:new_return_value]
else
next
end
end
result
ensure
- if @@record_request_hookpoints.include?([klass_name, meth]) && Sqreen::PerformanceNotifications.listen_for?
+ if record_req_hp
Sqreen::PerformanceNotifications.instrument('Callbacks/hooks_reporting/pre') do
Sqreen::PerformanceNotifications::LogPerformance.next_request
Sqreen::PerformanceNotifications::NewRelic.next_request
+ Sqreen::PerformanceNotifications::BinnedMetrics.finish_request
end
end
Thread.current[:sqreen_in_use] = false
end
end
@@ -437,10 +444,12 @@
elsif private_method_defined?(meth)
method_kind = :private
end
alias_method meth, saved_meth_name
send(method_kind, meth)
+
+ remove_method saved_meth_name
end
end
def get_saved_method_name(meth, suffix = nil)
"#{meth}_sq#{suffix}_not_modified".to_sym
@@ -448,10 +457,19 @@
def override_instance_method(klass_name, meth)
saved_meth_name = get_saved_method_name(meth)
new_method = "#{meth}_modified".to_sym
+ # do not include ancestors o/wise we might get a saved method from a
+ # superclass which is never called because the original name
+ # (instrumented) method of the superclass has been overridden
+ private_meths = klass_name.private_instance_methods(false)
+ if private_meths.include?(saved_meth_name)
+ Sqreen.log.debug { "#{saved_meth_name} found #{klass_name}##{meth} already instrumented" }
+ return saved_meth_name
+ end
+
p = Instrumentation.define_callback_method(meth, saved_meth_name,
klass_name)
method_kind = nil
klass_name.class_eval do
alias_method saved_meth_name, meth
@@ -662,10 +680,12 @@
attr_accessor :metrics_engine
# @return [Array<Sqreen::CB>]
def hardcoded_callbacks(framework)
[
- Sqreen::Rules::RunReqStartActions.new(framework)
+ Sqreen::Rules::RunReqStartActions.new(framework),
+ Sqreen::Rules::RunBlockUserActions.new(Sqreen, :identify, 0),
+ Sqreen::Rules::RunBlockUserActions.new(Sqreen, :auth_track, 1),
]
end
# Instrument the application code using the rules
# @param rules [Array<Hash>] Rules to instrument