sqreen 1.19.4 → 1.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -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/rule_cb.rb +2 -0
  25. data/lib/sqreen/rules/waf_cb.rb +11 -8
  26. data/lib/sqreen/runner.rb +43 -5
  27. data/lib/sqreen/sensitive_data_redactor.rb +19 -31
  28. data/lib/sqreen/session.rb +39 -37
  29. data/lib/sqreen/signals/conversions.rb +283 -0
  30. data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
  31. data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
  32. data/lib/sqreen/version.rb +1 -1
  33. data/lib/sqreen/weave/legacy/instrumentation.rb +0 -10
  34. metadata +44 -6
  35. data/lib/sqreen/backport.rb +0 -9
  36. data/lib/sqreen/backport/clock_gettime.rb +0 -74
  37. data/lib/sqreen/backport/original_name.rb +0 -88
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a1a0d2f8489dac7835a9d2135b0e35c15848a4fa094f7912f9979a83a9d2670e
4
- data.tar.gz: 9bfc5db45531824d4f968f45fe495c9fad5da7c258c368fec5821aba8f66b124
3
+ metadata.gz: 6f18004c730291041540b696217f1c70b449e179328f959705a07a148364bfe9
4
+ data.tar.gz: 417f8bb15cbee7faf4f1aa127552e38f0c929255493341d0f683daae37ab9894
5
5
  SHA512:
6
- metadata.gz: f2c2e5a91c6e415c6003dae1c3ca775b9d40eaacb34e4d28d07c991e46941bcb0bb0f1e9d01bdb1644562fb35852c9fb222bd8f1b83a008be3871ee6a5880cb9
7
- data.tar.gz: 9164671762553af1f0cd658e3d654432a3eebfe81050f32d9cf8fc7c36fedb8c40a530629e57a16bec62536a080a931a2f2b34ba1fcb33521ab2964db38bc224
6
+ metadata.gz: f891f7785362829c23028206d6ba656ae3860e8c13cb265a839608c2cf02ba5be6576337c8d2630d1b0c8eb5c69e9dc732d7c68581f9bb472157e900f7a49a15
7
+ data.tar.gz: b1e2e6708cfc177b66e5fe25dc85a9839e784dd4afffd49585f06050311d821c3eee9fe06ddff63a4eddabfc94b9307ca54e4a7301ebbcd5fc4d82096ec8efa7
@@ -1,6 +1,7 @@
1
- ## 1.19.4
1
+ ## 1.20.0
2
2
 
3
- * Fix signature check
3
+ * Enable new instrumentation engine by default
4
+ * Add signal-based backend communication
4
5
 
5
6
  ## 1.19.3
6
7
 
@@ -0,0 +1,25 @@
1
+ require 'sqreen/rules/rule_cb'
2
+ require 'sqreen/metrics/base'
3
+
4
+ module Sqreen
5
+ class AggregatedMetric
6
+ def initialize(values = {})
7
+ values.each do |k, v|
8
+ public_send "#{k}=", v
9
+ end
10
+ end
11
+
12
+ # @return [Sqreen::Rules::RuleCB]
13
+ attr_accessor :rule # optional
14
+
15
+ # @return [Sqreen::Metric::Base]
16
+ attr_accessor :metric
17
+
18
+ attr_accessor :start, :finish
19
+ attr_accessor :data
20
+
21
+ def name
22
+ metric.name
23
+ end
24
+ end
25
+ end
@@ -39,11 +39,15 @@ module Sqreen
39
39
  { :env => :SQREEN_LIBSQREEN, :name => :libsqreen,
40
40
  :default => true, :convert => :to_bool },
41
41
  { :env => :SQREEN_WEAVE, :name => :weave,
42
- :default => false, :convert => :to_bool },
42
+ :default => true, :convert => :to_bool },
43
43
  { :env => :SQREEN_WEAVE_STRATEGY, :name => :weave_strategy,
44
- :default => :chain, :convert => :to_sym },
45
- { :env => :SQREEN_URL, :name => :url,
44
+ :default => :prepend, :convert => :to_sym },
45
+ { :env => :SQREEN_URL, :name => :url,
46
46
  :default => 'https://back.sqreen.io' },
47
+ { :env => :SQREEN_INGESTION_URL, :name => :ingestion_url,
48
+ :default => 'https://ingestion.sqreen.com/' },
49
+ { :env => :SQREEN_PROXY_URL, :name => :proxy_url,
50
+ :default => nil },
47
51
  { :env => :SQREEN_TOKEN, :name => :token,
48
52
  :default => nil },
49
53
  { :env => :SQREEN_APP_NAME, :name => :app_name,
@@ -8,6 +8,7 @@
8
8
  # TODO: Sqreen::RequestRecord => sqreen/events
9
9
  # TODO: Sqreen.time
10
10
 
11
+ require 'sqreen/aggregated_metric'
11
12
  require 'sqreen/events/attack'
12
13
  require 'sqreen/events/remote_exception'
13
14
  require 'sqreen/mono_time'
@@ -91,9 +92,11 @@ module Sqreen
91
92
  def event_key(event)
92
93
  case event
93
94
  when Sqreen::Attack
94
- "att-#{event.type}"
95
+ "att-#{event.rule_name}"
95
96
  when Sqreen::RemoteException
96
97
  "rex-#{event.klass}"
98
+ when Sqreen::AggregatedMetric
99
+ "agg-metric"
97
100
  end
98
101
  end
99
102
  end
@@ -7,6 +7,7 @@
7
7
  # TODO: Sqreen::RemoteException => sqreen/events
8
8
  # TODO: Sqreen::RequestRecord => sqreen/events
9
9
 
10
+ require 'sqreen/log/loggable'
10
11
  require 'sqreen/events/attack'
11
12
  require 'sqreen/events/remote_exception'
12
13
  require 'sqreen/events/request_record'
@@ -15,6 +16,7 @@ module Sqreen
15
16
  module Deliveries
16
17
  # Simple delivery method that directly call session on event
17
18
  class Simple
19
+ include Log::Loggable
18
20
  attr_accessor :session
19
21
 
20
22
  def initialize(session)
@@ -29,6 +31,8 @@ module Sqreen
29
31
  session.post_sqreen_exception(event)
30
32
  when Sqreen::RequestRecord
31
33
  session.post_request_record(event)
34
+ when Sqreen::AggregatedMetric
35
+ logger.warn 'Delivery of metrics using signals is not supported with simple delivery'
32
36
  else
33
37
  session.post_event(event)
34
38
  end
@@ -8,17 +8,19 @@
8
8
  module Sqreen
9
9
  # Master interface for point in time events (e.g. Attack, RemoteException)
10
10
  class Event
11
+ # @return [Hash]
11
12
  attr_reader :payload
13
+
14
+ # @return [Time]
15
+ attr_accessor :time # writer used only in tests
16
+
12
17
  def initialize(payload)
13
18
  @payload = payload
14
- end
15
-
16
- def to_hash
17
- payload.to_hash
19
+ @time = Time.now.utc
18
20
  end
19
21
 
20
22
  def to_s
21
- "<#{self.class.name}: #{to_hash}>"
23
+ "<#{self.class.name}: #{payload.to_hash}>"
22
24
  end
23
25
  end
24
26
  end
@@ -11,6 +11,8 @@ module Sqreen
11
11
  # Attack
12
12
  # When creating a new attack, it gets automatically pushed to the event's
13
13
  # queue.
14
+ # XXX: TURNS OUT THIS CLASS IS ACTUALLY NOT USED ANYMORE
15
+ # Framework.observe is used instead with unstructured attack details
14
16
  class Attack < Event
15
17
  def self.record(payload)
16
18
  attack = Attack.new(payload)
@@ -26,11 +28,31 @@ module Sqreen
26
28
  payload['rule']['rulespack_id']
27
29
  end
28
30
 
29
- def type
31
+ def rule_name
30
32
  return nil unless payload['rule']
31
33
  payload['rule']['name']
32
34
  end
33
35
 
36
+ def test?
37
+ return nil unless payload['rule']
38
+ payload['rule']['test'] ? true : false
39
+ end
40
+
41
+ def beta?
42
+ return nil unless payload['rule']
43
+ payload['rule']['beta'] ? true : false
44
+ end
45
+
46
+ def block?
47
+ return nil unless payload['rule']
48
+ payload['rule']['block'] ? true : false
49
+ end
50
+
51
+ def attack_type
52
+ return nil unless payload['rule']
53
+ payload['rule']['attack_type']
54
+ end
55
+
34
56
  def time
35
57
  return nil unless payload['local']
36
58
  payload['local']['time']
@@ -44,22 +66,5 @@ module Sqreen
44
66
  def enqueue
45
67
  Sqreen.queue.push(self)
46
68
  end
47
-
48
- def to_hash
49
- res = {}
50
- rule_p = payload['rule']
51
- request_p = payload['request']
52
- res[:rule_name] = rule_p['name'] if rule_p && rule_p['name']
53
- res[:rulespack_id] = rule_p['rulespack_id'] if rule_p && rule_p['rulespack_id']
54
- res[:test] = rule_p['test'] if rule_p && rule_p['test']
55
- res[:infos] = payload['infos'] if payload['infos']
56
- res[:time] = time if time
57
- res[:client_ip] = request_p[:addr] if request_p && request_p[:addr]
58
- res[:request] = request_p if request_p
59
- res[:params] = payload['params'] if payload['params']
60
- res[:context] = payload['context'] if payload['context']
61
- res[:headers] = payload['headers'] if payload['headers']
62
- res
63
- end
64
69
  end
65
70
  end
@@ -30,27 +30,5 @@ module Sqreen
30
30
  def klass
31
31
  payload['exception'].class.name
32
32
  end
33
-
34
- def to_hash
35
- exception = payload['exception']
36
- ev = {
37
- :klass => exception.class.name,
38
- :message => exception.message,
39
- :params => payload['request_params'],
40
- :time => payload['time'],
41
- :infos => {
42
- :client_ip => payload['client_ip'],
43
- },
44
- :request => payload['request_infos'],
45
- :headers => payload['headers'],
46
- :rule_name => payload['rule_name'],
47
- :rulespack_id => payload['rulespack_id'],
48
- }
49
-
50
- ev[:infos].merge!(payload['infos']) if payload['infos']
51
- return ev unless exception.backtrace
52
- ev[:context] = { :backtrace => exception.backtrace.map(&:to_s) }
53
- ev
54
- end
55
33
  end
56
34
  end
@@ -14,6 +14,10 @@ require 'sqreen/sensitive_data_redactor'
14
14
  module Sqreen
15
15
  # When a request is deeemed worthy of being sent to the backend
16
16
  class RequestRecord < Sqreen::Event
17
+ attr_reader :redactor
18
+
19
+ # @param [Hash] payload
20
+ # @param [Sqreen::SensitiveDataRedactor] redactor
17
21
  def initialize(payload, redactor = nil)
18
22
  @redactor = redactor
19
23
  super(payload)
@@ -23,74 +27,18 @@ module Sqreen
23
27
  (payload && payload[:observed]) || {}
24
28
  end
25
29
 
26
- def to_hash
27
- res = { :version => '20171208' }
28
- if payload[:observed]
29
- res[:observed] = payload[:observed].dup
30
- rulespack = nil
31
- if observed[:attacks]
32
- res[:observed][:attacks] = observed[:attacks].map do |att|
33
- natt = att.dup
34
- rulespack = natt.delete(:rulespack_id) || rulespack
35
- natt
36
- end
37
- end
38
- if observed[:sqreen_exceptions]
39
- res[:observed][:sqreen_exceptions] = observed[:sqreen_exceptions].map do |exc|
40
- nex = exc.dup
41
- excp = nex.delete(:exception)
42
- if excp
43
- nex[:message] = excp.message
44
- nex[:klass] = excp.class.name
45
- end
46
- rulespack = nex.delete(:rulespack_id) || rulespack
47
- nex
48
- end
49
- end
50
- res[:rulespack_id] = rulespack unless rulespack.nil?
51
- if observed[:observations]
52
- res[:observed][:observations] = observed[:observations].map do |cat, key, value, time|
53
- { :category => cat, :key => key, :value => value, :time => time }
54
- end
55
- end
56
- if observed[:sdk]
57
- res[:observed][:sdk] = processed_sdk_calls
58
- end
59
- end
60
- res[:local] = payload['local'] if payload['local']
61
- if payload['request']
62
- res[:request] = payload['request'].dup
63
- res[:client_ip] = res[:request].delete(:client_ip) if res[:request][:client_ip]
64
- else
65
- res[:request] = {}
66
- end
67
- if payload['response']
68
- res[:response] = payload['response'].dup
69
- else
70
- res[:response] = {}
71
- end
72
-
73
- res[:request][:parameters] = payload['params'] if payload['params']
74
- res[:request][:headers] = payload['headers'] if payload['headers']
75
-
76
- res = Sqreen::EncodingSanitizer.sanitize(res)
30
+ def last_identify_args
31
+ return nil unless observed[:sdk]
77
32
 
78
- if @redactor
79
- res[:request], redacted = @redactor.redact(res[:request])
80
- if redacted.any? && res[:observed] && res[:observed][:attacks]
81
- res[:observed][:attacks] = @redactor.redact_attacks!(res[:observed][:attacks], redacted)
82
- end
83
- if redacted.any? && res[:observed] && res[:observed][:sqreen_exceptions]
84
- res[:observed][:sqreen_exceptions] = @redactor.redact_exceptions!(res[:observed][:sqreen_exceptions], redacted)
85
- end
33
+ observed[:sdk].reverse_each do |meth, _time, *args|
34
+ next unless meth == :identify
35
+ return args
86
36
  end
87
-
88
- res
37
+ nil
89
38
  end
90
39
 
91
- private
92
-
93
40
  def processed_sdk_calls
41
+ return [] unless observed[:sdk]
94
42
  auth_keys = last_identify_id
95
43
 
96
44
  observed[:sdk].map do |meth, time, *args|
@@ -102,6 +50,8 @@ module Sqreen
102
50
  end
103
51
  end
104
52
 
53
+ private
54
+
105
55
  def inject_identifiers(args, meth, auth_keys)
106
56
  return args unless meth == :track && auth_keys
107
57
 
@@ -118,13 +68,8 @@ module Sqreen
118
68
  end
119
69
 
120
70
  def last_identify_id
121
- return nil unless observed[:sdk]
122
-
123
- observed[:sdk].reverse_each do |meth, _time, *args|
124
- next unless meth == :identify
125
- return args.first if args.respond_to? :first
126
- end
127
- nil
71
+ args = last_identify_args
72
+ args.first if args.respond_to? :first
128
73
  end
129
74
  end
130
75
  end
@@ -58,12 +58,20 @@ module Sqreen
58
58
  Sqreen.log.debug { "close_request_record called. observed_items: #{observed_items}" }
59
59
 
60
60
  clean_request_record if observed_items.nil?
61
- if only_metric_observation
61
+ if Sqreen.features['use_signals'] || only_metric_observation
62
62
  push_metrics(observations_queue, queue)
63
- return clean_request_record
64
63
  end
64
+
65
+ if only_metric_observation
66
+ clean_request_record
67
+ return
68
+ end
69
+
70
+ # signals require request section to be present
71
+ payload_requests << 'request'
65
72
  payload = payload_creator.payload(payload_requests)
66
73
  payload[:observed] = observed_items
74
+
67
75
  queue.push create_request_record(payload)
68
76
  clean_request_record
69
77
  end
@@ -79,10 +87,13 @@ module Sqreen
79
87
  @redactor ||= SensitiveDataRedactor.from_config
80
88
  end
81
89
 
90
+ # pushes metric observations to the observations queue
91
+ # and clears the list for the request record
82
92
  def push_metrics(observations_queue, event_queue)
83
93
  observed_items[:observations].each do |obs|
84
94
  observations_queue.push obs
85
95
  end
96
+ observed_items[:observations] = []
86
97
  return unless observations_queue.size > MAX_OBS_QUEUE_LENGTH / 2
87
98
  event_queue.push Sqreen::METRICS_EVENT
88
99
  end
@@ -0,0 +1,72 @@
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/kit/signals/metric'
7
+ require 'sqreen/kit/signals/dto_helper'
8
+
9
+ # reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/payload/binning_metric/2020-01-01T00_00_00_000Z/schema.cue
10
+
11
+ module Sqreen
12
+ module Kit
13
+ module Signals
14
+ module Specialized
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ class Sqreen::Kit::Signals::Specialized::AggregatedMetric < Sqreen::Kit::Signals::Metric
21
+ add_mandatory_attrs :source, :payload
22
+
23
+ validate_str_attr :signal_name, /\Asq\.agent\.metric\..+\z/
24
+
25
+ def initialize(args)
26
+ self.payload_schema = Payload::SCHEMA_VERSION
27
+ super
28
+ end
29
+
30
+ class Payload
31
+ include Sqreen::Kit::Signals::DtoHelper
32
+
33
+ SCHEMA_VERSION = 'metric/2020-01-01T00:00:00.000Z'.freeze
34
+
35
+ add_mandatory_attrs :capture_interval_s,
36
+ :date_started,
37
+ :date_ended,
38
+ :values,
39
+ :kind
40
+
41
+ # mandatory
42
+ # @return [Integer]
43
+ attr_accessor :capture_interval_s
44
+
45
+ # mandatory
46
+ # @param [Time]
47
+ # @return [String]
48
+ attr_accessor_time :date_started
49
+
50
+ # mandatory
51
+ # @param [Time]
52
+ # @return [String]
53
+ attr_accessor_time :date_ended
54
+
55
+ # mandatory
56
+ # @return [Hash{String=>Object}]
57
+ attr_writer :values
58
+ def values
59
+ return nil if @values.nil?
60
+ @values.map do |k, v|
61
+ {
62
+ key: k.is_a?(Hash) || k.is_a?(Array) ? k : k.to_s,
63
+ value: v,
64
+ }
65
+ end
66
+ end
67
+
68
+ # mandatory
69
+ # @return [String]
70
+ attr_accessor :kind
71
+ end
72
+ end