sqreen 1.18.6-java → 1.20.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.
Files changed (190) 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/aggregated_metric.rb +25 -0
  18. data/lib/sqreen/attack_blocked.rb +2 -0
  19. data/lib/sqreen/binding_accessor.rb +2 -0
  20. data/lib/sqreen/binding_accessor/path_elem.rb +2 -0
  21. data/lib/sqreen/binding_accessor/transforms.rb +8 -1
  22. data/lib/sqreen/call_countable.rb +2 -0
  23. data/lib/sqreen/capped_queue.rb +2 -0
  24. data/lib/sqreen/cb.rb +2 -0
  25. data/lib/sqreen/cb_tree.rb +2 -0
  26. data/lib/sqreen/condition_evaluator.rb +2 -0
  27. data/lib/sqreen/conditionable.rb +2 -0
  28. data/lib/sqreen/configuration.rb +19 -1
  29. data/lib/sqreen/context.rb +2 -0
  30. data/lib/sqreen/default_cb.rb +2 -0
  31. data/lib/sqreen/deferred_logger.rb +2 -0
  32. data/lib/sqreen/deliveries.rb +2 -0
  33. data/lib/sqreen/deliveries/batch.rb +6 -1
  34. data/lib/sqreen/deliveries/simple.rb +6 -0
  35. data/lib/sqreen/dependency.rb +3 -1
  36. data/lib/sqreen/dependency/detector.rb +22 -14
  37. data/lib/sqreen/dependency/libsqreen.rb +4 -0
  38. data/lib/sqreen/dependency/new_relic.rb +2 -0
  39. data/lib/sqreen/dependency/rack.rb +10 -5
  40. data/lib/sqreen/dependency/rails.rb +4 -0
  41. data/lib/sqreen/dependency/sentry.rb +2 -0
  42. data/lib/sqreen/dependency/sinatra.rb +12 -1
  43. data/lib/sqreen/encoding_sanitizer.rb +2 -0
  44. data/lib/sqreen/error_handling_middleware.rb +2 -0
  45. data/lib/sqreen/event.rb +9 -5
  46. data/lib/sqreen/events/attack.rb +25 -18
  47. data/lib/sqreen/events/remote_exception.rb +2 -22
  48. data/lib/sqreen/events/request_record.rb +17 -70
  49. data/lib/sqreen/exception.rb +2 -0
  50. data/lib/sqreen/formatter_with_tid.rb +2 -0
  51. data/lib/sqreen/framework_cb.rb +2 -0
  52. data/lib/sqreen/frameworks.rb +2 -0
  53. data/lib/sqreen/frameworks/generic.rb +2 -0
  54. data/lib/sqreen/frameworks/rails.rb +1 -0
  55. data/lib/sqreen/frameworks/rails3.rb +2 -0
  56. data/lib/sqreen/frameworks/request_recorder.rb +15 -2
  57. data/lib/sqreen/frameworks/sinatra.rb +2 -0
  58. data/lib/sqreen/frameworks/sqreen_test.rb +2 -0
  59. data/lib/sqreen/graft.rb +12 -0
  60. data/lib/sqreen/graft/call.rb +150 -0
  61. data/lib/sqreen/{dependency → graft}/callback.rb +12 -4
  62. data/lib/sqreen/graft/hook.rb +316 -0
  63. data/lib/sqreen/{dependency → graft}/hook_point.rb +152 -33
  64. data/lib/sqreen/graft/hook_point_error.rb +10 -0
  65. data/lib/sqreen/invalid_signature_exception.rb +2 -0
  66. data/lib/sqreen/js.rb +2 -0
  67. data/lib/sqreen/js/call_context.rb +2 -0
  68. data/lib/sqreen/js/context_pool.rb +2 -0
  69. data/lib/sqreen/js/exec_js_runnable.rb +2 -0
  70. data/lib/sqreen/js/execjs_adapter.rb +2 -0
  71. data/lib/sqreen/js/executable_js.rb +2 -0
  72. data/lib/sqreen/js/js_service.rb +2 -0
  73. data/lib/sqreen/js/js_service_adapter.rb +2 -0
  74. data/lib/sqreen/js/mini_racer_adapter.rb +2 -0
  75. data/lib/sqreen/js/mini_racer_executable_js.rb +2 -0
  76. data/lib/sqreen/js/thread_local_exec_js_runnable.rb +2 -0
  77. data/lib/sqreen/kit/signals/specialized/aggregated_metric.rb +72 -0
  78. data/lib/sqreen/kit/signals/specialized/attack.rb +57 -0
  79. data/lib/sqreen/kit/signals/specialized/binning_metric.rb +76 -0
  80. data/lib/sqreen/kit/signals/specialized/http_trace.rb +26 -0
  81. data/lib/sqreen/kit/signals/specialized/sdk_track_call.rb +50 -0
  82. data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +57 -0
  83. data/lib/sqreen/{backport.rb → legacy.rb} +3 -2
  84. data/lib/sqreen/{instrumentation.rb → legacy/instrumentation.rb} +31 -2
  85. data/lib/sqreen/legacy/old_event_submission_strategy.rb +221 -0
  86. data/lib/sqreen/legacy/waf_redactions.rb +49 -0
  87. data/lib/sqreen/log.rb +2 -0
  88. data/lib/sqreen/log/loggable.rb +28 -0
  89. data/lib/sqreen/logger.rb +2 -0
  90. data/lib/sqreen/metrics.rb +2 -0
  91. data/lib/sqreen/metrics/average.rb +2 -0
  92. data/lib/sqreen/metrics/base.rb +5 -0
  93. data/lib/sqreen/metrics/binning.rb +2 -0
  94. data/lib/sqreen/metrics/collect.rb +2 -0
  95. data/lib/sqreen/metrics/sum.rb +2 -0
  96. data/lib/sqreen/metrics_store.rb +24 -12
  97. data/lib/sqreen/metrics_store/already_registered_metric.rb +2 -0
  98. data/lib/sqreen/metrics_store/unknown_metric.rb +2 -0
  99. data/lib/sqreen/metrics_store/unregistered_metric.rb +2 -0
  100. data/lib/sqreen/middleware.rb +2 -0
  101. data/lib/sqreen/mono_time.rb +2 -0
  102. data/lib/sqreen/node.rb +2 -0
  103. data/lib/sqreen/not_implemented_yet.rb +2 -0
  104. data/lib/sqreen/null_logger.rb +2 -0
  105. data/lib/sqreen/payload_creator.rb +2 -0
  106. data/lib/sqreen/payload_creator/header_section.rb +2 -0
  107. data/lib/sqreen/performance_notifications.rb +2 -0
  108. data/lib/sqreen/performance_notifications/binned_metrics.rb +10 -2
  109. data/lib/sqreen/performance_notifications/log.rb +2 -0
  110. data/lib/sqreen/performance_notifications/log_performance.rb +2 -0
  111. data/lib/sqreen/performance_notifications/metrics.rb +2 -0
  112. data/lib/sqreen/performance_notifications/newrelic.rb +2 -0
  113. data/lib/sqreen/prefix.rb +2 -0
  114. data/lib/sqreen/rails_middleware.rb +2 -0
  115. data/lib/sqreen/remote_command.rb +2 -0
  116. data/lib/sqreen/remote_command/failure_output.rb +5 -0
  117. data/lib/sqreen/rules.rb +6 -2
  118. data/lib/sqreen/rules/attrs.rb +2 -0
  119. data/lib/sqreen/rules/auth_track_cb.rb +2 -0
  120. data/lib/sqreen/rules/binding_accessor_matcher_cb.rb +2 -0
  121. data/lib/sqreen/rules/binding_accessor_metrics.rb +2 -0
  122. data/lib/sqreen/rules/blacklist_ips_cb.rb +2 -0
  123. data/lib/sqreen/rules/count_http_codes.rb +2 -0
  124. data/lib/sqreen/rules/crawler_user_agent_matches_cb.rb +2 -0
  125. data/lib/sqreen/rules/crawler_user_agent_matches_metrics_cb.rb +2 -0
  126. data/lib/sqreen/rules/custom_error_cb.rb +2 -0
  127. data/lib/sqreen/rules/devise_auth_track_cb.rb +2 -0
  128. data/lib/sqreen/rules/devise_signup_track_cb.rb +2 -0
  129. data/lib/sqreen/rules/execjs_cb.rb +2 -0
  130. data/lib/sqreen/rules/headers_insert_cb.rb +7 -0
  131. data/lib/sqreen/rules/matcher_rule.rb +2 -0
  132. data/lib/sqreen/rules/not_found_cb.rb +7 -0
  133. data/lib/sqreen/rules/rails_parameters_cb.rb +2 -0
  134. data/lib/sqreen/rules/record_request_context.rb +2 -0
  135. data/lib/sqreen/rules/regexp_rule_cb.rb +2 -0
  136. data/lib/sqreen/rules/rule_cb.rb +4 -0
  137. data/lib/sqreen/rules/run_req_start_actions.rb +3 -1
  138. data/lib/sqreen/rules/run_user_actions.rb +3 -1
  139. data/lib/sqreen/rules/shell_env_cb.rb +2 -0
  140. data/lib/sqreen/rules/signup_track_cb.rb +2 -0
  141. data/lib/sqreen/rules/update_request_context.rb +2 -0
  142. data/lib/sqreen/rules/url_matches_cb.rb +2 -0
  143. data/lib/sqreen/rules/user_agent_matches_cb.rb +2 -0
  144. data/lib/sqreen/rules/waf_cb.rb +41 -16
  145. data/lib/sqreen/rules/xss_cb.rb +2 -0
  146. data/lib/sqreen/run_when_called_cb.rb +2 -0
  147. data/lib/sqreen/runner.rb +68 -12
  148. data/lib/sqreen/runtime_infos.rb +2 -0
  149. data/lib/sqreen/safe_json.rb +2 -0
  150. data/lib/sqreen/sdk.rb +4 -0
  151. data/lib/sqreen/sensitive_data_redactor.rb +21 -31
  152. data/lib/sqreen/serializer.rb +2 -0
  153. data/lib/sqreen/session.rb +41 -37
  154. data/lib/sqreen/shared_storage.rb +2 -0
  155. data/lib/sqreen/shared_storage23.rb +2 -0
  156. data/lib/sqreen/shrink_wrap.rb +16 -0
  157. data/lib/sqreen/signals/conversions.rb +283 -0
  158. data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
  159. data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
  160. data/lib/sqreen/signature_verifier.rb +2 -0
  161. data/lib/sqreen/sinatra_middleware.rb +2 -0
  162. data/lib/sqreen/sqreen_signed_verifier.rb +2 -0
  163. data/lib/sqreen/token_invalid_exception.rb +2 -0
  164. data/lib/sqreen/token_not_found_exception.rb +2 -0
  165. data/lib/sqreen/trie.rb +2 -0
  166. data/lib/sqreen/unauthorized.rb +2 -0
  167. data/lib/sqreen/util.rb +5 -0
  168. data/lib/sqreen/util/capped_array.rb +2 -0
  169. data/lib/sqreen/util/capped_hash.rb +2 -0
  170. data/lib/sqreen/util/capped_string.rb +2 -0
  171. data/lib/sqreen/util/capper.rb +2 -0
  172. data/lib/sqreen/version.rb +3 -1
  173. data/lib/sqreen/waf_error.rb +2 -0
  174. data/lib/sqreen/weave.rb +12 -0
  175. data/lib/sqreen/weave/hardcoded.rb +19 -0
  176. data/lib/sqreen/weave/instrumentor.rb +48 -0
  177. data/lib/sqreen/weave/legacy.rb +12 -0
  178. data/lib/sqreen/weave/legacy/instrumentation.rb +406 -0
  179. data/lib/sqreen/web_server.rb +2 -0
  180. data/lib/sqreen/web_server/generic.rb +2 -0
  181. data/lib/sqreen/web_server/passenger.rb +2 -0
  182. data/lib/sqreen/web_server/puma.rb +2 -0
  183. data/lib/sqreen/web_server/rainbows.rb +2 -0
  184. data/lib/sqreen/web_server/thin.rb +2 -0
  185. data/lib/sqreen/web_server/unicorn.rb +2 -0
  186. data/lib/sqreen/web_server/webrick.rb +2 -0
  187. data/lib/sqreen/worker.rb +2 -0
  188. metadata +65 -9
  189. data/lib/sqreen/backport/original_name.rb +0 -86
  190. data/lib/sqreen/dependency/hook.rb +0 -102
@@ -1,6 +1,9 @@
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/legacy'
4
7
  require 'sqreen/cb_tree'
5
8
  require 'sqreen/log'
6
9
  require 'sqreen/exception'
@@ -36,6 +39,8 @@ require 'set'
36
39
  # end
37
40
 
38
41
  module Sqreen
42
+
43
+ module Legacy
39
44
  class Instrumentation
40
45
  OVERTIME_METRIC = 'request_overtime'.freeze
41
46
 
@@ -84,6 +89,7 @@ module Sqreen
84
89
  start = Sqreen.time
85
90
  res = cb.pre(instance, args, budget, &block)
86
91
  stop = Sqreen.time
92
+ Sqreen.log.debug { "ran pre cb #{cb} => #{res.inspect}" }
87
93
  # The first few pre callbacks could not have a request & hence a budget just yet so we try harder to find it
88
94
  budget = framework.remaining_perf_budget if framework && !budget && Sqreen.performance_budget
89
95
  if budget
@@ -139,6 +145,7 @@ module Sqreen
139
145
  start = Sqreen.time
140
146
  res = cb.post(return_val, instance, args, budget, &block)
141
147
  stop = Sqreen.time
148
+ Sqreen.log.debug { "ran post cb #{cb} => #{res.inspect}" }
142
149
  if budget
143
150
  budget -= (stop - start)
144
151
  cb.overtime! if budget <= 0.0
@@ -193,6 +200,7 @@ module Sqreen
193
200
  start = Sqreen.time
194
201
  res = cb.failing(exception, instance, args, budget, &block)
195
202
  stop = Sqreen.time
203
+ Sqreen.log.debug { "ran failing cb #{cb} => #{res.inspect}" }
196
204
  if budget
197
205
  budget -= (stop - start)
198
206
  cb.overtime! if budget <= 0.0
@@ -508,6 +516,7 @@ module Sqreen
508
516
  saved_meth_name
509
517
  end
510
518
 
519
+ ### bad idea anyway
511
520
  # WARNING We do not actually remove `meth`
512
521
  def unoverride_class_method(klass, meth)
513
522
  saved_meth_name = get_saved_method_name(meth)
@@ -526,6 +535,7 @@ module Sqreen
526
535
  end
527
536
  end
528
537
 
538
+ ### useless now
529
539
  if RUBY_VERSION < '1.9'
530
540
  def adjust_method_name(method)
531
541
  method.to_s
@@ -554,6 +564,8 @@ module Sqreen
554
564
  is_instance_method?(obj, method)
555
565
  end
556
566
 
567
+ ### is that actually used?
568
+ ### if so, do not attempt to alter frozen instances
557
569
  # Override a singleton method on an instance
558
570
  def override_singleton_method(instance, klass_name, meth)
559
571
  @@overriden_singleton_methods = true
@@ -647,8 +659,7 @@ module Sqreen
647
659
 
648
660
  already_overriden = @@overriden_methods.include? key
649
661
  unless already_overriden
650
- Sqreen.log.debug "#{key} not overriden, returning"
651
- return
662
+ Sqreen.log.debug "#{key} apparently not overridden"
652
663
  end
653
664
 
654
665
  defined_cbs = @@registered_callbacks.get(klass, method).flatten
@@ -674,6 +685,7 @@ module Sqreen
674
685
  elsif is_instance_method?(klass, method)
675
686
  unoverride_instance_method(klass, method)
676
687
  else
688
+ ### Module#prepend will take care of that
677
689
  # FIXME: Override define_method and other dynamic ways to
678
690
  # The following should be monitored to make sure we
679
691
  # don't forget dynamically added methods:
@@ -701,8 +713,13 @@ module Sqreen
701
713
  # @return [Array<Sqreen::CB>]
702
714
  def hardcoded_callbacks(framework)
703
715
  [
716
+ ### callback for performing sec responses based on ip
717
+ ### init redefined to implement smartass way to hook it upon the
718
+ ### framework's middleware #call
704
719
  Sqreen::Rules::RunReqStartActions.new(framework),
720
+ ### callback for performing sec responses based on user
705
721
  Sqreen::Rules::RunUserActions.new(Sqreen, :identify, 0),
722
+ ### callback for performing sec responses based on user
706
723
  Sqreen::Rules::RunUserActions.new(Sqreen, :auth_track, 1),
707
724
  ]
708
725
  end
@@ -711,6 +728,7 @@ module Sqreen
711
728
  # @param rules [Array<Hash>] Rules to instrument
712
729
  # @param framework [Sqreen::Frameworks::GenericFramework]
713
730
  def instrument!(rules, framework)
731
+ ### set up rule signature verifier
714
732
  verifier = nil
715
733
  if Sqreen.features['rules_signature'] &&
716
734
  Sqreen.config_get(:rules_verify_signature) == true &&
@@ -720,33 +738,44 @@ module Sqreen
720
738
  Sqreen.log.debug('Rules signature is not enabled')
721
739
  end
722
740
 
741
+ ### force clean instrumentation callback list
723
742
  remove_all_callbacks # Force cb tree to be empty before instrumenting
724
743
 
744
+ ### for each rule description, transform into format for adding callback
725
745
  rules.each do |rule|
726
746
  rcb = Sqreen::Rules.cb_from_rule(rule, self, metrics_engine, verifier)
727
747
  next unless rcb
748
+ ### attach framework to callback
728
749
  rcb.framework = framework
750
+ ### add callback
729
751
  add_callback(rcb)
730
752
  end
731
753
 
732
754
  # add hardcoded callbacks, observing priority
733
755
  hardcoded_callbacks(framework).each { |cb| add_callback(cb) }
734
756
 
757
+ ### globally declare instrumentation ready
758
+ ### from within instance method? not even thread local?
735
759
  Sqreen.instrumentation_ready = true
736
760
  end
737
761
 
738
762
  def initialize(metrics_engine = nil)
739
763
  self.metrics_engine = metrics_engine
740
764
  return if metrics_engine.nil?
765
+ ### init metric to count calls to sqreen
741
766
  metrics_engine.create_metric('name' => CallCountable::COUNT_CALLS,
742
767
  'period' => 60,
743
768
  'kind' => 'Sum')
769
+ ### init metric to count request whitelist matches (ip or path whitelist)
744
770
  metrics_engine.create_metric('name' => Sqreen::Rules::RecordRequestContext::WHITELISTED_METRIC,
745
771
  'period' => 60,
746
772
  'kind' => 'Sum')
773
+ ### init metric to count over budget hits
747
774
  metrics_engine.create_metric('name' => OVERTIME_METRIC,
748
775
  'period' => 60,
749
776
  'kind' => 'Sum')
750
777
  end
751
778
  end
752
779
  end
780
+
781
+ end
@@ -0,0 +1,221 @@
1
+ # typed: ignore
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/aggregated_metric'
7
+ require 'sqreen/log/loggable'
8
+ require 'sqreen/legacy/waf_redactions'
9
+
10
+ module Sqreen
11
+ module Legacy
12
+ # see also Sqreen::Signals::SignalsSubmissionStrategy
13
+ # usage in Sqreen:Session
14
+ class OldEventSubmissionStrategy
15
+ include Sqreen::Log::Loggable
16
+
17
+ RETRY_MANY = 301
18
+
19
+ def initialize(post_proc)
20
+ @post_proc = post_proc
21
+ end
22
+
23
+ def post_metrics(metrics)
24
+ return if metrics.nil? || metrics.empty?
25
+ payload = { metrics: metrics.map { |m| EventToHash.convert_agg_metric(m) } }
26
+ post('metrics', payload, {}, RETRY_MANY)
27
+ end
28
+
29
+ # @param attack [Sqreen::Attack]
30
+ def post_attack(attack)
31
+ post('attack', EventToHash.convert_attack(attack), {}, RETRY_MANY)
32
+ end
33
+
34
+ # @param [Sqreen::RequestRecord] request_record
35
+ def post_request_record(request_record)
36
+ rr_hash = EventToHash.convert_request_record(request_record)
37
+ post('request_record', rr_hash, {}, RETRY_MANY)
38
+ end
39
+
40
+ # Post an exception to Sqreen for analysis
41
+ # @param exception [RemoteException] Exception and context to be sent over
42
+ def post_sqreen_exception(exception)
43
+ data = EventToHash.convert_exception(exception)
44
+ post('sqreen_exception', data, {}, 5)
45
+ rescue StandardError => e
46
+ logger.warn(format('Could not post exception (network down? %s) %s',
47
+ e.inspect,
48
+ exception.inspect))
49
+ nil
50
+ end
51
+
52
+ def post_batch(events)
53
+ batch = events.map do |event|
54
+ h = case event
55
+ when AggregatedMetric
56
+ logger.warn "Aggregated metric event in non-signal mode. Signals disabled at runtime?"
57
+ next
58
+ when Attack # in practice only found inside req rec
59
+ EventToHash.convert_attack event
60
+ when RemoteException
61
+ EventToHash.convert_exception event
62
+ when RequestRecord
63
+ EventToHash.convert_request_record event
64
+ else
65
+ logger.warn "Unexpected event type: #{event}"
66
+ next
67
+ end
68
+ h['event_type'] = event_kind(event)
69
+ h
70
+ end
71
+ Sqreen.log.debug do
72
+ tally = Hash[events.group_by(&:class).map { |k, v| [k, v.count] }]
73
+ "Doing batch with the following tally of event types: #{tally}"
74
+ end
75
+ post('batch', { batch: batch }, {}, RETRY_MANY)
76
+ end
77
+
78
+ private
79
+
80
+ # see +Sqreen::Session.post+
81
+ def post(*args)
82
+ @post_proc[*args]
83
+ end
84
+
85
+ def event_kind(event)
86
+ case event
87
+ when Sqreen::RemoteException then 'sqreen_exception'
88
+ when Sqreen::Attack then 'attack'
89
+ when Sqreen::RequestRecord then 'request_record'
90
+ end
91
+ end
92
+ end
93
+
94
+ module EventToHash
95
+ class << self
96
+ # @param attack [Sqreen::Attack]
97
+ def convert_attack(attack)
98
+ payload = attack.payload
99
+ res = {}
100
+ rule_p = payload['rule']
101
+ request_p = payload['request']
102
+ res[:rule_name] = rule_p['name'] if rule_p && rule_p['name']
103
+ res[:rulespack_id] = rule_p['rulespack_id'] if rule_p && rule_p['rulespack_id']
104
+ res[:test] = rule_p['test'] if rule_p && rule_p['test']
105
+ res[:infos] = payload['infos'] if payload['infos']
106
+ res[:time] = attack.time
107
+ res[:client_ip] = request_p[:addr] if request_p && request_p[:addr]
108
+ res[:request] = request_p if request_p
109
+ res[:params] = payload['params'] if payload['params']
110
+ res[:context] = payload['context'] if payload['context']
111
+ res[:headers] = payload['headers'] if payload['headers']
112
+ res
113
+ end
114
+
115
+ # @param [Sqreen::RequestRecord] rr
116
+ def convert_request_record(rr)
117
+ res = { :version => '20171208' }
118
+ payload = rr.payload
119
+
120
+ if payload[:observed]
121
+ res[:observed] = payload[:observed].dup
122
+ rulespack = nil
123
+ if rr.observed[:attacks]
124
+ res[:observed][:attacks] = rr.observed[:attacks].map do |att|
125
+ natt = att.dup
126
+ [:attack_type, :block].each { |k| natt.delete(k) } # signals stuff
127
+ rulespack = natt.delete(:rulespack_id) || rulespack
128
+ natt
129
+ end
130
+ end
131
+ if rr.observed[:sqreen_exceptions]
132
+ res[:observed][:sqreen_exceptions] = rr.observed[:sqreen_exceptions].map do |exc|
133
+ nex = exc.dup
134
+ excp = nex.delete(:exception)
135
+ if excp
136
+ nex[:message] = excp.message
137
+ nex[:klass] = excp.class.name
138
+ end
139
+ rulespack = nex.delete(:rulespack_id) || rulespack
140
+ nex
141
+ end
142
+ end
143
+ res[:rulespack_id] = rulespack unless rulespack.nil?
144
+ if rr.observed[:observations]
145
+ res[:observed][:observations] = rr.observed[:observations].map do |cat, key, value, time|
146
+ { :category => cat, :key => key, :value => value, :time => time }
147
+ end
148
+ end
149
+ if rr.observed[:sdk] # rubocop:disable Style/IfUnlessModifier
150
+ res[:observed][:sdk] = rr.processed_sdk_calls
151
+ end
152
+ end
153
+ res[:local] = payload['local'] if payload['local']
154
+ if payload['request']
155
+ res[:request] = payload['request'].dup
156
+ res[:client_ip] = res[:request].delete(:client_ip) if res[:request][:client_ip]
157
+ else
158
+ res[:request] = {}
159
+ end
160
+ if payload['response']
161
+ res[:response] = payload['response'].dup
162
+ else
163
+ res[:response] = {}
164
+ end
165
+
166
+ res[:request][:parameters] = payload['params'] if payload['params']
167
+ res[:request][:headers] = payload['headers'] if payload['headers']
168
+
169
+ res = Sqreen::EncodingSanitizer.sanitize(res)
170
+
171
+ if rr.redactor
172
+ res[:request], redacted = rr.redactor.redact(res[:request])
173
+ redacted = redacted.uniq
174
+ if redacted.any? && res[:observed] && res[:observed][:attacks]
175
+ res[:observed][:attacks] = WafRedactions.redact_attacks!(res[:observed][:attacks], redacted)
176
+ end
177
+ if redacted.any? && res[:observed] && res[:observed][:sqreen_exceptions]
178
+ res[:observed][:sqreen_exceptions] = WafRedactions.redact_exceptions!(res[:observed][:sqreen_exceptions], redacted)
179
+ end
180
+ end
181
+
182
+ res
183
+ end
184
+
185
+ # @param exception_evt [Sqreen::RemoteException]
186
+ def convert_exception(exception_evt)
187
+ payload = exception_evt.payload
188
+ exception = payload['exception']
189
+ ev = {
190
+ :klass => exception.class.name,
191
+ :message => exception.message,
192
+ :params => payload['request_params'],
193
+ :time => payload['time'],
194
+ :infos => {
195
+ :client_ip => payload['client_ip'],
196
+ },
197
+ :request => payload['request_infos'],
198
+ :headers => payload['headers'],
199
+ :rule_name => payload['rule_name'],
200
+ :rulespack_id => payload['rulespack_id'],
201
+ }
202
+
203
+ ev[:infos].merge!(payload['infos']) if payload['infos']
204
+ return ev unless exception.backtrace
205
+ ev[:context] = { :backtrace => exception.backtrace.map(&:to_s) }
206
+ ev
207
+ end
208
+
209
+ # @param [Sqreen::AggregatedMetric] agg_metric
210
+ def convert_agg_metric(agg_metric)
211
+ {
212
+ name: agg_metric.name,
213
+ observation: agg_metric.data,
214
+ start: agg_metric.start,
215
+ finish: agg_metric.finish,
216
+ }
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,49 @@
1
+ # typed: ignore
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
+ module Legacy
8
+ module WafRedactions
9
+ class << self
10
+ def redact_attacks!(attacks, values)
11
+ return attacks if values.empty?
12
+
13
+ values = values.map { |v| v.downcase if v.is_a?(String) }
14
+
15
+ attacks.each do |e|
16
+ next(e) unless e[:infos]
17
+ next(e) unless e[:infos][:waf_data]
18
+
19
+ parsed = JSON.parse(e[:infos][:waf_data])
20
+ redacted = parsed.each do |w|
21
+ next unless (filters = w['filter'])
22
+
23
+ filters.each do |f|
24
+ next unless (v = f['resolved_value'])
25
+ next unless values.include?(v.downcase)
26
+
27
+ f['match_status'] = SensitiveDataRedactor::MASK
28
+ f['resolved_value'] = SensitiveDataRedactor::MASK
29
+ end
30
+ end
31
+ e[:infos][:waf_data] = JSON.dump(redacted)
32
+ end
33
+ end
34
+
35
+ # see https://github.com/sqreen/TechDoc/blob/master/content/specs/spec000022-waf-data-sanitization.md#changes-to-the-agents
36
+ def redact_exceptions!(exceptions, values)
37
+ return exceptions if values.empty?
38
+
39
+ exceptions.each do |e|
40
+ next(e) unless e[:infos]
41
+ next(e) unless e[:infos][:waf]
42
+
43
+ e[:infos][:waf].delete(:args)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ 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
 
@@ -0,0 +1,28 @@
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 'logger'
7
+
8
+ module Sqreen; end
9
+ module Sqreen::Log; end
10
+
11
+ module Sqreen::Log::Loggable
12
+ def self.included(klass)
13
+ klass.extend(ClassMethods)
14
+ end
15
+
16
+ module ClassMethods
17
+ def logger
18
+ # TODO: use progname for qualified log messages
19
+ # TODO: qualified logger proxies for selectable levels per component
20
+ # @logger ||= ::Logger.new(STDOUT, progname: name, level: Logger::DEBUG)
21
+ Sqreen.log
22
+ end
23
+ end
24
+
25
+ def logger
26
+ @logger || self.class.logger
27
+ end
28
+ end