sqreen 1.20.4 → 1.21.0.beta1
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 +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
|