sqreen 1.20.1-java → 1.22.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/lib/sqreen/actions/block_user.rb +1 -1
- data/lib/sqreen/actions/redirect_ip.rb +1 -1
- data/lib/sqreen/actions/redirect_user.rb +1 -1
- data/lib/sqreen/attack_detected.html +1 -2
- data/lib/sqreen/condition_evaluator.rb +8 -2
- data/lib/sqreen/configuration.rb +1 -1
- data/lib/sqreen/deferred_logger.rb +50 -14
- data/lib/sqreen/deliveries/batch.rb +8 -1
- data/lib/sqreen/dependency/detector.rb +11 -3
- data/lib/sqreen/dependency/new_relic.rb +10 -1
- data/lib/sqreen/deprecation.rb +38 -0
- data/lib/sqreen/ecosystem.rb +123 -0
- data/lib/sqreen/ecosystem/databases/database_connection_data.rb +23 -0
- data/lib/sqreen/ecosystem/databases/mongo.rb +39 -0
- data/lib/sqreen/ecosystem/databases/mysql.rb +54 -0
- data/lib/sqreen/ecosystem/databases/postgres.rb +51 -0
- data/lib/sqreen/ecosystem/databases/redis.rb +36 -0
- data/lib/sqreen/ecosystem/dispatch_table.rb +43 -0
- data/lib/sqreen/ecosystem/exception_reporting.rb +28 -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/messaging/bunny.rb +61 -0
- data/lib/sqreen/ecosystem/messaging/kafka.rb +70 -0
- data/lib/sqreen/ecosystem/messaging/kinesis.rb +66 -0
- data/lib/sqreen/ecosystem/messaging/sqs.rb +68 -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 +57 -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/consumer_data.rb +13 -0
- data/lib/sqreen/ecosystem/module_api/tracing/messaging_data.rb +35 -0
- data/lib/sqreen/ecosystem/module_api/tracing/producer_data.rb +13 -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 +48 -0
- data/lib/sqreen/ecosystem/tracing/modules/client.rb +35 -0
- data/lib/sqreen/ecosystem/tracing/modules/consumer.rb +35 -0
- data/lib/sqreen/ecosystem/tracing/modules/determine_ip.rb +28 -0
- data/lib/sqreen/ecosystem/tracing/modules/producer.rb +35 -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_consumer.rb +56 -0
- data/lib/sqreen/ecosystem/tracing/signals/tracing_producer.rb +56 -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/events/request_record.rb +0 -1
- data/lib/sqreen/frameworks/generic.rb +36 -1
- data/lib/sqreen/frameworks/rails.rb +0 -7
- data/lib/sqreen/frameworks/request_recorder.rb +2 -0
- data/lib/sqreen/graft/call.rb +85 -18
- data/lib/sqreen/graft/callback.rb +1 -1
- data/lib/sqreen/graft/hook.rb +192 -88
- data/lib/sqreen/graft/hook_point.rb +18 -11
- data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +2 -0
- data/lib/sqreen/legacy/instrumentation.rb +22 -10
- data/lib/sqreen/legacy/old_event_submission_strategy.rb +9 -2
- data/lib/sqreen/log.rb +3 -2
- data/lib/sqreen/log/loggable.rb +1 -0
- data/lib/sqreen/logger.rb +24 -0
- data/lib/sqreen/metrics_store.rb +11 -0
- data/lib/sqreen/null_logger.rb +22 -0
- data/lib/sqreen/remote_command.rb +4 -0
- data/lib/sqreen/rules.rb +8 -4
- data/lib/sqreen/rules/blacklist_ips_cb.rb +2 -2
- data/lib/sqreen/rules/custom_error_cb.rb +3 -3
- data/lib/sqreen/rules/rule_cb.rb +2 -0
- data/lib/sqreen/rules/waf_cb.rb +3 -3
- data/lib/sqreen/runner.rb +47 -7
- data/lib/sqreen/session.rb +2 -0
- data/lib/sqreen/signals/conversions.rb +6 -1
- data/lib/sqreen/version.rb +1 -1
- data/lib/sqreen/weave/budget.rb +46 -0
- data/lib/sqreen/weave/legacy/instrumentation.rb +252 -109
- data/lib/sqreen/worker.rb +6 -2
- metadata +60 -11
- data/lib/sqreen/encoding_sanitizer.rb +0 -27
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'sqreen/ecosystem/module_registry'
|
|
2
|
+
require 'sqreen/ecosystem/transaction_storage'
|
|
3
|
+
require 'sqreen/ecosystem/module_api/signal_producer'
|
|
4
|
+
|
|
5
|
+
module Sqreen
|
|
6
|
+
module Ecosystem
|
|
7
|
+
class TracingIdSetup
|
|
8
|
+
# @param [Array<Sqreen::Ecosystem::ModuleApi::SignalProducer>] signal_producer_modules
|
|
9
|
+
def initialize(signal_producer_modules)
|
|
10
|
+
@modules = signal_producer_modules
|
|
11
|
+
@tracing_id_prefix = nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def setup_modules
|
|
15
|
+
inject_out_of_tx_tracing_id_gen
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
attr_writer :tracing_id_prefix
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def inject_out_of_tx_tracing_id_gen
|
|
23
|
+
@modules.each do |mod|
|
|
24
|
+
mod.tracing_id_producer = method(:generate_tracing_id)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def generate_tracing_id
|
|
29
|
+
return nil unless @tracing_id_prefix
|
|
30
|
+
"#{@tracing_id_prefix}.#{SecureRandom.uuid}"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'sqreen/ecosystem/loggable'
|
|
2
|
+
|
|
3
|
+
module Sqreen
|
|
4
|
+
module Ecosystem
|
|
5
|
+
# The transaction storage is a mechanism for the modules to share
|
|
6
|
+
# request-scoped data with each other or to keep request-scoped objects
|
|
7
|
+
# themselves, although, for this last use case to be effective,
|
|
8
|
+
# propagation of request start/end events to the modules will likely be
|
|
9
|
+
# needed. A more generic notification of data availability to modules
|
|
10
|
+
# also may be needed in the future.
|
|
11
|
+
#
|
|
12
|
+
# This is not be used to share data with the Ecosystem client
|
|
13
|
+
#
|
|
14
|
+
# This class is not thread safe because it can call the lazy getter
|
|
15
|
+
# twice if [] is called concurrently.
|
|
16
|
+
class TransactionStorage
|
|
17
|
+
include Loggable
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
# @return [Sqreen::Ecosystem::TransactionStorage]
|
|
21
|
+
def create_thread_local
|
|
22
|
+
Thread.current[:tx_storage] = new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @return [Sqreen::Ecosystem::TransactionStorage]
|
|
26
|
+
def fetch_thread_local
|
|
27
|
+
Thread.current[:tx_storage]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def destroy_thread_local
|
|
31
|
+
Thread.current[:tx_storage] = nil
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def initialize
|
|
36
|
+
@values = {}
|
|
37
|
+
@values_lazy = {}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def []=(key, value)
|
|
41
|
+
@values[key] = value
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def set_lazy(key, &block)
|
|
45
|
+
@values_lazy[key] = block
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def [](key)
|
|
49
|
+
v = @values[key]
|
|
50
|
+
return v unless v.nil?
|
|
51
|
+
|
|
52
|
+
v = @values_lazy[key]
|
|
53
|
+
return nil if v.nil?
|
|
54
|
+
|
|
55
|
+
begin
|
|
56
|
+
@values[key] = v.call
|
|
57
|
+
rescue StandardError => e
|
|
58
|
+
logger.warn { "Error resolving key #{e} with lazy value: #{e.message}" }
|
|
59
|
+
raise
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require 'sqreen/log/loggable'
|
|
2
|
+
require 'sqreen/ecosystem'
|
|
3
|
+
require 'sqreen/ecosystem/dispatch_table'
|
|
4
|
+
require 'sqreen/ecosystem_integration/instrumentation_service'
|
|
5
|
+
require 'sqreen/ecosystem_integration/request_lifecycle_tracking'
|
|
6
|
+
require 'sqreen/ecosystem_integration/signal_consumption'
|
|
7
|
+
|
|
8
|
+
module Sqreen
|
|
9
|
+
# This class is the interface through which the agent interacts
|
|
10
|
+
# with the ecosystem.
|
|
11
|
+
#
|
|
12
|
+
# Other classes in the EcosystemIntegration module implement the
|
|
13
|
+
# functionality that the ecosystem requires in order to deliver
|
|
14
|
+
# data to the agent and to be informed by the agent of certain
|
|
15
|
+
# key events (see Sqreen::Ecosystem::DispatchTable).
|
|
16
|
+
class EcosystemIntegration
|
|
17
|
+
include Sqreen::Log::Loggable
|
|
18
|
+
|
|
19
|
+
# @param [Sqreen::Framework] framework
|
|
20
|
+
def initialize(framework, queue)
|
|
21
|
+
@framework = framework
|
|
22
|
+
@queue = queue
|
|
23
|
+
@request_lifecycle = RequestLifecycleTracking.new
|
|
24
|
+
@online = false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def init
|
|
28
|
+
raise 'already initialized' if @online
|
|
29
|
+
|
|
30
|
+
setup_dispatch_table
|
|
31
|
+
Ecosystem.init
|
|
32
|
+
logger.info 'Ecosystem successfully initialized'
|
|
33
|
+
@online = true
|
|
34
|
+
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
|
35
|
+
logger.warn { "Error initializing Ecosystem: #{e.message}" }
|
|
36
|
+
logger.debug { e.backtrace.map { |x| " #{x}" }.join("\n") }
|
|
37
|
+
Sqreen::RemoteException.record(e)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def disable
|
|
41
|
+
raise NotImplementedYet
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def request_start(rack_request)
|
|
45
|
+
return unless @online
|
|
46
|
+
|
|
47
|
+
Ecosystem.start_transaction
|
|
48
|
+
@request_lifecycle.notify_request_start(rack_request)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def request_end
|
|
52
|
+
return unless @online
|
|
53
|
+
|
|
54
|
+
Ecosystem.end_transaction
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def handle_tracing_command(trace_id_prefix, scopes_config)
|
|
58
|
+
return unless @online
|
|
59
|
+
|
|
60
|
+
Ecosystem.configure_sampling(trace_id_prefix, scopes_config)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def setup_dispatch_table
|
|
66
|
+
Ecosystem::DispatchTable.consume_signal =
|
|
67
|
+
create_signal_consumption.method(:consume_signal)
|
|
68
|
+
|
|
69
|
+
Ecosystem::DispatchTable.add_request_start_listener =
|
|
70
|
+
@request_lifecycle.method(:add_start_observer)
|
|
71
|
+
|
|
72
|
+
Ecosystem::DispatchTable.fetch_logger = lambda { logger }
|
|
73
|
+
|
|
74
|
+
Ecosystem::DispatchTable.instrument = InstrumentationService.method(:instrument)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def create_signal_consumption
|
|
78
|
+
SignalConsumption.new(@framework, @request_lifecycle, @queue)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'sqreen/log/loggable'
|
|
2
|
+
require 'sqreen/events/remote_exception'
|
|
3
|
+
require 'sqreen/mono_time'
|
|
4
|
+
|
|
5
|
+
module Sqreen
|
|
6
|
+
class EcosystemIntegration
|
|
7
|
+
module AroundCallbacks
|
|
8
|
+
class << self
|
|
9
|
+
include Log::Loggable::ClassMethods
|
|
10
|
+
|
|
11
|
+
# for instrumentation hooks
|
|
12
|
+
# instrumentation hooks already handle budgets, so nothing
|
|
13
|
+
# to do in that respect
|
|
14
|
+
def wrap_instrumentation_hook(module_name, action, callable)
|
|
15
|
+
perf_notif_name = "ecosystem_#{module_name}"
|
|
16
|
+
|
|
17
|
+
Proc.new do |*args|
|
|
18
|
+
begin
|
|
19
|
+
start = Sqreen.time
|
|
20
|
+
callable.call(*args)
|
|
21
|
+
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
|
22
|
+
# 2) rescue exceptions
|
|
23
|
+
logger.warn { "Error in #{module_name}:#{action}: #{e.message}" }
|
|
24
|
+
logger.debug { e.backtrace.map { |x| " #{x}" }.join("\n") }
|
|
25
|
+
Sqreen::RemoteException.record(e)
|
|
26
|
+
ensure
|
|
27
|
+
# 3) contribute to performance metrics
|
|
28
|
+
stop = Sqreen.time
|
|
29
|
+
Sqreen::PerformanceNotifications.notify(perf_notif_name, action, start, stop)
|
|
30
|
+
end # end proc
|
|
31
|
+
end # end begin
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# XXX: not used yet
|
|
35
|
+
def wrap_generic_callback(module_name, action, callable)
|
|
36
|
+
timer_name = "ecosystem:#{module_name}@#{action}"
|
|
37
|
+
perf_notif_name = "ecosystem_#{module_name}"
|
|
38
|
+
|
|
39
|
+
Proc.new do |*args|
|
|
40
|
+
begin
|
|
41
|
+
req_storage = Thread.current[:sqreen_http_request]
|
|
42
|
+
|
|
43
|
+
timer = Graft::Timer.new(timer_name) do |t|
|
|
44
|
+
# this is an epilogue to measure()
|
|
45
|
+
req_storage && req_storage[:timed_hooks] << t
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
req_timer = nil
|
|
49
|
+
timer.measure do
|
|
50
|
+
# not in a request, no budget; call cb
|
|
51
|
+
next callable.call(*args) unless req_storage
|
|
52
|
+
|
|
53
|
+
# 1) budget enforcement
|
|
54
|
+
# skip callback if budget already expended
|
|
55
|
+
next if req_storage[:time_budget_expended]
|
|
56
|
+
|
|
57
|
+
budget = req_storage[:time_budget]
|
|
58
|
+
if budget
|
|
59
|
+
req_timer = req_storage[:timer]
|
|
60
|
+
remaining = budget - req_timer.elapsed
|
|
61
|
+
unless remaining > 0
|
|
62
|
+
req_storage[:time_budget_expended] = true
|
|
63
|
+
next # skip callback
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
callable.call(*args)
|
|
68
|
+
end
|
|
69
|
+
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
|
70
|
+
# 2) rescue exceptions
|
|
71
|
+
logger.warn { "Error in #{module_name}:#{action}: #{e.message}" }
|
|
72
|
+
logger.debug { e.backtrace.map { |x| " #{x}" }.join("\n") }
|
|
73
|
+
Sqreen::RemoteException.record(e)
|
|
74
|
+
ensure
|
|
75
|
+
# 3) contribute to performance metrics
|
|
76
|
+
if timer
|
|
77
|
+
req_timer.include_measurements(timer) if req_timer
|
|
78
|
+
|
|
79
|
+
Sqreen::PerformanceNotifications.notify(
|
|
80
|
+
perf_notif_name, action, *timer.start_and_end
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
end # end begin
|
|
84
|
+
end # end proc
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'sqreen/graft/hook'
|
|
2
|
+
require 'sqreen/ecosystem_integration/around_callbacks'
|
|
3
|
+
|
|
4
|
+
module Sqreen
|
|
5
|
+
class EcosystemIntegration
|
|
6
|
+
module InstrumentationService
|
|
7
|
+
class << self
|
|
8
|
+
# @param [String] module_name
|
|
9
|
+
# @param [String] method in form A::B#c or A::B.c
|
|
10
|
+
# @param [Hash{Symbol=>Proc}] spec
|
|
11
|
+
def instrument(module_name, method, spec)
|
|
12
|
+
hook = Sqreen::Graft::Hook[method].add do
|
|
13
|
+
if spec[:before]
|
|
14
|
+
cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'pre', spec[:before])
|
|
15
|
+
before(nil, flow: true, &cb)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if spec[:after]
|
|
19
|
+
cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'post', spec[:after])
|
|
20
|
+
after(nil, flow: true, &cb)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if spec[:raised]
|
|
24
|
+
cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'failing', spec[:raised])
|
|
25
|
+
raised(nil, flow: true, &cb)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if spec[:ensured]
|
|
29
|
+
cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'finally', spec[:ensured])
|
|
30
|
+
ensured(nil, flow: true, &cb)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
hook.install
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'sqreen/events/remote_exception'
|
|
2
|
+
require 'sqreen/log/loggable'
|
|
3
|
+
|
|
4
|
+
module Sqreen
|
|
5
|
+
class EcosystemIntegration
|
|
6
|
+
# This class gets notified of request start/end and
|
|
7
|
+
# 1) distributes such events to listeners (typically ecosystem modules;
|
|
8
|
+
# the method add_start_observer is exposed to ecosystem modules through
|
|
9
|
+
# +Sqreen::Ecosystem::ModuleApi::EventListener+ and the dispatch table).
|
|
10
|
+
# 2) keeps track of whether a request is active on this thread. This is
|
|
11
|
+
# so that users of this class can have this information without needing
|
|
12
|
+
# to subscribe to request start/events and keeping thread local state
|
|
13
|
+
# themselves.
|
|
14
|
+
# XXX: Since the Ecosystem is also notified of request start/end, it could
|
|
15
|
+
# notify its modules of request start without going through the dispatch
|
|
16
|
+
# table and call add_start_observer. We need to think if we want to keep
|
|
17
|
+
# the transaction / request distinction or if they should just be
|
|
18
|
+
# assumed to be the same, though.
|
|
19
|
+
class RequestLifecycleTracking
|
|
20
|
+
include Sqreen::Log::Loggable
|
|
21
|
+
|
|
22
|
+
def initialize
|
|
23
|
+
@start_observers = []
|
|
24
|
+
@tl_key = "#{object_id}_req_in_flight"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# API for classes needing to know the request state
|
|
28
|
+
|
|
29
|
+
# @param cb A callback taking a Rack::Request
|
|
30
|
+
def add_start_observer(cb)
|
|
31
|
+
@start_observers << cb
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def in_request?
|
|
35
|
+
Thread.current[@tl_key] ? true : false
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# API for classes notifying this one of request events
|
|
39
|
+
|
|
40
|
+
def notify_request_start(rack_req)
|
|
41
|
+
Thread.current[@tl_key] = true
|
|
42
|
+
return if @start_observers.empty?
|
|
43
|
+
@start_observers.each do |cb|
|
|
44
|
+
begin
|
|
45
|
+
cb.call(rack_req)
|
|
46
|
+
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
|
47
|
+
logger.warn { "Error calling #{cb} on request start: #{e.message}" }
|
|
48
|
+
Sqreen::RemoteException.record(e)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def notify_request_end
|
|
54
|
+
Thread.current[@tl_key] = false
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'sqreen/log/loggable'
|
|
2
|
+
|
|
3
|
+
module Sqreen
|
|
4
|
+
class EcosystemIntegration
|
|
5
|
+
class SignalConsumption
|
|
6
|
+
include Sqreen::Log::Loggable
|
|
7
|
+
|
|
8
|
+
PAYLOAD_CREATOR_SECTIONS = %w[request response params headers].freeze
|
|
9
|
+
|
|
10
|
+
# @param [Sqreen::Frameworks::GenericFramework] framework
|
|
11
|
+
# @param [Sqreen::EcosystemIntegration::RequestLifecycleTracking]
|
|
12
|
+
# @param [Sqreen::CappedQueue]
|
|
13
|
+
def initialize(framework, req_lifecycle, queue)
|
|
14
|
+
@framework = framework
|
|
15
|
+
@req_lifecycle = req_lifecycle
|
|
16
|
+
@queue = queue
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def consume_signal(signal)
|
|
20
|
+
# transitional
|
|
21
|
+
unless Sqreen.features.fetch('use_signals', DEFAULT_USE_SIGNALS)
|
|
22
|
+
logger.debug { "Discarding signal #{signal} (signals disabled)" }
|
|
23
|
+
return
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if @req_lifecycle.in_request?
|
|
27
|
+
# add it to the request record
|
|
28
|
+
@framework.observe(:signals, signal, PAYLOAD_CREATOR_SECTIONS, true)
|
|
29
|
+
else
|
|
30
|
+
@queue.push signal
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -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
|
|
@@ -209,7 +218,16 @@ module Sqreen
|
|
|
209
218
|
|
|
210
219
|
# Should the agent not be starting up?
|
|
211
220
|
def prevent_startup
|
|
221
|
+
# SQREEN-880 - prevent Sqreen startup on Sidekiq workers
|
|
222
|
+
return :sidekiq_cli if defined?(Sidekiq::CLI)
|
|
223
|
+
return :delayed_job if defined?(Delayed::Command)
|
|
224
|
+
|
|
225
|
+
# Prevent Sqreen startup on rake tasks - unless this is a Sqreen test
|
|
226
|
+
run_in_test = sqreen_configuration.get(:run_in_test)
|
|
227
|
+
return :rake if !run_in_test && $0.end_with?('rake')
|
|
228
|
+
|
|
212
229
|
return :irb if $0 == 'irb'
|
|
230
|
+
|
|
213
231
|
return if sqreen_configuration.nil?
|
|
214
232
|
disable = sqreen_configuration.get(:disable)
|
|
215
233
|
return :config_disable if disable == true || disable.to_s.to_i == 1
|
|
@@ -251,8 +269,12 @@ module Sqreen
|
|
|
251
269
|
# Nota: cleanup should be performed at end of request (see clean_request)
|
|
252
270
|
def store_request(object)
|
|
253
271
|
return unless ensure_rack_loaded
|
|
272
|
+
|
|
273
|
+
rack_req = Rack::Request.new(object)
|
|
274
|
+
@req_start_cb.call(rack_req)
|
|
275
|
+
|
|
254
276
|
self.remaining_perf_budget = Sqreen.performance_budget
|
|
255
|
-
SharedStorage.set(:request,
|
|
277
|
+
SharedStorage.set(:request, rack_req)
|
|
256
278
|
SharedStorage.set(:xss_params, nil)
|
|
257
279
|
SharedStorage.set(:whitelisted, nil)
|
|
258
280
|
SharedStorage.set(:request_overtime, nil)
|
|
@@ -281,6 +303,7 @@ module Sqreen
|
|
|
281
303
|
SharedStorage.set(:xss_params, nil)
|
|
282
304
|
SharedStorage.set(:whitelisted, nil)
|
|
283
305
|
SharedStorage.set(:request_overtime, nil)
|
|
306
|
+
@req_end_cb.call
|
|
284
307
|
end
|
|
285
308
|
|
|
286
309
|
def remaining_perf_budget
|
|
@@ -377,6 +400,18 @@ module Sqreen
|
|
|
377
400
|
r
|
|
378
401
|
end
|
|
379
402
|
|
|
403
|
+
def body
|
|
404
|
+
return nil unless request.respond_to?(:body)
|
|
405
|
+
return nil unless request.body.respond_to?(:read)
|
|
406
|
+
return nil unless request.body.respond_to?(:rewind)
|
|
407
|
+
|
|
408
|
+
body_io = request.body
|
|
409
|
+
body = body_io.read(4096)
|
|
410
|
+
body_io.rewind
|
|
411
|
+
|
|
412
|
+
body
|
|
413
|
+
end
|
|
414
|
+
|
|
380
415
|
# Expose current working directory
|
|
381
416
|
def cwd
|
|
382
417
|
Dir.getwd
|