sqreen 1.19.2 → 1.21.0.beta2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/lib/sqreen/agent_message.rb +20 -0
- data/lib/sqreen/aggregated_metric.rb +25 -0
- data/lib/sqreen/attack_detected.html +1 -2
- data/lib/sqreen/ca.crt +24 -0
- data/lib/sqreen/configuration.rb +10 -4
- data/lib/sqreen/deliveries/batch.rb +12 -2
- data/lib/sqreen/deliveries/simple.rb +4 -0
- data/lib/sqreen/ecosystem.rb +96 -0
- data/lib/sqreen/ecosystem/dispatch_table.rb +43 -0
- data/lib/sqreen/ecosystem/exception_reporting.rb +26 -0
- data/lib/sqreen/ecosystem/http/net_http.rb +50 -0
- data/lib/sqreen/ecosystem/http/rack_request.rb +39 -0
- data/lib/sqreen/ecosystem/loggable.rb +13 -0
- data/lib/sqreen/ecosystem/module_api.rb +30 -0
- data/lib/sqreen/ecosystem/module_api/event_listener.rb +18 -0
- data/lib/sqreen/ecosystem/module_api/instrumentation.rb +23 -0
- data/lib/sqreen/ecosystem/module_api/message_producer.rb +51 -0
- data/lib/sqreen/ecosystem/module_api/signal_producer.rb +24 -0
- data/lib/sqreen/ecosystem/module_api/tracing.rb +45 -0
- data/lib/sqreen/ecosystem/module_api/tracing/client_data.rb +31 -0
- data/lib/sqreen/ecosystem/module_api/tracing/server_data.rb +27 -0
- data/lib/sqreen/ecosystem/module_api/tracing_id_generation.rb +16 -0
- data/lib/sqreen/ecosystem/module_api/transaction_storage.rb +71 -0
- data/lib/sqreen/ecosystem/module_registry.rb +44 -0
- data/lib/sqreen/ecosystem/redis/redis_connection.rb +43 -0
- data/lib/sqreen/ecosystem/tracing/modules/client.rb +31 -0
- data/lib/sqreen/ecosystem/tracing/modules/server.rb +30 -0
- data/lib/sqreen/ecosystem/tracing/sampler.rb +160 -0
- data/lib/sqreen/ecosystem/tracing/sampling_configuration.rb +150 -0
- data/lib/sqreen/ecosystem/tracing/signals/tracing_client.rb +53 -0
- data/lib/sqreen/ecosystem/tracing/signals/tracing_server.rb +53 -0
- data/lib/sqreen/ecosystem/tracing_broker.rb +101 -0
- data/lib/sqreen/ecosystem/tracing_id_setup.rb +34 -0
- data/lib/sqreen/ecosystem/transaction_storage.rb +64 -0
- data/lib/sqreen/ecosystem/util/call_writers_from_init.rb +13 -0
- data/lib/sqreen/ecosystem_integration.rb +81 -0
- data/lib/sqreen/ecosystem_integration/around_callbacks.rb +89 -0
- data/lib/sqreen/ecosystem_integration/instrumentation_service.rb +38 -0
- data/lib/sqreen/ecosystem_integration/request_lifecycle_tracking.rb +58 -0
- data/lib/sqreen/ecosystem_integration/signal_consumption.rb +35 -0
- data/lib/sqreen/endpoint_testing.rb +184 -0
- data/lib/sqreen/event.rb +7 -5
- data/lib/sqreen/events/attack.rb +23 -18
- data/lib/sqreen/events/remote_exception.rb +0 -22
- data/lib/sqreen/events/request_record.rb +15 -70
- data/lib/sqreen/frameworks/generic.rb +15 -1
- data/lib/sqreen/frameworks/request_recorder.rb +13 -2
- data/lib/sqreen/graft/call.rb +9 -0
- data/lib/sqreen/kit/signals/specialized/aggregated_metric.rb +72 -0
- data/lib/sqreen/kit/signals/specialized/attack.rb +57 -0
- data/lib/sqreen/kit/signals/specialized/binning_metric.rb +76 -0
- data/lib/sqreen/kit/signals/specialized/http_trace.rb +26 -0
- data/lib/sqreen/kit/signals/specialized/sdk_track_call.rb +50 -0
- data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +57 -0
- data/lib/sqreen/legacy/old_event_submission_strategy.rb +227 -0
- data/lib/sqreen/legacy/waf_redactions.rb +49 -0
- data/lib/sqreen/log/loggable.rb +1 -1
- data/lib/sqreen/metrics/base.rb +3 -0
- data/lib/sqreen/metrics_store.rb +22 -12
- data/lib/sqreen/performance_notifications/binned_metrics.rb +8 -2
- data/lib/sqreen/remote_command.rb +3 -0
- data/lib/sqreen/rules.rb +4 -2
- data/lib/sqreen/rules/rule_cb.rb +2 -0
- data/lib/sqreen/rules/waf_cb.rb +13 -10
- data/lib/sqreen/runner.rb +94 -13
- data/lib/sqreen/sensitive_data_redactor.rb +19 -31
- data/lib/sqreen/session.rb +53 -43
- data/lib/sqreen/signals/conversions.rb +288 -0
- data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
- data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
- data/lib/sqreen/version.rb +1 -1
- metadata +83 -10
- data/lib/sqreen/backport.rb +0 -9
- data/lib/sqreen/backport/clock_gettime.rb +0 -74
- data/lib/sqreen/backport/original_name.rb +0 -88
@@ -22,8 +22,17 @@ module Sqreen
|
|
22
22
|
include RequestRecorder
|
23
23
|
attr_accessor :sqreen_configuration
|
24
24
|
|
25
|
+
attr_writer :req_start_cb, :req_end_cb
|
26
|
+
|
25
27
|
def initialize
|
26
28
|
clean_request_record
|
29
|
+
|
30
|
+
# for notifying the ecosystem of request boundaries
|
31
|
+
# XXX: this should be refactored. It shouldn't be
|
32
|
+
# the framework doing these notifications to the ecosystem
|
33
|
+
# Probably the rule callback should do it itself
|
34
|
+
@req_start_cb = Proc.new {}
|
35
|
+
@req_end_cb = Proc.new {}
|
27
36
|
end
|
28
37
|
|
29
38
|
# What kind of database is this
|
@@ -251,8 +260,12 @@ module Sqreen
|
|
251
260
|
# Nota: cleanup should be performed at end of request (see clean_request)
|
252
261
|
def store_request(object)
|
253
262
|
return unless ensure_rack_loaded
|
263
|
+
|
264
|
+
rack_req = Rack::Request.new(object)
|
265
|
+
@req_start_cb.call(rack_req)
|
266
|
+
|
254
267
|
self.remaining_perf_budget = Sqreen.performance_budget
|
255
|
-
SharedStorage.set(:request,
|
268
|
+
SharedStorage.set(:request, rack_req)
|
256
269
|
SharedStorage.set(:xss_params, nil)
|
257
270
|
SharedStorage.set(:whitelisted, nil)
|
258
271
|
SharedStorage.set(:request_overtime, nil)
|
@@ -281,6 +294,7 @@ module Sqreen
|
|
281
294
|
SharedStorage.set(:xss_params, nil)
|
282
295
|
SharedStorage.set(:whitelisted, nil)
|
283
296
|
SharedStorage.set(:request_overtime, nil)
|
297
|
+
@req_end_cb.call
|
284
298
|
end
|
285
299
|
|
286
300
|
def remaining_perf_budget
|
@@ -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
|
data/lib/sqreen/graft/call.rb
CHANGED
@@ -138,6 +138,15 @@ module Sqreen
|
|
138
138
|
@blips << Timer.read
|
139
139
|
end
|
140
140
|
|
141
|
+
def include_measurements(another_timer)
|
142
|
+
@blips += another_timer.instance_variable_get(:@blips)
|
143
|
+
end
|
144
|
+
|
145
|
+
def start_and_end
|
146
|
+
raise 'Not exactly two measurements recorded' unless size == 2
|
147
|
+
@blips
|
148
|
+
end
|
149
|
+
|
141
150
|
def size
|
142
151
|
@blips.size
|
143
152
|
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
|
@@ -0,0 +1,57 @@
|
|
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/point'
|
7
|
+
require 'sqreen/kit/signals/dto_helper'
|
8
|
+
|
9
|
+
# reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/payload/attack/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::Attack < Sqreen::Kit::Signals::Point
|
21
|
+
add_mandatory_attrs :source, :time, :payload
|
22
|
+
|
23
|
+
validate_str_attr :signal_name, /\Asq\.agent\.attack\..+\z/
|
24
|
+
validate_str_attr :source, /\Asqreen:rule:[a-f0-9]{40}:.+\z/
|
25
|
+
|
26
|
+
def initialize(values = {})
|
27
|
+
self.payload_schema = Payload::SCHEMA_VERSION
|
28
|
+
self.time = values[:time] || Time.now
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def payload=(payload)
|
33
|
+
unless payload.is_a?(Payload)
|
34
|
+
raise ArgumentError, "Payload should be a #{Payload}"
|
35
|
+
end
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
class Payload
|
40
|
+
include Sqreen::Kit::Signals::DtoHelper
|
41
|
+
|
42
|
+
SCHEMA_VERSION = 'attack/2020-01-01T00:00:00.000Z'.freeze
|
43
|
+
|
44
|
+
add_mandatory_attrs :test, :block, :infos
|
45
|
+
|
46
|
+
# all are mandatory
|
47
|
+
|
48
|
+
# @return [Boolean]
|
49
|
+
attr_accessor :test
|
50
|
+
|
51
|
+
# @return [Boolean]
|
52
|
+
attr_accessor :block
|
53
|
+
|
54
|
+
# @return [Hash{String|Symbol=>Object}]
|
55
|
+
attr_accessor :infos
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,76 @@
|
|
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::BinningMetric < Sqreen::Kit::Signals::Metric
|
21
|
+
add_mandatory_attrs :source, :time, :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_binning/2020-01-01T00:00:00.000Z'.freeze
|
34
|
+
|
35
|
+
add_mandatory_attrs :capture_interval_s,
|
36
|
+
:date_started,
|
37
|
+
:date_ended,
|
38
|
+
:max, :base, :unit, :bins
|
39
|
+
|
40
|
+
# mandatory
|
41
|
+
# @return [Integer]
|
42
|
+
attr_accessor :capture_interval_s
|
43
|
+
|
44
|
+
# mandatory
|
45
|
+
# @param [Time]
|
46
|
+
# @return [String]
|
47
|
+
attr_accessor_time :date_started
|
48
|
+
|
49
|
+
# mandatory
|
50
|
+
# @param [Time]
|
51
|
+
# @return [String]
|
52
|
+
attr_accessor_time :date_ended
|
53
|
+
|
54
|
+
# mandatory
|
55
|
+
# @return [Float]
|
56
|
+
attr_accessor :max
|
57
|
+
|
58
|
+
# mandatory
|
59
|
+
# @return [Float]
|
60
|
+
attr_accessor :base
|
61
|
+
|
62
|
+
# mandatory
|
63
|
+
# @return [Float]
|
64
|
+
attr_accessor :unit
|
65
|
+
|
66
|
+
# mandatory
|
67
|
+
# @return [Hash{Integer=>Integer}]
|
68
|
+
attr_accessor :bins
|
69
|
+
|
70
|
+
def to_h
|
71
|
+
{
|
72
|
+
kind: 'binning',
|
73
|
+
}.merge(super)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,26 @@
|
|
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/trace'
|
7
|
+
require 'sqreen/kit/signals/context/http_context'
|
8
|
+
require 'sqreen/kit/signals/dto_helper'
|
9
|
+
|
10
|
+
module Sqreen
|
11
|
+
module Kit
|
12
|
+
module Signals
|
13
|
+
module Specialized
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Sqreen::Kit::Signals::Specialized::HttpTrace < Sqreen::Kit::Signals::Trace
|
20
|
+
add_mandatory_attrs :context
|
21
|
+
|
22
|
+
def initialize(values = {})
|
23
|
+
self.context_schema = ::Sqreen::Kit::Signals::Context::HttpContext::SCHEMA_VERSION
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
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/point'
|
7
|
+
require 'sqreen/kit/signals/dto_helper'
|
8
|
+
|
9
|
+
# reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/payload/sdk_call/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::SdkTrackCall < Sqreen::Kit::Signals::Point
|
21
|
+
add_mandatory_attrs :source, :time, :payload
|
22
|
+
|
23
|
+
validate_str_attr :signal_name, /\Asq\.sdk\..+\z/
|
24
|
+
|
25
|
+
def initialize(values = {})
|
26
|
+
self.payload_schema = Payload::SCHEMA_VERSION
|
27
|
+
self.source = "sqreen:sdk:track"
|
28
|
+
self.time = values[:time] || Time.now
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def payload=(payload)
|
33
|
+
unless payload.is_a?(Payload)
|
34
|
+
raise ArgumentError, "Payload should be a #{Payload}"
|
35
|
+
end
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
class Payload
|
40
|
+
include Sqreen::Kit::Signals::DtoHelper
|
41
|
+
|
42
|
+
SCHEMA_VERSION = 'track_event/2020-01-01T00:00:00.000Z'.freeze
|
43
|
+
|
44
|
+
# @return [Hash{String|Symbol=>Object}]
|
45
|
+
attr_accessor :properties
|
46
|
+
|
47
|
+
# @return [Hash{String|Symbol=>String}]
|
48
|
+
attr_accessor :user_identifiers
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,57 @@
|
|
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/point'
|
7
|
+
require 'sqreen/kit/signals/dto_helper'
|
8
|
+
|
9
|
+
# reference: https://github.com/sqreen/SignalsSchemas/blob/master/schemas/payload/sqreen_exception/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::SqreenException < Sqreen::Kit::Signals::Point
|
21
|
+
PAYLOAD_SCHEMA_VERSION = 'sqreen_exception/2020-01-01T00:00:00.000Z'.freeze
|
22
|
+
|
23
|
+
# @return [Hash]
|
24
|
+
attr_accessor :infos
|
25
|
+
|
26
|
+
# @return [Exception]
|
27
|
+
attr_accessor :ruby_exception
|
28
|
+
|
29
|
+
add_mandatory_attrs :source, :time, :ruby_exception
|
30
|
+
|
31
|
+
validate_str_attr :source, /\A(?:sqreen:rule:[a-f0-9]{40}:.+)|(?:sqreen:agent:.+)\z/
|
32
|
+
|
33
|
+
def self.attributes_for_to_h_self
|
34
|
+
[] # don't include ruby_exception in list of attributes for to_h
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(values = {})
|
38
|
+
self.payload_schema = PAYLOAD_SCHEMA_VERSION
|
39
|
+
self.signal_name = 'sq.agent.exception'
|
40
|
+
self.time = values[:time] || Time.now
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
def payload
|
45
|
+
return nil unless @ruby_exception
|
46
|
+
compact_hash({
|
47
|
+
klass: @ruby_exception.class.to_s,
|
48
|
+
message: @ruby_exception.message,
|
49
|
+
infos: @infos,
|
50
|
+
})
|
51
|
+
end
|
52
|
+
|
53
|
+
def location
|
54
|
+
return nil unless @ruby_exception
|
55
|
+
Sqreen::Kit::Signals::Location.new(exception: @ruby_exception)
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,227 @@
|
|
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 Sqreen::Kit::Signals::Signal
|
59
|
+
logger.warn "Signal event in non-signal mode"
|
60
|
+
next
|
61
|
+
when Sqreen::Kit::Signals::Trace
|
62
|
+
logger.warn "Trace event in non-signal mode"
|
63
|
+
next
|
64
|
+
when Attack # in practice only found inside req rec
|
65
|
+
EventToHash.convert_attack event
|
66
|
+
when RemoteException
|
67
|
+
EventToHash.convert_exception event
|
68
|
+
when RequestRecord
|
69
|
+
EventToHash.convert_request_record event
|
70
|
+
else
|
71
|
+
logger.warn "Unexpected event type: #{event}"
|
72
|
+
next
|
73
|
+
end
|
74
|
+
h['event_type'] = event_kind(event)
|
75
|
+
h
|
76
|
+
end
|
77
|
+
Sqreen.log.debug do
|
78
|
+
tally = Hash[events.group_by(&:class).map { |k, v| [k, v.count] }]
|
79
|
+
"Doing batch with the following tally of event types: #{tally}"
|
80
|
+
end
|
81
|
+
post('batch', { batch: batch.compact }, {}, RETRY_MANY)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# see +Sqreen::Session.post+
|
87
|
+
def post(*args)
|
88
|
+
@post_proc[*args]
|
89
|
+
end
|
90
|
+
|
91
|
+
def event_kind(event)
|
92
|
+
case event
|
93
|
+
when Sqreen::RemoteException then 'sqreen_exception'
|
94
|
+
when Sqreen::Attack then 'attack'
|
95
|
+
when Sqreen::RequestRecord then 'request_record'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
module EventToHash
|
101
|
+
class << self
|
102
|
+
# @param attack [Sqreen::Attack]
|
103
|
+
def convert_attack(attack)
|
104
|
+
payload = attack.payload
|
105
|
+
res = {}
|
106
|
+
rule_p = payload['rule']
|
107
|
+
request_p = payload['request']
|
108
|
+
res[:rule_name] = rule_p['name'] if rule_p && rule_p['name']
|
109
|
+
res[:rulespack_id] = rule_p['rulespack_id'] if rule_p && rule_p['rulespack_id']
|
110
|
+
res[:test] = rule_p['test'] if rule_p && rule_p['test']
|
111
|
+
res[:infos] = payload['infos'] if payload['infos']
|
112
|
+
res[:time] = attack.time
|
113
|
+
res[:client_ip] = request_p[:addr] if request_p && request_p[:addr]
|
114
|
+
res[:request] = request_p if request_p
|
115
|
+
res[:params] = payload['params'] if payload['params']
|
116
|
+
res[:context] = payload['context'] if payload['context']
|
117
|
+
res[:headers] = payload['headers'] if payload['headers']
|
118
|
+
res
|
119
|
+
end
|
120
|
+
|
121
|
+
# @param [Sqreen::RequestRecord] rr
|
122
|
+
def convert_request_record(rr)
|
123
|
+
res = { :version => '20171208' }
|
124
|
+
payload = rr.payload
|
125
|
+
|
126
|
+
if payload[:observed]
|
127
|
+
res[:observed] = payload[:observed].dup
|
128
|
+
rulespack = nil
|
129
|
+
if rr.observed[:attacks]
|
130
|
+
res[:observed][:attacks] = rr.observed[:attacks].map do |att|
|
131
|
+
natt = att.dup
|
132
|
+
[:attack_type, :block].each { |k| natt.delete(k) } # signals stuff
|
133
|
+
rulespack = natt.delete(:rulespack_id) || rulespack
|
134
|
+
natt
|
135
|
+
end
|
136
|
+
end
|
137
|
+
if rr.observed[:sqreen_exceptions]
|
138
|
+
res[:observed][:sqreen_exceptions] = rr.observed[:sqreen_exceptions].map do |exc|
|
139
|
+
nex = exc.dup
|
140
|
+
excp = nex.delete(:exception)
|
141
|
+
if excp
|
142
|
+
nex[:message] = excp.message
|
143
|
+
nex[:klass] = excp.class.name
|
144
|
+
end
|
145
|
+
rulespack = nex.delete(:rulespack_id) || rulespack
|
146
|
+
nex
|
147
|
+
end
|
148
|
+
end
|
149
|
+
res[:rulespack_id] = rulespack unless rulespack.nil?
|
150
|
+
if rr.observed[:observations]
|
151
|
+
res[:observed][:observations] = rr.observed[:observations].map do |cat, key, value, time|
|
152
|
+
{ :category => cat, :key => key, :value => value, :time => time }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
if rr.observed[:sdk] # rubocop:disable Style/IfUnlessModifier
|
156
|
+
res[:observed][:sdk] = rr.processed_sdk_calls
|
157
|
+
end
|
158
|
+
end
|
159
|
+
res[:local] = payload['local'] if payload['local']
|
160
|
+
if payload['request']
|
161
|
+
res[:request] = payload['request'].dup
|
162
|
+
res[:client_ip] = res[:request].delete(:client_ip) if res[:request][:client_ip]
|
163
|
+
else
|
164
|
+
res[:request] = {}
|
165
|
+
end
|
166
|
+
if payload['response']
|
167
|
+
res[:response] = payload['response'].dup
|
168
|
+
else
|
169
|
+
res[:response] = {}
|
170
|
+
end
|
171
|
+
|
172
|
+
res[:request][:parameters] = payload['params'] if payload['params']
|
173
|
+
res[:request][:headers] = payload['headers'] if payload['headers']
|
174
|
+
|
175
|
+
res = Sqreen::EncodingSanitizer.sanitize(res)
|
176
|
+
|
177
|
+
if rr.redactor
|
178
|
+
res[:request], redacted = rr.redactor.redact(res[:request])
|
179
|
+
redacted = redacted.uniq
|
180
|
+
if redacted.any? && res[:observed] && res[:observed][:attacks]
|
181
|
+
res[:observed][:attacks] = WafRedactions.redact_attacks!(res[:observed][:attacks], redacted)
|
182
|
+
end
|
183
|
+
if redacted.any? && res[:observed] && res[:observed][:sqreen_exceptions]
|
184
|
+
res[:observed][:sqreen_exceptions] = WafRedactions.redact_exceptions!(res[:observed][:sqreen_exceptions], redacted)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
res
|
189
|
+
end
|
190
|
+
|
191
|
+
# @param exception_evt [Sqreen::RemoteException]
|
192
|
+
def convert_exception(exception_evt)
|
193
|
+
payload = exception_evt.payload
|
194
|
+
exception = payload['exception']
|
195
|
+
ev = {
|
196
|
+
:klass => exception.class.name,
|
197
|
+
:message => exception.message,
|
198
|
+
:params => payload['request_params'],
|
199
|
+
:time => payload['time'],
|
200
|
+
:infos => {
|
201
|
+
:client_ip => payload['client_ip'],
|
202
|
+
},
|
203
|
+
:request => payload['request_infos'],
|
204
|
+
:headers => payload['headers'],
|
205
|
+
:rule_name => payload['rule_name'],
|
206
|
+
:rulespack_id => payload['rulespack_id'],
|
207
|
+
}
|
208
|
+
|
209
|
+
ev[:infos].merge!(payload['infos']) if payload['infos']
|
210
|
+
return ev unless exception.backtrace
|
211
|
+
ev[:context] = { :backtrace => exception.backtrace.map(&:to_s) }
|
212
|
+
ev
|
213
|
+
end
|
214
|
+
|
215
|
+
# @param [Sqreen::AggregatedMetric] agg_metric
|
216
|
+
def convert_agg_metric(agg_metric)
|
217
|
+
{
|
218
|
+
name: agg_metric.name,
|
219
|
+
observation: agg_metric.data,
|
220
|
+
start: agg_metric.start,
|
221
|
+
finish: agg_metric.finish,
|
222
|
+
}
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|