sqreen 1.20.1-java → 1.22.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.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -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/attack_detected.html +1 -2
  7. data/lib/sqreen/condition_evaluator.rb +8 -2
  8. data/lib/sqreen/configuration.rb +1 -1
  9. data/lib/sqreen/deferred_logger.rb +50 -14
  10. data/lib/sqreen/deliveries/batch.rb +8 -1
  11. data/lib/sqreen/dependency/detector.rb +11 -3
  12. data/lib/sqreen/dependency/new_relic.rb +10 -1
  13. data/lib/sqreen/deprecation.rb +38 -0
  14. data/lib/sqreen/ecosystem.rb +123 -0
  15. data/lib/sqreen/ecosystem/databases/database_connection_data.rb +23 -0
  16. data/lib/sqreen/ecosystem/databases/mongo.rb +39 -0
  17. data/lib/sqreen/ecosystem/databases/mysql.rb +54 -0
  18. data/lib/sqreen/ecosystem/databases/postgres.rb +51 -0
  19. data/lib/sqreen/ecosystem/databases/redis.rb +36 -0
  20. data/lib/sqreen/ecosystem/dispatch_table.rb +43 -0
  21. data/lib/sqreen/ecosystem/exception_reporting.rb +28 -0
  22. data/lib/sqreen/ecosystem/http/net_http.rb +50 -0
  23. data/lib/sqreen/ecosystem/http/rack_request.rb +39 -0
  24. data/lib/sqreen/ecosystem/loggable.rb +13 -0
  25. data/lib/sqreen/ecosystem/messaging/bunny.rb +61 -0
  26. data/lib/sqreen/ecosystem/messaging/kafka.rb +70 -0
  27. data/lib/sqreen/ecosystem/messaging/kinesis.rb +66 -0
  28. data/lib/sqreen/ecosystem/messaging/sqs.rb +68 -0
  29. data/lib/sqreen/ecosystem/module_api.rb +30 -0
  30. data/lib/sqreen/ecosystem/module_api/event_listener.rb +18 -0
  31. data/lib/sqreen/ecosystem/module_api/instrumentation.rb +23 -0
  32. data/lib/sqreen/ecosystem/module_api/message_producer.rb +57 -0
  33. data/lib/sqreen/ecosystem/module_api/signal_producer.rb +24 -0
  34. data/lib/sqreen/ecosystem/module_api/tracing.rb +45 -0
  35. data/lib/sqreen/ecosystem/module_api/tracing/client_data.rb +31 -0
  36. data/lib/sqreen/ecosystem/module_api/tracing/consumer_data.rb +13 -0
  37. data/lib/sqreen/ecosystem/module_api/tracing/messaging_data.rb +35 -0
  38. data/lib/sqreen/ecosystem/module_api/tracing/producer_data.rb +13 -0
  39. data/lib/sqreen/ecosystem/module_api/tracing/server_data.rb +27 -0
  40. data/lib/sqreen/ecosystem/module_api/tracing_id_generation.rb +16 -0
  41. data/lib/sqreen/ecosystem/module_api/transaction_storage.rb +71 -0
  42. data/lib/sqreen/ecosystem/module_registry.rb +48 -0
  43. data/lib/sqreen/ecosystem/tracing/modules/client.rb +35 -0
  44. data/lib/sqreen/ecosystem/tracing/modules/consumer.rb +35 -0
  45. data/lib/sqreen/ecosystem/tracing/modules/determine_ip.rb +28 -0
  46. data/lib/sqreen/ecosystem/tracing/modules/producer.rb +35 -0
  47. data/lib/sqreen/ecosystem/tracing/modules/server.rb +30 -0
  48. data/lib/sqreen/ecosystem/tracing/sampler.rb +160 -0
  49. data/lib/sqreen/ecosystem/tracing/sampling_configuration.rb +150 -0
  50. data/lib/sqreen/ecosystem/tracing/signals/tracing_client.rb +53 -0
  51. data/lib/sqreen/ecosystem/tracing/signals/tracing_consumer.rb +56 -0
  52. data/lib/sqreen/ecosystem/tracing/signals/tracing_producer.rb +56 -0
  53. data/lib/sqreen/ecosystem/tracing/signals/tracing_server.rb +53 -0
  54. data/lib/sqreen/ecosystem/tracing_broker.rb +101 -0
  55. data/lib/sqreen/ecosystem/tracing_id_setup.rb +34 -0
  56. data/lib/sqreen/ecosystem/transaction_storage.rb +64 -0
  57. data/lib/sqreen/ecosystem/util/call_writers_from_init.rb +13 -0
  58. data/lib/sqreen/ecosystem_integration.rb +81 -0
  59. data/lib/sqreen/ecosystem_integration/around_callbacks.rb +89 -0
  60. data/lib/sqreen/ecosystem_integration/instrumentation_service.rb +38 -0
  61. data/lib/sqreen/ecosystem_integration/request_lifecycle_tracking.rb +58 -0
  62. data/lib/sqreen/ecosystem_integration/signal_consumption.rb +35 -0
  63. data/lib/sqreen/events/request_record.rb +0 -1
  64. data/lib/sqreen/frameworks/generic.rb +36 -1
  65. data/lib/sqreen/frameworks/rails.rb +0 -7
  66. data/lib/sqreen/frameworks/request_recorder.rb +2 -0
  67. data/lib/sqreen/graft/call.rb +85 -18
  68. data/lib/sqreen/graft/callback.rb +1 -1
  69. data/lib/sqreen/graft/hook.rb +192 -88
  70. data/lib/sqreen/graft/hook_point.rb +18 -11
  71. data/lib/sqreen/kit/signals/specialized/sqreen_exception.rb +2 -0
  72. data/lib/sqreen/legacy/instrumentation.rb +22 -10
  73. data/lib/sqreen/legacy/old_event_submission_strategy.rb +9 -2
  74. data/lib/sqreen/log.rb +3 -2
  75. data/lib/sqreen/log/loggable.rb +1 -0
  76. data/lib/sqreen/logger.rb +24 -0
  77. data/lib/sqreen/metrics_store.rb +11 -0
  78. data/lib/sqreen/null_logger.rb +22 -0
  79. data/lib/sqreen/remote_command.rb +4 -0
  80. data/lib/sqreen/rules.rb +8 -4
  81. data/lib/sqreen/rules/blacklist_ips_cb.rb +2 -2
  82. data/lib/sqreen/rules/custom_error_cb.rb +3 -3
  83. data/lib/sqreen/rules/rule_cb.rb +2 -0
  84. data/lib/sqreen/rules/waf_cb.rb +3 -3
  85. data/lib/sqreen/runner.rb +47 -7
  86. data/lib/sqreen/session.rb +2 -0
  87. data/lib/sqreen/signals/conversions.rb +6 -1
  88. data/lib/sqreen/version.rb +1 -1
  89. data/lib/sqreen/weave/budget.rb +46 -0
  90. data/lib/sqreen/weave/legacy/instrumentation.rb +252 -109
  91. data/lib/sqreen/worker.rb +6 -2
  92. metadata +60 -11
  93. data/lib/sqreen/encoding_sanitizer.rb +0 -27
@@ -0,0 +1,23 @@
1
+ require 'sqreen/ecosystem/module_api/tracing/client_data'
2
+
3
+ module Sqreen
4
+ module Ecosystem
5
+ module Databases
6
+ class DatabaseConnectionData
7
+ include ModuleApi::Tracing::ClientData
8
+
9
+ # @return [Integer]
10
+ attr_accessor :port
11
+
12
+ # @return [String]
13
+ attr_accessor :unix_socket
14
+
15
+ # @return [String]
16
+ attr_accessor :username
17
+
18
+ # @return [String]
19
+ attr_accessor :db
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,39 @@
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/databases/database_connection_data'
5
+
6
+ module Sqreen
7
+ module Ecosystem
8
+ module Databases
9
+ class Mongo
10
+ include ModuleApi::Instrumentation
11
+ include ModuleApi::MessageProducer
12
+
13
+ def setup
14
+ advice = wrap_for_interest(DatabaseConnectionData, &method(:after_advice))
15
+ instrument 'Mongo::Client#initialize', after: advice
16
+ end
17
+
18
+ private
19
+
20
+ # @param [Sqreen::Graft::CallbackCall] call
21
+ def after_advice(call, _ball)
22
+ return if call.raised
23
+
24
+ client = call.instance
25
+ server_addrs = client.cluster.servers.map(&:address)
26
+
27
+ server_addrs.map do |addr|
28
+ DatabaseConnectionData.new(
29
+ transport: :mongo,
30
+ host: addr.host,
31
+ port: addr.port,
32
+ db: client.database.name,
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,54 @@
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 Databases
10
+ class Mysql
11
+ include ModuleApi::Instrumentation
12
+ include ModuleApi::MessageProducer
13
+
14
+ def setup
15
+ advice = wrap_for_interest(DatabaseConnectionData, &method(:after_advice))
16
+ instrument 'Mysql2::Client#connect', after: advice
17
+ end
18
+
19
+ private
20
+
21
+ # instance is of type +Mysql2::Client+
22
+ # VALUE rb_mysql_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database,
23
+ # VALUE socket, VALUE flags, VALUE conn_attrs) {
24
+ # @param [Sqreen::Graft::CallbackCall]
25
+ def after_advice(call, _ball)
26
+ args = call.args
27
+
28
+ # build & submit signal
29
+ signal = DatabaseConnectionData.new(transport: :mysql)
30
+
31
+ user = args[0]
32
+ host = args[2]
33
+ port = args[3]
34
+ db = args[4]
35
+ socket = args[5]
36
+
37
+ if socket && !socket.empty?
38
+ signal.unix_socket = socket
39
+ signal.host = 'localhost'
40
+ signal.ip = '::1'
41
+ else
42
+ signal.host = host
43
+ end
44
+
45
+ signal.port = port if port != 0
46
+ signal.username = user
47
+ signal.db = db
48
+
49
+ signal
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,51 @@
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/databases/database_connection_data'
5
+
6
+ module Sqreen
7
+ module Ecosystem
8
+ module Databases
9
+ class Postgres
10
+ include ModuleApi::Instrumentation
11
+ include ModuleApi::MessageProducer
12
+
13
+ def setup
14
+ advice = wrap_for_interest(DatabaseConnectionData, &method(:after_advice))
15
+ instrument 'PG::Connection#initialize', after: advice
16
+ end
17
+
18
+ private
19
+
20
+ # instance is of type +PG::Connection+
21
+ # > c = PG::Connection.new(host: '172.17.0.2', password: 'mysecretpassword', user: 'postgres')
22
+ # => #<PG::Connection:0x000055b44d077d10>
23
+ # > %i{host port user db}.map { |m| c.send m }
24
+ # => ["172.17.0.2", 5432, "postgres", "postgres"]
25
+ def after_advice(call, _ball)
26
+ conn = call.instance
27
+
28
+ # build & submit signal
29
+ signal = DatabaseConnectionData.new(transport: :postgres)
30
+
31
+ host = conn.host
32
+ if host
33
+ if host.include?('/')
34
+ signal.unix_socket = host
35
+ signal.host = 'localhost'
36
+ signal.ip = '::1'
37
+ else
38
+ signal.host = host
39
+ end
40
+ end
41
+
42
+ signal.port = conn.port
43
+ signal.username = conn.user
44
+ signal.db = conn.db
45
+
46
+ signal
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,36 @@
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/databases/database_connection_data'
5
+
6
+ module Sqreen
7
+ module Ecosystem
8
+ module Databases
9
+ class Redis
10
+ include ModuleApi::Instrumentation
11
+ include ModuleApi::MessageProducer
12
+
13
+ def setup
14
+ advice = wrap_for_interest(DatabaseConnectionData, &method(:after_advice))
15
+ instrument 'Redis#initialize', after: advice
16
+ end
17
+
18
+ private
19
+
20
+ # @param [Sqreen::Graft::CallbackCall] call
21
+ def after_advice(call, _ball)
22
+ return if call.raised
23
+
24
+ conn = call.instance.connection
25
+
26
+ DatabaseConnectionData.new(
27
+ transport: :redis,
28
+ host: conn[:host],
29
+ port: conn[:port],
30
+ db: conn[:db].to_s,
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
36
+ 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,28 @@
1
+ require 'sqreen/ecosystem/dispatch_table'
2
+ require 'sqreen/ecosystem/loggable'
3
+ require 'sqreen/kit/configuration'
4
+ require 'sqreen/kit/signals/specialized/sqreen_exception'
5
+
6
+ module Sqreen
7
+ module Ecosystem
8
+ module ExceptionReporting
9
+ include Loggable
10
+
11
+ private
12
+
13
+ # @param [String] message
14
+ # @param [Exception] e
15
+ def report_exception(message, e)
16
+ logger.warn { "#{message}: #{e.message}" }
17
+ logger.debug { e.backtrace.map { |x| " #{x}" }.join("\n") }
18
+
19
+ signal = Sqreen::Kit::Signals::Specialized::SqreenException.new(
20
+ ruby_exception: e,
21
+ source: Sqreen::Kit::Configuration.default_source
22
+ )
23
+
24
+ DispatchTable.consume_signal[signal]
25
+ end
26
+ end
27
+ end
28
+ 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,61 @@
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/consumer_data'
5
+ require 'sqreen/ecosystem/module_api/tracing/producer_data'
6
+
7
+ module Sqreen
8
+ module Ecosystem
9
+ module Messaging
10
+ class Bunny
11
+ include ModuleApi::Loggable
12
+ include ModuleApi::Instrumentation
13
+ include ModuleApi::MessageProducer
14
+
15
+ def setup
16
+ advice_send = wrap_for_interest(ModuleApi::Tracing::ProducerData, &method(:after_send_advice))
17
+ advice_receive = wrap_for_interest(ModuleApi::Tracing::ConsumerData, &method(:after_receive_advice))
18
+ advice_receive_consumer = wrap_for_interest(ModuleApi::Tracing::ConsumerData, &method(:after_receive_advice_consumer))
19
+ instrument 'Bunny::Queue#publish', after: advice_send
20
+ instrument 'Bunny::Queue#pop', after: advice_receive
21
+ instrument 'Bunny::Consumer#call', after: advice_receive_consumer
22
+ end
23
+
24
+ private
25
+
26
+ # @param [Sqreen::Graft::CallbackCall] call
27
+ def after_send_advice(call, _ball)
28
+ return if call.raised
29
+
30
+ create_signal(call.instance, ModuleApi::Tracing::ProducerData)
31
+ end
32
+
33
+ # @param [Sqreen::Graft::CallbackCall] call
34
+ def after_receive_advice(call, _ball)
35
+ return if call.raised
36
+
37
+ create_signal(call.instance, ModuleApi::Tracing::ConsumerData)
38
+ end
39
+
40
+ # @param [Sqreen::Graft::CallbackCall] call
41
+ def after_receive_advice_consumer(call, _ball)
42
+ return if call.raised
43
+
44
+ queue = call.instance.queue
45
+ create_signal(queue, ModuleApi::Tracing::ConsumerData)
46
+ end
47
+
48
+ # @param [Bunny::Queue] q
49
+ def create_signal(q, clazz)
50
+ conn = q.channel.connection
51
+
52
+ clazz.new(
53
+ message_type: :amqp,
54
+ host: conn.host,
55
+ topic: q.name,
56
+ )
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end