sqreen 1.18.2-java → 1.19.0-java
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 +35 -0
- data/LICENSE +3 -0
- data/lib/sqreen.rb +2 -0
- data/lib/sqreen/actions.rb +13 -337
- data/lib/sqreen/actions/actions_index.rb +16 -0
- data/lib/sqreen/actions/base.rb +104 -0
- data/lib/sqreen/actions/block_ip.rb +34 -0
- data/lib/sqreen/actions/block_user.rb +46 -0
- data/lib/sqreen/actions/ip_range_indexed_action_class.rb +16 -0
- data/lib/sqreen/actions/ip_ranges_index.rb +57 -0
- data/lib/sqreen/actions/redirect_ip.rb +42 -0
- data/lib/sqreen/actions/redirect_user.rb +47 -0
- data/lib/sqreen/actions/repository.rb +43 -0
- data/lib/sqreen/actions/unknown_action_type.rb +20 -0
- data/lib/sqreen/actions/user_action_class.rb +16 -0
- data/lib/sqreen/actions/users_index.rb +35 -0
- data/lib/sqreen/agent.rb +6 -2
- data/lib/sqreen/attack_blocked.rb +19 -0
- data/lib/sqreen/backport.rb +2 -0
- data/lib/sqreen/backport/clock_gettime.rb +74 -0
- data/lib/sqreen/backport/original_name.rb +2 -0
- data/lib/sqreen/binding_accessor.rb +11 -102
- data/lib/sqreen/binding_accessor/path_elem.rb +10 -0
- data/lib/sqreen/binding_accessor/transforms.rb +114 -0
- data/lib/sqreen/call_countable.rb +2 -0
- data/lib/sqreen/capped_queue.rb +4 -0
- data/lib/sqreen/{callbacks.rb → cb.rb} +3 -53
- data/lib/sqreen/{callback_tree.rb → cb_tree.rb} +4 -2
- data/lib/sqreen/condition_evaluator.rb +24 -5
- data/lib/sqreen/conditionable.rb +2 -0
- data/lib/sqreen/configuration.rb +19 -0
- data/lib/sqreen/context.rb +2 -0
- data/lib/sqreen/default_cb.rb +22 -0
- data/lib/sqreen/deferred_logger.rb +65 -0
- data/lib/sqreen/deliveries.rb +12 -0
- data/lib/sqreen/deliveries/batch.rb +9 -1
- data/lib/sqreen/deliveries/simple.rb +7 -0
- data/lib/sqreen/dependency.rb +3 -1
- data/lib/sqreen/dependency/detector.rb +22 -14
- data/lib/sqreen/dependency/libsqreen.rb +32 -0
- data/lib/sqreen/dependency/new_relic.rb +2 -0
- data/lib/sqreen/dependency/rack.rb +10 -5
- data/lib/sqreen/dependency/rails.rb +8 -0
- data/lib/sqreen/dependency/sentry.rb +2 -0
- data/lib/sqreen/dependency/sinatra.rb +58 -14
- data/lib/sqreen/encoding_sanitizer.rb +2 -0
- data/lib/sqreen/error_handling_middleware.rb +32 -0
- data/lib/sqreen/event.rb +4 -0
- data/lib/sqreen/events/attack.rb +4 -0
- data/lib/sqreen/events/remote_exception.rb +2 -0
- data/lib/sqreen/events/request_record.rb +13 -56
- data/lib/sqreen/exception.rb +11 -40
- data/lib/sqreen/formatter_with_tid.rb +47 -0
- data/lib/sqreen/framework_cb.rb +30 -0
- data/lib/sqreen/frameworks.rb +9 -0
- data/lib/sqreen/frameworks/generic.rb +22 -2
- data/lib/sqreen/frameworks/rails.rb +3 -0
- data/lib/sqreen/frameworks/rails3.rb +2 -0
- data/lib/sqreen/frameworks/request_recorder.rb +5 -0
- data/lib/sqreen/frameworks/sinatra.rb +4 -0
- data/lib/sqreen/frameworks/sqreen_test.rb +4 -0
- data/lib/sqreen/graft.rb +12 -0
- data/lib/sqreen/graft/call.rb +150 -0
- data/lib/sqreen/{dependency → graft}/callback.rb +12 -4
- data/lib/sqreen/graft/hook.rb +316 -0
- data/lib/sqreen/{dependency → graft}/hook_point.rb +152 -33
- data/lib/sqreen/graft/hook_point_error.rb +10 -0
- data/lib/sqreen/invalid_signature_exception.rb +10 -0
- data/lib/sqreen/js.rb +11 -0
- data/lib/sqreen/js/call_context.rb +12 -0
- data/lib/sqreen/js/context_pool.rb +62 -0
- data/lib/sqreen/js/exec_js_runnable.rb +22 -0
- data/lib/sqreen/js/execjs_adapter.rb +8 -47
- data/lib/sqreen/js/executable_js.rb +14 -0
- data/lib/sqreen/js/js_service.rb +4 -22
- data/lib/sqreen/js/js_service_adapter.rb +20 -0
- data/lib/sqreen/js/mini_racer_adapter.rb +8 -180
- data/lib/sqreen/js/mini_racer_executable_js.rb +144 -0
- data/lib/sqreen/js/thread_local_exec_js_runnable.rb +49 -0
- data/lib/{sqreen-alt.rb → sqreen/legacy.rb} +5 -1
- data/lib/sqreen/{instrumentation.rb → legacy/instrumentation.rb} +44 -15
- data/lib/sqreen/log.rb +10 -188
- data/lib/sqreen/log/loggable.rb +28 -0
- data/lib/sqreen/logger.rb +85 -0
- data/lib/sqreen/metrics.rb +2 -0
- data/lib/sqreen/metrics/average.rb +2 -0
- data/lib/sqreen/metrics/base.rb +2 -0
- data/lib/sqreen/metrics/binning.rb +2 -0
- data/lib/sqreen/metrics/collect.rb +2 -0
- data/lib/sqreen/metrics/sum.rb +2 -0
- data/lib/sqreen/metrics_store.rb +5 -11
- data/lib/sqreen/metrics_store/already_registered_metric.rb +13 -0
- data/lib/sqreen/metrics_store/unknown_metric.rb +13 -0
- data/lib/sqreen/metrics_store/unregistered_metric.rb +13 -0
- data/lib/sqreen/middleware.rb +2 -34
- data/lib/sqreen/mono_time.rb +4 -0
- data/lib/sqreen/node.rb +46 -0
- data/lib/sqreen/not_implemented_yet.rb +10 -0
- data/lib/sqreen/null_logger.rb +26 -0
- data/lib/sqreen/payload_creator.rb +4 -19
- data/lib/sqreen/payload_creator/header_section.rb +30 -0
- data/lib/sqreen/performance_notifications.rb +2 -0
- data/lib/sqreen/performance_notifications/binned_metrics.rb +2 -0
- data/lib/sqreen/performance_notifications/log.rb +2 -0
- data/lib/sqreen/performance_notifications/log_performance.rb +2 -0
- data/lib/sqreen/performance_notifications/metrics.rb +2 -0
- data/lib/sqreen/performance_notifications/newrelic.rb +2 -0
- data/lib/sqreen/prefix.rb +35 -0
- data/lib/sqreen/rails_middleware.rb +16 -0
- data/lib/sqreen/remote_command.rb +3 -8
- data/lib/sqreen/remote_command/failure_output.rb +16 -0
- data/lib/sqreen/rules.rb +34 -2
- data/lib/sqreen/{rule_attributes.rb → rules/attrs.rb} +2 -0
- data/lib/sqreen/{rules_callbacks/sdk_auth_track.rb → rules/auth_track_cb.rb} +4 -2
- data/lib/sqreen/{rules_callbacks/binding_accessor_matcher.rb → rules/binding_accessor_matcher_cb.rb} +6 -8
- data/lib/sqreen/{rules_callbacks → rules}/binding_accessor_metrics.rb +3 -1
- data/lib/sqreen/{rules_callbacks/blacklist_ips.rb → rules/blacklist_ips_cb.rb} +5 -2
- data/lib/sqreen/{rules_callbacks → rules}/count_http_codes.rb +4 -2
- data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches.rb → rules/crawler_user_agent_matches_cb.rb} +3 -1
- data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches_metrics.rb → rules/crawler_user_agent_matches_metrics_cb.rb} +3 -1
- data/lib/sqreen/{rules_callbacks/custom_error.rb → rules/custom_error_cb.rb} +3 -1
- data/lib/sqreen/{rules_callbacks/devise_auth_track.rb → rules/devise_auth_track_cb.rb} +4 -2
- data/lib/sqreen/{rules_callbacks/devise_signup_track.rb → rules/devise_signup_track_cb.rb} +4 -2
- data/lib/sqreen/{rules_callbacks/execjs.rb → rules/execjs_cb.rb} +51 -50
- data/lib/sqreen/{rules_callbacks/headers_insert.rb → rules/headers_insert_cb.rb} +8 -1
- data/lib/sqreen/{rules_callbacks → rules}/matcher_rule.rb +4 -2
- data/lib/sqreen/{rules_callbacks/not_found.rb → rules/not_found_cb.rb} +7 -2
- data/lib/sqreen/{rules_callbacks/rails_parameters.rb → rules/rails_parameters_cb.rb} +3 -1
- data/lib/sqreen/{rules_callbacks → rules}/record_request_context.rb +3 -1
- data/lib/sqreen/{rules_callbacks/regexp_rule.rb → rules/regexp_rule_cb.rb} +3 -1
- data/lib/sqreen/{rule_callback.rb → rules/rule_cb.rb} +4 -2
- data/lib/sqreen/{rules_callbacks → rules}/run_req_start_actions.rb +7 -3
- data/lib/sqreen/{rules_callbacks → rules}/run_user_actions.rb +4 -2
- data/lib/sqreen/{rules_callbacks/shell_env.rb → rules/shell_env_cb.rb} +3 -1
- data/lib/sqreen/{rules_callbacks/sdk_signup_track.rb → rules/signup_track_cb.rb} +4 -2
- data/lib/sqreen/rules/update_request_context.rb +22 -0
- data/lib/sqreen/{rules_callbacks/url_matches.rb → rules/url_matches_cb.rb} +3 -1
- data/lib/sqreen/{rules_callbacks/user_agent_matches.rb → rules/user_agent_matches_cb.rb} +3 -1
- data/lib/sqreen/{rules_callbacks/waf.rb → rules/waf_cb.rb} +41 -21
- data/lib/sqreen/{rules_callbacks/reflected_xss.rb → rules/xss_cb.rb} +12 -7
- data/lib/sqreen/run_when_called_cb.rb +23 -0
- data/lib/sqreen/runner.rb +25 -7
- data/lib/sqreen/runtime_infos.rb +4 -9
- data/lib/sqreen/safe_json.rb +2 -0
- data/lib/sqreen/sdk.rb +4 -0
- data/lib/sqreen/sensitive_data_redactor.rb +113 -0
- data/lib/sqreen/serializer.rb +2 -0
- data/lib/sqreen/session.rb +2 -0
- data/lib/sqreen/shared_storage.rb +2 -0
- data/lib/sqreen/shared_storage23.rb +2 -0
- data/lib/sqreen/shrink_wrap.rb +16 -0
- data/lib/sqreen/signature_verifier.rb +22 -0
- data/lib/sqreen/sinatra_middleware.rb +16 -0
- data/lib/sqreen/{rules_signature.rb → sqreen_signed_verifier.rb} +7 -17
- data/lib/sqreen/token_invalid_exception.rb +10 -0
- data/lib/sqreen/token_not_found_exception.rb +11 -0
- data/lib/sqreen/trie.rb +5 -64
- data/lib/sqreen/unauthorized.rb +10 -0
- data/lib/sqreen/util.rb +7 -0
- data/lib/sqreen/util/capped_array.rb +35 -0
- data/lib/sqreen/util/capped_hash.rb +41 -0
- data/lib/sqreen/util/capped_string.rb +26 -0
- data/lib/sqreen/util/capper.rb +67 -0
- data/lib/sqreen/version.rb +3 -1
- data/lib/sqreen/waf_error.rb +20 -0
- data/lib/sqreen/weave.rb +12 -0
- data/lib/sqreen/weave/hardcoded.rb +19 -0
- data/lib/sqreen/weave/instrumentor.rb +48 -0
- data/lib/sqreen/weave/legacy.rb +12 -0
- data/lib/sqreen/weave/legacy/instrumentation.rb +406 -0
- data/lib/sqreen/web_server.rb +2 -0
- data/lib/sqreen/web_server/generic.rb +2 -0
- data/lib/sqreen/web_server/passenger.rb +2 -0
- data/lib/sqreen/web_server/puma.rb +2 -0
- data/lib/sqreen/web_server/rainbows.rb +2 -0
- data/lib/sqreen/web_server/thin.rb +2 -0
- data/lib/sqreen/web_server/unicorn.rb +2 -0
- data/lib/sqreen/web_server/webrick.rb +2 -0
- data/lib/sqreen/worker.rb +2 -0
- metadata +105 -39
- data/lib/sqreen/dependency/hook.rb +0 -102
- data/lib/sqreen/rules_callbacks.rb +0 -35
- data/lib/sqreen/rules_callbacks/inspect_rule.rb +0 -25
data/lib/sqreen/util.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/util'
|
|
7
|
+
|
|
8
|
+
class Sqreen::Util::CappedArray < Array
|
|
9
|
+
attr_reader :size_cap, :depth_cap
|
|
10
|
+
|
|
11
|
+
def initialize(*args, &block)
|
|
12
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
|
13
|
+
size_cap = opts[:size_cap] || 150
|
|
14
|
+
depth_cap = opts[:depth_cap] || 10
|
|
15
|
+
@size_cap = size_cap
|
|
16
|
+
@depth_cap = depth_cap
|
|
17
|
+
|
|
18
|
+
super(*args, &block)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def <<(value)
|
|
22
|
+
keep?(size, value) ? super : self
|
|
23
|
+
end
|
|
24
|
+
alias_method :append, :<<
|
|
25
|
+
|
|
26
|
+
def []=(index, value)
|
|
27
|
+
super if keep?(index, value)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def keep?(index, value)
|
|
33
|
+
index < size_cap && (depth_cap > 0 || !value.is_a?(Hash) && !value.is_a?(Array))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/util'
|
|
7
|
+
|
|
8
|
+
class Sqreen::Util::CappedHash < Hash
|
|
9
|
+
attr_reader :size_cap, :depth_cap
|
|
10
|
+
|
|
11
|
+
def initialize(*args, &block)
|
|
12
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
|
13
|
+
size_cap = opts[:size_cap] || 150
|
|
14
|
+
depth_cap = opts[:depth_cap] || 10
|
|
15
|
+
@size_cap = size_cap
|
|
16
|
+
@depth_cap = depth_cap
|
|
17
|
+
|
|
18
|
+
super(*args, &block)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def []=(key, value)
|
|
22
|
+
super if key?(key) || keep?(value)
|
|
23
|
+
end
|
|
24
|
+
alias_method :store, :[]=
|
|
25
|
+
|
|
26
|
+
def merge!(h)
|
|
27
|
+
h.each { |k, v| self[k] = block_given? ? yield(k, self[k], v) : v }
|
|
28
|
+
end
|
|
29
|
+
alias_method :update, :merge!
|
|
30
|
+
|
|
31
|
+
def replace(h)
|
|
32
|
+
keep_if { false }
|
|
33
|
+
merge!(h)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def keep?(value)
|
|
39
|
+
size < size_cap && (depth_cap > 0 || !value.is_a?(Hash) && !value.is_a?(Array))
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/util'
|
|
7
|
+
|
|
8
|
+
class Sqreen::Util::CappedString < String
|
|
9
|
+
attr_reader :size_cap
|
|
10
|
+
|
|
11
|
+
def initialize(*args, &block)
|
|
12
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
|
13
|
+
size_cap = opts[:size_cap] || 4096
|
|
14
|
+
@size_cap = size_cap
|
|
15
|
+
super(*args, &block)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def <<(value)
|
|
19
|
+
return self unless size < size_cap
|
|
20
|
+
|
|
21
|
+
value = value[0, size_cap - size] if size + value.size > size_cap
|
|
22
|
+
|
|
23
|
+
super(value)
|
|
24
|
+
end
|
|
25
|
+
alias_method :concat, :<<
|
|
26
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/util'
|
|
7
|
+
require 'sqreen/util/capped_hash'
|
|
8
|
+
require 'sqreen/util/capped_string'
|
|
9
|
+
require 'sqreen/util/capped_array'
|
|
10
|
+
|
|
11
|
+
class Sqreen::Util::Capper
|
|
12
|
+
attr_reader :string_size_cap, :size_cap, :depth_cap
|
|
13
|
+
|
|
14
|
+
def initialize(opts = {})
|
|
15
|
+
string_size_cap = opts[:string_size_cap] || 4096
|
|
16
|
+
size_cap = opts[:size_cap] || 150
|
|
17
|
+
depth_cap = opts[:depth_cap] || 10
|
|
18
|
+
flat_size_cap = opts[:flat_size_cap] || 10000
|
|
19
|
+
|
|
20
|
+
@string_size_cap = string_size_cap
|
|
21
|
+
@size_cap = size_cap
|
|
22
|
+
@depth_cap = depth_cap
|
|
23
|
+
@flat_size_cap = flat_size_cap
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def call(e)
|
|
27
|
+
r_call(e).first
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def r_call(e, opts = {})
|
|
33
|
+
size = opts[:size] || @flat_size_cap
|
|
34
|
+
depth = opts[:depth] || @depth_cap
|
|
35
|
+
|
|
36
|
+
case e
|
|
37
|
+
when Hash
|
|
38
|
+
h = Sqreen::Util::CappedHash.new(size_cap: size_cap, depth_cap: depth)
|
|
39
|
+
e.each do |k, v|
|
|
40
|
+
break unless size > 0
|
|
41
|
+
k_capped, = r_call(k, size: size, depth: depth - 1)
|
|
42
|
+
v_capped, s = r_call(v, size: size, depth: depth - 1)
|
|
43
|
+
size -= s
|
|
44
|
+
h[k_capped] = v_capped
|
|
45
|
+
end
|
|
46
|
+
[h, h.size]
|
|
47
|
+
when Array
|
|
48
|
+
a = Sqreen::Util::CappedArray.new(size_cap: size_cap, depth_cap: depth)
|
|
49
|
+
e.each do |v|
|
|
50
|
+
break unless size > 0
|
|
51
|
+
c, s = r_call(v, size: size, depth: depth - 1)
|
|
52
|
+
a << c
|
|
53
|
+
size -= s
|
|
54
|
+
end
|
|
55
|
+
[a, a.size]
|
|
56
|
+
when String
|
|
57
|
+
return unless size > 0
|
|
58
|
+
size -= 1
|
|
59
|
+
s = Sqreen::Util::CappedString.new(size_cap: string_size_cap) << e
|
|
60
|
+
[s, 1]
|
|
61
|
+
else
|
|
62
|
+
return unless size > 0
|
|
63
|
+
size -= 1
|
|
64
|
+
[e, 1]
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
data/lib/sqreen/version.rb
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/exception'
|
|
7
|
+
|
|
8
|
+
module Sqreen
|
|
9
|
+
class WAFError < Sqreen::Exception
|
|
10
|
+
attr_reader :rule_name, :error, :data, :args
|
|
11
|
+
|
|
12
|
+
def initialize(rule_name, error, data = nil, args = nil)
|
|
13
|
+
super(error.to_s)
|
|
14
|
+
@rule_name = rule_name
|
|
15
|
+
@error = error
|
|
16
|
+
@data = data
|
|
17
|
+
@args = args
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/sqreen/weave.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/log/loggable'
|
|
7
|
+
|
|
8
|
+
module Sqreen
|
|
9
|
+
module Weave
|
|
10
|
+
include Sqreen::Log::Loggable
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/weave'
|
|
7
|
+
|
|
8
|
+
class Sqreen::Weave::Hardcoded
|
|
9
|
+
# [
|
|
10
|
+
# ### callback for performing sec responses based on ip
|
|
11
|
+
# ### init redefined to implement smartass way to hook it upon the
|
|
12
|
+
# ### framework's middleware #call
|
|
13
|
+
# Sqreen::Rules::RunReqStartActions.new(framework),
|
|
14
|
+
# ### callback for performing sec responses based on user
|
|
15
|
+
# Sqreen::Rules::RunUserActions.new(Sqreen, :identify, 0),
|
|
16
|
+
# ### callback for performing sec responses based on user
|
|
17
|
+
# Sqreen::Rules::RunUserActions.new(Sqreen, :auth_track, 1),
|
|
18
|
+
# ]
|
|
19
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/weave'
|
|
7
|
+
|
|
8
|
+
# rule loader: decouple from runner
|
|
9
|
+
# remote rules from back
|
|
10
|
+
# local rules from local files
|
|
11
|
+
# => rule list (what is a rule?)
|
|
12
|
+
# => to callback (what is a callback?)
|
|
13
|
+
# => to instrumentation (== attach callbacks to their targets using graft)
|
|
14
|
+
|
|
15
|
+
# make shit like instrument framework independent (block passing?)
|
|
16
|
+
# => too much things assume only one framework
|
|
17
|
+
# possible to do run req actions without hardcoded cbs?
|
|
18
|
+
# (data comes from actions command, native cb merely binds to middleware)
|
|
19
|
+
# can cb be a form of abstraction?
|
|
20
|
+
|
|
21
|
+
# rule sig: decouple/split
|
|
22
|
+
# - data signer/checker
|
|
23
|
+
# apply this to rule data
|
|
24
|
+
|
|
25
|
+
# whitelist is mixed in
|
|
26
|
+
|
|
27
|
+
# metrics
|
|
28
|
+
# three dedicated metrics: abstract and isolate
|
|
29
|
+
|
|
30
|
+
class Sqreen::Weave::Instrumentor
|
|
31
|
+
def initialize(metrics_engine)
|
|
32
|
+
### bail out if no metric engine
|
|
33
|
+
### init metric to count calls to sqreen
|
|
34
|
+
### init metric to count request whitelist matches (ip or path whitelist)
|
|
35
|
+
### init metric to count over budget hits
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def instrument!(rules, framework)
|
|
39
|
+
### set up rule signature verifier
|
|
40
|
+
### force clean instrumentation callback list
|
|
41
|
+
### for each rule description, transform into format for adding callback
|
|
42
|
+
### attach framework to callback
|
|
43
|
+
### install callback, observing priority
|
|
44
|
+
### for each hardcoded callback
|
|
45
|
+
### install hardcoded callbacks, observing priority
|
|
46
|
+
### globally declare instrumentation ready
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
4
|
+
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
5
|
+
|
|
6
|
+
require 'sqreen/weave/legacy'
|
|
7
|
+
require 'sqreen/graft/hook_point'
|
|
8
|
+
require 'sqreen/call_countable'
|
|
9
|
+
require 'sqreen/rules'
|
|
10
|
+
require 'sqreen/rules/record_request_context'
|
|
11
|
+
|
|
12
|
+
class Sqreen::Weave::Legacy::Instrumentation
|
|
13
|
+
attr_accessor :metrics_engine
|
|
14
|
+
|
|
15
|
+
def initialize(metrics_engine, opts = {})
|
|
16
|
+
Sqreen::Weave.logger.debug { "#{self.class.name}#initialize #{metrics_engine}" }
|
|
17
|
+
@hooks = []
|
|
18
|
+
|
|
19
|
+
self.metrics_engine = metrics_engine
|
|
20
|
+
|
|
21
|
+
### bail out if no metric engine
|
|
22
|
+
return if metrics_engine.nil?
|
|
23
|
+
|
|
24
|
+
### init metric to count calls to sqreen
|
|
25
|
+
metrics_engine.create_metric(
|
|
26
|
+
'name' => 'sqreen_call_counts',
|
|
27
|
+
'period' => 60,
|
|
28
|
+
'kind' => 'Sum',
|
|
29
|
+
)
|
|
30
|
+
### init metric to count request whitelist matches (ip or path whitelist)
|
|
31
|
+
metrics_engine.create_metric(
|
|
32
|
+
'name' => 'whitelisted',
|
|
33
|
+
'period' => 60,
|
|
34
|
+
'kind' => 'Sum',
|
|
35
|
+
)
|
|
36
|
+
### init metric to count over budget hits
|
|
37
|
+
metrics_engine.create_metric(
|
|
38
|
+
'name' => 'request_overtime',
|
|
39
|
+
'period' => 60,
|
|
40
|
+
'kind' => 'Sum',
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# PerformanceNotifications::Binning
|
|
44
|
+
metrics_engine.create_metric(
|
|
45
|
+
'name' => 'req',
|
|
46
|
+
'period' => opts[:period] || 60,
|
|
47
|
+
'kind' => 'Binning',
|
|
48
|
+
'options' => opts[:perf_metric] || { 'base' => 2.0, 'factor' => 0.1 },
|
|
49
|
+
)
|
|
50
|
+
metrics_engine.create_metric(
|
|
51
|
+
'name' => 'sq',
|
|
52
|
+
'period' => opts[:period] || 60,
|
|
53
|
+
'kind' => 'Binning',
|
|
54
|
+
'options' => opts[:perf_metric] || { 'base' => 2.0, 'factor' => 0.1 },
|
|
55
|
+
)
|
|
56
|
+
metrics_engine.create_metric(
|
|
57
|
+
'name' => 'pct',
|
|
58
|
+
'period' => opts[:period] || 60,
|
|
59
|
+
'kind' => 'Binning',
|
|
60
|
+
'options' => opts[:perf_metric_percent] || { 'base' => 1.3, 'factor' => 1.0 },
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
Sqreen.thread_cpu_time? && metrics_engine.create_metric(
|
|
64
|
+
'name' => 'sq_thread_cpu_pct',
|
|
65
|
+
'period' => opts[:period] || 60,
|
|
66
|
+
'kind' => 'Binning',
|
|
67
|
+
'options' => opts[:perf_metric_percent] || { 'base' => 1.3, 'factor' => 1.0 },
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# needed by Sqreen::Runner#initialize
|
|
72
|
+
def instrument!(rules, framework)
|
|
73
|
+
Sqreen::Weave.logger.debug { "#{rules.count} rules, #{framework}" }
|
|
74
|
+
|
|
75
|
+
strategy = Sqreen.config_get(:weave_strategy)
|
|
76
|
+
if strategy == :prepend && !Module.respond_to?(:prepend)
|
|
77
|
+
Sqreen::Weave.logger.warn { "strategy: #{strategy.inspect} unavailable, falling back to :chain" }
|
|
78
|
+
strategy = :chain
|
|
79
|
+
elsif strategy == :chain && Gem::Specification.select { |s| s.name == 'scout_apm' && Gem::Requirement.new('>= 2.5.2').satisfied_by?(Gem::Version.new(s.version)) }.any?
|
|
80
|
+
Sqreen::Weave.logger.warn { "strategy: #{strategy.inspect} unavailable with scout_apm >= 2.5.2, switching to :prepend" }
|
|
81
|
+
strategy = :prepend
|
|
82
|
+
end
|
|
83
|
+
Sqreen::Weave.logger.debug { "strategy: #{strategy.inspect}" }
|
|
84
|
+
|
|
85
|
+
### set up rule signature verifier
|
|
86
|
+
verifier = nil
|
|
87
|
+
### force clean instrumentation callback list
|
|
88
|
+
@hooks = []
|
|
89
|
+
### for each rule description
|
|
90
|
+
rules.each do |rule|
|
|
91
|
+
Sqreen::Weave.logger.debug { "Processing rule: #{rule['name']}" }
|
|
92
|
+
### transform into format for adding callback
|
|
93
|
+
rule_callback = Sqreen::Rules.cb_from_rule(rule, self, metrics_engine, verifier)
|
|
94
|
+
next unless rule_callback
|
|
95
|
+
### attach framework to callback
|
|
96
|
+
rule_callback.framework = framework
|
|
97
|
+
### install callback, observing priority
|
|
98
|
+
Sqreen::Weave.logger.debug { "Adding rule callback: #{rule_callback}" }
|
|
99
|
+
@hooks << add_callback("weave,rule=#{rule['name']}", rule_callback, strategy)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
### for each hardcoded callback
|
|
103
|
+
hardcoded_callbacks(framework).each do |hard_callback|
|
|
104
|
+
Sqreen::Weave.logger.debug { "Adding hardcoded callback: #{hard_callback}" }
|
|
105
|
+
### install hardcoded callbacks, observing priority
|
|
106
|
+
@hooks << add_callback('weave,hardcoded', hard_callback, strategy)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
metrics_engine = self.metrics_engine
|
|
110
|
+
request_hook = Sqreen::Graft::Hook['Sqreen::ShrinkWrap#call', strategy]
|
|
111
|
+
@hooks << request_hook
|
|
112
|
+
request_hook.add do
|
|
113
|
+
before('wave,meta,request', rank: -100000, mandatory: true) do |_call|
|
|
114
|
+
next unless Sqreen.instrumentation_ready
|
|
115
|
+
|
|
116
|
+
uuid = SecureRandom.uuid
|
|
117
|
+
now = Sqreen::Graft::Timer.read
|
|
118
|
+
Thread.current[:sqreen_http_request] = {
|
|
119
|
+
uuid: uuid,
|
|
120
|
+
start_time: now,
|
|
121
|
+
time_budget: Sqreen.performance_budget,
|
|
122
|
+
time_budget_expended: false,
|
|
123
|
+
timer: Sqreen::Graft::Timer.new("request_#{uuid}"),
|
|
124
|
+
timed_callbacks: [],
|
|
125
|
+
timed_hooks: [],
|
|
126
|
+
timed_hooks_before: [],
|
|
127
|
+
timed_hooks_after: [],
|
|
128
|
+
timed_hooks_raised: [],
|
|
129
|
+
timed_hooks_ensured: [],
|
|
130
|
+
skipped_callbacks: [],
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
Sqreen::Weave.logger.debug { "request.uuid: #{uuid}" }
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
ensured('weave,meta,request', rank: 100000, mandatory: true) do |_call|
|
|
137
|
+
request = Thread.current[:sqreen_http_request]
|
|
138
|
+
|
|
139
|
+
next if request.nil?
|
|
140
|
+
|
|
141
|
+
Thread.current[:sqreen_http_request] = nil
|
|
142
|
+
now = Sqreen::Graft::Timer.read
|
|
143
|
+
utc_now = Time.now.utc
|
|
144
|
+
|
|
145
|
+
request[:timed_callbacks].each do |timer|
|
|
146
|
+
duration = timer.duration
|
|
147
|
+
# stop = now
|
|
148
|
+
# start = now - duration
|
|
149
|
+
timer.tag =~ /weave,rule=(.*)$/ && rule = $1
|
|
150
|
+
timer.tag =~ /@before/ && whence = 'pre'
|
|
151
|
+
timer.tag =~ /@after/ && whence = 'post'
|
|
152
|
+
timer.tag =~ /@raised/ && whence = 'failing'
|
|
153
|
+
|
|
154
|
+
next unless rule && whence
|
|
155
|
+
|
|
156
|
+
# Sqreen::PerformanceNotifications.notify(rule, whence, start, stop)
|
|
157
|
+
# => BinnedMetrics
|
|
158
|
+
metric_name = "sq.#{rule}.#{whence}"
|
|
159
|
+
unless metrics_engine.metric?(metric_name)
|
|
160
|
+
metrics_engine.create_metric(
|
|
161
|
+
'name' => metric_name,
|
|
162
|
+
'period' => 60,
|
|
163
|
+
'kind' => 'Binning',
|
|
164
|
+
'options' => { 'base' => 2.0, 'factor' => 0.1 },
|
|
165
|
+
)
|
|
166
|
+
end
|
|
167
|
+
metrics_engine.update(metric_name, now, nil, duration * 1000)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
metric_name = 'sq.hooks_pre.pre'
|
|
171
|
+
duration = request[:timed_hooks_before].sum(&:duration)
|
|
172
|
+
unless metrics_engine.metric?(metric_name)
|
|
173
|
+
metrics_engine.create_metric(
|
|
174
|
+
'name' => metric_name,
|
|
175
|
+
'period' => 60,
|
|
176
|
+
'kind' => 'Binning',
|
|
177
|
+
'options' => { 'base' => 2.0, 'factor' => 0.1 },
|
|
178
|
+
)
|
|
179
|
+
end
|
|
180
|
+
metrics_engine.update(metric_name, now, nil, duration * 1000)
|
|
181
|
+
|
|
182
|
+
metric_name = 'sq.hooks_post.post'
|
|
183
|
+
duration = request[:timed_hooks_after].sum(&:duration)
|
|
184
|
+
unless metrics_engine.metric?(metric_name)
|
|
185
|
+
metrics_engine.create_metric(
|
|
186
|
+
'name' => metric_name,
|
|
187
|
+
'period' => 60,
|
|
188
|
+
'kind' => 'Binning',
|
|
189
|
+
'options' => { 'base' => 2.0, 'factor' => 0.1 },
|
|
190
|
+
)
|
|
191
|
+
end
|
|
192
|
+
metrics_engine.update(metric_name, now, nil, duration * 1000)
|
|
193
|
+
|
|
194
|
+
metric_name = 'sq.hooks_failing.failing'
|
|
195
|
+
duration = request[:timed_hooks_raised].sum(&:duration)
|
|
196
|
+
unless metrics_engine.metric?(metric_name)
|
|
197
|
+
metrics_engine.create_metric(
|
|
198
|
+
'name' => metric_name,
|
|
199
|
+
'period' => 60,
|
|
200
|
+
'kind' => 'Binning',
|
|
201
|
+
'options' => { 'base' => 2.0, 'factor' => 0.1 },
|
|
202
|
+
)
|
|
203
|
+
end
|
|
204
|
+
metrics_engine.update(metric_name, now, nil, duration * 1000)
|
|
205
|
+
|
|
206
|
+
skipped = request[:skipped_callbacks].map(&:name)
|
|
207
|
+
Sqreen::Weave.logger.debug { "request:#{request[:uuid]} callback.skipped.size: #{skipped.count} callback.skipped: [#{skipped.join(', ')}]" }
|
|
208
|
+
timer = request[:timer]
|
|
209
|
+
total = timer.duration
|
|
210
|
+
Sqreen::Weave.logger.debug { "request:#{request[:uuid]} timer.total: #{'%.03fus' % (total * 1_000_000)} timer.size: #{timer.size}" }
|
|
211
|
+
timings = request[:timed_callbacks].map(&:to_s)
|
|
212
|
+
total = request[:timed_callbacks].sum(&:duration)
|
|
213
|
+
Sqreen::Weave.logger.debug { "request:#{request[:uuid]} callback.total: #{'%.03fus' % (total * 1_000_000)} callback.timings: [#{timings.join(', ')}]" }
|
|
214
|
+
timings = request[:timed_hooks].map(&:to_s)
|
|
215
|
+
total = request[:timed_hooks].sum(&:duration)
|
|
216
|
+
Sqreen::Weave.logger.debug { "request:#{request[:uuid]} hook.total: #{'%.03fus' % (total * 1_000_000)} hook.timings: [#{timings.join(', ')}]" }
|
|
217
|
+
|
|
218
|
+
skipped = request[:skipped_callbacks].map(&:name)
|
|
219
|
+
skipped_rule_name = skipped.first && skipped.first =~ /weave,rule=(.*)$/ && $1
|
|
220
|
+
Sqreen.observations_queue.push(['request_overtime', skipped_rule_name, 1, utc_now]) if skipped_rule_name
|
|
221
|
+
|
|
222
|
+
sqreen_request_duration = total
|
|
223
|
+
Sqreen.observations_queue.push(['sq', nil, sqreen_request_duration * 1000, utc_now])
|
|
224
|
+
|
|
225
|
+
request_duration = now - request[:start_time]
|
|
226
|
+
Sqreen.observations_queue.push(['req', nil, request_duration * 1000, utc_now])
|
|
227
|
+
|
|
228
|
+
sqreen_request_ratio = (sqreen_request_duration * 100.0) / (request_duration - sqreen_request_duration)
|
|
229
|
+
Sqreen.observations_queue.push(['pct', nil, sqreen_request_ratio, utc_now])
|
|
230
|
+
end
|
|
231
|
+
end.install
|
|
232
|
+
|
|
233
|
+
### globally declare instrumentation ready
|
|
234
|
+
Sqreen.instrumentation_ready = true
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# needed by Sqreen::Runner
|
|
238
|
+
def remove_all_callbacks
|
|
239
|
+
Sqreen.instrumentation_ready = false
|
|
240
|
+
|
|
241
|
+
loop do
|
|
242
|
+
hook = @hooks.pop
|
|
243
|
+
break unless hook
|
|
244
|
+
Sqreen::Weave.logger.debug { "hook.deinstrument: #{hook}" }
|
|
245
|
+
hook.uninstall
|
|
246
|
+
hook.clear
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# needed by #instrument!
|
|
251
|
+
def add_callback(rule, callback, strategy)
|
|
252
|
+
Sqreen::Weave.logger.debug { "Adding rule: #{rule} callback: #{callback}" }
|
|
253
|
+
klass = callback.klass
|
|
254
|
+
method = callback.method
|
|
255
|
+
|
|
256
|
+
if Sqreen::Graft::HookPoint.new("#{klass}.#{method}").exist?
|
|
257
|
+
hook_point = "#{klass}.#{method}"
|
|
258
|
+
elsif Sqreen::Graft::HookPoint.new("#{klass}##{method}").exist?
|
|
259
|
+
hook_point = "#{klass}##{method}"
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
return if hook_point.nil?
|
|
263
|
+
|
|
264
|
+
priority = callback.priority || 100
|
|
265
|
+
block = callback.respond_to?(:block) ? callback.block : true
|
|
266
|
+
ignore = -> { callback.whitelisted? } if callback.respond_to?(:whitelisted?)
|
|
267
|
+
|
|
268
|
+
hook = Sqreen::Graft::Hook[hook_point, strategy]
|
|
269
|
+
hook.add do
|
|
270
|
+
if callback.pre?
|
|
271
|
+
before(rule, rank: priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
|
|
272
|
+
return unless Thread.current[:sqreen_http_request]
|
|
273
|
+
|
|
274
|
+
i = call.instance
|
|
275
|
+
a = call.args
|
|
276
|
+
r = call.remaining
|
|
277
|
+
|
|
278
|
+
Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#pre instance=#{i}" }
|
|
279
|
+
begin
|
|
280
|
+
ret = callback.pre(i, a, r)
|
|
281
|
+
rescue StandardError => e
|
|
282
|
+
Sqreen::Weave.logger.warn { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#pre instance=#{i} => exception=#{e}" }
|
|
283
|
+
if callback.respond_to?(:record_exception)
|
|
284
|
+
callback.record_exception(e)
|
|
285
|
+
else
|
|
286
|
+
Sqreen::RemoteException.record(e)
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#pre instance=#{i} => return=#{ret.inspect}" }
|
|
290
|
+
|
|
291
|
+
case ret[:status]
|
|
292
|
+
when :skip, 'skip'
|
|
293
|
+
throw(b, b.return(ret[:new_return_value]).break!) if ret.key?(:new_return_value)
|
|
294
|
+
when :modify_args, 'modify_args'
|
|
295
|
+
throw(b, b.args(ret[:args]))
|
|
296
|
+
when :raise, 'raise'
|
|
297
|
+
throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
|
|
298
|
+
throw(b, b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required.")))
|
|
299
|
+
end unless ret.nil?
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
if callback.post?
|
|
304
|
+
after(rule, rank: -priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
|
|
305
|
+
return unless Thread.current[:sqreen_http_request]
|
|
306
|
+
|
|
307
|
+
i = call.instance
|
|
308
|
+
v = call.returned
|
|
309
|
+
a = call.args
|
|
310
|
+
r = call.remaining
|
|
311
|
+
|
|
312
|
+
Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#post instance=#{i}" }
|
|
313
|
+
begin
|
|
314
|
+
ret = callback.post(v, i, a, r)
|
|
315
|
+
rescue StandardError => e
|
|
316
|
+
Sqreen::Weave.logger.warn { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#post instance=#{i} => exception=#{e}" }
|
|
317
|
+
if callback.respond_to?(:record_exception)
|
|
318
|
+
callback.record_exception(e)
|
|
319
|
+
else
|
|
320
|
+
Sqreen::RemoteException.record(e)
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#post instance=#{i} => return=#{ret.inspect}" }
|
|
324
|
+
|
|
325
|
+
case ret[:status]
|
|
326
|
+
when :override, 'override'
|
|
327
|
+
throw(b, b.return(ret[:new_return_value])) if ret.key?(:new_return_value)
|
|
328
|
+
when :raise, 'raise'
|
|
329
|
+
throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
|
|
330
|
+
throw(b, b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required.")))
|
|
331
|
+
end unless ret.nil?
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
if callback.failing?
|
|
336
|
+
raised(rule, rank: priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
|
|
337
|
+
return unless Thread.current[:sqreen_http_request]
|
|
338
|
+
|
|
339
|
+
i = call.instance
|
|
340
|
+
e = call.raised
|
|
341
|
+
a = call.args
|
|
342
|
+
r = call.remaining
|
|
343
|
+
|
|
344
|
+
Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#failing instance=#{i}" }
|
|
345
|
+
begin
|
|
346
|
+
ret = callback.failing(e, i, a, r)
|
|
347
|
+
rescue StandardError => e
|
|
348
|
+
Sqreen::Weave.logger.warn { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#failing instance=#{i} => exception=#{e}" }
|
|
349
|
+
if callback.respond_to?(:record_exception)
|
|
350
|
+
callback.record_exception(e)
|
|
351
|
+
else
|
|
352
|
+
Sqreen::RemoteException.record(e)
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#failing instance=#{i} => return=#{ret.inspect}" }
|
|
356
|
+
|
|
357
|
+
raise e if ret.nil?
|
|
358
|
+
|
|
359
|
+
case ret[:status]
|
|
360
|
+
when :override, 'override'
|
|
361
|
+
throw(b, b.return(ret[:new_return_value])) if ret.key?(:new_return_value)
|
|
362
|
+
when :retry, 'retry'
|
|
363
|
+
throw(b, b.retry)
|
|
364
|
+
when :raise, 'raise'
|
|
365
|
+
throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
|
|
366
|
+
throw(b, b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required.")))
|
|
367
|
+
when :reraise, 'reraise'
|
|
368
|
+
throw(b, b.raise(e))
|
|
369
|
+
else
|
|
370
|
+
throw(b, b.raise(e))
|
|
371
|
+
end unless ret.nil?
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
end.install
|
|
375
|
+
|
|
376
|
+
hook
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# needed by Sqreen::Rules.cb_from_rule
|
|
380
|
+
def valid_method?(klass, method)
|
|
381
|
+
if Sqreen::Graft::HookPoint.new("#{klass}.#{method}").exist?
|
|
382
|
+
Sqreen::Weave.logger.debug { "HookPoint found: #{klass}.#{method}" }
|
|
383
|
+
true
|
|
384
|
+
elsif Sqreen::Graft::HookPoint.new("#{klass}##{method}").exist?
|
|
385
|
+
Sqreen::Weave.logger.debug { "HookPoint found: #{klass}##{method}" }
|
|
386
|
+
true
|
|
387
|
+
else
|
|
388
|
+
Sqreen::Weave.logger.debug { "HookPoint not found: #{klass} #{method}" }
|
|
389
|
+
false
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# needed by #instrument!
|
|
394
|
+
def hardcoded_callbacks(framework)
|
|
395
|
+
[
|
|
396
|
+
### callback for performing sec responses based on ip
|
|
397
|
+
### init redefined to implement smartass way to hook it upon the
|
|
398
|
+
### framework's middleware #call
|
|
399
|
+
Sqreen::Rules::RunReqStartActions.new(framework),
|
|
400
|
+
### callback for performing sec responses based on user
|
|
401
|
+
Sqreen::Rules::RunUserActions.new(Sqreen, :identify, 0),
|
|
402
|
+
### callback for performing sec responses based on user
|
|
403
|
+
Sqreen::Rules::RunUserActions.new(Sqreen, :auth_track, 1),
|
|
404
|
+
]
|
|
405
|
+
end
|
|
406
|
+
end
|