sqreen 1.17.0-java → 1.17.2.beta1-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 +418 -0
- data/README.md +5 -5
- data/lib/sqreen.rb +2 -72
- data/lib/sqreen/agent.rb +37 -0
- data/lib/sqreen/call_countable.rb +6 -6
- data/lib/sqreen/conditionable.rb +6 -6
- data/lib/sqreen/dependency.rb +18 -0
- data/lib/sqreen/dependency/callback.rb +34 -0
- data/lib/sqreen/dependency/detector.rb +97 -0
- data/lib/sqreen/dependency/hook.rb +102 -0
- data/lib/sqreen/dependency/hook_point.rb +219 -0
- data/lib/sqreen/dependency/new_relic.rb +17 -0
- data/lib/sqreen/dependency/rack.rb +36 -0
- data/lib/sqreen/dependency/rails.rb +30 -0
- data/lib/sqreen/dependency/sentry.rb +17 -0
- data/lib/sqreen/exception.rb +3 -0
- data/lib/sqreen/frameworks/generic.rb +2 -97
- data/lib/sqreen/frameworks/rails.rb +4 -13
- data/lib/sqreen/frameworks/sinatra.rb +0 -25
- data/lib/sqreen/instrumentation.rb +5 -4
- data/lib/sqreen/rules_callbacks/execjs.rb +3 -0
- data/lib/sqreen/rules_callbacks/record_request_context.rb +4 -1
- data/lib/sqreen/runner.rb +0 -3
- data/lib/sqreen/session.rb +40 -45
- data/lib/sqreen/version.rb +1 -1
- data/lib/sqreen/web_server.rb +54 -0
- data/lib/sqreen/web_server/generic.rb +24 -0
- data/lib/sqreen/web_server/passenger.rb +33 -0
- data/lib/sqreen/web_server/puma.rb +62 -0
- data/lib/sqreen/web_server/rainbows.rb +14 -0
- data/lib/sqreen/web_server/thin.rb +14 -0
- data/lib/sqreen/web_server/unicorn.rb +52 -0
- data/lib/sqreen/web_server/webrick.rb +14 -0
- data/lib/sqreen/worker.rb +68 -0
- metadata +28 -6
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
|
+
|
4
|
+
module Sqreen
|
5
|
+
module Dependency
|
6
|
+
module NewRelic
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def ignore_sqreen_exceptions
|
10
|
+
return unless defined?(NewRelic::Agent::Agent)
|
11
|
+
NewRelic::Agent::Agent.instance.error_collector.ignore(['Sqreen::AttackBlocked'])
|
12
|
+
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
13
|
+
Sqreen.log.warn "Failed ignoring AttackBlocked on NewRelic: #{e.inspect}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
|
+
|
4
|
+
module Sqreen
|
5
|
+
module Dependency
|
6
|
+
module Rack
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def find_handler(&block)
|
10
|
+
Sqreen::Dependency::Hook.add('Rack::Server#server') do
|
11
|
+
after do |callback, _, server, _|
|
12
|
+
block.call(server)
|
13
|
+
callback.disable # do this once, :server is a lazy init accessor
|
14
|
+
end
|
15
|
+
end
|
16
|
+
Sqreen::Dependency::Hook['Rack::Server#server'].install
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_run(handler, &block)
|
20
|
+
Sqreen.log.debug "[#{Process.pid}] #{handler.inspect}"
|
21
|
+
hookpoint_name = "#{handler.name}.run"
|
22
|
+
|
23
|
+
Sqreen::Dependency::Hook.add(hookpoint_name) do
|
24
|
+
before { block.call(handler) }
|
25
|
+
end
|
26
|
+
Sqreen::Dependency::Hook[hookpoint_name].install
|
27
|
+
end
|
28
|
+
|
29
|
+
def rackup?
|
30
|
+
return false if Sqreen::Dependency::Rails.server?
|
31
|
+
|
32
|
+
Sqreen::Dependency.const_exist?('Rack::Server') && ObjectSpace.each_object(::Rack::Server).count > 0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
|
+
|
4
|
+
module Sqreen
|
5
|
+
module Dependency
|
6
|
+
module Rails
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def required?
|
10
|
+
Sqreen::Dependency.const_exist?('Rails::Application')
|
11
|
+
end
|
12
|
+
|
13
|
+
def server?
|
14
|
+
Sqreen::Dependency.const_exist?('Rails::Server') && ObjectSpace.each_object(::Rails::Server).count > 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect_middlewares
|
18
|
+
Sqreen.log.debug { "Middlewares: " << ::Rails.application.middleware.map(&:inspect).inspect }
|
19
|
+
end
|
20
|
+
|
21
|
+
def insert_sqreen_middlewares
|
22
|
+
Sqreen.log.debug { 'Inserting Sqreen middlewares for Rails' }
|
23
|
+
app = ::Rails.application
|
24
|
+
app.middleware.insert_after(::Rack::Runtime, Sqreen::Middleware)
|
25
|
+
app.middleware.insert_after(::ActionDispatch::DebugExceptions, Sqreen::RailsMiddleware)
|
26
|
+
app.middleware.insert_after(::ActionDispatch::DebugExceptions, Sqreen::ErrorHandlingMiddleware)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
|
+
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
|
+
|
4
|
+
module Sqreen
|
5
|
+
module Dependency
|
6
|
+
module Sentry
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def ignore_sqreen_exceptions
|
10
|
+
return unless defined?(Raven) && Raven.respond_to?(:configuration)
|
11
|
+
Raven.configuration.excluded_exceptions += ['Sqreen::AttackBlocked']
|
12
|
+
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
13
|
+
Sqreen.log.warn "Failed setting Sentry's excluded_exceptions: #{e.inspect}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/sqreen/exception.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
|
+
|
3
4
|
require 'ipaddr'
|
4
5
|
require 'set'
|
5
6
|
|
@@ -17,11 +18,6 @@ module Sqreen
|
|
17
18
|
attr_accessor :sqreen_configuration
|
18
19
|
|
19
20
|
def initialize
|
20
|
-
if defined?(Rack::Builder)
|
21
|
-
hook_rack_builder
|
22
|
-
else
|
23
|
-
to_app_done(Process.pid)
|
24
|
-
end
|
25
21
|
clean_request_record
|
26
22
|
end
|
27
23
|
|
@@ -205,12 +201,6 @@ module Sqreen
|
|
205
201
|
nil
|
206
202
|
end
|
207
203
|
|
208
|
-
# Main entry point for sqreen.
|
209
|
-
# launch whenever we are ready
|
210
|
-
def on_start
|
211
|
-
yield self
|
212
|
-
end
|
213
|
-
|
214
204
|
# Should the agent not be starting up?
|
215
205
|
def prevent_startup
|
216
206
|
return :irb if $0 == 'irb'
|
@@ -221,23 +211,7 @@ module Sqreen
|
|
221
211
|
|
222
212
|
# Instrument with our rules when the framework as finished loading
|
223
213
|
def instrument_when_ready!(instrumentor, rules)
|
224
|
-
|
225
|
-
instrumentor.instrument!(rules, self)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
def to_app_done(val)
|
230
|
-
return if @to_app_done
|
231
|
-
@to_app_done = val
|
232
|
-
return unless @wait
|
233
|
-
@wait.each(&:call)
|
234
|
-
@wait.clear
|
235
|
-
end
|
236
|
-
|
237
|
-
def wait_for_to_app(&block)
|
238
|
-
yield && return if @to_app_done
|
239
|
-
@wait ||= []
|
240
|
-
@wait << block
|
214
|
+
instrumentor.instrument!(rules, self)
|
241
215
|
end
|
242
216
|
|
243
217
|
# Does the parameters value include this value
|
@@ -456,15 +430,6 @@ module Sqreen
|
|
456
430
|
end
|
457
431
|
end
|
458
432
|
|
459
|
-
def on_pre_fork_preload?
|
460
|
-
# unlike with worker_fork_detection, we can't be instrument Puma::Cluster
|
461
|
-
# in time for intercepting run
|
462
|
-
stack = Kernel.caller_locations
|
463
|
-
|
464
|
-
puma_preload?(stack) || unicorn_preload?(stack)
|
465
|
-
end
|
466
|
-
|
467
|
-
|
468
433
|
protected
|
469
434
|
|
470
435
|
# Is this a whitelisted path?
|
@@ -485,22 +450,6 @@ module Sqreen
|
|
485
450
|
ret.first
|
486
451
|
end
|
487
452
|
|
488
|
-
def hook_rack_request(klass)
|
489
|
-
@calling_pid = Process.pid
|
490
|
-
klass.class_eval do
|
491
|
-
define_method(:call_with_sqreen) do |*args, &block|
|
492
|
-
rv = call_without_sqreen(*args, &block)
|
493
|
-
if Sqreen.framework.instance_variable_get('@calling_pid') != Process.pid
|
494
|
-
Sqreen.framework.instance_variable_set('@calling_pid', Process.pid)
|
495
|
-
yield Sqreen.framework
|
496
|
-
end
|
497
|
-
rv
|
498
|
-
end
|
499
|
-
alias_method :call_without_sqreen, :call
|
500
|
-
alias_method :call, :call_with_sqreen
|
501
|
-
end
|
502
|
-
end
|
503
|
-
|
504
453
|
def hook_rack_builder
|
505
454
|
Rack::Builder.class_eval do
|
506
455
|
define_method(:to_app_with_sqreen) do |*args, &block|
|
@@ -547,52 +496,8 @@ module Sqreen
|
|
547
496
|
false
|
548
497
|
end
|
549
498
|
|
550
|
-
def sentry_ignore_exceptions
|
551
|
-
return unless defined?(Raven) && Raven.respond_to?(:configuration)
|
552
|
-
Raven.configuration.excluded_exceptions += ['Sqreen::AttackBlocked']
|
553
|
-
rescue
|
554
|
-
Sqreen.log.warn "Failed setting Sentry's excluded_exceptions: #{e.inspect}"
|
555
|
-
end
|
556
|
-
|
557
|
-
def newrelic_ignore_errors
|
558
|
-
return unless defined?(NewRelic::Agent::Agent)
|
559
|
-
NewRelic::Agent::Agent.instance.
|
560
|
-
error_collector.ignore(['Sqreen::AttackBlocked'])
|
561
|
-
rescue
|
562
|
-
Sqreen.log.warn "Failed ignoring AttackBlocked on NewRelic: #{e.inspect}"
|
563
|
-
end
|
564
|
-
|
565
|
-
# if it doesn't detect the fork it's not a problem
|
566
|
-
def worker_fork_detection
|
567
|
-
# only Puma currently supported
|
568
|
-
return unless defined?(Puma::Cluster) && Puma::Cluster.instance_methods.include?(:worker)
|
569
|
-
cur_worker_meth = Puma::Cluster.instance_method(:worker)
|
570
|
-
Puma::Cluster.class_eval do
|
571
|
-
define_method(:worker) do |*args|
|
572
|
-
Sqreen.on_forked_worker = true
|
573
|
-
cur_worker_meth.bind(self)[*args]
|
574
|
-
end
|
575
|
-
end
|
576
|
-
end
|
577
|
-
|
578
499
|
private
|
579
500
|
|
580
|
-
def puma_preload?(stack)
|
581
|
-
cluster_run = stack.each_with_index.find { |b, _i| b.path =~ /puma\/cluster\.rb\z/ && b.label == 'run' }
|
582
|
-
return false unless cluster_run
|
583
|
-
frame_atop = stack[cluster_run[1] - 1]
|
584
|
-
frame_atop.label == 'load_and_bind'
|
585
|
-
end
|
586
|
-
|
587
|
-
def unicorn_preload?(stack)
|
588
|
-
build_app = stack.each_with_index.find do |b, _i|
|
589
|
-
b.path =~ /unicorn\/http_server\.rb\z/ && b.label == 'build_app!'
|
590
|
-
end
|
591
|
-
return false unless build_app
|
592
|
-
frame_below = stack[build_app[1] + 1]
|
593
|
-
frame_below.label == 'start'
|
594
|
-
end
|
595
|
-
|
596
501
|
def split_ip_addresses(ip_addresses)
|
597
502
|
return [] unless ip_addresses
|
598
503
|
|
@@ -15,6 +15,10 @@ module Sqreen
|
|
15
15
|
'Mysql2' => :mysql,
|
16
16
|
}.freeze
|
17
17
|
|
18
|
+
def initialize
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
18
22
|
def framework_infos
|
19
23
|
{
|
20
24
|
:framework_type => 'Rails',
|
@@ -89,19 +93,6 @@ module Sqreen
|
|
89
93
|
end
|
90
94
|
end
|
91
95
|
|
92
|
-
def on_start(&block)
|
93
|
-
@calling_pid = Process.pid
|
94
|
-
Init.startup do |app|
|
95
|
-
worker_fork_detection
|
96
|
-
sentry_ignore_exceptions
|
97
|
-
newrelic_ignore_errors
|
98
|
-
hook_rack_request(app.class, &block)
|
99
|
-
app.config.after_initialize do
|
100
|
-
yield self
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
96
|
def prevent_startup
|
106
97
|
res = super
|
107
98
|
return res if res
|
@@ -15,15 +15,6 @@ module Sqreen
|
|
15
15
|
h
|
16
16
|
end
|
17
17
|
|
18
|
-
def on_start(&block)
|
19
|
-
worker_fork_detection
|
20
|
-
sentry_ignore_exceptions
|
21
|
-
newrelic_ignore_errors
|
22
|
-
hook_app_build(Sinatra::Base)
|
23
|
-
hook_rack_request(Sinatra::Application, &block)
|
24
|
-
yield self
|
25
|
-
end
|
26
|
-
|
27
18
|
def db_settings(options = {})
|
28
19
|
adapter = options[:connection_adapter]
|
29
20
|
return nil unless adapter
|
@@ -39,22 +30,6 @@ module Sqreen
|
|
39
30
|
db_infos = { :name => adapter_name }
|
40
31
|
[db_type, db_infos]
|
41
32
|
end
|
42
|
-
|
43
|
-
def hook_app_build(klass)
|
44
|
-
klass.singleton_class.class_eval do
|
45
|
-
define_method(:setup_default_middleware_with_sqreen) do |builder|
|
46
|
-
ret = setup_default_middleware_without_sqreen(builder)
|
47
|
-
builder.instance_variable_get('@use').insert(2, proc do |app|
|
48
|
-
# Inject error middle just before sinatra one
|
49
|
-
Sqreen::ErrorHandlingMiddleware.new(app)
|
50
|
-
end)
|
51
|
-
ret
|
52
|
-
end
|
53
|
-
|
54
|
-
alias_method :setup_default_middleware_without_sqreen, :setup_default_middleware
|
55
|
-
alias_method :setup_default_middleware, :setup_default_middleware_with_sqreen
|
56
|
-
end
|
57
|
-
end
|
58
33
|
end
|
59
34
|
end
|
60
35
|
end
|
@@ -43,7 +43,6 @@ module Sqreen
|
|
43
43
|
POST_CB = 'post'.freeze
|
44
44
|
FAILING_CB = 'failing'.freeze
|
45
45
|
|
46
|
-
MGMT_COST = 0.000025
|
47
46
|
@@override_semaphore = Mutex.new
|
48
47
|
@@overriden_singleton_methods = false
|
49
48
|
|
@@ -115,7 +114,7 @@ module Sqreen
|
|
115
114
|
Sqreen::PerformanceNotifications.notify(rule || cb.class.name, PRE_CB, start, stop)
|
116
115
|
end
|
117
116
|
all_stop = Sqreen.time
|
118
|
-
framework.remaining_perf_budget = budget - (all_stop - all_start)
|
117
|
+
framework.remaining_perf_budget = budget - (all_stop - all_start) if framework && budget
|
119
118
|
Sqreen::PerformanceNotifications.notify('hooks_pre', PRE_CB, all_start, all_stop)
|
120
119
|
returns
|
121
120
|
#end
|
@@ -168,7 +167,7 @@ module Sqreen
|
|
168
167
|
end
|
169
168
|
all_stop = Sqreen.time
|
170
169
|
if framework && budget && framework.remaining_perf_budget
|
171
|
-
framework.remaining_perf_budget = budget - (all_stop - all_start)
|
170
|
+
framework.remaining_perf_budget = budget - (all_stop - all_start)
|
172
171
|
end
|
173
172
|
Sqreen::PerformanceNotifications.notify('hooks_post', POST_CB, all_start, all_stop)
|
174
173
|
returns
|
@@ -222,7 +221,7 @@ module Sqreen
|
|
222
221
|
end
|
223
222
|
all_stop = Sqreen.time
|
224
223
|
if framework && budget && framework.remaining_perf_budget
|
225
|
-
framework.remaining_perf_budget = budget - (all_stop - all_start)
|
224
|
+
framework.remaining_perf_budget = budget - (all_stop - all_start)
|
226
225
|
end
|
227
226
|
Sqreen::PerformanceNotifications.notify('hooks_failing', FAILING_CB, all_start, all_stop)
|
228
227
|
returns
|
@@ -254,6 +253,7 @@ module Sqreen
|
|
254
253
|
@sqreen_multi_instr ||= nil
|
255
254
|
|
256
255
|
proc do |*args, &block|
|
256
|
+
Sqreen.log.debug { "Calling instrumented #{klass_name} #{original_meth} => #{meth}" }
|
257
257
|
budget = nil
|
258
258
|
skip_call = Thread.current[:sqreen_in_use]
|
259
259
|
begin
|
@@ -626,6 +626,7 @@ module Sqreen
|
|
626
626
|
end
|
627
627
|
end
|
628
628
|
|
629
|
+
Sqreen.log.debug "Adding callback #{cb} for #{klass} #{method}"
|
629
630
|
@@registered_callbacks.add(cb)
|
630
631
|
@@unovertimable_hookpoints << key unless cb.overtimeable
|
631
632
|
@@instrumented_pid = Process.pid
|
@@ -50,18 +50,21 @@ module Sqreen
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def pre(inst, args, budget = nil, &_block)
|
53
|
+
Sqreen.log.debug { "#{self.class} pre args: #{args.inspect}" }
|
53
54
|
return unless pre?
|
54
55
|
|
55
56
|
call_callback('pre', budget, inst, @cb_bas['pre'], args)
|
56
57
|
end
|
57
58
|
|
58
59
|
def post(rv, inst, args, budget = nil, &_block)
|
60
|
+
Sqreen.log.debug { "#{self.class} post args: #{args.inspect}" }
|
59
61
|
return unless post?
|
60
62
|
|
61
63
|
call_callback('post', budget, inst, @cb_bas['post'], args, rv)
|
62
64
|
end
|
63
65
|
|
64
66
|
def failing(rv, inst, args, budget = nil, &_block)
|
67
|
+
Sqreen.log.debug { "#{self.class} failing args: #{args.inspect}" }
|
65
68
|
return unless failing?
|
66
69
|
|
67
70
|
call_callback('failing', budget, inst, @cb_bas['failing'], args, rv)
|
@@ -18,6 +18,7 @@ module Sqreen
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def pre(_inst, args, _budget = nil, &_block)
|
21
|
+
Sqreen.log.debug { "RecordRequestContext pre args: #{args.inspect}" }
|
21
22
|
framework.store_request(args[0])
|
22
23
|
wh = framework.whitelisted_match
|
23
24
|
if wh
|
@@ -31,12 +32,14 @@ module Sqreen
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def post(rv, _inst, args, _budget = nil, &_block)
|
35
|
+
Sqreen.log.debug { "RecordRequestContext post args: #{args.inspect}" }
|
34
36
|
framework.store_response(rv, args[0])
|
35
37
|
framework.clean_request
|
36
38
|
advise_action(nil)
|
37
39
|
end
|
38
40
|
|
39
|
-
def failing(_exception, _inst,
|
41
|
+
def failing(_exception, _inst, args, _budget = nil, &_block)
|
42
|
+
Sqreen.log.debug { "RecordRequestContext failing args: #{args.inspect}" }
|
40
43
|
framework.clean_request
|
41
44
|
advise_action(nil)
|
42
45
|
end
|
data/lib/sqreen/runner.rb
CHANGED
@@ -58,9 +58,6 @@ module Sqreen
|
|
58
58
|
attr_accessor :logged_in
|
59
59
|
alias logged_in? logged_in
|
60
60
|
|
61
|
-
attr_accessor :on_forked_worker
|
62
|
-
alias on_forked_worker? on_forked_worker
|
63
|
-
|
64
61
|
attr_reader :whitelisted_paths
|
65
62
|
def update_whitelisted_paths(paths)
|
66
63
|
@whitelisted_paths = paths.freeze
|
data/lib/sqreen/session.rb
CHANGED
@@ -33,9 +33,10 @@ module Sqreen
|
|
33
33
|
RETRY_CONNECT_SECONDS = 10
|
34
34
|
RETRY_REQUEST_SECONDS = 10
|
35
35
|
|
36
|
-
MAX_DELAY =
|
36
|
+
MAX_DELAY = 300
|
37
37
|
|
38
|
-
|
38
|
+
RETRY_FOREVER = :forever
|
39
|
+
RETRY_MANY = 301
|
39
40
|
|
40
41
|
MUTEX = Mutex.new
|
41
42
|
METRICS_KEY = 'metrics'.freeze
|
@@ -108,14 +109,6 @@ module Sqreen
|
|
108
109
|
end
|
109
110
|
end
|
110
111
|
|
111
|
-
def resilient_post(path, data, headers = {})
|
112
|
-
post(path, data, headers, RETRY_LONG)
|
113
|
-
end
|
114
|
-
|
115
|
-
def resilient_get(path, headers = {})
|
116
|
-
get(path, headers, RETRY_LONG)
|
117
|
-
end
|
118
|
-
|
119
112
|
def post(path, data, headers = {}, max_retry = 2)
|
120
113
|
do_http_request(:POST, path, data, headers, max_retry)
|
121
114
|
end
|
@@ -133,7 +126,7 @@ module Sqreen
|
|
133
126
|
|
134
127
|
current_retry += 1
|
135
128
|
|
136
|
-
raise e if current_retry >= max_retry || e.is_a?(Sqreen::NotImplementedYet)
|
129
|
+
raise e if max_retry != RETRY_FOREVER && current_retry >= max_retry || e.is_a?(Sqreen::NotImplementedYet) || e.is_a?(Sqreen::Unauthorized)
|
137
130
|
|
138
131
|
sleep_delay = [MAX_DELAY, retry_request_seconds * current_retry].min
|
139
132
|
Sqreen.log.debug format("Sleeping %ds before retry #{current_retry}/#{max_retry}", sleep_delay)
|
@@ -173,41 +166,44 @@ module Sqreen
|
|
173
166
|
path = prefix_path(path)
|
174
167
|
Sqreen.log.debug format('%s %s (%s)', method, path, @token)
|
175
168
|
|
176
|
-
|
169
|
+
payload = {}
|
177
170
|
resiliently(RETRY_REQUEST_SECONDS, max_retry) do
|
178
|
-
|
171
|
+
res = nil
|
179
172
|
MUTEX.synchronize do
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
173
|
+
res = case method.upcase
|
174
|
+
when :GET
|
175
|
+
@con.get(path, headers)
|
176
|
+
when :POST
|
177
|
+
json_data = nil
|
178
|
+
unless data.nil?
|
179
|
+
serialized = Serializer.serialize(data)
|
180
|
+
json_data = compress(SafeJSON.dump(serialized))
|
181
|
+
end
|
182
|
+
@con.post(path, json_data, headers)
|
183
|
+
else
|
184
|
+
Sqreen.log.debug format('unknown method %s', method)
|
185
|
+
raise Sqreen::NotImplementedYet
|
186
|
+
end
|
187
|
+
end
|
188
|
+
if res && res.code == '401'
|
189
|
+
raise Sqreen::Unauthorized, 'HTTP 401: shall relogin'
|
194
190
|
end
|
195
|
-
if
|
196
|
-
if
|
197
|
-
|
198
|
-
unless
|
199
|
-
Sqreen.log.debug(format('Cannot %s %s. Parsed response body was: %s', method, path,
|
191
|
+
if res && res.body
|
192
|
+
if res['Content-Type'] && res['Content-Type'].start_with?('application/json')
|
193
|
+
payload = JSON.parse(res.body)
|
194
|
+
unless payload['status']
|
195
|
+
Sqreen.log.debug(format('Cannot %s %s. Parsed response body was: %s', method, path, payload.inspect))
|
200
196
|
end
|
201
197
|
else
|
202
|
-
Sqreen.log.debug "Unexpected response Content-Type: #{
|
203
|
-
Sqreen.log.debug "Unexpected response body: #{
|
198
|
+
Sqreen.log.debug "Unexpected response Content-Type: #{res['Content-Type']}"
|
199
|
+
Sqreen.log.debug "Unexpected response body: #{res.body.inspect}"
|
204
200
|
end
|
205
201
|
else
|
206
202
|
Sqreen.log.debug 'warning: empty return value'
|
207
203
|
end
|
208
204
|
end
|
209
205
|
Sqreen.log.debug format('%s %s (DONE in %f ms)', method, path, (Time.now.utc - now) * 1000)
|
210
|
-
|
206
|
+
payload
|
211
207
|
end
|
212
208
|
|
213
209
|
def compress(data)
|
@@ -227,7 +223,7 @@ module Sqreen
|
|
227
223
|
|
228
224
|
Sqreen.log.warn "Using app name: #{headers['x-app-name']}"
|
229
225
|
|
230
|
-
res =
|
226
|
+
res = post('app-login', RuntimeInfos.all(framework), headers, RETRY_FOREVER)
|
231
227
|
|
232
228
|
if !res || !res['status']
|
233
229
|
public_error = format('Cannot login. Token may be invalid: %s', @token)
|
@@ -243,7 +239,7 @@ module Sqreen
|
|
243
239
|
end
|
244
240
|
|
245
241
|
def rules
|
246
|
-
|
242
|
+
get('rulespack', {}, RETRY_MANY)
|
247
243
|
end
|
248
244
|
|
249
245
|
def heartbeat(cmd_res = {}, metrics = [])
|
@@ -251,30 +247,29 @@ module Sqreen
|
|
251
247
|
payload['metrics'] = metrics unless metrics.nil? || metrics.empty?
|
252
248
|
payload['command_results'] = cmd_res unless cmd_res.nil? || cmd_res.empty?
|
253
249
|
|
254
|
-
post('app-beat', payload.empty? ? nil : payload, {},
|
250
|
+
post('app-beat', payload.empty? ? nil : payload, {}, RETRY_MANY)
|
255
251
|
end
|
256
252
|
|
257
253
|
def post_metrics(metrics)
|
258
254
|
return if metrics.nil? || metrics.empty?
|
259
255
|
payload = { METRICS_KEY => metrics }
|
260
|
-
|
256
|
+
post(METRICS_KEY, payload, {}, RETRY_MANY)
|
261
257
|
end
|
262
258
|
|
263
259
|
def post_attack(attack)
|
264
|
-
|
260
|
+
post('attack', attack.to_hash, {}, RETRY_MANY)
|
265
261
|
end
|
266
262
|
|
267
263
|
def post_bundle(bundle_sig, dependencies)
|
268
|
-
|
269
|
-
'dependencies' => dependencies)
|
264
|
+
post('bundle', { 'bundle_signature' => bundle_sig, 'dependencies' => dependencies }, {}, RETRY_MANY)
|
270
265
|
end
|
271
266
|
|
272
267
|
def get_actionspack
|
273
|
-
|
268
|
+
get('actionspack', {}, RETRY_MANY)
|
274
269
|
end
|
275
270
|
|
276
271
|
def post_request_record(request_record)
|
277
|
-
|
272
|
+
post('request_record', request_record.to_hash, {}, RETRY_MANY)
|
278
273
|
end
|
279
274
|
|
280
275
|
# Post an exception to Sqreen for analysis
|
@@ -300,7 +295,7 @@ module Sqreen
|
|
300
295
|
tally = Hash[events.group_by(&:class).map{ |k,v| [k, v.count] }]
|
301
296
|
"Doing batch with the following tally of event types: #{tally}"
|
302
297
|
end
|
303
|
-
|
298
|
+
post(BATCH_KEY, { BATCH_KEY => batch }, {}, RETRY_MANY)
|
304
299
|
end
|
305
300
|
|
306
301
|
# Perform agent logout
|