sqreen 1.21.0.beta2 → 1.21.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -7
- 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/condition_evaluator.rb +9 -2
- data/lib/sqreen/conditionable.rb +24 -6
- data/lib/sqreen/configuration.rb +1 -1
- data/lib/sqreen/deferred_logger.rb +50 -14
- data/lib/sqreen/deprecation.rb +38 -0
- data/lib/sqreen/ecosystem_integration.rb +7 -1
- data/lib/sqreen/ecosystem_integration/around_callbacks.rb +20 -10
- data/lib/sqreen/ecosystem_integration/instrumentation_service.rb +8 -4
- data/lib/sqreen/events/request_record.rb +0 -1
- data/lib/sqreen/frameworks/generic.rb +9 -0
- data/lib/sqreen/frameworks/rails.rb +0 -7
- data/lib/sqreen/frameworks/request_recorder.rb +2 -0
- data/lib/sqreen/graft/call.rb +99 -21
- data/lib/sqreen/graft/callback.rb +1 -1
- data/lib/sqreen/graft/hook.rb +212 -100
- data/lib/sqreen/graft/hook_point.rb +18 -11
- data/lib/sqreen/legacy/instrumentation.rb +22 -10
- data/lib/sqreen/legacy/old_event_submission_strategy.rb +2 -1
- 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.rb +1 -0
- data/lib/sqreen/metrics/req_detailed.rb +41 -0
- data/lib/sqreen/metrics_store.rb +11 -0
- data/lib/sqreen/null_logger.rb +22 -0
- data/lib/sqreen/remote_command.rb +1 -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 +4 -2
- data/lib/sqreen/rules/waf_cb.rb +3 -3
- data/lib/sqreen/runner.rb +46 -5
- data/lib/sqreen/version.rb +1 -1
- data/lib/sqreen/weave/budget.rb +35 -0
- data/lib/sqreen/weave/legacy/instrumentation.rb +274 -132
- data/lib/sqreen/worker.rb +6 -2
- metadata +22 -6
- data/lib/sqreen/encoding_sanitizer.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88934827e2aa5f84ae21f96fb33afdada009fb118d94e8940fe61973812da4d4
|
4
|
+
data.tar.gz: b30da2199b4dc96d0193c671872ac192396c988ef67845c26fc1ed36a7704bfd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19942da7597a18aee5b46aa4ef664c5083eadf3a878c5f431f9dde83196fc15f3263509c6cda6537a5c823de310f117dbb7c600130478a0828d2dbc73f0bf53c
|
7
|
+
data.tar.gz: c8b1293e8480043d3b494d6335725f649107c56e7bf282580592de7d680eaeb9475bd9091ea280ad2d2e473b100789a9b80c3dac93b9ddebbddb2f8ec4f3ced6
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,18 @@
|
|
1
|
-
## 1.21.0.
|
2
|
-
|
3
|
-
*
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
*
|
1
|
+
## 1.21.0.beta3
|
2
|
+
|
3
|
+
* Avoid fd leak in `custom_error_cb` (ARB-109)
|
4
|
+
* Support `skip_rem_cbs` (ARB-107)
|
5
|
+
* Fix instrumentation in Ruby 2.0
|
6
|
+
* Fix encoding exception on `hash_key_include` (ARB-53)
|
7
|
+
* Fix erroneous start in non-Rails context (SQREEN-880)
|
8
|
+
* Make metrics thread-safe
|
9
|
+
* Add restart command
|
10
|
+
* Fix `overtime_cb`
|
11
|
+
* Add `perf_level` 2
|
12
|
+
* Several performance optimizations
|
13
|
+
* WAF: rename `budget_in_ms` to `max_budget_ms`
|
14
|
+
* Transport/Tracing with http module
|
15
|
+
* Update the blocking page
|
8
16
|
|
9
17
|
## 1.20.1
|
10
18
|
|
@@ -24,7 +24,7 @@ module Sqreen
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def do_run(identity_params)
|
27
|
-
Sqreen.log.
|
27
|
+
Sqreen.log.debug 'Will request redirect for user with identity ' \
|
28
28
|
"#{identity_params} (action: #{id})."
|
29
29
|
|
30
30
|
e = Sqreen::AttackBlocked.new(
|
@@ -67,7 +67,7 @@ module Sqreen
|
|
67
67
|
return true if rem <= 0
|
68
68
|
if hash.is_a?(Array)
|
69
69
|
return hash.any? do |v|
|
70
|
-
|
70
|
+
hash_key_include?(values, v, min_value_size, rem - 1)
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -81,7 +81,14 @@ module Sqreen
|
|
81
81
|
if hkey.respond_to?(:empty?) && hkey.empty?
|
82
82
|
false
|
83
83
|
else
|
84
|
-
|
84
|
+
key_incl =
|
85
|
+
if values.is_a?(String)
|
86
|
+
str_include? values, hkey.to_s
|
87
|
+
else
|
88
|
+
values.include?(hkey.to_s)
|
89
|
+
end
|
90
|
+
|
91
|
+
key_incl || hash_key_include?(values, hval, min_value_size, rem - 1)
|
85
92
|
end
|
86
93
|
end
|
87
94
|
end
|
data/lib/sqreen/conditionable.rb
CHANGED
@@ -28,21 +28,39 @@ module Sqreen
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def pre_with_conditions(inst, args, budget = nil, &block)
|
31
|
+
return pre_without_conditions(inst, args, budget, &block) if pre_conditions.nil?
|
32
|
+
|
31
33
|
eargs = [nil, framework, inst, args, @data, nil]
|
32
|
-
return nil
|
33
|
-
|
34
|
+
return nil unless pre_conditions.evaluate(*eargs)
|
35
|
+
|
36
|
+
res = pre_without_conditions(inst, args, budget, &block)
|
37
|
+
return { passed_conditions: true } unless res.is_a?(Hash)
|
38
|
+
res[:passed_conditions] = true
|
39
|
+
res
|
34
40
|
end
|
35
41
|
|
36
42
|
def post_with_conditions(rv, inst, args, budget = nil, &block)
|
43
|
+
return post_without_conditions(rv, inst, args, budget, &block) if post_conditions.nil?
|
44
|
+
|
37
45
|
eargs = [nil, framework, inst, args, @data, rv]
|
38
|
-
return nil
|
39
|
-
|
46
|
+
return nil unless post_conditions.evaluate(*eargs)
|
47
|
+
|
48
|
+
res = post_without_conditions(rv, inst, args, budget, &block)
|
49
|
+
return { passed_conditions: true } if res.nil?
|
50
|
+
res[:passed_conditions] = true
|
51
|
+
res
|
40
52
|
end
|
41
53
|
|
42
54
|
def failing_with_conditions(rv, inst, args, budget = nil, &block)
|
55
|
+
return failing_without_conditions(rv, inst, args, budget, &block) if failing_conditions.nil?
|
56
|
+
|
43
57
|
eargs = [nil, framework, inst, args, @data, rv]
|
44
|
-
return nil
|
45
|
-
|
58
|
+
return nil unless failing_conditions.evaluate(*eargs)
|
59
|
+
|
60
|
+
res = failing_without_conditions(rv, inst, args, budget, &block)
|
61
|
+
return { passed_conditions: true } if res.nil?
|
62
|
+
res[:passed_conditions] = true
|
63
|
+
res
|
46
64
|
end
|
47
65
|
|
48
66
|
protected
|
data/lib/sqreen/configuration.rb
CHANGED
@@ -57,7 +57,7 @@ module Sqreen
|
|
57
57
|
{ :env => :SQREEN_RULES_SIGNATURE, :name => :rules_verify_signature,
|
58
58
|
:default => true },
|
59
59
|
{ :env => :SQREEN_LOG_LEVEL, :name => :log_level,
|
60
|
-
:default => '
|
60
|
+
:default => 'INFO', :choice => %w[UNKNOWN FATAL ERROR WARN INFO DEBUG] },
|
61
61
|
{ :env => :SQREEN_LOG_LOCATION, :name => :log_location,
|
62
62
|
:default => 'log/sqreen.log' },
|
63
63
|
{ :env => :SQREEN_RUN_IN_TEST, :name => :run_in_test,
|
@@ -9,35 +9,70 @@ require 'sqreen/logger'
|
|
9
9
|
|
10
10
|
module Sqreen
|
11
11
|
class DeferredLogger
|
12
|
-
|
12
|
+
MAX_ENTRIES = 1000
|
13
|
+
|
14
|
+
Entry = Struct.new(:severity, :message)
|
13
15
|
|
14
16
|
def initialize
|
15
17
|
@buffer = StringIO.new
|
16
18
|
@logger = ::Logger.new(@buffer)
|
19
|
+
@entries = []
|
20
|
+
@mutex = Mutex.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def debug?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def info?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
def warn?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def error?
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
def fatal?
|
40
|
+
true
|
17
41
|
end
|
18
42
|
|
19
43
|
def debug(msg = nil, &block)
|
20
|
-
|
44
|
+
add(::Logger::DEBUG, msg, &block)
|
21
45
|
end
|
22
46
|
|
23
47
|
def info(msg = nil, &block)
|
24
|
-
|
48
|
+
add(::Logger::INFO, msg, &block)
|
25
49
|
end
|
26
50
|
|
27
51
|
def warn(msg = nil, &block)
|
28
|
-
|
52
|
+
add(::Logger::WARN, msg, &block)
|
29
53
|
end
|
30
54
|
|
31
55
|
def error(msg = nil, &block)
|
32
|
-
|
56
|
+
add(::Logger::ERROR, msg, &block)
|
33
57
|
end
|
34
58
|
|
35
59
|
def fatal(msg = nil, &block)
|
36
|
-
|
60
|
+
add(::Logger::FATAL, msg, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def unknown(msg = nil, &block)
|
64
|
+
add(::Logger::UNKNOWN, msg, &block)
|
37
65
|
end
|
38
66
|
|
39
67
|
def add(severity, msg = nil, &block)
|
40
|
-
|
68
|
+
@mutex.synchronize do
|
69
|
+
@entries.shift if @entries.count >= MAX_ENTRIES
|
70
|
+
mark = @buffer.pos
|
71
|
+
@logger.add(severity, msg, &block)
|
72
|
+
@buffer.seek(mark)
|
73
|
+
@entries << Entry.new(severity, @buffer.read)
|
74
|
+
@buffer.truncate(0)
|
75
|
+
end
|
41
76
|
end
|
42
77
|
|
43
78
|
def formatter=(value)
|
@@ -45,21 +80,22 @@ module Sqreen
|
|
45
80
|
end
|
46
81
|
|
47
82
|
def flush_to(logger)
|
48
|
-
|
83
|
+
@mutex.synchronize do
|
84
|
+
@entries.each do |entry|
|
85
|
+
next if entry.severity < logger.level
|
86
|
+
logger.instance_eval { @logdev }.write(entry.message)
|
87
|
+
end
|
88
|
+
reset
|
89
|
+
end
|
49
90
|
end
|
50
91
|
|
51
92
|
private
|
52
93
|
|
53
|
-
def read
|
54
|
-
@buffer.rewind
|
55
|
-
@buffer.read
|
56
|
-
end
|
57
|
-
|
58
94
|
def reset
|
59
95
|
buffer = StringIO.new
|
60
96
|
logger = ::Logger.new(buffer)
|
61
97
|
logger.formatter = @logger.formatter
|
62
|
-
@buffer, @logger = buffer, logger
|
98
|
+
@buffer, @logger, @entries = buffer, logger, []
|
63
99
|
end
|
64
100
|
end
|
65
101
|
end
|
@@ -0,0 +1,38 @@
|
|
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
|
+
require 'sqreen/log/loggable'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
module Deprecation
|
10
|
+
include Sqreen::Log::Loggable
|
11
|
+
|
12
|
+
module_function
|
13
|
+
|
14
|
+
def deprecate(method)
|
15
|
+
return unless ENV['SQREEN_DEBUG_DEPRECATION']
|
16
|
+
|
17
|
+
owner = method.owner
|
18
|
+
deprecated = :"_deprecated_#{method.name}"
|
19
|
+
klass = owner.is_a?(Module)
|
20
|
+
target = klass ? owner.to_s : owner.class.to_s
|
21
|
+
|
22
|
+
method.owner.instance_eval do
|
23
|
+
alias_method deprecated, method.name
|
24
|
+
|
25
|
+
define_method(method.name) do |*args, &block|
|
26
|
+
msg = [
|
27
|
+
"deprecation",
|
28
|
+
"target:#{target}",
|
29
|
+
"method:#{method.name}",
|
30
|
+
"caller:#{Kernel.caller_locations[0]}",
|
31
|
+
].join(' ')
|
32
|
+
Sqreen::Deprecation.logger.info(msg)
|
33
|
+
send(deprecated, *args, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'sqreen/log/loggable'
|
2
|
+
require 'sqreen/metrics_store'
|
2
3
|
require 'sqreen/ecosystem'
|
3
4
|
require 'sqreen/ecosystem/dispatch_table'
|
5
|
+
require 'sqreen/ecosystem_integration/around_callbacks'
|
4
6
|
require 'sqreen/ecosystem_integration/instrumentation_service'
|
5
7
|
require 'sqreen/ecosystem_integration/request_lifecycle_tracking'
|
6
8
|
require 'sqreen/ecosystem_integration/signal_consumption'
|
@@ -17,9 +19,12 @@ module Sqreen
|
|
17
19
|
include Sqreen::Log::Loggable
|
18
20
|
|
19
21
|
# @param [Sqreen::Framework] framework
|
20
|
-
|
22
|
+
# @param [Proc] create_binning_metric
|
23
|
+
def initialize(framework, queue, create_binning_metric)
|
21
24
|
@framework = framework
|
22
25
|
@queue = queue
|
26
|
+
# XXX: created metrics are insulated from feature upgrades
|
27
|
+
@create_binning_metric = create_binning_metric
|
23
28
|
@request_lifecycle = RequestLifecycleTracking.new
|
24
29
|
@online = false
|
25
30
|
end
|
@@ -28,6 +33,7 @@ module Sqreen
|
|
28
33
|
raise 'already initialized' if @online
|
29
34
|
|
30
35
|
setup_dispatch_table
|
36
|
+
AroundCallbacks.create_metric = @create_binning_metric
|
31
37
|
Ecosystem.init
|
32
38
|
logger.info 'Ecosystem successfully initialized'
|
33
39
|
@online = true
|
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'sqreen/metrics_store'
|
1
2
|
require 'sqreen/log/loggable'
|
2
3
|
require 'sqreen/events/remote_exception'
|
3
4
|
require 'sqreen/mono_time'
|
5
|
+
require 'sqreen/graft/call'
|
4
6
|
|
5
7
|
module Sqreen
|
6
8
|
class EcosystemIntegration
|
@@ -8,27 +10,32 @@ module Sqreen
|
|
8
10
|
class << self
|
9
11
|
include Log::Loggable::ClassMethods
|
10
12
|
|
13
|
+
# @return [Proc]
|
14
|
+
attr_accessor :create_metric
|
15
|
+
|
11
16
|
# for instrumentation hooks
|
12
|
-
# instrumentation hooks already handle budgets
|
13
|
-
# to do in that respect
|
17
|
+
# instrumentation hooks already handle budgets/metrics
|
14
18
|
def wrap_instrumentation_hook(module_name, action, callable)
|
15
|
-
|
19
|
+
# make tag similar to that of rules
|
20
|
+
# TODO: move to structured tags to avoid silly string manips
|
21
|
+
action_for_metric = if %w[pre post failing finally].include?(action)
|
22
|
+
action
|
23
|
+
else
|
24
|
+
'pre'
|
25
|
+
end
|
26
|
+
metric_name = "sq.ecosystem_#{module_name}.#{action_for_metric}"
|
27
|
+
create_metric.call(metric_name)
|
16
28
|
|
17
29
|
Proc.new do |*args|
|
18
30
|
begin
|
19
|
-
start = Sqreen.time
|
20
31
|
callable.call(*args)
|
21
32
|
rescue ::Exception => e # rubocop:disable Lint/RescueException
|
22
33
|
# 2) rescue exceptions
|
23
34
|
logger.warn { "Error in #{module_name}:#{action}: #{e.message}" }
|
24
35
|
logger.debug { e.backtrace.map { |x| " #{x}" }.join("\n") }
|
25
36
|
Sqreen::RemoteException.record(e)
|
26
|
-
|
27
|
-
|
28
|
-
stop = Sqreen.time
|
29
|
-
Sqreen::PerformanceNotifications.notify(perf_notif_name, action, start, stop)
|
30
|
-
end # end proc
|
31
|
-
end # end begin
|
37
|
+
end # end begin
|
38
|
+
end # end proc
|
32
39
|
end
|
33
40
|
|
34
41
|
# XXX: not used yet
|
@@ -36,6 +43,8 @@ module Sqreen
|
|
36
43
|
timer_name = "ecosystem:#{module_name}@#{action}"
|
37
44
|
perf_notif_name = "ecosystem_#{module_name}"
|
38
45
|
|
46
|
+
# XXX: register metric
|
47
|
+
|
39
48
|
Proc.new do |*args|
|
40
49
|
begin
|
41
50
|
req_storage = Thread.current[:sqreen_http_request]
|
@@ -76,6 +85,7 @@ module Sqreen
|
|
76
85
|
if timer
|
77
86
|
req_timer.include_measurements(timer) if req_timer
|
78
87
|
|
88
|
+
# XXX: PerformanceNotifications is used no more
|
79
89
|
Sqreen::PerformanceNotifications.notify(
|
80
90
|
perf_notif_name, action, *timer.start_and_end
|
81
91
|
)
|
@@ -12,22 +12,26 @@ module Sqreen
|
|
12
12
|
hook = Sqreen::Graft::Hook[method].add do
|
13
13
|
if spec[:before]
|
14
14
|
cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'pre', spec[:before])
|
15
|
-
|
15
|
+
tag = "weave,rule=ecosystem_#{module_name}"
|
16
|
+
before(tag, flow: true, &cb)
|
16
17
|
end
|
17
18
|
|
18
19
|
if spec[:after]
|
19
20
|
cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'post', spec[:after])
|
20
|
-
|
21
|
+
tag = "weave,rule=ecosystem_#{module_name}"
|
22
|
+
after(tag, flow: true, &cb)
|
21
23
|
end
|
22
24
|
|
23
25
|
if spec[:raised]
|
24
26
|
cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'failing', spec[:raised])
|
25
|
-
|
27
|
+
tag = "weave,rule=ecosystem_#{module_name}"
|
28
|
+
raised(tag, flow: true, &cb)
|
26
29
|
end
|
27
30
|
|
28
31
|
if spec[:ensured]
|
29
32
|
cb = AroundCallbacks.wrap_instrumentation_hook(module_name, 'finally', spec[:ensured])
|
30
|
-
|
33
|
+
tag = "weave,rule=ecosystem_#{module_name}"
|
34
|
+
ensured(tag, flow: true, &cb)
|
31
35
|
end
|
32
36
|
end
|
33
37
|
hook.install
|
@@ -218,7 +218,16 @@ module Sqreen
|
|
218
218
|
|
219
219
|
# Should the agent not be starting up?
|
220
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
|
+
|
221
229
|
return :irb if $0 == 'irb'
|
230
|
+
|
222
231
|
return if sqreen_configuration.nil?
|
223
232
|
disable = sqreen_configuration.get(:disable)
|
224
233
|
return :config_disable if disable == true || disable.to_s.to_i == 1
|