sqreen 1.15.0-java → 1.15.5-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/lib/sqreen/actions.rb +114 -43
- data/lib/sqreen/callback_tree.rb +16 -3
- data/lib/sqreen/callbacks.rb +7 -34
- data/lib/sqreen/capped_queue.rb +5 -1
- data/lib/sqreen/configuration.rb +4 -0
- data/lib/sqreen/deliveries/batch.rb +7 -4
- data/lib/sqreen/event.rb +4 -0
- data/lib/sqreen/events/request_record.rb +40 -7
- data/lib/sqreen/frameworks/generic.rb +0 -2
- data/lib/sqreen/frameworks/request_recorder.rb +14 -1
- data/lib/sqreen/instrumentation.rb +57 -33
- data/lib/sqreen/js/mini_racer_adapter.rb +46 -8
- data/lib/sqreen/metrics/average.rb +1 -1
- data/lib/sqreen/metrics/base.rb +4 -2
- data/lib/sqreen/metrics/binning.rb +3 -2
- data/lib/sqreen/metrics/collect.rb +1 -1
- data/lib/sqreen/metrics/sum.rb +1 -1
- data/lib/sqreen/metrics_store.rb +10 -5
- data/lib/sqreen/mono_time.rb +18 -0
- data/lib/sqreen/performance_notifications.rb +13 -38
- data/lib/sqreen/performance_notifications/binned_metrics.rb +12 -14
- data/lib/sqreen/performance_notifications/log.rb +6 -1
- data/lib/sqreen/performance_notifications/log_performance.rb +3 -1
- data/lib/sqreen/performance_notifications/metrics.rb +6 -3
- data/lib/sqreen/performance_notifications/newrelic.rb +6 -2
- data/lib/sqreen/remote_command.rb +26 -0
- data/lib/sqreen/rule_attributes.rb +1 -0
- data/lib/sqreen/rule_callback.rb +38 -0
- data/lib/sqreen/rules_callbacks/binding_accessor_matcher.rb +3 -2
- data/lib/sqreen/rules_callbacks/blacklist_ips.rb +1 -1
- data/lib/sqreen/rules_callbacks/run_block_user_actions.rb +1 -1
- data/lib/sqreen/rules_callbacks/run_req_start_actions.rb +8 -2
- data/lib/sqreen/runner.rb +11 -8
- data/lib/sqreen/sdk.rb +7 -1
- data/lib/sqreen/session.rb +4 -0
- data/lib/sqreen/trie.rb +274 -0
- data/lib/sqreen/version.rb +1 -1
- metadata +4 -2
data/lib/sqreen/metrics_store.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'sqreen/exception'
|
5
5
|
require 'sqreen/metrics'
|
6
|
+
require 'sqreen/mono_time'
|
6
7
|
|
7
8
|
module Sqreen
|
8
9
|
# This store and register metrics
|
@@ -17,6 +18,7 @@ module Sqreen
|
|
17
18
|
class AlreadyRegisteredMetric < Sqreen::Exception
|
18
19
|
end
|
19
20
|
|
21
|
+
# definition keys
|
20
22
|
NAME_KEY = 'name'.freeze
|
21
23
|
KIND_KEY = 'kind'.freeze
|
22
24
|
PERIOD_KEY = 'period'.freeze
|
@@ -29,7 +31,7 @@ module Sqreen
|
|
29
31
|
|
30
32
|
def initialize
|
31
33
|
@store = []
|
32
|
-
@metrics = {}
|
34
|
+
@metrics = {} # name => (metric, period, start)
|
33
35
|
end
|
34
36
|
|
35
37
|
# Definition contains a name,period and aggregate at least
|
@@ -54,17 +56,17 @@ module Sqreen
|
|
54
56
|
@metrics.key?(name)
|
55
57
|
end
|
56
58
|
|
59
|
+
# @params at [Time] when is the store emptied
|
57
60
|
def update(name, at, key, value)
|
58
|
-
at = at.utc
|
59
61
|
metric, period, start = @metrics[name]
|
60
62
|
raise UnregisteredMetric, "Unknown metric #{name}" unless metric
|
61
63
|
next_sample(name, at) if start.nil? || (start + period) < at
|
62
|
-
metric.update(
|
64
|
+
metric.update(key, value)
|
63
65
|
end
|
64
66
|
|
65
67
|
# Drains every metrics and returns the store content
|
66
68
|
# @params at [Time] when is the store emptied
|
67
|
-
def publish(flush = true, at =
|
69
|
+
def publish(flush = true, at = Sqreen.time)
|
68
70
|
@metrics.each do |name, (_, period, start)|
|
69
71
|
next_sample(name, at) if flush || !start.nil? && (start + period) < at
|
70
72
|
end
|
@@ -78,10 +80,13 @@ module Sqreen
|
|
78
80
|
def next_sample(name, at)
|
79
81
|
metric = @metrics[name][0]
|
80
82
|
r = metric.next_sample(at)
|
81
|
-
@metrics[name][2] = at # start
|
83
|
+
@metrics[name][2] = at # new start
|
82
84
|
if r
|
83
85
|
r[NAME_KEY] = name
|
84
86
|
obs = r[Metric::OBSERVATION_KEY]
|
87
|
+
start_of_mono = Time.now.utc - Sqreen.time
|
88
|
+
r[Metric::START_KEY] = start_of_mono + r[Metric::START_KEY]
|
89
|
+
r[Metric::FINISH_KEY] = start_of_mono + r[Metric::FINISH_KEY]
|
85
90
|
@store << r if obs && (!obs.respond_to?(:empty?) || !obs.empty?)
|
86
91
|
end
|
87
92
|
r
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Sqreen
|
2
|
+
has_mono_time = begin
|
3
|
+
Process.clock_gettime Process::CLOCK_MONOTONIC
|
4
|
+
true
|
5
|
+
rescue StandardError
|
6
|
+
false
|
7
|
+
end
|
8
|
+
|
9
|
+
if has_mono_time
|
10
|
+
def self.time
|
11
|
+
Process.clock_gettime Process::CLOCK_MONOTONIC
|
12
|
+
end
|
13
|
+
else
|
14
|
+
def self.time
|
15
|
+
Time.now.to_f
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,12 +1,7 @@
|
|
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
|
-
|
5
|
-
Process.clock_gettime Process::CLOCK_MONOTONIC
|
6
|
-
SQREEN_MONO_TIME = Process::CLOCK_MONOTONIC
|
7
|
-
rescue StandardError
|
8
|
-
SQREEN_MONO_TIME = nil
|
9
|
-
end
|
4
|
+
require 'sqreen/mono_time'
|
10
5
|
|
11
6
|
module Sqreen
|
12
7
|
# This module enable us to keep track of sqreen resource usage
|
@@ -17,39 +12,29 @@ module Sqreen
|
|
17
12
|
@subscriptions_all = {}
|
18
13
|
@subscription_id = 0
|
19
14
|
class << self
|
20
|
-
#
|
21
|
-
# returns a subscription
|
15
|
+
# Subscribe to receive notifications about an event
|
16
|
+
# returns a subscription identification
|
22
17
|
def subscribe(&block)
|
23
18
|
id = (@subscription_id += 1)
|
24
19
|
@subscriptions_all[id] = block
|
25
20
|
id
|
26
21
|
end
|
27
22
|
|
28
|
-
if SQREEN_MONO_TIME
|
29
|
-
def time
|
30
|
-
Process.clock_gettime(SQREEN_MONO_TIME)
|
31
|
-
end
|
32
|
-
else
|
33
|
-
def time
|
34
|
-
Time.now
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
23
|
# Is there a subscriber
|
39
24
|
def listen_for?
|
40
25
|
!@subscriptions_all.empty?
|
41
26
|
end
|
42
27
|
|
43
28
|
# Instrument a call identified by key
|
44
|
-
def instrument(
|
29
|
+
def instrument(rule, cb, meta = {}, &block)
|
45
30
|
return yield unless listen_for?
|
46
|
-
_instrument(
|
31
|
+
_instrument(rule, cb, meta, &block)
|
47
32
|
end
|
48
33
|
|
49
|
-
def notify(
|
34
|
+
def notify(rule, cb, start, stop, meta = {})
|
50
35
|
return unless listen_for?
|
51
36
|
notifiers.each do |callable|
|
52
|
-
callable.call(
|
37
|
+
callable.call(rule, cb, start, stop, meta)
|
53
38
|
end
|
54
39
|
end
|
55
40
|
|
@@ -70,22 +55,12 @@ module Sqreen
|
|
70
55
|
@subscriptions_all.values
|
71
56
|
end
|
72
57
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
notify(key, start, stop, meta)
|
80
|
-
end
|
81
|
-
else
|
82
|
-
def _instrument(key, meta)
|
83
|
-
start = Time.now
|
84
|
-
yield
|
85
|
-
ensure
|
86
|
-
stop = Time.now
|
87
|
-
notify(key, start, stop, meta)
|
88
|
-
end
|
58
|
+
def _instrument(rule, cb, meta)
|
59
|
+
start = Sqreen.time
|
60
|
+
yield
|
61
|
+
ensure
|
62
|
+
stop = Sqreen.time
|
63
|
+
notify(rule, cb, start, stop, meta)
|
89
64
|
end
|
90
65
|
end
|
91
66
|
end
|
@@ -16,8 +16,6 @@ module Sqreen
|
|
16
16
|
EVENT_TOTAL_TIME = 'sq'.freeze # sqreen total overhead callback time
|
17
17
|
EVENT_PERCENT = 'pct'.freeze # sqreen total overhead percent of time
|
18
18
|
|
19
|
-
EVT_NAME_REGEXP = %r{\ACallbacks/([^/]+)/([^/]+)\z}
|
20
|
-
|
21
19
|
# @param metrics_store [Sqreen::MetricsStore]
|
22
20
|
def initialize(metrics_store, period, perf_metric_opts, perf_metric_percent_opts)
|
23
21
|
@metrics_store = metrics_store
|
@@ -49,32 +47,28 @@ module Sqreen
|
|
49
47
|
@subid = nil
|
50
48
|
end
|
51
49
|
|
52
|
-
def log(
|
53
|
-
return unless event =~ EVT_NAME_REGEXP
|
54
|
-
rule, cb = Regexp.last_match.captures
|
55
|
-
|
50
|
+
def log(rule, cb, start, finish, _meta)
|
56
51
|
metric_name = "sq.#{rule}.#{cb}"
|
57
52
|
ensure_metric(metric_name)
|
58
53
|
|
59
|
-
finish_time = SQREEN_MONO_TIME ? Time.now.utc : finish
|
60
54
|
time_millis = (finish - start) * 1000
|
61
55
|
# Ensure we always have a timings if we somehow missed the request start
|
62
|
-
SharedStorage[:sqreen_request_time]
|
63
|
-
|
64
|
-
metrics_store.update(metric_name,
|
56
|
+
SharedStorage[:sqreen_request_time] =
|
57
|
+
(SharedStorage[:sqreen_request_time] || 0) + time_millis
|
58
|
+
metrics_store.update(metric_name, finish, nil, time_millis)
|
65
59
|
end
|
66
60
|
|
67
61
|
def start_request
|
68
|
-
SharedStorage[:request_start_time] =
|
62
|
+
SharedStorage[:request_start_time] = Sqreen.time
|
69
63
|
SharedStorage[:sqreen_request_time] = 0.0
|
70
64
|
end
|
71
65
|
|
72
66
|
def finish_request
|
73
67
|
start_time = SharedStorage[:request_start_time]
|
74
|
-
finish_time =
|
68
|
+
finish_time = Sqreen.time
|
75
69
|
duration_millis = (finish_time - start_time) * 1000
|
76
70
|
|
77
|
-
finish_time_obj =
|
71
|
+
finish_time_obj = Time.now.utc
|
78
72
|
# format of evt is [cat, key, value, timestamp]
|
79
73
|
Sqreen.observations_queue.push(
|
80
74
|
[EVENT_REQ, nil, duration_millis, finish_time_obj]
|
@@ -108,7 +102,11 @@ module Sqreen
|
|
108
102
|
class << self
|
109
103
|
# @return [Sqreen::PerformanceNotifications::BinnedMetrics]
|
110
104
|
attr_reader :instance
|
111
|
-
def enable(metrics_store, period = 60,
|
105
|
+
def enable(metrics_store, period = 60,
|
106
|
+
base = DEFAULT_PERF_BASE,
|
107
|
+
factor = DEFAULT_PERF_UNIT,
|
108
|
+
base_pct = DEFAULT_PERF_PCT_BASE,
|
109
|
+
factor_pct = DEFAULT_PERF_PCT_UNIT)
|
112
110
|
disable
|
113
111
|
@instance = new(metrics_store, period,
|
114
112
|
{'base'=> base, 'factor' => factor},
|
@@ -10,14 +10,19 @@ module Sqreen
|
|
10
10
|
@subid = nil
|
11
11
|
@facility = nil
|
12
12
|
class << self
|
13
|
-
def log(
|
13
|
+
def log(rule, cb, start, finish, meta)
|
14
14
|
(@facility || Sqreen.log).debug do
|
15
15
|
meta_str = nil
|
16
16
|
meta_str = ": #{meta.inspect}" unless meta.empty?
|
17
|
+
event = event_name(rule, cb)
|
17
18
|
format('%s took %.2fms%s', event, (finish - start) * 1000, meta_str)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
22
|
+
def event_name(rule, cb)
|
23
|
+
"Callbacks/#{rule}/#{cb}"
|
24
|
+
end
|
25
|
+
|
21
26
|
def enable(facility = nil)
|
22
27
|
return unless @subid.nil?
|
23
28
|
@facility = facility
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
3
|
|
4
4
|
require 'sqreen/performance_notifications'
|
5
|
+
require 'sqreen/performance_notifications/log'
|
5
6
|
|
6
7
|
module Sqreen
|
7
8
|
module PerformanceNotifications
|
@@ -23,7 +24,8 @@ module Sqreen
|
|
23
24
|
SharedStorage.set(:log_performance_timings, value)
|
24
25
|
end
|
25
26
|
|
26
|
-
def log(
|
27
|
+
def log(rule, cb, start, finish, _meta)
|
28
|
+
event = event_name(rule, cb)
|
27
29
|
timings << [event, start, finish]
|
28
30
|
end
|
29
31
|
|
@@ -2,17 +2,20 @@
|
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
3
|
|
4
4
|
require 'sqreen/performance_notifications'
|
5
|
+
require 'sqreen/performance_notifications/log'
|
6
|
+
require 'sqreen/runner'
|
5
7
|
|
6
8
|
module Sqreen
|
7
9
|
module PerformanceNotifications
|
8
10
|
# Log performances in sqreen metrics_store
|
9
|
-
class Metrics
|
11
|
+
class Metrics < Log
|
10
12
|
@subid = nil
|
11
13
|
@facility = nil
|
12
14
|
class << self
|
13
15
|
EVENT_CAT = 'sqreen_time'.freeze
|
14
|
-
def log(
|
15
|
-
|
16
|
+
def log(rule, cb, start, finish, _meta)
|
17
|
+
event = event_name(rule, cb)
|
18
|
+
evt = [EVENT_CAT, event, (finish - start) * 1000, Time.now.utc]
|
16
19
|
Sqreen.observations_queue.push(evt)
|
17
20
|
end
|
18
21
|
|
@@ -2,11 +2,14 @@
|
|
2
2
|
# Please refer to our terms for more information: https://www.sqreen.io/terms.html
|
3
3
|
|
4
4
|
require 'sqreen/performance_notifications'
|
5
|
+
require 'sqreen/performance_notifications/log'
|
6
|
+
require 'sqreen/log'
|
7
|
+
require 'sqreen/shared_storage'
|
5
8
|
|
6
9
|
module Sqreen
|
7
10
|
module PerformanceNotifications
|
8
11
|
# Log performances on the console
|
9
|
-
class NewRelic
|
12
|
+
class NewRelic < Log
|
10
13
|
@subid = nil
|
11
14
|
@level = 0
|
12
15
|
|
@@ -24,7 +27,8 @@ module Sqreen
|
|
24
27
|
SharedStorage.set(:log_performance_nr_timings, value)
|
25
28
|
end
|
26
29
|
|
27
|
-
def log(
|
30
|
+
def log(rule, cb, start, finish, _meta)
|
31
|
+
event = event_name(rule, cb)
|
28
32
|
timings << [event, start, finish]
|
29
33
|
end
|
30
34
|
|
@@ -59,6 +59,7 @@ module Sqreen
|
|
59
59
|
Sqreen.log.debug { commands.inspect }
|
60
60
|
return res_list
|
61
61
|
end
|
62
|
+
commands = coalesce_reloads(commands, res_list)
|
62
63
|
commands.each do |cmd_json|
|
63
64
|
Sqreen.log.debug { cmd_json }
|
64
65
|
cmd = RemoteCommand.new(cmd_json)
|
@@ -69,6 +70,31 @@ module Sqreen
|
|
69
70
|
res_list
|
70
71
|
end
|
71
72
|
|
73
|
+
# will need changes if we ever distinguish forced/soft reloads
|
74
|
+
# ('force' parameter in the command)
|
75
|
+
def self.coalesce_reloads(commands, res_list)
|
76
|
+
new_commands = []
|
77
|
+
saw_rules_reload = false
|
78
|
+
commands.reverse_each do |cmd_json|
|
79
|
+
name = cmd_json['name']
|
80
|
+
unless name == 'rules_reload'
|
81
|
+
new_commands.unshift cmd_json
|
82
|
+
next
|
83
|
+
end
|
84
|
+
|
85
|
+
if saw_rules_reload
|
86
|
+
res_list[cmd_json['uuid']] =
|
87
|
+
{ :status => false, :reason => "redundant rules_reload ignored" }
|
88
|
+
else
|
89
|
+
saw_rules_reload = true
|
90
|
+
new_commands.unshift cmd_json
|
91
|
+
next
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
new_commands
|
96
|
+
end
|
97
|
+
|
72
98
|
def to_h
|
73
99
|
{
|
74
100
|
:name => @name,
|
data/lib/sqreen/rule_callback.rb
CHANGED
@@ -47,6 +47,44 @@ module Sqreen
|
|
47
47
|
@rule[Attrs::RULESPACK_ID]
|
48
48
|
end
|
49
49
|
|
50
|
+
def priority
|
51
|
+
@rule[Attrs::PRIORITY] || super
|
52
|
+
end
|
53
|
+
|
54
|
+
# Record an attack event into Sqreen system
|
55
|
+
# @param infos [Hash] Additional information about request
|
56
|
+
def record_event(infos, at = Time.now.utc)
|
57
|
+
return unless framework
|
58
|
+
payload = {
|
59
|
+
:infos => infos,
|
60
|
+
:rulespack_id => rulespack_id,
|
61
|
+
:rule_name => rule_name,
|
62
|
+
:test => test,
|
63
|
+
:time => at,
|
64
|
+
}
|
65
|
+
if payload_tpl.include?('context')
|
66
|
+
payload[:backtrace] = Sqreen::Context.new.bt
|
67
|
+
end
|
68
|
+
framework.observe(:attacks, payload, payload_tpl)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Record an exception that just occurred
|
72
|
+
# @param exception [Exception] Exception to send over
|
73
|
+
# @param infos [Hash] Additional contextual information
|
74
|
+
def record_exception(exception, infos = {}, at = Time.now.utc)
|
75
|
+
return unless framework
|
76
|
+
payload = {
|
77
|
+
:exception => exception,
|
78
|
+
:infos => infos,
|
79
|
+
:rulespack_id => rulespack_id,
|
80
|
+
:rule_name => rule_name,
|
81
|
+
:test => test,
|
82
|
+
:time => at,
|
83
|
+
:backtrace => exception.backtrace || Sqreen::Context.bt,
|
84
|
+
}
|
85
|
+
framework.observe(:sqreen_exceptions, payload)
|
86
|
+
end
|
87
|
+
|
50
88
|
# Recommend taking an action (optionnally adding more data/context)
|
51
89
|
#
|
52
90
|
# This will format the requested action and optionnally
|
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'sqreen/rule_callback'
|
5
5
|
require 'sqreen/binding_accessor'
|
6
|
+
require 'sqreen/mono_time'
|
6
7
|
require 'sqreen/rules_callbacks/matcher_rule'
|
7
8
|
|
8
9
|
module Sqreen
|
@@ -49,7 +50,7 @@ module Sqreen
|
|
49
50
|
|
50
51
|
def pre(inst, args, budget = nil, &_block)
|
51
52
|
unless budget.nil?
|
52
|
-
finish = budget + Sqreen
|
53
|
+
finish = budget + Sqreen.time
|
53
54
|
end
|
54
55
|
resol_cache = Hash.new do |hash, accessor|
|
55
56
|
hash[accessor] = accessor.resolve(binding, framework, inst, args)
|
@@ -61,7 +62,7 @@ module Sqreen
|
|
61
62
|
next unless val.respond_to?(:each)
|
62
63
|
next if val.respond_to?(:seek)
|
63
64
|
val.each do |v|
|
64
|
-
if !budget.nil? && Sqreen
|
65
|
+
if !budget.nil? && Sqreen.time > finish
|
65
66
|
return nil
|
66
67
|
end
|
67
68
|
next if !v.is_a?(String) || (!matcher.min_size.nil? && v.size < matcher.min_size)
|