sqreen 1.19.0.beta1 → 1.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -2
  3. data/lib/sqreen/aggregated_metric.rb +25 -0
  4. data/lib/sqreen/configuration.rb +7 -3
  5. data/lib/sqreen/deliveries/batch.rb +4 -1
  6. data/lib/sqreen/deliveries/simple.rb +4 -0
  7. data/lib/sqreen/event.rb +7 -5
  8. data/lib/sqreen/events/attack.rb +23 -18
  9. data/lib/sqreen/events/remote_exception.rb +0 -22
  10. data/lib/sqreen/events/request_record.rb +15 -70
  11. data/lib/sqreen/frameworks/request_recorder.rb +13 -2
  12. data/lib/sqreen/kit/signals/specialized/aggregated_metric.rb +72 -0
  13. data/lib/sqreen/kit/signals/specialized/attack.rb +57 -0
  14. data/lib/sqreen/kit/signals/specialized/binning_metric.rb +76 -0
  15. data/lib/sqreen/kit/signals/specialized/http_trace.rb +26 -0
  16. data/lib/sqreen/kit/signals/specialized/sdk_track_call.rb +50 -0
  17. data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +57 -0
  18. data/lib/sqreen/legacy/old_event_submission_strategy.rb +221 -0
  19. data/lib/sqreen/legacy/waf_redactions.rb +49 -0
  20. data/lib/sqreen/metrics/base.rb +3 -0
  21. data/lib/sqreen/metrics_store.rb +22 -12
  22. data/lib/sqreen/performance_notifications/binned_metrics.rb +8 -2
  23. data/lib/sqreen/rules.rb +4 -2
  24. data/lib/sqreen/rules/not_found_cb.rb +2 -0
  25. data/lib/sqreen/rules/rule_cb.rb +2 -0
  26. data/lib/sqreen/rules/waf_cb.rb +39 -16
  27. data/lib/sqreen/runner.rb +48 -6
  28. data/lib/sqreen/sensitive_data_redactor.rb +19 -31
  29. data/lib/sqreen/session.rb +39 -37
  30. data/lib/sqreen/signals/conversions.rb +283 -0
  31. data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
  32. data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
  33. data/lib/sqreen/version.rb +1 -1
  34. data/lib/sqreen/weave/legacy/instrumentation.rb +15 -7
  35. metadata +55 -14
  36. data/lib/sqreen/backport.rb +0 -9
  37. data/lib/sqreen/backport/clock_gettime.rb +0 -74
  38. data/lib/sqreen/backport/original_name.rb +0 -88
@@ -0,0 +1,78 @@
1
+ require 'sqreen/aggregated_metric'
2
+ require 'sqreen/kit'
3
+ require 'sqreen/kit/string_sanitizer'
4
+ require 'sqreen/signals/conversions'
5
+ require 'sqreen/log/loggable'
6
+
7
+ module Sqreen
8
+ module Signals
9
+ # see also Sqreen::Legacy::OldEventSubmissionStrategy
10
+ # usage in Sqreen:Session
11
+ class SignalsSubmissionStrategy
12
+ include Sqreen::Log::Loggable
13
+
14
+ # @param [Array<Sqreen::AggregatedMetric>] metrics
15
+ def post_metrics(metrics)
16
+ return if metrics.nil? || metrics.empty?
17
+
18
+ guarded 'Failed to serialize or submit aggregated metrics' do
19
+ batch = metrics.map do |m|
20
+ Conversions.convert_metric_sample(m)
21
+ end
22
+ client.report_batch(batch)
23
+ end
24
+ end
25
+
26
+ # @param _attack [Sqreen::Attack]
27
+ # XXX: unused
28
+ def post_attack(_attack)
29
+ raise NotImplementedError
30
+ end
31
+
32
+ # @param request_record [Sqreen::RequestRecord]
33
+ def post_request_record(request_record)
34
+ guarded 'Failed to serialize or submit request record' do
35
+ trace = Conversions.convert_req_record(request_record)
36
+ append_sanitizing_filter(trace)
37
+ client.report_trace(trace)
38
+ end
39
+ end
40
+
41
+ # Post an exception to Sqreen for analysis
42
+ # @param exception [RemoteException] Exception and context to be sent over
43
+ def post_sqreen_exception(exception)
44
+ guarded 'Failed to serialize or submit exception', false do
45
+ data = Conversions.convert_exception(exception)
46
+ append_sanitizing_filter(data)
47
+ client.report_signal(data)
48
+ end
49
+ end
50
+
51
+ def post_batch(events)
52
+ guarded 'Failed to serialize or submit batch of events' do
53
+ batch = Conversions.convert_batch(events)
54
+ batch.each { |sig_or_trace| append_sanitizing_filter(sig_or_trace) }
55
+ client.report_batch(batch)
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def append_sanitizing_filter(sig_or_trace)
62
+ sig_or_trace.append_to_h_filter Kit::StringSanitizer.method(:sanitize)
63
+ end
64
+
65
+ # we don't want exceptions to propagate and kill the worker thread
66
+ def guarded(msg, report = true)
67
+ yield
68
+ rescue StandardError => e
69
+ logger.warn "#{msg}: #{e.message}\n#{e.backtrace.map { |x| " #{x}" }.join("\n")}"
70
+ post_sqreen_exception(RemoteException.new(e)) if report
71
+ end
72
+
73
+ def client
74
+ Sqreen::Kit.auth_signals_client
75
+ end
76
+ end
77
+ end
78
+ end
@@ -4,5 +4,5 @@
4
4
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
5
 
6
6
  module Sqreen
7
- VERSION = '1.19.0.beta1'.freeze
7
+ VERSION = '1.20.0'.freeze
8
8
  end
@@ -76,6 +76,9 @@ class Sqreen::Weave::Legacy::Instrumentation
76
76
  if strategy == :prepend && !Module.respond_to?(:prepend)
77
77
  Sqreen::Weave.logger.warn { "strategy: #{strategy.inspect} unavailable, falling back to :chain" }
78
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
79
82
  end
80
83
  Sqreen::Weave.logger.debug { "strategy: #{strategy.inspect}" }
81
84
 
@@ -108,6 +111,8 @@ class Sqreen::Weave::Legacy::Instrumentation
108
111
  @hooks << request_hook
109
112
  request_hook.add do
110
113
  before('wave,meta,request', rank: -100000, mandatory: true) do |_call|
114
+ next unless Sqreen.instrumentation_ready
115
+
111
116
  uuid = SecureRandom.uuid
112
117
  now = Sqreen::Graft::Timer.read
113
118
  Thread.current[:sqreen_http_request] = {
@@ -130,6 +135,9 @@ class Sqreen::Weave::Legacy::Instrumentation
130
135
 
131
136
  ensured('weave,meta,request', rank: 100000, mandatory: true) do |_call|
132
137
  request = Thread.current[:sqreen_http_request]
138
+
139
+ next if request.nil?
140
+
133
141
  Thread.current[:sqreen_http_request] = nil
134
142
  now = Sqreen::Graft::Timer.read
135
143
  utc_now = Time.now.utc
@@ -261,7 +269,7 @@ class Sqreen::Weave::Legacy::Instrumentation
261
269
  hook.add do
262
270
  if callback.pre?
263
271
  before(rule, rank: priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
264
- return unless Sqreen.instrumentation_ready
272
+ next unless Thread.current[:sqreen_http_request]
265
273
 
266
274
  i = call.instance
267
275
  a = call.args
@@ -288,13 +296,13 @@ class Sqreen::Weave::Legacy::Instrumentation
288
296
  when :raise, 'raise'
289
297
  throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
290
298
  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?
299
+ end unless ret.nil? || !ret.is_a?(Hash)
292
300
  end
293
301
  end
294
302
 
295
303
  if callback.post?
296
304
  after(rule, rank: -priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
297
- return unless Sqreen.instrumentation_ready
305
+ next unless Thread.current[:sqreen_http_request]
298
306
 
299
307
  i = call.instance
300
308
  v = call.returned
@@ -320,13 +328,13 @@ class Sqreen::Weave::Legacy::Instrumentation
320
328
  when :raise, 'raise'
321
329
  throw(b, b.raise(ret[:exception])) if ret.key?(:exception)
322
330
  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?
331
+ end unless ret.nil? || !ret.is_a?(Hash)
324
332
  end
325
333
  end
326
334
 
327
335
  if callback.failing?
328
336
  raised(rule, rank: priority, mandatory: !callback.overtimeable, flow: block, ignore: ignore) do |call, b|
329
- return unless Sqreen.instrumentation_ready
337
+ next unless Thread.current[:sqreen_http_request]
330
338
 
331
339
  i = call.instance
332
340
  e = call.raised
@@ -346,7 +354,7 @@ class Sqreen::Weave::Legacy::Instrumentation
346
354
  end
347
355
  Sqreen::Weave.logger.debug { "#{rule} klass=#{callback.klass} method=#{callback.method} when=#failing instance=#{i} => return=#{ret.inspect}" }
348
356
 
349
- raise e if ret.nil?
357
+ throw(b, b.raise(e)) if ret.nil? || !ret.is_a?(Hash)
350
358
 
351
359
  case ret[:status]
352
360
  when :override, 'override'
@@ -360,7 +368,7 @@ class Sqreen::Weave::Legacy::Instrumentation
360
368
  throw(b, b.raise(e))
361
369
  else
362
370
  throw(b, b.raise(e))
363
- end unless ret.nil?
371
+ end unless ret.nil? || !ret.is_a?(Hash)
364
372
  end
365
373
  end
366
374
  end.install
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqreen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.19.0.beta1
4
+ version: 1.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sqreen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-11 00:00:00.000000000 Z
11
+ date: 2020-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sqreen-backport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqreen-kit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.2.0
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: sq_mini_racer
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -30,14 +58,14 @@ dependencies:
30
58
  requirements:
31
59
  - - "~>"
32
60
  - !ruby/object:Gem::Version
33
- version: 0.3.0.0
61
+ version: 0.6.1.0.0
34
62
  type: :runtime
35
63
  prerelease: false
36
64
  version_requirements: !ruby/object:Gem::Requirement
37
65
  requirements:
38
66
  - - "~>"
39
67
  - !ruby/object:Gem::Version
40
- version: 0.3.0.0
68
+ version: 0.6.1.0.0
41
69
  description: Sqreen is a SaaS based Application protection and monitoring platform
42
70
  that integrates directly into your Ruby applications. Learn more at https://sqreen.com.
43
71
  email: contact@sqreen.com
@@ -65,11 +93,9 @@ files:
65
93
  - lib/sqreen/actions/user_action_class.rb
66
94
  - lib/sqreen/actions/users_index.rb
67
95
  - lib/sqreen/agent.rb
96
+ - lib/sqreen/aggregated_metric.rb
68
97
  - lib/sqreen/attack_blocked.rb
69
98
  - lib/sqreen/attack_detected.html
70
- - lib/sqreen/backport.rb
71
- - lib/sqreen/backport/clock_gettime.rb
72
- - lib/sqreen/backport/original_name.rb
73
99
  - lib/sqreen/binding_accessor.rb
74
100
  - lib/sqreen/binding_accessor/path_elem.rb
75
101
  - lib/sqreen/binding_accessor/transforms.rb
@@ -129,8 +155,16 @@ files:
129
155
  - lib/sqreen/js/mini_racer_adapter.rb
130
156
  - lib/sqreen/js/mini_racer_executable_js.rb
131
157
  - lib/sqreen/js/thread_local_exec_js_runnable.rb
158
+ - lib/sqreen/kit/signals/specialized/aggregated_metric.rb
159
+ - lib/sqreen/kit/signals/specialized/attack.rb
160
+ - lib/sqreen/kit/signals/specialized/binning_metric.rb
161
+ - lib/sqreen/kit/signals/specialized/http_trace.rb
162
+ - lib/sqreen/kit/signals/specialized/sdk_track_call.rb
163
+ - lib/sqreen/kit/signals/specialized/sqreen_exception.rb
132
164
  - lib/sqreen/legacy.rb
133
165
  - lib/sqreen/legacy/instrumentation.rb
166
+ - lib/sqreen/legacy/old_event_submission_strategy.rb
167
+ - lib/sqreen/legacy/waf_redactions.rb
134
168
  - lib/sqreen/log.rb
135
169
  - lib/sqreen/log/loggable.rb
136
170
  - lib/sqreen/logger.rb
@@ -201,6 +235,9 @@ files:
201
235
  - lib/sqreen/shared_storage.rb
202
236
  - lib/sqreen/shared_storage23.rb
203
237
  - lib/sqreen/shrink_wrap.rb
238
+ - lib/sqreen/signals/conversions.rb
239
+ - lib/sqreen/signals/http_trace_redaction.rb
240
+ - lib/sqreen/signals/signals_submission_strategy.rb
204
241
  - lib/sqreen/signature_verifier.rb
205
242
  - lib/sqreen/sinatra_middleware.rb
206
243
  - lib/sqreen/sqreen_signed_verifier.rb
@@ -232,10 +269,13 @@ files:
232
269
  homepage: https://www.sqreen.com/
233
270
  licenses:
234
271
  - Sqreen
235
- metadata: {}
236
- post_install_message: |2
237
- This is a Sqreen beta release and may not work in all situations.
238
- Make sure to review CHANGELOG.md for important details.
272
+ metadata:
273
+ homepage_uri: https://sqreen.com
274
+ documentation_uri: https://docs.sqreen.com/
275
+ changelog_uri: https://docs.sqreen.com/ruby/release-notes/
276
+ source_code_uri: https://github.com/sqreen/ruby-agent
277
+ bug_tracker_uri: https://github.com/sqreen/ruby-agent/issues
278
+ post_install_message:
239
279
  rdoc_options: []
240
280
  require_paths:
241
281
  - lib
@@ -246,11 +286,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
246
286
  version: 1.9.3
247
287
  required_rubygems_version: !ruby/object:Gem::Requirement
248
288
  requirements:
249
- - - ">"
289
+ - - ">="
250
290
  - !ruby/object:Gem::Version
251
- version: 1.3.1
291
+ version: '0'
252
292
  requirements: []
253
- rubygems_version: 3.0.3
293
+ rubyforge_project:
294
+ rubygems_version: 2.7.7
254
295
  signing_key:
255
296
  specification_version: 4
256
297
  summary: Sqreen Ruby agent
@@ -1,9 +0,0 @@
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
- module Sqreen
7
- module Backport
8
- end
9
- end
@@ -1,74 +0,0 @@
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/backport'
7
-
8
- module Sqreen
9
- module Backport
10
- module ClockGettime
11
- class << self
12
- def supported?
13
- Process.respond_to?(:clock_gettime)
14
- end
15
- end
16
-
17
- unless supported?
18
- require 'ffi'
19
-
20
- class Timespec < FFI::Struct
21
- layout :tv_sec => :time_t, :tv_nsec => :long
22
- end
23
-
24
- module LibC
25
- extend FFI::Library
26
- ffi_lib FFI::Library::LIBC
27
-
28
- # TODO: FFI::NotFoundError
29
-
30
- if RUBY_PLATFORM =~ /darwin/
31
- attach_function :mach_absolute_time, [], :uint64
32
- end
33
-
34
- attach_function :clock_gettime, [:int, :pointer], :int
35
- end
36
-
37
- module Constants
38
- case RUBY_PLATFORM
39
- when /darwin/
40
- CLOCK_REALTIME = 0
41
- CLOCK_MONOTONIC = 6
42
- CLOCK_PROCESS_CPUTIME_ID = 12
43
- CLOCK_THERAD_CPUTIME_ID = 16
44
- when /linux/
45
- CLOCK_REALTIME = 0
46
- CLOCK_MONOTONIC = 1
47
- CLOCK_PROCESS_CPUTIME_ID = 2
48
- CLOCK_THREAD_CPUTIME_ID = 3
49
- end
50
- end
51
-
52
- def clock_gettime(clock_id, unit = :float_second)
53
- unless unit == :float_second
54
- raise "Process.clock_gettime: unsupported unit #{unit.inspect}"
55
- end
56
-
57
- t = Timespec.new
58
- ret = LibC.clock_gettime(clock_id, t.pointer)
59
-
60
- raise SystemCallError, "Errno #{FFI.errno}" if ret == -1
61
-
62
- t[:tv_sec].to_f + t[:tv_nsec].to_f / 1_000_000_000
63
- end
64
- end
65
- end
66
- end
67
- end
68
-
69
- unless Sqreen::Backport::ClockGettime.supported?
70
- Process.instance_eval do
71
- extend Sqreen::Backport::ClockGettime
72
- include Sqreen::Backport::ClockGettime::Constants
73
- end
74
- end
@@ -1,88 +0,0 @@
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
- module Sqreen
7
- module Backport
8
- module OriginalName
9
- HAS_UNBOUND_METHOD_ORIGINAL_NAME = ::UnboundMethod.instance_methods(false).include?(:original_name)
10
- HAS_METHOD_ORIGINAL_NAME = ::Method.instance_methods(false).include?(:original_name)
11
-
12
- def original_name
13
- self.class.get_original_name(owner, original_name_key) || self.original_name = name
14
- end
15
-
16
- private
17
-
18
- def original_name=(name)
19
- self.class.set_original_name(owner, original_name_key, name)
20
- end
21
-
22
- def original_name_key
23
- return hash if is_a?(::UnboundMethod)
24
-
25
- owner.instance_method(name).hash
26
- end
27
-
28
- class << self
29
- def supported?
30
- !::Kernel.const_defined?(:JRUBY_VERSION) && HAS_UNBOUND_METHOD_ORIGINAL_NAME && HAS_METHOD_ORIGINAL_NAME
31
- end
32
-
33
- def included(klass)
34
- klass.extend(ClassMethods)
35
- end
36
-
37
- def prepended(klass)
38
- klass.extend(ClassMethods)
39
- end
40
- end
41
-
42
- class Store < ::Hash; end
43
-
44
- module ClassMethods
45
- def original_names(owner)
46
- owner.instance_eval { @__sqreen_backport_original_names ||= Store.new }
47
- end
48
-
49
- def get_original_name(owner, key)
50
- original_names(owner)[key]
51
- end
52
-
53
- def set_original_name(owner, key, name)
54
- original_names(owner)[key] ||= name
55
- end
56
- end
57
- end
58
- end
59
- end
60
-
61
- class UnboundMethod
62
- if Sqreen::Backport::OriginalName::HAS_UNBOUND_METHOD_ORIGINAL_NAME
63
- prepend Sqreen::Backport::OriginalName
64
- else
65
- include Sqreen::Backport::OriginalName
66
- end
67
- end unless Sqreen::Backport::OriginalName.supported?
68
-
69
- class Method
70
- if Sqreen::Backport::OriginalName::HAS_METHOD_ORIGINAL_NAME
71
- prepend Sqreen::Backport::OriginalName
72
- else
73
- include Sqreen::Backport::OriginalName
74
- end
75
- end unless Sqreen::Backport::OriginalName.supported?
76
-
77
- class Module
78
- alias_method(:alias_method_without_original_name, :alias_method)
79
-
80
- def alias_method_with_original_name(newname, oldname)
81
- alias_method_without_original_name(newname, oldname).tap do
82
- instance_method(newname).send(:original_name=, :"#{oldname}")
83
- end
84
- end
85
-
86
- alias_method_with_original_name(:alias_method_without_original_name, :alias_method)
87
- alias_method_with_original_name(:alias_method, :alias_method_with_original_name)
88
- end unless Sqreen::Backport::OriginalName.supported?