sqreen 1.19.1-java → 1.21.0.beta3-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +34 -0
  3. data/lib/sqreen/actions/block_user.rb +1 -1
  4. data/lib/sqreen/actions/redirect_ip.rb +1 -1
  5. data/lib/sqreen/actions/redirect_user.rb +1 -1
  6. data/lib/sqreen/agent_message.rb +20 -0
  7. data/lib/sqreen/aggregated_metric.rb +25 -0
  8. data/lib/sqreen/attack_detected.html +1 -2
  9. data/lib/sqreen/ca.crt +24 -0
  10. data/lib/sqreen/condition_evaluator.rb +9 -2
  11. data/lib/sqreen/conditionable.rb +24 -6
  12. data/lib/sqreen/configuration.rb +11 -5
  13. data/lib/sqreen/deferred_logger.rb +50 -14
  14. data/lib/sqreen/deliveries/batch.rb +12 -2
  15. data/lib/sqreen/deliveries/simple.rb +4 -0
  16. data/lib/sqreen/deprecation.rb +38 -0
  17. data/lib/sqreen/ecosystem.rb +96 -0
  18. data/lib/sqreen/ecosystem/dispatch_table.rb +43 -0
  19. data/lib/sqreen/ecosystem/exception_reporting.rb +26 -0
  20. data/lib/sqreen/ecosystem/http/net_http.rb +50 -0
  21. data/lib/sqreen/ecosystem/http/rack_request.rb +39 -0
  22. data/lib/sqreen/ecosystem/loggable.rb +13 -0
  23. data/lib/sqreen/ecosystem/module_api.rb +30 -0
  24. data/lib/sqreen/ecosystem/module_api/event_listener.rb +18 -0
  25. data/lib/sqreen/ecosystem/module_api/instrumentation.rb +23 -0
  26. data/lib/sqreen/ecosystem/module_api/message_producer.rb +51 -0
  27. data/lib/sqreen/ecosystem/module_api/signal_producer.rb +24 -0
  28. data/lib/sqreen/ecosystem/module_api/tracing.rb +45 -0
  29. data/lib/sqreen/ecosystem/module_api/tracing/client_data.rb +31 -0
  30. data/lib/sqreen/ecosystem/module_api/tracing/server_data.rb +27 -0
  31. data/lib/sqreen/ecosystem/module_api/tracing_id_generation.rb +16 -0
  32. data/lib/sqreen/ecosystem/module_api/transaction_storage.rb +71 -0
  33. data/lib/sqreen/ecosystem/module_registry.rb +44 -0
  34. data/lib/sqreen/ecosystem/redis/redis_connection.rb +43 -0
  35. data/lib/sqreen/ecosystem/tracing/modules/client.rb +31 -0
  36. data/lib/sqreen/ecosystem/tracing/modules/server.rb +30 -0
  37. data/lib/sqreen/ecosystem/tracing/sampler.rb +160 -0
  38. data/lib/sqreen/ecosystem/tracing/sampling_configuration.rb +150 -0
  39. data/lib/sqreen/ecosystem/tracing/signals/tracing_client.rb +53 -0
  40. data/lib/sqreen/ecosystem/tracing/signals/tracing_server.rb +53 -0
  41. data/lib/sqreen/ecosystem/tracing_broker.rb +101 -0
  42. data/lib/sqreen/ecosystem/tracing_id_setup.rb +34 -0
  43. data/lib/sqreen/ecosystem/transaction_storage.rb +64 -0
  44. data/lib/sqreen/ecosystem/util/call_writers_from_init.rb +13 -0
  45. data/lib/sqreen/ecosystem_integration.rb +87 -0
  46. data/lib/sqreen/ecosystem_integration/around_callbacks.rb +99 -0
  47. data/lib/sqreen/ecosystem_integration/instrumentation_service.rb +42 -0
  48. data/lib/sqreen/ecosystem_integration/request_lifecycle_tracking.rb +58 -0
  49. data/lib/sqreen/ecosystem_integration/signal_consumption.rb +35 -0
  50. data/lib/sqreen/endpoint_testing.rb +184 -0
  51. data/lib/sqreen/event.rb +7 -5
  52. data/lib/sqreen/events/attack.rb +23 -18
  53. data/lib/sqreen/events/remote_exception.rb +0 -22
  54. data/lib/sqreen/events/request_record.rb +15 -71
  55. data/lib/sqreen/frameworks/generic.rb +24 -1
  56. data/lib/sqreen/frameworks/rails.rb +0 -7
  57. data/lib/sqreen/frameworks/request_recorder.rb +15 -2
  58. data/lib/sqreen/graft/call.rb +106 -19
  59. data/lib/sqreen/graft/callback.rb +1 -1
  60. data/lib/sqreen/graft/hook.rb +212 -100
  61. data/lib/sqreen/graft/hook_point.rb +18 -11
  62. data/lib/sqreen/kit/signals/specialized/aggregated_metric.rb +72 -0
  63. data/lib/sqreen/kit/signals/specialized/attack.rb +57 -0
  64. data/lib/sqreen/kit/signals/specialized/binning_metric.rb +76 -0
  65. data/lib/sqreen/kit/signals/specialized/http_trace.rb +26 -0
  66. data/lib/sqreen/kit/signals/specialized/sdk_track_call.rb +50 -0
  67. data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +57 -0
  68. data/lib/sqreen/legacy/instrumentation.rb +22 -10
  69. data/lib/sqreen/legacy/old_event_submission_strategy.rb +228 -0
  70. data/lib/sqreen/legacy/waf_redactions.rb +49 -0
  71. data/lib/sqreen/log.rb +3 -2
  72. data/lib/sqreen/log/loggable.rb +2 -1
  73. data/lib/sqreen/logger.rb +24 -0
  74. data/lib/sqreen/metrics.rb +1 -0
  75. data/lib/sqreen/metrics/base.rb +3 -0
  76. data/lib/sqreen/metrics/req_detailed.rb +41 -0
  77. data/lib/sqreen/metrics_store.rb +33 -12
  78. data/lib/sqreen/null_logger.rb +22 -0
  79. data/lib/sqreen/performance_notifications/binned_metrics.rb +8 -2
  80. data/lib/sqreen/remote_command.rb +4 -0
  81. data/lib/sqreen/rules.rb +12 -6
  82. data/lib/sqreen/rules/blacklist_ips_cb.rb +2 -2
  83. data/lib/sqreen/rules/custom_error_cb.rb +3 -3
  84. data/lib/sqreen/rules/not_found_cb.rb +2 -0
  85. data/lib/sqreen/rules/rule_cb.rb +6 -2
  86. data/lib/sqreen/rules/waf_cb.rb +16 -13
  87. data/lib/sqreen/runner.rb +138 -16
  88. data/lib/sqreen/sensitive_data_redactor.rb +19 -31
  89. data/lib/sqreen/session.rb +53 -43
  90. data/lib/sqreen/signals/conversions.rb +288 -0
  91. data/lib/sqreen/signals/http_trace_redaction.rb +111 -0
  92. data/lib/sqreen/signals/signals_submission_strategy.rb +78 -0
  93. data/lib/sqreen/version.rb +1 -1
  94. data/lib/sqreen/weave/budget.rb +35 -0
  95. data/lib/sqreen/weave/legacy/instrumentation.rb +277 -135
  96. data/lib/sqreen/worker.rb +6 -2
  97. metadata +86 -10
  98. data/lib/sqreen/backport.rb +0 -9
  99. data/lib/sqreen/backport/clock_gettime.rb +0 -74
  100. data/lib/sqreen/backport/original_name.rb +0 -88
  101. data/lib/sqreen/encoding_sanitizer.rb +0 -27
@@ -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
@@ -0,0 +1,96 @@
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_broker'
6
+ require 'sqreen/ecosystem/tracing_id_setup'
7
+ require 'sqreen/ecosystem/module_api/message_producer'
8
+ require 'sqreen/ecosystem/module_api/tracing_id_generation'
9
+ require 'sqreen/ecosystem/module_api/tracing'
10
+
11
+ module Sqreen
12
+ # The API for the ecosystem client (together with the dispatch table)
13
+ module Ecosystem
14
+ class << self
15
+ def init(opts = {})
16
+ @registry = ModuleRegistry.new
17
+ register_modules(opts[:modules])
18
+ @registry.init_all
19
+
20
+ # setup tracing generation
21
+ tracing_id_mods = @registry.module_subset(ModuleApi::TracingIdGeneration)
22
+ @tracing_id_setup = TracingIdSetup.new(tracing_id_mods)
23
+ @tracing_id_setup.setup_modules
24
+
25
+ # configure tracing broker with the consumers (tracing modules)
26
+ tracing_modules = @registry.module_subset(ModuleApi::Tracing)
27
+ @tracing_broker = TracingBroker.new(tracing_modules)
28
+
29
+ # inject tracing broker in message producers
30
+ @registry.each_module(ModuleApi::MessageProducer) do |mod|
31
+ mod.tracing_broker = @tracing_broker
32
+ end
33
+ rescue ::Exception # rubocop:disable Lint/RescueException
34
+ # TODO: modules must be disabled at this point
35
+ raise
36
+ end
37
+
38
+ def reset
39
+ instance_variables.each do |ia|
40
+ instance_variable_set(ia, nil)
41
+ end
42
+ end
43
+
44
+ # To be called by the Ecosystem client when a new transaction
45
+ # (generally: request) is started
46
+ # In the future, it's intended that request end/start detection be handled
47
+ # by the Ecosystem itself, so control will flow in the other direction,
48
+ # from the ecosystem to its client
49
+ def start_transaction
50
+ TransactionStorage.create_thread_local
51
+ end
52
+
53
+ def end_transaction
54
+ TransactionStorage.destroy_thread_local
55
+ end
56
+
57
+ # @param [String] tracing_id_prefix
58
+ # @param [Array<Hash{String=>Object}>] sampling_config
59
+ def configure_sampling(tracing_id_prefix, sampling_config)
60
+ @tracing_id_setup.tracing_id_prefix = tracing_id_prefix
61
+ built_samp_cfg = Tracing::SamplingConfiguration.new(sampling_config)
62
+ @tracing_broker.sampling_configuration = built_samp_cfg
63
+ end
64
+
65
+ private
66
+
67
+ def register_modules(modules)
68
+ return register_all_modules unless modules
69
+
70
+ modules.each { |mod| register mod }
71
+ end
72
+
73
+ def register_all_modules
74
+ # replace with something more magical?
75
+ require_relative 'ecosystem/http/rack_request'
76
+ register Http::RackRequest.new
77
+
78
+ require_relative 'ecosystem/http/net_http'
79
+ register Http::NetHttp.new
80
+
81
+ require_relative 'ecosystem/redis/redis_connection'
82
+ register Redis::RedisConnection.new
83
+
84
+ require_relative 'ecosystem/tracing/modules/client'
85
+ register Tracing::Modules::Client.new
86
+
87
+ require_relative 'ecosystem/tracing/modules/server'
88
+ register Tracing::Modules::Server.new
89
+ end
90
+
91
+ def register(mod)
92
+ @registry.register mod
93
+ end
94
+ end
95
+ end
96
+ 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,26 @@
1
+ require 'sqreen/ecosystem/dispatch_table'
2
+ require 'sqreen/ecosystem/loggable'
3
+ require 'sqreen/kit/signals/specialized/sqreen_exception'
4
+
5
+ module Sqreen
6
+ module Ecosystem
7
+ module ExceptionReporting
8
+ include Loggable
9
+
10
+ private
11
+
12
+ # @param [String] message
13
+ # @param [Exception] e
14
+ def report_exception(message, e)
15
+ logger.warn { "#{message}: #{e.message}" }
16
+ logger.debug { e.backtrace.map { |x| " #{x}" }.join("\n") }
17
+
18
+ signal = Sqreen::Kit::Signals::Specialized::SqreenException.new(
19
+ ruby_exception: e
20
+ )
21
+
22
+ DispatchTable.consume_signal signal
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,50 @@
1
+ require 'sqreen/ecosystem/module_api'
2
+ require 'sqreen/ecosystem/module_api/instrumentation'
3
+ require 'sqreen/ecosystem/module_api/message_producer'
4
+ require 'sqreen/ecosystem/module_api/tracing_id_generation'
5
+ require 'sqreen/ecosystem/module_api/tracing/client_data'
6
+
7
+ module Sqreen
8
+ module Ecosystem
9
+ module Http
10
+ class NetHttp
11
+ class HttpConnectionData
12
+ include ModuleApi::Tracing::ClientData
13
+ end
14
+
15
+ include ModuleApi::Instrumentation
16
+ include ModuleApi::MessageProducer
17
+ include ModuleApi::TracingIdGeneration
18
+
19
+ def setup
20
+ advice = wrap_for_interest(HttpConnectionData, &method(:before_advice))
21
+ instrument 'Net::HTTP#request', before: advice
22
+ end
23
+
24
+ private
25
+
26
+ # instr. def request(req, body = nil, &block) # :yield: +response+
27
+ # req is of type +Net::HTTPGenericRequest+
28
+ def before_advice(call, _ball)
29
+ tracing_id = create_tracing_id
30
+
31
+ # build & submit signal
32
+ host = call.instance.address
33
+ port = call.instance.port
34
+
35
+ # add tracing header
36
+ req = call.args[0]
37
+ req[ModuleApi::TRACE_ID_HEADER] = tracing_id
38
+
39
+ host += ':' + port.to_s if port != 80 && port != 443
40
+
41
+ HttpConnectionData.new(
42
+ transport: 'http',
43
+ host: host,
44
+ tracing_identifier: tracing_id
45
+ )
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,39 @@
1
+ require 'sqreen/ecosystem/module_api'
2
+ require 'sqreen/ecosystem/module_api/event_listener'
3
+ require 'sqreen/ecosystem/module_api/message_producer'
4
+ require 'sqreen/ecosystem/module_api/tracing/server_data'
5
+
6
+ module Sqreen
7
+ module Ecosystem
8
+ module Http
9
+ class RackRequest
10
+ class HttpServerData
11
+ include ModuleApi::Tracing::ServerData
12
+ end
13
+
14
+ include ModuleApi::EventListener
15
+ include ModuleApi::MessageProducer
16
+
17
+ def setup
18
+ advice = wrap_for_interest(
19
+ ModuleApi::Tracing::ServerData,
20
+ &method(:handle_request)
21
+ )
22
+ on_request_start(&advice)
23
+ end
24
+
25
+ private
26
+
27
+ def handle_request(rack_request)
28
+ trace_id = rack_request.env[ModuleApi::TRACE_ID_ENV_KEY]
29
+
30
+ HttpServerData.new(
31
+ transport: 'http',
32
+ client_ip: rack_request.ip,
33
+ tracing_identifier: trace_id
34
+ )
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ require 'sqreen/ecosystem/dispatch_table'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module Loggable
6
+ private
7
+
8
+ def logger
9
+ DispatchTable.fetch_logger.call
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,30 @@
1
+ require 'sqreen/ecosystem/loggable'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ # The API that the transport/tracing modules are written against
6
+ module ModuleApi
7
+ TRACE_ID_HEADER = 'X-Sqreen-Trace-Identifier'.freeze
8
+ TRACE_ID_ENV_KEY = 'HTTP_X_SQREEN_TRACE_IDENTIFIER'.freeze
9
+
10
+ Loggable = Sqreen::Ecosystem::Loggable
11
+
12
+ module ClassMethods
13
+ attr_writer :module_name
14
+
15
+ def module_name
16
+ if instance_variable_defined?(:@module_name)
17
+ @module_name
18
+ else
19
+ # to snake case
20
+ @module_name = to_s.sub(/.*::/, '').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.included(mod)
26
+ mod.extend(ClassMethods)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ require 'sqreen/ecosystem/dispatch_table'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module ModuleApi
6
+ module EventListener
7
+ private
8
+
9
+ # XXX: callbacks need to be wrapped in order ot handle
10
+ # perfcap, exceptions, and maybe other concerns applying
11
+ # across the board
12
+ def on_request_start(&cb)
13
+ DispatchTable.add_request_start_listener.call(cb)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'sqreen/ecosystem/module_api'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module ModuleApi
6
+ module Instrumentation
7
+ def self.included(mod)
8
+ mod.send :include, ModuleApi unless mod.ancestors.include?(ModuleApi)
9
+ end
10
+
11
+ private
12
+
13
+ # Just forwards the call to the instrumentation service
14
+ # @param [String] method
15
+ # @param [Hash{Symbol=>Proc}] advice keys are one of: :before, :after,
16
+ # :raised,
17
+ def instrument(method, advice)
18
+ DispatchTable.instrument.call(self.class.module_name, method, advice)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,51 @@
1
+ require 'sqreen/ecosystem/loggable'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module ModuleApi
6
+ module MessageProducer
7
+ include Loggable
8
+
9
+ # method for ecosystem to inject the config
10
+ # @param [Sqreen::Ecosystem::TracingBroker]
11
+ attr_writer :tracing_broker
12
+
13
+ private
14
+
15
+ def determine_interest(type, hints = {})
16
+ @tracing_broker.interested_consumers(type, hints)
17
+ end
18
+
19
+ def publish(data, interested)
20
+ @tracing_broker.publish(data, interested)
21
+ end
22
+
23
+ # Convenience wrapper.
24
+ # Wraps a callback, skipping it if there is no interest in the type
25
+ # produced and submitting the return value as a message to the
26
+ # tracing broker
27
+ def wrap_for_interest(type, gen_hints = nil, &block)
28
+ raise ArgumentError, 'no block passed' if block.nil?
29
+
30
+ proc do |*args|
31
+ hints = gen_hints[*args] if gen_hints
32
+ interested = determine_interest(type, hints || {})
33
+
34
+ unless interested
35
+ logger.debug { "No interested consumers in #{type}" }
36
+ next
37
+ end
38
+
39
+ res = block[*args]
40
+
41
+ next if res.nil?
42
+
43
+ raise 'unexpected return type' unless res.is_a?(type)
44
+
45
+ @tracing_broker.publish(res, interested)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,24 @@
1
+ require 'sqreen/ecosystem/dispatch_table'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module ModuleApi
6
+ module SignalProducer
7
+ # for injection
8
+ # callable taking no arguments and generating a tracing id
9
+ attr_writer :tracing_id_producer
10
+
11
+ private
12
+
13
+ def create_tracing_id
14
+ @tracing_id_producer.call
15
+ end
16
+
17
+ # @param [Sqreen::Kit::Signals::Signal] signal
18
+ def submit_signal(signal)
19
+ DispatchTable.consume_signal.call(signal)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end