sqreen 1.18.4-java → 1.19.2-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.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/lib/sqreen/actions.rb +2 -0
  4. data/lib/sqreen/actions/actions_index.rb +16 -0
  5. data/lib/sqreen/actions/base.rb +4 -10
  6. data/lib/sqreen/actions/block_ip.rb +2 -0
  7. data/lib/sqreen/actions/block_user.rb +2 -0
  8. data/lib/sqreen/actions/ip_range_indexed_action_class.rb +4 -24
  9. data/lib/sqreen/actions/ip_ranges_index.rb +32 -11
  10. data/lib/sqreen/actions/redirect_ip.rb +2 -0
  11. data/lib/sqreen/actions/redirect_user.rb +2 -0
  12. data/lib/sqreen/actions/repository.rb +27 -8
  13. data/lib/sqreen/actions/unknown_action_type.rb +4 -0
  14. data/lib/sqreen/actions/user_action_class.rb +5 -30
  15. data/lib/sqreen/actions/users_index.rb +35 -0
  16. data/lib/sqreen/agent.rb +2 -1
  17. data/lib/sqreen/attack_blocked.rb +2 -0
  18. data/lib/sqreen/backport.rb +2 -0
  19. data/lib/sqreen/backport/clock_gettime.rb +74 -0
  20. data/lib/sqreen/backport/original_name.rb +2 -0
  21. data/lib/sqreen/binding_accessor.rb +2 -0
  22. data/lib/sqreen/binding_accessor/path_elem.rb +2 -0
  23. data/lib/sqreen/binding_accessor/transforms.rb +8 -1
  24. data/lib/sqreen/call_countable.rb +2 -0
  25. data/lib/sqreen/capped_queue.rb +2 -0
  26. data/lib/sqreen/cb.rb +2 -0
  27. data/lib/sqreen/cb_tree.rb +2 -0
  28. data/lib/sqreen/condition_evaluator.rb +2 -0
  29. data/lib/sqreen/conditionable.rb +2 -0
  30. data/lib/sqreen/configuration.rb +14 -0
  31. data/lib/sqreen/context.rb +2 -0
  32. data/lib/sqreen/default_cb.rb +2 -0
  33. data/lib/sqreen/deferred_logger.rb +2 -0
  34. data/lib/sqreen/deliveries.rb +2 -0
  35. data/lib/sqreen/deliveries/batch.rb +2 -0
  36. data/lib/sqreen/deliveries/simple.rb +2 -0
  37. data/lib/sqreen/dependency.rb +3 -1
  38. data/lib/sqreen/dependency/detector.rb +22 -14
  39. data/lib/sqreen/dependency/libsqreen.rb +4 -0
  40. data/lib/sqreen/dependency/new_relic.rb +2 -0
  41. data/lib/sqreen/dependency/rack.rb +10 -5
  42. data/lib/sqreen/dependency/rails.rb +4 -0
  43. data/lib/sqreen/dependency/sentry.rb +2 -0
  44. data/lib/sqreen/dependency/sinatra.rb +12 -1
  45. data/lib/sqreen/encoding_sanitizer.rb +2 -0
  46. data/lib/sqreen/error_handling_middleware.rb +2 -0
  47. data/lib/sqreen/event.rb +2 -0
  48. data/lib/sqreen/events/attack.rb +2 -0
  49. data/lib/sqreen/events/remote_exception.rb +2 -0
  50. data/lib/sqreen/events/request_record.rb +2 -0
  51. data/lib/sqreen/exception.rb +2 -0
  52. data/lib/sqreen/formatter_with_tid.rb +2 -0
  53. data/lib/sqreen/framework_cb.rb +2 -0
  54. data/lib/sqreen/frameworks.rb +2 -0
  55. data/lib/sqreen/frameworks/generic.rb +2 -0
  56. data/lib/sqreen/frameworks/rails.rb +1 -0
  57. data/lib/sqreen/frameworks/rails3.rb +2 -0
  58. data/lib/sqreen/frameworks/request_recorder.rb +2 -0
  59. data/lib/sqreen/frameworks/sinatra.rb +2 -0
  60. data/lib/sqreen/frameworks/sqreen_test.rb +2 -0
  61. data/lib/sqreen/graft.rb +12 -0
  62. data/lib/sqreen/graft/call.rb +150 -0
  63. data/lib/sqreen/{dependency → graft}/callback.rb +12 -4
  64. data/lib/sqreen/graft/hook.rb +316 -0
  65. data/lib/sqreen/{dependency → graft}/hook_point.rb +152 -33
  66. data/lib/sqreen/graft/hook_point_error.rb +10 -0
  67. data/lib/sqreen/invalid_signature_exception.rb +2 -0
  68. data/lib/sqreen/js.rb +2 -0
  69. data/lib/sqreen/js/call_context.rb +2 -0
  70. data/lib/sqreen/js/context_pool.rb +2 -0
  71. data/lib/sqreen/js/exec_js_runnable.rb +2 -0
  72. data/lib/sqreen/js/execjs_adapter.rb +2 -0
  73. data/lib/sqreen/js/executable_js.rb +2 -0
  74. data/lib/sqreen/js/js_service.rb +2 -0
  75. data/lib/sqreen/js/js_service_adapter.rb +2 -0
  76. data/lib/sqreen/js/mini_racer_adapter.rb +2 -0
  77. data/lib/sqreen/js/mini_racer_executable_js.rb +2 -0
  78. data/lib/sqreen/js/thread_local_exec_js_runnable.rb +2 -0
  79. data/lib/sqreen/legacy.rb +8 -0
  80. data/lib/sqreen/{instrumentation.rb → legacy/instrumentation.rb} +31 -2
  81. data/lib/sqreen/log.rb +2 -0
  82. data/lib/sqreen/log/loggable.rb +28 -0
  83. data/lib/sqreen/logger.rb +2 -0
  84. data/lib/sqreen/metrics.rb +2 -0
  85. data/lib/sqreen/metrics/average.rb +2 -0
  86. data/lib/sqreen/metrics/base.rb +2 -0
  87. data/lib/sqreen/metrics/binning.rb +2 -0
  88. data/lib/sqreen/metrics/collect.rb +2 -0
  89. data/lib/sqreen/metrics/sum.rb +2 -0
  90. data/lib/sqreen/metrics_store.rb +2 -0
  91. data/lib/sqreen/metrics_store/already_registered_metric.rb +2 -0
  92. data/lib/sqreen/metrics_store/unknown_metric.rb +2 -0
  93. data/lib/sqreen/metrics_store/unregistered_metric.rb +2 -0
  94. data/lib/sqreen/middleware.rb +2 -0
  95. data/lib/sqreen/mono_time.rb +2 -0
  96. data/lib/sqreen/node.rb +2 -0
  97. data/lib/sqreen/not_implemented_yet.rb +2 -0
  98. data/lib/sqreen/null_logger.rb +2 -0
  99. data/lib/sqreen/payload_creator.rb +2 -0
  100. data/lib/sqreen/payload_creator/header_section.rb +2 -0
  101. data/lib/sqreen/performance_notifications.rb +2 -0
  102. data/lib/sqreen/performance_notifications/binned_metrics.rb +2 -0
  103. data/lib/sqreen/performance_notifications/log.rb +2 -0
  104. data/lib/sqreen/performance_notifications/log_performance.rb +2 -0
  105. data/lib/sqreen/performance_notifications/metrics.rb +2 -0
  106. data/lib/sqreen/performance_notifications/newrelic.rb +2 -0
  107. data/lib/sqreen/prefix.rb +2 -0
  108. data/lib/sqreen/rails_middleware.rb +2 -0
  109. data/lib/sqreen/remote_command.rb +2 -0
  110. data/lib/sqreen/remote_command/failure_output.rb +5 -0
  111. data/lib/sqreen/rules.rb +2 -0
  112. data/lib/sqreen/rules/attrs.rb +2 -0
  113. data/lib/sqreen/rules/auth_track_cb.rb +2 -0
  114. data/lib/sqreen/rules/binding_accessor_matcher_cb.rb +2 -0
  115. data/lib/sqreen/rules/binding_accessor_metrics.rb +2 -0
  116. data/lib/sqreen/rules/blacklist_ips_cb.rb +2 -0
  117. data/lib/sqreen/rules/count_http_codes.rb +2 -0
  118. data/lib/sqreen/rules/crawler_user_agent_matches_cb.rb +2 -0
  119. data/lib/sqreen/rules/crawler_user_agent_matches_metrics_cb.rb +2 -0
  120. data/lib/sqreen/rules/custom_error_cb.rb +2 -0
  121. data/lib/sqreen/rules/devise_auth_track_cb.rb +2 -0
  122. data/lib/sqreen/rules/devise_signup_track_cb.rb +2 -0
  123. data/lib/sqreen/rules/execjs_cb.rb +2 -0
  124. data/lib/sqreen/rules/headers_insert_cb.rb +7 -0
  125. data/lib/sqreen/rules/matcher_rule.rb +2 -0
  126. data/lib/sqreen/rules/not_found_cb.rb +7 -0
  127. data/lib/sqreen/rules/rails_parameters_cb.rb +2 -0
  128. data/lib/sqreen/rules/record_request_context.rb +2 -0
  129. data/lib/sqreen/rules/regexp_rule_cb.rb +2 -0
  130. data/lib/sqreen/rules/rule_cb.rb +2 -0
  131. data/lib/sqreen/rules/run_req_start_actions.rb +3 -1
  132. data/lib/sqreen/rules/run_user_actions.rb +3 -1
  133. data/lib/sqreen/rules/shell_env_cb.rb +2 -0
  134. data/lib/sqreen/rules/signup_track_cb.rb +2 -0
  135. data/lib/sqreen/rules/update_request_context.rb +2 -0
  136. data/lib/sqreen/rules/url_matches_cb.rb +2 -0
  137. data/lib/sqreen/rules/user_agent_matches_cb.rb +2 -0
  138. data/lib/sqreen/rules/waf_cb.rb +30 -7
  139. data/lib/sqreen/rules/xss_cb.rb +2 -0
  140. data/lib/sqreen/run_when_called_cb.rb +2 -0
  141. data/lib/sqreen/runner.rb +25 -7
  142. data/lib/sqreen/runtime_infos.rb +2 -0
  143. data/lib/sqreen/safe_json.rb +2 -0
  144. data/lib/sqreen/sdk.rb +4 -0
  145. data/lib/sqreen/sensitive_data_redactor.rb +2 -0
  146. data/lib/sqreen/serializer.rb +2 -0
  147. data/lib/sqreen/session.rb +2 -0
  148. data/lib/sqreen/shared_storage.rb +2 -0
  149. data/lib/sqreen/shared_storage23.rb +2 -0
  150. data/lib/sqreen/shrink_wrap.rb +16 -0
  151. data/lib/sqreen/signature_verifier.rb +2 -0
  152. data/lib/sqreen/sinatra_middleware.rb +2 -0
  153. data/lib/sqreen/sqreen_signed_verifier.rb +2 -0
  154. data/lib/sqreen/token_invalid_exception.rb +2 -0
  155. data/lib/sqreen/token_not_found_exception.rb +2 -0
  156. data/lib/sqreen/trie.rb +2 -0
  157. data/lib/sqreen/unauthorized.rb +2 -0
  158. data/lib/sqreen/util.rb +5 -0
  159. data/lib/sqreen/util/capped_array.rb +2 -0
  160. data/lib/sqreen/util/capped_hash.rb +2 -0
  161. data/lib/sqreen/util/capped_string.rb +2 -0
  162. data/lib/sqreen/util/capper.rb +2 -0
  163. data/lib/sqreen/version.rb +3 -1
  164. data/lib/sqreen/waf_error.rb +2 -0
  165. data/lib/sqreen/weave.rb +12 -0
  166. data/lib/sqreen/weave/hardcoded.rb +19 -0
  167. data/lib/sqreen/weave/instrumentor.rb +48 -0
  168. data/lib/sqreen/weave/legacy.rb +12 -0
  169. data/lib/sqreen/weave/legacy/instrumentation.rb +406 -0
  170. data/lib/sqreen/web_server.rb +2 -0
  171. data/lib/sqreen/web_server/generic.rb +2 -0
  172. data/lib/sqreen/web_server/passenger.rb +2 -0
  173. data/lib/sqreen/web_server/puma.rb +2 -0
  174. data/lib/sqreen/web_server/rainbows.rb +2 -0
  175. data/lib/sqreen/web_server/thin.rb +2 -0
  176. data/lib/sqreen/web_server/unicorn.rb +2 -0
  177. data/lib/sqreen/web_server/webrick.rb +2 -0
  178. data/lib/sqreen/worker.rb +2 -0
  179. metadata +26 -7
  180. data/lib/sqreen/dependency/hook.rb +0 -102
@@ -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/weave'
7
+
8
+ module Sqreen
9
+ module Weave
10
+ module Legacy; end
11
+ end
12
+ 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
+ next 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? || !ret.is_a?(Hash)
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
+ next 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? || !ret.is_a?(Hash)
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
+ next 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
+ throw(b, b.raise(e)) if ret.nil? || !ret.is_a?(Hash)
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? || !ret.is_a?(Hash)
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
@@ -1,3 +1,5 @@
1
+ # typed: ignore
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -1,3 +1,5 @@
1
+ # typed: true
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -1,3 +1,5 @@
1
+ # typed: ignore
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -1,3 +1,5 @@
1
+ # typed: ignore
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5
 
@@ -1,3 +1,5 @@
1
+ # typed: ignore
2
+
1
3
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
5