sqreen 1.18.6-java → 1.20.0-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 +27 -0
- data/lib/sqreen/actions.rb +2 -0
- data/lib/sqreen/actions/actions_index.rb +16 -0
- data/lib/sqreen/actions/base.rb +4 -10
- data/lib/sqreen/actions/block_ip.rb +2 -0
- data/lib/sqreen/actions/block_user.rb +2 -0
- data/lib/sqreen/actions/ip_range_indexed_action_class.rb +4 -24
- data/lib/sqreen/actions/ip_ranges_index.rb +32 -11
- data/lib/sqreen/actions/redirect_ip.rb +2 -0
- data/lib/sqreen/actions/redirect_user.rb +2 -0
- data/lib/sqreen/actions/repository.rb +27 -8
- data/lib/sqreen/actions/unknown_action_type.rb +4 -0
- data/lib/sqreen/actions/user_action_class.rb +5 -30
- data/lib/sqreen/actions/users_index.rb +35 -0
- data/lib/sqreen/agent.rb +2 -1
- data/lib/sqreen/aggregated_metric.rb +25 -0
- data/lib/sqreen/attack_blocked.rb +2 -0
- data/lib/sqreen/binding_accessor.rb +2 -0
- data/lib/sqreen/binding_accessor/path_elem.rb +2 -0
- data/lib/sqreen/binding_accessor/transforms.rb +8 -1
- data/lib/sqreen/call_countable.rb +2 -0
- data/lib/sqreen/capped_queue.rb +2 -0
- data/lib/sqreen/cb.rb +2 -0
- data/lib/sqreen/cb_tree.rb +2 -0
- data/lib/sqreen/condition_evaluator.rb +2 -0
- data/lib/sqreen/conditionable.rb +2 -0
- data/lib/sqreen/configuration.rb +19 -1
- data/lib/sqreen/context.rb +2 -0
- data/lib/sqreen/default_cb.rb +2 -0
- data/lib/sqreen/deferred_logger.rb +2 -0
- data/lib/sqreen/deliveries.rb +2 -0
- data/lib/sqreen/deliveries/batch.rb +6 -1
- data/lib/sqreen/deliveries/simple.rb +6 -0
- data/lib/sqreen/dependency.rb +3 -1
- data/lib/sqreen/dependency/detector.rb +22 -14
- data/lib/sqreen/dependency/libsqreen.rb +4 -0
- data/lib/sqreen/dependency/new_relic.rb +2 -0
- data/lib/sqreen/dependency/rack.rb +10 -5
- data/lib/sqreen/dependency/rails.rb +4 -0
- data/lib/sqreen/dependency/sentry.rb +2 -0
- data/lib/sqreen/dependency/sinatra.rb +12 -1
- data/lib/sqreen/encoding_sanitizer.rb +2 -0
- data/lib/sqreen/error_handling_middleware.rb +2 -0
- data/lib/sqreen/event.rb +9 -5
- data/lib/sqreen/events/attack.rb +25 -18
- data/lib/sqreen/events/remote_exception.rb +2 -22
- data/lib/sqreen/events/request_record.rb +17 -70
- data/lib/sqreen/exception.rb +2 -0
- data/lib/sqreen/formatter_with_tid.rb +2 -0
- data/lib/sqreen/framework_cb.rb +2 -0
- data/lib/sqreen/frameworks.rb +2 -0
- data/lib/sqreen/frameworks/generic.rb +2 -0
- data/lib/sqreen/frameworks/rails.rb +1 -0
- data/lib/sqreen/frameworks/rails3.rb +2 -0
- data/lib/sqreen/frameworks/request_recorder.rb +15 -2
- data/lib/sqreen/frameworks/sinatra.rb +2 -0
- data/lib/sqreen/frameworks/sqreen_test.rb +2 -0
- data/lib/sqreen/graft.rb +12 -0
- data/lib/sqreen/graft/call.rb +150 -0
- data/lib/sqreen/{dependency → graft}/callback.rb +12 -4
- data/lib/sqreen/graft/hook.rb +316 -0
- data/lib/sqreen/{dependency → graft}/hook_point.rb +152 -33
- data/lib/sqreen/graft/hook_point_error.rb +10 -0
- data/lib/sqreen/invalid_signature_exception.rb +2 -0
- data/lib/sqreen/js.rb +2 -0
- data/lib/sqreen/js/call_context.rb +2 -0
- data/lib/sqreen/js/context_pool.rb +2 -0
- data/lib/sqreen/js/exec_js_runnable.rb +2 -0
- data/lib/sqreen/js/execjs_adapter.rb +2 -0
- data/lib/sqreen/js/executable_js.rb +2 -0
- data/lib/sqreen/js/js_service.rb +2 -0
- data/lib/sqreen/js/js_service_adapter.rb +2 -0
- data/lib/sqreen/js/mini_racer_adapter.rb +2 -0
- data/lib/sqreen/js/mini_racer_executable_js.rb +2 -0
- data/lib/sqreen/js/thread_local_exec_js_runnable.rb +2 -0
- data/lib/sqreen/kit/signals/specialized/aggregated_metric.rb +72 -0
- data/lib/sqreen/kit/signals/specialized/attack.rb +57 -0
- data/lib/sqreen/kit/signals/specialized/binning_metric.rb +76 -0
- data/lib/sqreen/kit/signals/specialized/http_trace.rb +26 -0
- data/lib/sqreen/kit/signals/specialized/sdk_track_call.rb +50 -0
- data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +57 -0
- data/lib/sqreen/{backport.rb → legacy.rb} +3 -2
- data/lib/sqreen/{instrumentation.rb → legacy/instrumentation.rb} +31 -2
- data/lib/sqreen/legacy/old_event_submission_strategy.rb +221 -0
- data/lib/sqreen/legacy/waf_redactions.rb +49 -0
- data/lib/sqreen/log.rb +2 -0
- data/lib/sqreen/log/loggable.rb +28 -0
- data/lib/sqreen/logger.rb +2 -0
- data/lib/sqreen/metrics.rb +2 -0
- data/lib/sqreen/metrics/average.rb +2 -0
- data/lib/sqreen/metrics/base.rb +5 -0
- data/lib/sqreen/metrics/binning.rb +2 -0
- data/lib/sqreen/metrics/collect.rb +2 -0
- data/lib/sqreen/metrics/sum.rb +2 -0
- data/lib/sqreen/metrics_store.rb +24 -12
- data/lib/sqreen/metrics_store/already_registered_metric.rb +2 -0
- data/lib/sqreen/metrics_store/unknown_metric.rb +2 -0
- data/lib/sqreen/metrics_store/unregistered_metric.rb +2 -0
- data/lib/sqreen/middleware.rb +2 -0
- data/lib/sqreen/mono_time.rb +2 -0
- data/lib/sqreen/node.rb +2 -0
- data/lib/sqreen/not_implemented_yet.rb +2 -0
- data/lib/sqreen/null_logger.rb +2 -0
- data/lib/sqreen/payload_creator.rb +2 -0
- data/lib/sqreen/payload_creator/header_section.rb +2 -0
- data/lib/sqreen/performance_notifications.rb +2 -0
- data/lib/sqreen/performance_notifications/binned_metrics.rb +10 -2
- data/lib/sqreen/performance_notifications/log.rb +2 -0
- data/lib/sqreen/performance_notifications/log_performance.rb +2 -0
- data/lib/sqreen/performance_notifications/metrics.rb +2 -0
- data/lib/sqreen/performance_notifications/newrelic.rb +2 -0
- data/lib/sqreen/prefix.rb +2 -0
- data/lib/sqreen/rails_middleware.rb +2 -0
- data/lib/sqreen/remote_command.rb +2 -0
- data/lib/sqreen/remote_command/failure_output.rb +5 -0
- data/lib/sqreen/rules.rb +6 -2
- data/lib/sqreen/rules/attrs.rb +2 -0
- data/lib/sqreen/rules/auth_track_cb.rb +2 -0
- data/lib/sqreen/rules/binding_accessor_matcher_cb.rb +2 -0
- data/lib/sqreen/rules/binding_accessor_metrics.rb +2 -0
- data/lib/sqreen/rules/blacklist_ips_cb.rb +2 -0
- data/lib/sqreen/rules/count_http_codes.rb +2 -0
- data/lib/sqreen/rules/crawler_user_agent_matches_cb.rb +2 -0
- data/lib/sqreen/rules/crawler_user_agent_matches_metrics_cb.rb +2 -0
- data/lib/sqreen/rules/custom_error_cb.rb +2 -0
- data/lib/sqreen/rules/devise_auth_track_cb.rb +2 -0
- data/lib/sqreen/rules/devise_signup_track_cb.rb +2 -0
- data/lib/sqreen/rules/execjs_cb.rb +2 -0
- data/lib/sqreen/rules/headers_insert_cb.rb +7 -0
- data/lib/sqreen/rules/matcher_rule.rb +2 -0
- data/lib/sqreen/rules/not_found_cb.rb +7 -0
- data/lib/sqreen/rules/rails_parameters_cb.rb +2 -0
- data/lib/sqreen/rules/record_request_context.rb +2 -0
- data/lib/sqreen/rules/regexp_rule_cb.rb +2 -0
- data/lib/sqreen/rules/rule_cb.rb +4 -0
- data/lib/sqreen/rules/run_req_start_actions.rb +3 -1
- data/lib/sqreen/rules/run_user_actions.rb +3 -1
- data/lib/sqreen/rules/shell_env_cb.rb +2 -0
- data/lib/sqreen/rules/signup_track_cb.rb +2 -0
- data/lib/sqreen/rules/update_request_context.rb +2 -0
- data/lib/sqreen/rules/url_matches_cb.rb +2 -0
- data/lib/sqreen/rules/user_agent_matches_cb.rb +2 -0
- data/lib/sqreen/rules/waf_cb.rb +41 -16
- data/lib/sqreen/rules/xss_cb.rb +2 -0
- data/lib/sqreen/run_when_called_cb.rb +2 -0
- data/lib/sqreen/runner.rb +68 -12
- data/lib/sqreen/runtime_infos.rb +2 -0
- data/lib/sqreen/safe_json.rb +2 -0
- data/lib/sqreen/sdk.rb +4 -0
- data/lib/sqreen/sensitive_data_redactor.rb +21 -31
- data/lib/sqreen/serializer.rb +2 -0
- data/lib/sqreen/session.rb +41 -37
- data/lib/sqreen/shared_storage.rb +2 -0
- data/lib/sqreen/shared_storage23.rb +2 -0
- data/lib/sqreen/shrink_wrap.rb +16 -0
- data/lib/sqreen/signals/conversions.rb +283 -0
- data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
- data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
- data/lib/sqreen/signature_verifier.rb +2 -0
- data/lib/sqreen/sinatra_middleware.rb +2 -0
- data/lib/sqreen/sqreen_signed_verifier.rb +2 -0
- data/lib/sqreen/token_invalid_exception.rb +2 -0
- data/lib/sqreen/token_not_found_exception.rb +2 -0
- data/lib/sqreen/trie.rb +2 -0
- data/lib/sqreen/unauthorized.rb +2 -0
- data/lib/sqreen/util.rb +5 -0
- data/lib/sqreen/util/capped_array.rb +2 -0
- data/lib/sqreen/util/capped_hash.rb +2 -0
- data/lib/sqreen/util/capped_string.rb +2 -0
- data/lib/sqreen/util/capper.rb +2 -0
- data/lib/sqreen/version.rb +3 -1
- data/lib/sqreen/waf_error.rb +2 -0
- data/lib/sqreen/weave.rb +12 -0
- data/lib/sqreen/weave/hardcoded.rb +19 -0
- data/lib/sqreen/weave/instrumentor.rb +48 -0
- data/lib/sqreen/weave/legacy.rb +12 -0
- data/lib/sqreen/weave/legacy/instrumentation.rb +406 -0
- data/lib/sqreen/web_server.rb +2 -0
- data/lib/sqreen/web_server/generic.rb +2 -0
- data/lib/sqreen/web_server/passenger.rb +2 -0
- data/lib/sqreen/web_server/puma.rb +2 -0
- data/lib/sqreen/web_server/rainbows.rb +2 -0
- data/lib/sqreen/web_server/thin.rb +2 -0
- data/lib/sqreen/web_server/unicorn.rb +2 -0
- data/lib/sqreen/web_server/webrick.rb +2 -0
- data/lib/sqreen/worker.rb +2 -0
- metadata +65 -9
- data/lib/sqreen/backport/original_name.rb +0 -86
- data/lib/sqreen/dependency/hook.rb +0 -102
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
|
|
1
3
|
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
4
|
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
5
|
|
|
@@ -59,7 +61,7 @@ module Sqreen
|
|
|
59
61
|
obj.each do |k, v|
|
|
60
62
|
ck = k.is_a?(String) ? k.downcase : k
|
|
61
63
|
if @keys.include?(ck)
|
|
62
|
-
redacted
|
|
64
|
+
redacted += SensitiveDataRedactor.all_strings(v)
|
|
63
65
|
v = MASK
|
|
64
66
|
else
|
|
65
67
|
v, r = redact(v)
|
|
@@ -72,39 +74,27 @@ module Sqreen
|
|
|
72
74
|
[result, redacted]
|
|
73
75
|
end
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
next(e) unless e[:infos]
|
|
82
|
-
next(e) unless e[:infos][:waf_data]
|
|
83
|
-
|
|
84
|
-
parsed = JSON.parse(e[:infos][:waf_data])
|
|
85
|
-
redacted = parsed.each do |w|
|
|
86
|
-
next unless (filters = w['filter'])
|
|
87
|
-
|
|
88
|
-
filters.each do |f|
|
|
89
|
-
next unless (v = f['resolved_value'])
|
|
90
|
-
next unless values.include?(v.downcase)
|
|
77
|
+
class << self
|
|
78
|
+
def all_strings(v)
|
|
79
|
+
accum = []
|
|
80
|
+
all_strings_impl(v, accum)
|
|
81
|
+
accum
|
|
82
|
+
end
|
|
91
83
|
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def all_strings_impl(obj, accum)
|
|
87
|
+
case obj
|
|
88
|
+
when String
|
|
89
|
+
accum << obj
|
|
90
|
+
when Array
|
|
91
|
+
obj.each { |el| all_strings_impl(el, accum) }
|
|
92
|
+
when Hash
|
|
93
|
+
obj.each do |k, v|
|
|
94
|
+
all_strings_impl(k, accum)
|
|
95
|
+
all_strings_impl(v, accum)
|
|
94
96
|
end
|
|
95
97
|
end
|
|
96
|
-
e[:infos][:waf_data] = JSON.dump(redacted)
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def redact_exceptions!(exceptions, values)
|
|
101
|
-
return exceptions if values.empty?
|
|
102
|
-
|
|
103
|
-
exceptions.each do |e|
|
|
104
|
-
next(e) unless e[:infos]
|
|
105
|
-
next(e) unless e[:infos][:waf]
|
|
106
|
-
|
|
107
|
-
e[:infos][:waf].delete(:args)
|
|
108
98
|
end
|
|
109
99
|
end
|
|
110
100
|
end
|
data/lib/sqreen/serializer.rb
CHANGED
data/lib/sqreen/session.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# typed: ignore
|
|
2
|
+
|
|
1
3
|
# Copyright (c) 2015 Sqreen. All Rights Reserved.
|
|
2
4
|
# Please refer to our terms for more information: https://www.sqreen.com/terms.html
|
|
3
5
|
|
|
@@ -9,6 +11,10 @@ require 'sqreen/events/attack'
|
|
|
9
11
|
require 'sqreen/events/request_record'
|
|
10
12
|
require 'sqreen/exception'
|
|
11
13
|
require 'sqreen/safe_json'
|
|
14
|
+
require 'sqreen/kit'
|
|
15
|
+
require 'sqreen/kit/configuration'
|
|
16
|
+
require 'sqreen/signals/signals_submission_strategy'
|
|
17
|
+
require 'sqreen/legacy/old_event_submission_strategy'
|
|
12
18
|
|
|
13
19
|
require 'net/https'
|
|
14
20
|
require 'uri'
|
|
@@ -39,13 +45,12 @@ module Sqreen
|
|
|
39
45
|
RETRY_MANY = 301
|
|
40
46
|
|
|
41
47
|
MUTEX = Mutex.new
|
|
42
|
-
METRICS_KEY = 'metrics'.freeze
|
|
43
48
|
|
|
44
49
|
@@path_prefix = '/sqreen/v0/'
|
|
45
50
|
|
|
46
51
|
attr_accessor :request_compression
|
|
47
52
|
|
|
48
|
-
def initialize(server_url, token, app_name = nil)
|
|
53
|
+
def initialize(server_url, token, app_name = nil, proxy_url = nil)
|
|
49
54
|
@token = token
|
|
50
55
|
@app_name = app_name
|
|
51
56
|
@session_id = nil
|
|
@@ -57,16 +62,35 @@ module Sqreen
|
|
|
57
62
|
uri = parse_uri(server_url)
|
|
58
63
|
use_ssl = (uri.scheme == 'https')
|
|
59
64
|
|
|
65
|
+
proxy_params = []
|
|
66
|
+
if proxy_url
|
|
67
|
+
proxy_uri = parse_uri(proxy_url)
|
|
68
|
+
proxy_params = [proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password]
|
|
69
|
+
end
|
|
70
|
+
|
|
60
71
|
@req_nb = 0
|
|
61
72
|
|
|
62
|
-
@http = Net::HTTP.new(uri.host, uri.port)
|
|
73
|
+
@http = Net::HTTP.new(uri.host, uri.port, *proxy_params)
|
|
63
74
|
@http.use_ssl = use_ssl
|
|
75
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE if ENV['SQREEN_SSL_NO_VERIFY'] # for testing
|
|
64
76
|
if use_ssl
|
|
65
77
|
cert_file = File.join(File.dirname(__FILE__), 'ca.crt')
|
|
66
78
|
cert_store = OpenSSL::X509::Store.new
|
|
67
79
|
cert_store.add_file cert_file
|
|
68
80
|
@http.cert_store = cert_store
|
|
69
81
|
end
|
|
82
|
+
self.use_signals = false
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def use_signals=(do_use)
|
|
86
|
+
return if do_use == @use_signals
|
|
87
|
+
|
|
88
|
+
@use_signals = do_use
|
|
89
|
+
if do_use
|
|
90
|
+
@evt_sub_strategy = Sqreen::Signals::SignalsSubmissionStrategy.new
|
|
91
|
+
else
|
|
92
|
+
@evt_sub_strategy = Sqreen::Legacy::OldEventSubmissionStrategy.new(method(:post))
|
|
93
|
+
end
|
|
70
94
|
end
|
|
71
95
|
|
|
72
96
|
def parse_uri(uri)
|
|
@@ -233,6 +257,8 @@ module Sqreen
|
|
|
233
257
|
end
|
|
234
258
|
Sqreen.log.info 'Login success.'
|
|
235
259
|
@session_id = res['session_id']
|
|
260
|
+
Kit::Configuration.session_key = @session_id
|
|
261
|
+
Kit.reset
|
|
236
262
|
Sqreen.log.debug { "received session_id #{@session_id}" }
|
|
237
263
|
Sqreen.logged_in = true
|
|
238
264
|
res
|
|
@@ -244,20 +270,24 @@ module Sqreen
|
|
|
244
270
|
|
|
245
271
|
def heartbeat(cmd_res = {}, metrics = [])
|
|
246
272
|
payload = {}
|
|
247
|
-
|
|
273
|
+
unless metrics.nil? || metrics.empty?
|
|
274
|
+
# never reached with signals
|
|
275
|
+
payload['metrics'] = metrics.map do |m|
|
|
276
|
+
Sqreen::Legacy::EventToHash.convert_agg_metric(m)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
248
279
|
payload['command_results'] = cmd_res unless cmd_res.nil? || cmd_res.empty?
|
|
249
280
|
|
|
250
281
|
post('app-beat', payload.empty? ? nil : payload, {}, RETRY_MANY)
|
|
251
282
|
end
|
|
252
283
|
|
|
253
284
|
def post_metrics(metrics)
|
|
254
|
-
|
|
255
|
-
payload = { METRICS_KEY => metrics }
|
|
256
|
-
post(METRICS_KEY, payload, {}, RETRY_MANY)
|
|
285
|
+
@evt_sub_strategy.post_metrics(metrics)
|
|
257
286
|
end
|
|
258
287
|
|
|
288
|
+
# XXX never called
|
|
259
289
|
def post_attack(attack)
|
|
260
|
-
|
|
290
|
+
@evt_sub_strategy.post_attack(attack)
|
|
261
291
|
end
|
|
262
292
|
|
|
263
293
|
def post_bundle(bundle_sig, dependencies)
|
|
@@ -269,33 +299,17 @@ module Sqreen
|
|
|
269
299
|
end
|
|
270
300
|
|
|
271
301
|
def post_request_record(request_record)
|
|
272
|
-
|
|
302
|
+
@evt_sub_strategy.post_request_record(request_record)
|
|
273
303
|
end
|
|
274
304
|
|
|
275
305
|
# Post an exception to Sqreen for analysis
|
|
276
306
|
# @param exception [RemoteException] Exception and context to be sent over
|
|
277
307
|
def post_sqreen_exception(exception)
|
|
278
|
-
|
|
279
|
-
rescue StandardError => e
|
|
280
|
-
Sqreen.log.warn(format('Could not post exception (network down? %s) %s',
|
|
281
|
-
e.inspect,
|
|
282
|
-
exception.to_hash.inspect))
|
|
283
|
-
nil
|
|
308
|
+
@evt_sub_strategy.post_sqreen_exception(exception)
|
|
284
309
|
end
|
|
285
310
|
|
|
286
|
-
BATCH_KEY = 'batch'.freeze
|
|
287
|
-
EVENT_TYPE_KEY = 'event_type'.freeze
|
|
288
311
|
def post_batch(events)
|
|
289
|
-
|
|
290
|
-
h = event.to_hash
|
|
291
|
-
h[EVENT_TYPE_KEY] = event_kind(event)
|
|
292
|
-
h
|
|
293
|
-
end
|
|
294
|
-
Sqreen.log.debug do
|
|
295
|
-
tally = Hash[events.group_by(&:class).map{ |k,v| [k, v.count] }]
|
|
296
|
-
"Doing batch with the following tally of event types: #{tally}"
|
|
297
|
-
end
|
|
298
|
-
post(BATCH_KEY, { BATCH_KEY => batch }, {}, RETRY_MANY)
|
|
312
|
+
@evt_sub_strategy.post_batch(events)
|
|
299
313
|
end
|
|
300
314
|
|
|
301
315
|
# Perform agent logout
|
|
@@ -311,15 +325,5 @@ module Sqreen
|
|
|
311
325
|
Sqreen.logged_in = false
|
|
312
326
|
disconnect
|
|
313
327
|
end
|
|
314
|
-
|
|
315
|
-
protected
|
|
316
|
-
|
|
317
|
-
def event_kind(event)
|
|
318
|
-
case event
|
|
319
|
-
when Sqreen::RemoteException then 'sqreen_exception'
|
|
320
|
-
when Sqreen::Attack then 'attack'
|
|
321
|
-
when Sqreen::RequestRecord then 'request_record'
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
328
|
end
|
|
325
329
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# typed: true
|
|
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
|
+
module Sqreen
|
|
7
|
+
class ShrinkWrap
|
|
8
|
+
def initialize(app)
|
|
9
|
+
@app = app
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call(env)
|
|
13
|
+
@app.call(env)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
require 'sqreen/version'
|
|
2
|
+
require 'sqreen/rules/rule_cb'
|
|
3
|
+
require 'sqreen/metrics/base'
|
|
4
|
+
require 'sqreen/metrics/binning'
|
|
5
|
+
require 'sqreen/signals/http_trace_redaction'
|
|
6
|
+
require 'sqreen/kit/signals/signal_attributes'
|
|
7
|
+
require 'sqreen/kit/signals/specialized/aggregated_metric'
|
|
8
|
+
require 'sqreen/kit/signals/specialized/attack'
|
|
9
|
+
require 'sqreen/kit/signals/specialized/binning_metric'
|
|
10
|
+
require 'sqreen/kit/signals/specialized/sqreen_exception'
|
|
11
|
+
require 'sqreen/kit/signals/specialized/http_trace'
|
|
12
|
+
require 'sqreen/kit/signals/specialized/sdk_track_call'
|
|
13
|
+
|
|
14
|
+
module Sqreen
|
|
15
|
+
module Signals
|
|
16
|
+
module Conversions # rubocop:disable Metrics/ModuleLength
|
|
17
|
+
class << self
|
|
18
|
+
# @param [Sqreen::AggregatedMetric] agg
|
|
19
|
+
# @return [Sqreen::Kit::Signals::Metric]
|
|
20
|
+
def convert_metric_sample(agg)
|
|
21
|
+
attrs = {
|
|
22
|
+
signal_name: "sq.agent.metric.#{agg.name}",
|
|
23
|
+
source: if agg.rule
|
|
24
|
+
"sqreen:rules:#{agg.rule.rulespack_id}:#{agg.rule.rule_name}"
|
|
25
|
+
else
|
|
26
|
+
agent_gen_source
|
|
27
|
+
end,
|
|
28
|
+
time: agg.finish,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if agg.metric.is_a?(Sqreen::Metric::Binning)
|
|
32
|
+
conv_binning_metric(agg, attrs)
|
|
33
|
+
else
|
|
34
|
+
conv_generic_metric(agg, attrs)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @param [Sqreen::Attack] attack
|
|
39
|
+
# XXX: not used because we don't use Sqreen::Attack
|
|
40
|
+
def convert_attack(attack)
|
|
41
|
+
# no need to set actor/context as we only include them in request records/traces
|
|
42
|
+
Kit::Signals::Specialized::Attack.new(
|
|
43
|
+
signal_name: "sq.agent.attack.#{attack.attack_type}",
|
|
44
|
+
source: "sqreen:rule:#{attack.rulespack_id}:#{attack.rule_name}",
|
|
45
|
+
time: attack.time,
|
|
46
|
+
location: Kit::Signals::Location.new(stack_trace: attack.backtrace),
|
|
47
|
+
payload: Kit::Signals::Specialized::Attack::Payload.new(
|
|
48
|
+
test: attack.test?,
|
|
49
|
+
block: attack.block?,
|
|
50
|
+
infos: attack.infos
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# see Sqreen::Rules::RuleCB.record_event
|
|
56
|
+
def convert_unstructured_attack(payload)
|
|
57
|
+
Kit::Signals::Specialized::Attack.new(
|
|
58
|
+
signal_name: "sq.agent.attack.#{payload[:attack_type]}",
|
|
59
|
+
source: "sqreen:rule:#{payload[:rulespack_id]}:#{payload[:rule_name]}",
|
|
60
|
+
time: payload[:time],
|
|
61
|
+
location: (Kit::Signals::Location.new(stack_trace: payload[:backtrace]) if payload[:backtrace]),
|
|
62
|
+
payload: Kit::Signals::Specialized::Attack::Payload.new(
|
|
63
|
+
test: payload[:test],
|
|
64
|
+
block: payload[:block],
|
|
65
|
+
infos: payload[:infos]
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @param [Sqreen::RemoteException] exception
|
|
71
|
+
# @return [Sqreen::Kit::Signals::Specialized::SqreenException]
|
|
72
|
+
def convert_exception(exception)
|
|
73
|
+
payload = exception.payload
|
|
74
|
+
|
|
75
|
+
infos = payload['client_ip'] ? { client_ip: payload['client_ip'] } : {}
|
|
76
|
+
infos.merge!(payload['infos'] || {})
|
|
77
|
+
|
|
78
|
+
Kit::Signals::Specialized::SqreenException.new(
|
|
79
|
+
source: if payload['rule_name']
|
|
80
|
+
"sqreen:rule:#{payload['rulespack_id']}:#{payload['rule_name']}"
|
|
81
|
+
else
|
|
82
|
+
agent_gen_source
|
|
83
|
+
end,
|
|
84
|
+
time: exception.time,
|
|
85
|
+
ruby_exception: payload['exception'],
|
|
86
|
+
infos: infos
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# see Sqreen::Rules::RuleCB.record_exception
|
|
91
|
+
# @param [Hash] payload
|
|
92
|
+
# @return [Sqreen::Kit::Signals::Specialized::SqreenException]
|
|
93
|
+
def convert_unstructured_exception(payload)
|
|
94
|
+
Kit::Signals::Specialized::SqreenException.new(
|
|
95
|
+
source: "sqreen:rule:#{payload[:rulespack_id]}:#{payload[:rule_name]}",
|
|
96
|
+
time: payload[:time],
|
|
97
|
+
ruby_exception: payload[:exception],
|
|
98
|
+
infos: payload[:infos]
|
|
99
|
+
)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @param [Sqreen::RequestRecord] req_rec
|
|
103
|
+
# @return [Sqreen::Kit::Signals::Specialized::HttpTrace]
|
|
104
|
+
def convert_req_record(req_rec)
|
|
105
|
+
payload = req_rec.payload
|
|
106
|
+
|
|
107
|
+
request_p = payload['request']
|
|
108
|
+
id_args = req_rec.last_identify_args
|
|
109
|
+
identifiers = id_args[0] if id_args
|
|
110
|
+
traits = id_args[1] if id_args
|
|
111
|
+
|
|
112
|
+
observed = payload[:observed] || {}
|
|
113
|
+
signals = []
|
|
114
|
+
signals += (observed[:attacks] || [])
|
|
115
|
+
.map { |att| convert_unstructured_attack(att) }
|
|
116
|
+
signals += (observed[:sqreen_exceptions] || [])
|
|
117
|
+
.map { |sq_exc| convert_unstructured_exception(sq_exc) }
|
|
118
|
+
signals += req_rec.processed_sdk_calls
|
|
119
|
+
.select { |h| h[:name] == :track }
|
|
120
|
+
.map { |h| convert_track(h) }
|
|
121
|
+
|
|
122
|
+
trace = Kit::Signals::Specialized::HttpTrace.new(
|
|
123
|
+
actor: Kit::Signals::Actor.new(
|
|
124
|
+
ip_addresses: [request_p[:client_ip]].compact,
|
|
125
|
+
user_agent: request_p[:user_agent],
|
|
126
|
+
identifiers: identifiers,
|
|
127
|
+
traits: traits,
|
|
128
|
+
),
|
|
129
|
+
location_infra: location_infra,
|
|
130
|
+
context: convert_request(request_p,
|
|
131
|
+
payload['response'],
|
|
132
|
+
payload['headers'],
|
|
133
|
+
payload['params']),
|
|
134
|
+
data: signals
|
|
135
|
+
)
|
|
136
|
+
HttpTraceRedaction.redact_trace!(trace, req_rec.redactor)
|
|
137
|
+
trace
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# @param [Array<Sqreen::Kit::Signals::Signal|Sqreen::Kit::Signals::Trace>] batch
|
|
141
|
+
def convert_batch(batch)
|
|
142
|
+
batch.map do |evt|
|
|
143
|
+
case evt
|
|
144
|
+
when RemoteException
|
|
145
|
+
convert_exception(evt)
|
|
146
|
+
when AggregatedMetric
|
|
147
|
+
convert_metric_sample(evt)
|
|
148
|
+
when RequestRecord
|
|
149
|
+
convert_req_record(evt)
|
|
150
|
+
else
|
|
151
|
+
raise NotImplementedError, "Unknown type of event in batch: #{evt}"
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
private
|
|
157
|
+
|
|
158
|
+
def agent_gen_source
|
|
159
|
+
"sqreen:agent:ruby:#{Sqreen::VERSION}"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def location_infra
|
|
163
|
+
@location_infra ||= begin
|
|
164
|
+
Kit::Signals::LocationInfra.new(
|
|
165
|
+
agent_version: Sqreen::VERSION,
|
|
166
|
+
os_type: RuntimeInfos.os[:os_type],
|
|
167
|
+
hostname: RuntimeInfos.hostname,
|
|
168
|
+
runtime_type: RuntimeInfos.runtime[:runtime_type],
|
|
169
|
+
runtime_version: RuntimeInfos.runtime[:runtime_version],
|
|
170
|
+
libsqreen_version: RuntimeInfos.libsqreen_version,
|
|
171
|
+
)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# see Sqreen::RequestRecord.processed_sdk_calls
|
|
176
|
+
def convert_track(call_info)
|
|
177
|
+
options = call_info[:args][1] || {}
|
|
178
|
+
Kit::Signals::Specialized::SdkTrackCall.new(
|
|
179
|
+
signal_name: "sq.sdk.#{call_info[:args][0]}",
|
|
180
|
+
time: call_info[:time],
|
|
181
|
+
payload: Kit::Signals::Specialized::SdkTrackCall::Payload.new(
|
|
182
|
+
properties: options[:properties],
|
|
183
|
+
user_identifiers: options[:user_identifiers]
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# @param [Hash] req_payload
|
|
189
|
+
# @param [Hash] headers_payload
|
|
190
|
+
# @param [Hash] params_payload
|
|
191
|
+
# see the PayloadCreator abomination for reference
|
|
192
|
+
# TODO: do not convert from the old payload to the new payload
|
|
193
|
+
# Have an intermediate object that gets the data from the framework.
|
|
194
|
+
# (Or convert directly from the framework, but this needs to be
|
|
195
|
+
# done during the request, not just before event is transmitted)
|
|
196
|
+
def convert_request(req_payload, resp_payload, headers_payload, params_payload)
|
|
197
|
+
req_payload ||= {}
|
|
198
|
+
headers_payload ||= {}
|
|
199
|
+
resp_payload ||= {}
|
|
200
|
+
params_payload ||= {}
|
|
201
|
+
|
|
202
|
+
other = params_payload['other']
|
|
203
|
+
other = merge_hash_append(other, params_payload['rack'])
|
|
204
|
+
other = merge_hash_append(other, params_payload['grape_params'])
|
|
205
|
+
other = merge_hash_append(other, params_payload['rack_routing'])
|
|
206
|
+
|
|
207
|
+
Sqreen::Kit::Signals::Context::HttpContext.new(
|
|
208
|
+
{
|
|
209
|
+
rid: req_payload[:rid],
|
|
210
|
+
headers: headers_payload,
|
|
211
|
+
user_agent: req_payload[:user_agent],
|
|
212
|
+
scheme: req_payload[:scheme],
|
|
213
|
+
verb: req_payload[:verb],
|
|
214
|
+
host: req_payload[:host],
|
|
215
|
+
port: req_payload[:port],
|
|
216
|
+
remote_ip: req_payload[:remote_ip],
|
|
217
|
+
remote_port: req_payload[:remote_port] || 0,
|
|
218
|
+
path: req_payload[:path],
|
|
219
|
+
referer: req_payload[:referer],
|
|
220
|
+
params_query: params_payload['query'],
|
|
221
|
+
params_form: params_payload['form'],
|
|
222
|
+
params_other: other,
|
|
223
|
+
# endpoint, is_reveal_replayed not set
|
|
224
|
+
status: resp_payload[:status],
|
|
225
|
+
content_length: resp_payload[:content_length],
|
|
226
|
+
content_type: resp_payload[:content_type],
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def merge_hash_append(hash1, hash2)
|
|
232
|
+
return nil if hash1.nil? && hash2.nil?
|
|
233
|
+
return hash1 if hash2.nil? || hash2.empty?
|
|
234
|
+
return hash2 if hash1.nil? || hash1.empty?
|
|
235
|
+
|
|
236
|
+
pairs = (hash1.keys + hash2.keys).map do |key|
|
|
237
|
+
values1 = hash1[key]
|
|
238
|
+
values2 = hash2[key]
|
|
239
|
+
values = [values1, values2].compact
|
|
240
|
+
values = values.first if values.size == 1
|
|
241
|
+
[key, values]
|
|
242
|
+
end
|
|
243
|
+
Hash[pairs]
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# @param [Sqreen::AggregatedMetric] agg
|
|
247
|
+
# @param [Hash] attrs
|
|
248
|
+
def conv_generic_metric(agg, attrs)
|
|
249
|
+
attrs[:payload] = Kit::Signals::Specialized::AggregatedMetric::Payload.new(
|
|
250
|
+
kind: metric_kind(agg.metric),
|
|
251
|
+
capture_interval_s: agg.metric.period,
|
|
252
|
+
date_started: agg.start,
|
|
253
|
+
date_ended: agg.finish,
|
|
254
|
+
values: agg.data
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
Kit::Signals::Specialized::AggregatedMetric.new(attrs)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# @param [Sqreen::AggregatedMetric] agg
|
|
261
|
+
# @param [Hash] attrs
|
|
262
|
+
def conv_binning_metric(agg, attrs)
|
|
263
|
+
attrs[:payload] = Kit::Signals::Specialized::BinningMetric::Payload.new(
|
|
264
|
+
capture_interval_s: agg.metric.period,
|
|
265
|
+
date_started: agg.start,
|
|
266
|
+
date_ended: agg.finish,
|
|
267
|
+
base: agg.data['b'],
|
|
268
|
+
unit: agg.data['u'],
|
|
269
|
+
max: agg.data['v']['max'],
|
|
270
|
+
bins: agg.data['v'].reject { |k, _v| k == 'max' }
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
Kit::Signals::Specialized::BinningMetric.new(attrs)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# @param [Sqreen::Metric::Base] metric
|
|
277
|
+
def metric_kind(metric)
|
|
278
|
+
metric.class.name.sub(/.*::/, '').sub(/Metric$/, '')
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|