sqreen 1.18.6 → 1.19.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -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 +5 -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 +2 -0
  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 +21 -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 +398 -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 -11
  180. data/lib/sqreen/dependency/hook.rb +0 -102
@@ -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
 
@@ -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: 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
 
data/lib/sqreen/runner.rb CHANGED
@@ -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
 
@@ -18,8 +20,9 @@ require 'sqreen/deliveries/simple'
18
20
  require 'sqreen/deliveries/batch'
19
21
  require 'sqreen/performance_notifications/metrics'
20
22
  require 'sqreen/performance_notifications/binned_metrics'
21
- require 'sqreen/instrumentation'
23
+ require 'sqreen/legacy/instrumentation'
22
24
  require 'sqreen/call_countable'
25
+ require 'sqreen/weave/legacy/instrumentation'
23
26
 
24
27
  module Sqreen
25
28
  @features = {}
@@ -117,7 +120,12 @@ module Sqreen
117
120
  register_exit_cb if set_at_exit
118
121
 
119
122
  self.metrics_engine = MetricsStore.new
120
- @instrumenter = Instrumentation.new(metrics_engine)
123
+
124
+ if @configuration.get(:weave)
125
+ @instrumenter = Sqreen::Weave::Legacy::Instrumentation.new(metrics_engine)
126
+ else
127
+ @instrumenter = Sqreen::Legacy::Instrumentation.new(metrics_engine)
128
+ end
121
129
 
122
130
  Sqreen.log.debug "Using token #{@token}"
123
131
  response = create_session(session_class)
@@ -235,7 +243,7 @@ module Sqreen
235
243
  def remove_instrumentation(_context_infos = {})
236
244
  Sqreen.log.debug 'Removing instrumentation'
237
245
  instrumenter.remove_all_callbacks
238
- Sqreen::Actions::Repository.instance.clear
246
+ Sqreen::Actions::Repository.clear
239
247
  Sqreen.log.debug 'Instrumentation removed'
240
248
  true
241
249
  end
@@ -244,7 +252,6 @@ module Sqreen
244
252
  Sqreen.log.debug 'Reloading rules'
245
253
  rulespack_id, rules = load_rules
246
254
  instrumenter.remove_all_callbacks
247
- Sqreen::Actions::Repository.instance.clear
248
255
 
249
256
  @framework.instrument_when_ready!(instrumenter, rules)
250
257
  Sqreen.log.debug 'Rules reloaded'
@@ -304,12 +311,18 @@ module Sqreen
304
311
  Sqreen.update_features(features)
305
312
  session.request_compression = features['request_compression'] if session
306
313
  self.performance_metrics_period = features['performance_metrics_period']
314
+
315
+ unless @configuration.get(:weave)
316
+
307
317
  config_binned_metrics(features['perf_level'] || DEFAULT_PERF_LEVEL,
308
318
  features['perf_base'] || PerformanceNotifications::BinnedMetrics::DEFAULT_PERF_BASE,
309
319
  features['perf_unit'] || PerformanceNotifications::BinnedMetrics::DEFAULT_PERF_UNIT,
310
320
  features['perf_pct_base'] || PerformanceNotifications::BinnedMetrics::DEFAULT_PERF_PCT_BASE,
311
321
  features['perf_pct_unit'] || PerformanceNotifications::BinnedMetrics::DEFAULT_PERF_PCT_UNIT,
312
322
  )
323
+
324
+ end
325
+
313
326
  self.call_counts_metrics_period = features['call_counts_metrics_period']
314
327
  hd = features['heartbeat_delay'].to_i
315
328
  self.heartbeat_delay = hd if hd > 0
@@ -456,13 +469,12 @@ module Sqreen
456
469
  def load_actions(hashes)
457
470
  unsupported = Set.new
458
471
 
459
- repos = Sqreen::Actions::Repository.instance
460
- repos.clear
472
+ new_repos = Sqreen::Actions::Repository.new
461
473
 
462
474
  actions = hashes.map do |h|
463
475
  begin
464
476
  act = Sqreen::Actions.deserialize_action(h)
465
- repos.add h['parameters'], act
477
+ new_repos.add h['parameters'], act
466
478
  act
467
479
  rescue Sqreen::Actions::UnknownActionType => e
468
480
  Sqreen.log.warn("Unsupported action type: #{e.action_type}")
@@ -476,6 +488,8 @@ module Sqreen
476
488
  actions = actions.reject(&:nil?)
477
489
  Sqreen.log.debug("Added #{actions.size} valid actions")
478
490
 
491
+ Sqreen::Actions::Repository.current = new_repos
492
+
479
493
  unsupported
480
494
  end
481
495
  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
 
data/lib/sqreen/sdk.rb CHANGED
@@ -1,6 +1,10 @@
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
 
6
+ require 'sqreen/frameworks'
7
+
4
8
  # Sqreen Namespace
5
9
  module Sqreen
6
10
 
@@ -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: 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: false
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
 
@@ -0,0 +1,16 @@
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
+ module Sqreen
7
+ class ShrinkWrap
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
@@ -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: 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: false
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: strong
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: strong
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
 
data/lib/sqreen/trie.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # typed: false
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: strong
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
 
data/lib/sqreen/util.rb CHANGED
@@ -1,2 +1,7 @@
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
+
1
6
  module Sqreen; end
2
7
  module Sqreen::Util; end
@@ -1,3 +1,5 @@
1
+ # typed: false
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: false
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: false
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,6 +1,8 @@
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
 
4
6
  module Sqreen
5
- VERSION = '1.18.6'.freeze
7
+ VERSION = '1.19.0.beta1'.freeze
6
8
  end
@@ -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
 
@@ -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,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,398 @@
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
+ end
80
+ Sqreen::Weave.logger.debug { "strategy: #{strategy.inspect}" }
81
+
82
+ ### set up rule signature verifier
83
+ verifier = nil
84
+ ### force clean instrumentation callback list
85
+ @hooks = []
86
+ ### for each rule description
87
+ rules.each do |rule|
88
+ Sqreen::Weave.logger.debug { "Processing rule: #{rule['name']}" }
89
+ ### transform into format for adding callback
90
+ rule_callback = Sqreen::Rules.cb_from_rule(rule, self, metrics_engine, verifier)
91
+ next unless rule_callback
92
+ ### attach framework to callback
93
+ rule_callback.framework = framework
94
+ ### install callback, observing priority
95
+ Sqreen::Weave.logger.debug { "Adding rule callback: #{rule_callback}" }
96
+ @hooks << add_callback("weave,rule=#{rule['name']}", rule_callback, strategy)
97
+ end
98
+
99
+ ### for each hardcoded callback
100
+ hardcoded_callbacks(framework).each do |hard_callback|
101
+ Sqreen::Weave.logger.debug { "Adding hardcoded callback: #{hard_callback}" }
102
+ ### install hardcoded callbacks, observing priority
103
+ @hooks << add_callback('weave,hardcoded', hard_callback, strategy)
104
+ end
105
+
106
+ metrics_engine = self.metrics_engine
107
+ request_hook = Sqreen::Graft::Hook['Sqreen::ShrinkWrap#call', strategy]
108
+ @hooks << request_hook
109
+ request_hook.add do
110
+ before('wave,meta,request', rank: -100000, mandatory: true) do |_call|
111
+ uuid = SecureRandom.uuid
112
+ now = Sqreen::Graft::Timer.read
113
+ Thread.current[:sqreen_http_request] = {
114
+ uuid: uuid,
115
+ start_time: now,
116
+ time_budget: Sqreen.performance_budget,
117
+ time_budget_expended: false,
118
+ timer: Sqreen::Graft::Timer.new("request_#{uuid}"),
119
+ timed_callbacks: [],
120
+ timed_hooks: [],
121
+ timed_hooks_before: [],
122
+ timed_hooks_after: [],
123
+ timed_hooks_raised: [],
124
+ timed_hooks_ensured: [],
125
+ skipped_callbacks: [],
126
+ }
127
+
128
+ Sqreen::Weave.logger.debug { "request.uuid: #{uuid}" }
129
+ end
130
+
131
+ ensured('weave,meta,request', rank: 100000, mandatory: true) do |_call|
132
+ request = Thread.current[:sqreen_http_request]
133
+ Thread.current[:sqreen_http_request] = nil
134
+ now = Sqreen::Graft::Timer.read
135
+ utc_now = Time.now.utc
136
+
137
+ request[:timed_callbacks].each do |timer|
138
+ duration = timer.duration
139
+ # stop = now
140
+ # start = now - duration
141
+ timer.tag =~ /weave,rule=(.*)$/ && rule = $1
142
+ timer.tag =~ /@before/ && whence = 'pre'
143
+ timer.tag =~ /@after/ && whence = 'post'
144
+ timer.tag =~ /@raised/ && whence = 'failing'
145
+
146
+ next unless rule && whence
147
+
148
+ # Sqreen::PerformanceNotifications.notify(rule, whence, start, stop)
149
+ # => BinnedMetrics
150
+ metric_name = "sq.#{rule}.#{whence}"
151
+ unless metrics_engine.metric?(metric_name)
152
+ metrics_engine.create_metric(
153
+ 'name' => metric_name,
154
+ 'period' => 60,
155
+ 'kind' => 'Binning',
156
+ 'options' => { 'base' => 2.0, 'factor' => 0.1 },
157
+ )
158
+ end
159
+ metrics_engine.update(metric_name, now, nil, duration * 1000)
160
+ end
161
+
162
+ metric_name = 'sq.hooks_pre.pre'
163
+ duration = request[:timed_hooks_before].sum(&:duration)
164
+ unless metrics_engine.metric?(metric_name)
165
+ metrics_engine.create_metric(
166
+ 'name' => metric_name,
167
+ 'period' => 60,
168
+ 'kind' => 'Binning',
169
+ 'options' => { 'base' => 2.0, 'factor' => 0.1 },
170
+ )
171
+ end
172
+ metrics_engine.update(metric_name, now, nil, duration * 1000)
173
+
174
+ metric_name = 'sq.hooks_post.post'
175
+ duration = request[:timed_hooks_after].sum(&:duration)
176
+ unless metrics_engine.metric?(metric_name)
177
+ metrics_engine.create_metric(
178
+ 'name' => metric_name,
179
+ 'period' => 60,
180
+ 'kind' => 'Binning',
181
+ 'options' => { 'base' => 2.0, 'factor' => 0.1 },
182
+ )
183
+ end
184
+ metrics_engine.update(metric_name, now, nil, duration * 1000)
185
+
186
+ metric_name = 'sq.hooks_failing.failing'
187
+ duration = request[:timed_hooks_raised].sum(&:duration)
188
+ unless metrics_engine.metric?(metric_name)
189
+ metrics_engine.create_metric(
190
+ 'name' => metric_name,
191
+ 'period' => 60,
192
+ 'kind' => 'Binning',
193
+ 'options' => { 'base' => 2.0, 'factor' => 0.1 },
194
+ )
195
+ end
196
+ metrics_engine.update(metric_name, now, nil, duration * 1000)
197
+
198
+ skipped = request[:skipped_callbacks].map(&:name)
199
+ Sqreen::Weave.logger.debug { "request:#{request[:uuid]} callback.skipped.size: #{skipped.count} callback.skipped: [#{skipped.join(', ')}]" }
200
+ timer = request[:timer]
201
+ total = timer.duration
202
+ Sqreen::Weave.logger.debug { "request:#{request[:uuid]} timer.total: #{'%.03fus' % (total * 1_000_000)} timer.size: #{timer.size}" }
203
+ timings = request[:timed_callbacks].map(&:to_s)
204
+ total = request[:timed_callbacks].sum(&:duration)
205
+ Sqreen::Weave.logger.debug { "request:#{request[:uuid]} callback.total: #{'%.03fus' % (total * 1_000_000)} callback.timings: [#{timings.join(', ')}]" }
206
+ timings = request[:timed_hooks].map(&:to_s)
207
+ total = request[:timed_hooks].sum(&:duration)
208
+ Sqreen::Weave.logger.debug { "request:#{request[:uuid]} hook.total: #{'%.03fus' % (total * 1_000_000)} hook.timings: [#{timings.join(', ')}]" }
209
+
210
+ skipped = request[:skipped_callbacks].map(&:name)
211
+ skipped_rule_name = skipped.first && skipped.first =~ /weave,rule=(.*)$/ && $1
212
+ Sqreen.observations_queue.push(['request_overtime', skipped_rule_name, 1, utc_now]) if skipped_rule_name
213
+
214
+ sqreen_request_duration = total
215
+ Sqreen.observations_queue.push(['sq', nil, sqreen_request_duration * 1000, utc_now])
216
+
217
+ request_duration = now - request[:start_time]
218
+ Sqreen.observations_queue.push(['req', nil, request_duration * 1000, utc_now])
219
+
220
+ sqreen_request_ratio = (sqreen_request_duration * 100.0) / (request_duration - sqreen_request_duration)
221
+ Sqreen.observations_queue.push(['pct', nil, sqreen_request_ratio, utc_now])
222
+ end
223
+ end.install
224
+
225
+ ### globally declare instrumentation ready
226
+ Sqreen.instrumentation_ready = true
227
+ end
228
+
229
+ # needed by Sqreen::Runner
230
+ def remove_all_callbacks
231
+ Sqreen.instrumentation_ready = false
232
+
233
+ loop do
234
+ hook = @hooks.pop
235
+ break unless hook
236
+ Sqreen::Weave.logger.debug { "hook.deinstrument: #{hook}" }
237
+ hook.uninstall
238
+ hook.clear
239
+ end
240
+ end
241
+
242
+ # needed by #instrument!
243
+ def add_callback(rule, callback, strategy)
244
+ Sqreen::Weave.logger.debug { "Adding rule: #{rule} callback: #{callback}" }
245
+ klass = callback.klass
246
+ method = callback.method
247
+
248
+ if Sqreen::Graft::HookPoint.new("#{klass}.#{method}").exist?
249
+ hook_point = "#{klass}.#{method}"
250
+ elsif Sqreen::Graft::HookPoint.new("#{klass}##{method}").exist?
251
+ hook_point = "#{klass}##{method}"
252
+ end
253
+
254
+ return if hook_point.nil?
255
+
256
+ priority = callback.priority || 100
257
+ block = callback.respond_to?(:block) ? callback.block : true
258
+ ignore = -> { callback.whitelisted? } if callback.respond_to?(:whitelisted?)
259
+
260
+ hook = Sqreen::Graft::Hook[hook_point, strategy]
261
+ hook.add do
262
+ if callback.pre?
263
+ before(rule, rank: priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
264
+ return unless Sqreen.instrumentation_ready
265
+
266
+ i = call.instance
267
+ a = call.args
268
+ r = call.remaining
269
+
270
+ Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#pre instance=#{i}" }
271
+ begin
272
+ ret = callback.pre(i, a, r)
273
+ rescue StandardError => e
274
+ Sqreen::Weave.logger.warn { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#pre instance=#{i} => exception=#{e}" }
275
+ if callback.respond_to?(:record_exception)
276
+ callback.record_exception(e)
277
+ else
278
+ Sqreen::RemoteException.record(e)
279
+ end
280
+ end
281
+ Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#pre instance=#{i} => return=#{ret.inspect}" }
282
+
283
+ case ret[:status]
284
+ when :skip, 'skip'
285
+ throw(b, b.return(ret[:new_return_value]).break!) if ret.key?(:new_return_value)
286
+ when :modify_args, 'modify_args'
287
+ throw(b, b.args(ret[:args]))
288
+ when :raise, 'raise'
289
+ throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
290
+ throw(b, b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required.")))
291
+ end unless ret.nil?
292
+ end
293
+ end
294
+
295
+ if callback.post?
296
+ after(rule, rank: -priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
297
+ return unless Sqreen.instrumentation_ready
298
+
299
+ i = call.instance
300
+ v = call.returned
301
+ a = call.args
302
+ r = call.remaining
303
+
304
+ Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#post instance=#{i}" }
305
+ begin
306
+ ret = callback.post(v, i, a, r)
307
+ rescue StandardError => e
308
+ Sqreen::Weave.logger.warn { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#post instance=#{i} => exception=#{e}" }
309
+ if callback.respond_to?(:record_exception)
310
+ callback.record_exception(e)
311
+ else
312
+ Sqreen::RemoteException.record(e)
313
+ end
314
+ end
315
+ Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#post instance=#{i} => return=#{ret.inspect}" }
316
+
317
+ case ret[:status]
318
+ when :override, 'override'
319
+ throw(b, b.return(ret[:new_return_value])) if ret.key?(:new_return_value)
320
+ when :raise, 'raise'
321
+ throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
322
+ throw(b, b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required.")))
323
+ end unless ret.nil?
324
+ end
325
+ end
326
+
327
+ if callback.failing?
328
+ raised(rule, rank: priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
329
+ return unless Sqreen.instrumentation_ready
330
+
331
+ i = call.instance
332
+ e = call.raised
333
+ a = call.args
334
+ r = call.remaining
335
+
336
+ Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#failing instance=#{i}" }
337
+ begin
338
+ ret = callback.failing(e, i, a, r)
339
+ rescue StandardError => e
340
+ Sqreen::Weave.logger.warn { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#failing instance=#{i} => exception=#{e}" }
341
+ if callback.respond_to?(:record_exception)
342
+ callback.record_exception(e)
343
+ else
344
+ Sqreen::RemoteException.record(e)
345
+ end
346
+ end
347
+ Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#failing instance=#{i} => return=#{ret.inspect}" }
348
+
349
+ raise e if ret.nil?
350
+
351
+ case ret[:status]
352
+ when :override, 'override'
353
+ throw(b, b.return(ret[:new_return_value])) if ret.key?(:new_return_value)
354
+ when :retry, 'retry'
355
+ throw(b, b.retry)
356
+ when :raise, 'raise'
357
+ throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
358
+ throw(b, b.raise(Sqreen::AttackBlocked.new("Sqreen blocked a security threat (type: #{callback.rule_name}). No action is required.")))
359
+ when :reraise, 'reraise'
360
+ throw(b, b.raise(e))
361
+ else
362
+ throw(b, b.raise(e))
363
+ end unless ret.nil?
364
+ end
365
+ end
366
+ end.install
367
+
368
+ hook
369
+ end
370
+
371
+ # needed by Sqreen::Rules.cb_from_rule
372
+ def valid_method?(klass, method)
373
+ if Sqreen::Graft::HookPoint.new("#{klass}.#{method}").exist?
374
+ Sqreen::Weave.logger.debug { "HookPoint found: #{klass}.#{method}" }
375
+ true
376
+ elsif Sqreen::Graft::HookPoint.new("#{klass}##{method}").exist?
377
+ Sqreen::Weave.logger.debug { "HookPoint found: #{klass}##{method}" }
378
+ true
379
+ else
380
+ Sqreen::Weave.logger.debug { "HookPoint not found: #{klass} #{method}" }
381
+ false
382
+ end
383
+ end
384
+
385
+ # needed by #instrument!
386
+ def hardcoded_callbacks(framework)
387
+ [
388
+ ### callback for performing sec responses based on ip
389
+ ### init redefined to implement smartass way to hook it upon the
390
+ ### framework's middleware #call
391
+ Sqreen::Rules::RunReqStartActions.new(framework),
392
+ ### callback for performing sec responses based on user
393
+ Sqreen::Rules::RunUserActions.new(Sqreen, :identify, 0),
394
+ ### callback for performing sec responses based on user
395
+ Sqreen::Rules::RunUserActions.new(Sqreen, :auth_track, 1),
396
+ ]
397
+ end
398
+ end