sqreen 1.20.4 → 1.21.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +0 -25
- 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 +2 -8
- data/lib/sqreen/configuration.rb +1 -1
- data/lib/sqreen/deferred_logger.rb +14 -50
- data/lib/sqreen/deliveries/batch.rb +8 -1
- data/lib/sqreen/ecosystem.rb +80 -0
- data/lib/sqreen/ecosystem/dispatch_table.rb +43 -0
- data/lib/sqreen/ecosystem/http/net_http.rb +51 -0
- data/lib/sqreen/ecosystem/http/rack_request.rb +38 -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/signal_producer.rb +26 -0
- data/lib/sqreen/ecosystem/module_api/tracing_push_down.rb +34 -0
- data/lib/sqreen/ecosystem/module_api/transaction_storage.rb +71 -0
- data/lib/sqreen/ecosystem/module_registry.rb +39 -0
- data/lib/sqreen/ecosystem/redis/redis_connection.rb +35 -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_id_setup.rb +34 -0
- data/lib/sqreen/ecosystem/transaction_storage.rb +64 -0
- data/lib/sqreen/ecosystem_integration.rb +70 -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 +56 -0
- data/lib/sqreen/ecosystem_integration/signal_consumption.rb +35 -0
- data/lib/sqreen/encoding_sanitizer.rb +27 -0
- data/lib/sqreen/events/request_record.rb +1 -0
- data/lib/sqreen/frameworks/generic.rb +15 -10
- data/lib/sqreen/frameworks/rails.rb +7 -0
- data/lib/sqreen/frameworks/request_recorder.rb +0 -2
- data/lib/sqreen/graft/call.rb +23 -72
- data/lib/sqreen/graft/callback.rb +1 -1
- data/lib/sqreen/graft/hook.rb +85 -187
- data/lib/sqreen/graft/hook_point.rb +1 -1
- data/lib/sqreen/legacy/instrumentation.rb +10 -22
- data/lib/sqreen/legacy/old_event_submission_strategy.rb +8 -3
- data/lib/sqreen/log.rb +2 -3
- data/lib/sqreen/log/loggable.rb +0 -1
- data/lib/sqreen/logger.rb +0 -24
- data/lib/sqreen/metrics_store.rb +0 -11
- data/lib/sqreen/null_logger.rb +0 -22
- data/lib/sqreen/remote_command.rb +3 -1
- data/lib/sqreen/rules.rb +4 -8
- 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 +0 -2
- data/lib/sqreen/rules/waf_cb.rb +3 -3
- data/lib/sqreen/runner.rb +21 -33
- 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/legacy/instrumentation.rb +103 -194
- data/lib/sqreen/worker.rb +2 -6
- metadata +35 -10
- data/lib/sqreen/deprecation.rb +0 -38
- data/lib/sqreen/weave/budget.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49a6c95ab34d19ae0f769e475ae67c2c3e4d19b17582ee09d8a6d231ac3d9150
|
4
|
+
data.tar.gz: ad1ea7a80f3582ba90ffc6aa1cef7040459c56f65ea4712a023923b8bc7801e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0da6438f20a00a84914db2bb06c24feab53e164feae1cb7d2af0b53afe24c5d5ea54a0cb68a8872a49aadedae4450de57e63da6a4f4a2ec21ac85eaa84c13acf
|
7
|
+
data.tar.gz: 3e75918e810529674e10d693fd2a62c0eeeeecb18bac06a25fdd686d29c45d55333abb0feea790ec1d89e29ce71097bd1de16c2d31d98a6219e985d806793008
|
data/CHANGELOG.md
CHANGED
@@ -1,28 +1,3 @@
|
|
1
|
-
## 1.20.4
|
2
|
-
|
3
|
-
* Fix missing budget check
|
4
|
-
* Improve performance
|
5
|
-
* Align internal setting name for WAF
|
6
|
-
* Include response information in all payloads
|
7
|
-
* Improve robustness against invalid Unicode
|
8
|
-
* Prevent rule execution to pursue in early block cases
|
9
|
-
|
10
|
-
## 1.20.4.beta1
|
11
|
-
|
12
|
-
* Add optional dynamic time budget
|
13
|
-
* Add advanced per request metrics
|
14
|
-
* Improve robustness against exception in instrumentation
|
15
|
-
* Improve metric engine thread safety
|
16
|
-
* Restrict deferred logger to final logger severity on agent boot
|
17
|
-
|
18
|
-
## 1.20.3
|
19
|
-
|
20
|
-
* Fix signature check
|
21
|
-
|
22
|
-
## 1.20.2
|
23
|
-
|
24
|
-
* Fix performance regression in instrumentation engine
|
25
|
-
|
26
1
|
## 1.20.1
|
27
2
|
|
28
3
|
* Add fallback mechanisms when connecting to new Sqreen backend API domains
|
@@ -24,7 +24,7 @@ module Sqreen
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def do_run(identity_params)
|
27
|
-
Sqreen.log.
|
27
|
+
Sqreen.log.info '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
|
-
hash_key_include?(values, v, min_value_size, rem - 1)
|
70
|
+
ConditionEvaluator.hash_key_include?(values, v, min_value_size, rem - 1)
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -81,13 +81,7 @@ module Sqreen
|
|
81
81
|
if hkey.respond_to?(:empty?) && hkey.empty?
|
82
82
|
false
|
83
83
|
else
|
84
|
-
|
85
|
-
str_include?(values, hkey.to_s)
|
86
|
-
else
|
87
|
-
values.include?(hkey.to_s)
|
88
|
-
end
|
89
|
-
|
90
|
-
key_incl || hash_key_include?(values, hval, min_value_size, rem - 1)
|
84
|
+
values.include?(hkey.to_s) || ConditionEvaluator.hash_key_include?(values, hval, min_value_size, rem - 1)
|
91
85
|
end
|
92
86
|
end
|
93
87
|
end
|
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 => 'WARN', :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,70 +9,35 @@ require 'sqreen/logger'
|
|
9
9
|
|
10
10
|
module Sqreen
|
11
11
|
class DeferredLogger
|
12
|
-
|
13
|
-
|
14
|
-
Entry = Struct.new(:severity, :message)
|
12
|
+
include Singleton
|
15
13
|
|
16
14
|
def initialize
|
17
15
|
@buffer = StringIO.new
|
18
16
|
@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
|
41
17
|
end
|
42
18
|
|
43
19
|
def debug(msg = nil, &block)
|
44
|
-
|
20
|
+
@logger.debug(msg, &block)
|
45
21
|
end
|
46
22
|
|
47
23
|
def info(msg = nil, &block)
|
48
|
-
|
24
|
+
@logger.info(msg, &block)
|
49
25
|
end
|
50
26
|
|
51
27
|
def warn(msg = nil, &block)
|
52
|
-
|
28
|
+
@logger.warn(msg, &block)
|
53
29
|
end
|
54
30
|
|
55
31
|
def error(msg = nil, &block)
|
56
|
-
|
32
|
+
@logger.error(msg, &block)
|
57
33
|
end
|
58
34
|
|
59
35
|
def fatal(msg = nil, &block)
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
def unknown(msg = nil, &block)
|
64
|
-
add(::Logger::UNKNOWN, msg, &block)
|
36
|
+
@logger.error(msg, &block)
|
65
37
|
end
|
66
38
|
|
67
39
|
def add(severity, msg = nil, &block)
|
68
|
-
|
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
|
40
|
+
send(Sqreen::Logger::SEVERITY_TO_METHOD[severity], msg, &block)
|
76
41
|
end
|
77
42
|
|
78
43
|
def formatter=(value)
|
@@ -80,22 +45,21 @@ module Sqreen
|
|
80
45
|
end
|
81
46
|
|
82
47
|
def flush_to(logger)
|
83
|
-
@
|
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
|
48
|
+
logger.instance_eval { @logdev }.write(read).tap { reset }
|
90
49
|
end
|
91
50
|
|
92
51
|
private
|
93
52
|
|
53
|
+
def read
|
54
|
+
@buffer.rewind
|
55
|
+
@buffer.read
|
56
|
+
end
|
57
|
+
|
94
58
|
def reset
|
95
59
|
buffer = StringIO.new
|
96
60
|
logger = ::Logger.new(buffer)
|
97
61
|
logger.formatter = @logger.formatter
|
98
|
-
@buffer, @logger
|
62
|
+
@buffer, @logger = buffer, logger
|
99
63
|
end
|
100
64
|
end
|
101
65
|
end
|
@@ -13,6 +13,8 @@ require 'sqreen/events/attack'
|
|
13
13
|
require 'sqreen/events/remote_exception'
|
14
14
|
require 'sqreen/mono_time'
|
15
15
|
require 'sqreen/deliveries/simple'
|
16
|
+
require 'sqreen/kit/signals/signal'
|
17
|
+
require 'sqreen/kit/signals/trace'
|
16
18
|
|
17
19
|
module Sqreen
|
18
20
|
module Deliveries
|
@@ -58,7 +60,7 @@ module Sqreen
|
|
58
60
|
def post_batch_needed?(event)
|
59
61
|
now = Sqreen.time
|
60
62
|
# do not use any? {} due to side effects inside block
|
61
|
-
event_keys(event).map do |key|
|
63
|
+
event_keys(event).uniq.map do |key|
|
62
64
|
was = @first_seen[key]
|
63
65
|
@first_seen[key] ||= now
|
64
66
|
was.nil? || current_batch.size > max_batch || now > (was + max_staleness)
|
@@ -86,6 +88,7 @@ module Sqreen
|
|
86
88
|
res += event.observed.fetch(:sdk, []).select { |e|
|
87
89
|
e[0] == :track
|
88
90
|
}.map { |e| "sdk-track".freeze }
|
91
|
+
res += event.observed.fetch(:signals, []).map { "signal".freeze }
|
89
92
|
return res
|
90
93
|
end
|
91
94
|
|
@@ -97,6 +100,10 @@ module Sqreen
|
|
97
100
|
"rex-#{event.klass}"
|
98
101
|
when Sqreen::AggregatedMetric
|
99
102
|
"agg-metric"
|
103
|
+
when Sqreen::Kit::Signals::Signal
|
104
|
+
"signal"
|
105
|
+
when Sqreen::Kit::Signals::Trace
|
106
|
+
"signal"
|
100
107
|
end
|
101
108
|
end
|
102
109
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'sqreen/ecosystem/module_registry'
|
3
|
+
require 'sqreen/ecosystem/tracing/sampling_configuration'
|
4
|
+
require 'sqreen/ecosystem/transaction_storage'
|
5
|
+
require 'sqreen/ecosystem/tracing_id_setup'
|
6
|
+
require 'sqreen/ecosystem/module_api/tracing_push_down'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
# The API for the ecosystem client (together with the dispatch table)
|
10
|
+
module Ecosystem
|
11
|
+
class << self
|
12
|
+
def init(opts = {})
|
13
|
+
@registry = ModuleRegistry.new
|
14
|
+
register_modules(opts[:modules])
|
15
|
+
@registry.init_all
|
16
|
+
|
17
|
+
@tracing_id_setup = TracingIdSetup.new(@registry)
|
18
|
+
@tracing_id_setup.setup_modules
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset
|
22
|
+
instance_variables.each do |ia|
|
23
|
+
instance_variable_set(ia, nil)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# To be called by the Ecosystem client when a new transaction
|
28
|
+
# (generally: request) is started
|
29
|
+
# In the future, it's intended that request end/start detection be handled
|
30
|
+
# by the Ecosystem itself, so control will flow in the other direction,
|
31
|
+
# from the ecosystem to its client
|
32
|
+
def start_transaction
|
33
|
+
TransactionStorage.create_thread_local
|
34
|
+
end
|
35
|
+
|
36
|
+
def end_transaction
|
37
|
+
TransactionStorage.destroy_thread_local
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param [String] tracing_id_prefix
|
41
|
+
# @param [Array<Hash{String=>Object}>] sampling_config
|
42
|
+
def configure_sampling(tracing_id_prefix, sampling_config)
|
43
|
+
@tracing_id_setup.tracing_id_prefix = tracing_id_prefix
|
44
|
+
built_samp_cfg = Tracing::SamplingConfiguration.new(sampling_config)
|
45
|
+
inject_sampling_config(built_samp_cfg)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def register_modules(modules)
|
51
|
+
return register_all_modules unless modules
|
52
|
+
|
53
|
+
modules.each { |mod| register mod }
|
54
|
+
end
|
55
|
+
|
56
|
+
def register_all_modules
|
57
|
+
# replace with something more magical?
|
58
|
+
require_relative 'ecosystem/http/rack_request'
|
59
|
+
register Http::RackRequest.new
|
60
|
+
|
61
|
+
require_relative 'ecosystem/http/net_http'
|
62
|
+
register Http::NetHttp.new
|
63
|
+
|
64
|
+
require_relative 'ecosystem/redis/redis_connection'
|
65
|
+
register Redis::RedisConnection.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def register(mod)
|
69
|
+
@registry.register mod
|
70
|
+
end
|
71
|
+
|
72
|
+
# @param [Sqreen::Ecosystem::SamplingConfiguration] config
|
73
|
+
def inject_sampling_config(config)
|
74
|
+
@registry.each_module(Sqreen::Ecosystem::ModuleApi::TracingPushDown) do |mod|
|
75
|
+
mod.sampling_config = config
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Sqreen
|
4
|
+
module Ecosystem
|
5
|
+
# Configured by the ecosystem client
|
6
|
+
module DispatchTable
|
7
|
+
class << self
|
8
|
+
# data consumption
|
9
|
+
# argument: +Sqreen::Kit::Signals::Signal+
|
10
|
+
# see +Sqreen::EcosystemIntegration::SignalConsumption#consume_signal+
|
11
|
+
attr_accessor :consume_signal
|
12
|
+
|
13
|
+
# argument: block taking a Rack::Request
|
14
|
+
# see +Sqreen::EcosystemIntegration::RequestLifecycleTracking#add_start_observer+
|
15
|
+
attr_accessor :add_request_start_listener
|
16
|
+
|
17
|
+
attr_accessor :fetch_logger
|
18
|
+
|
19
|
+
# argument: callback taking:
|
20
|
+
# * the method to instrument
|
21
|
+
# * A Hash{Symbol=>Proc} with the advice. The proc takes the
|
22
|
+
# arguments and the ball, so these details of the instrumentation
|
23
|
+
# implementation leak through the abstraction
|
24
|
+
# see +Sqreen::EcosystemIntegration::InstrumentationService+
|
25
|
+
attr_accessor :instrument
|
26
|
+
|
27
|
+
def reset
|
28
|
+
instance_variables.each do |ia|
|
29
|
+
instance_variable_set(ia, nil)
|
30
|
+
end
|
31
|
+
|
32
|
+
# set default logger
|
33
|
+
logger = ::Logger.new(STDERR)
|
34
|
+
logger.level = ::Logger::WARN
|
35
|
+
logger.progname = 'sqreen-ecosystem'
|
36
|
+
self.fetch_logger = proc { logger }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
reset
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'sqreen/ecosystem/module_api'
|
2
|
+
require 'sqreen/ecosystem/module_api/instrumentation'
|
3
|
+
require 'sqreen/ecosystem/module_api/tracing_push_down'
|
4
|
+
require 'sqreen/ecosystem/module_api/signal_producer'
|
5
|
+
require 'sqreen/ecosystem/module_api/transaction_storage'
|
6
|
+
require 'sqreen/ecosystem/tracing/signals/tracing_client'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
module Ecosystem
|
10
|
+
module Http
|
11
|
+
class NetHttp
|
12
|
+
include ModuleApi::Instrumentation
|
13
|
+
include ModuleApi::SignalProducer
|
14
|
+
include ModuleApi::TracingPushDown
|
15
|
+
|
16
|
+
def setup
|
17
|
+
instrument 'Net::HTTP#request', before: method(:before_advice)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# instr. def request(req, body = nil, &block) # :yield: +response+
|
23
|
+
# req is of type +Net::HTTPGenericRequest+
|
24
|
+
def before_advice(call, _ball)
|
25
|
+
return unless should_sample?('client')
|
26
|
+
|
27
|
+
tracing_id = create_tracing_id
|
28
|
+
|
29
|
+
# build & submit signal
|
30
|
+
host = call.instance.address
|
31
|
+
port = call.instance.port
|
32
|
+
|
33
|
+
host += ':' + port.to_s if port != 80 && port != 443
|
34
|
+
|
35
|
+
signal = Tracing::Signals::TracingClient.new
|
36
|
+
signal.payload = Tracing::Signals::TracingClient::Payload.new(
|
37
|
+
transport: 'http',
|
38
|
+
host: host,
|
39
|
+
tracing_identifier: tracing_id
|
40
|
+
)
|
41
|
+
|
42
|
+
submit_signal signal
|
43
|
+
|
44
|
+
# add tracing header, if available
|
45
|
+
req = call.args[0]
|
46
|
+
req[ModuleApi::TRACE_ID_HEADER] = tracing_id
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'sqreen/ecosystem/module_api'
|
2
|
+
require 'sqreen/ecosystem/module_api/event_listener'
|
3
|
+
require 'sqreen/ecosystem/module_api/signal_producer'
|
4
|
+
require 'sqreen/ecosystem/module_api/tracing_push_down'
|
5
|
+
require 'sqreen/ecosystem/tracing/signals/tracing_server'
|
6
|
+
|
7
|
+
module Sqreen
|
8
|
+
module Ecosystem
|
9
|
+
module Http
|
10
|
+
class RackRequest
|
11
|
+
include ModuleApi::EventListener
|
12
|
+
include ModuleApi::TracingPushDown
|
13
|
+
include ModuleApi::SignalProducer
|
14
|
+
|
15
|
+
def setup
|
16
|
+
on_request_start(&method(:handle_request))
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def handle_request(rack_request)
|
22
|
+
return unless should_sample?('server')
|
23
|
+
|
24
|
+
trace_id = rack_request.env[ModuleApi::TRACE_ID_ENV_KEY]
|
25
|
+
|
26
|
+
signal = Tracing::Signals::TracingServer.new
|
27
|
+
signal.payload = Tracing::Signals::TracingServer::Payload.new(
|
28
|
+
transport: 'http',
|
29
|
+
client_ip: rack_request.ip,
|
30
|
+
tracing_identifier: trace_id
|
31
|
+
)
|
32
|
+
|
33
|
+
submit_signal signal
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|