tcell_agent 2.0.0 → 2.5.0

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +2 -2
  3. data/bin/tcell_agent +41 -150
  4. data/lib/tcell_agent/agent.rb +87 -52
  5. data/lib/tcell_agent/config_initializer.rb +63 -0
  6. data/lib/tcell_agent/configuration.rb +72 -267
  7. data/lib/tcell_agent/hooks/login_fraud.rb +1 -1
  8. data/lib/tcell_agent/instrument_servers.rb +14 -18
  9. data/lib/tcell_agent/instrumentation/cmdi.rb +47 -15
  10. data/lib/tcell_agent/instrumentation/lfi.rb +72 -15
  11. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/file.rb +21 -0
  12. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/io.rb +75 -0
  13. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/kernel.rb +80 -0
  14. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/file.rb +21 -0
  15. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/io.rb +75 -0
  16. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/kernel.rb +80 -0
  17. data/lib/tcell_agent/instrumentation.rb +14 -6
  18. data/lib/tcell_agent/logger.rb +3 -4
  19. data/lib/tcell_agent/policies/command_injection_policy.rb +1 -1
  20. data/lib/tcell_agent/policies/dataloss_policy.rb +15 -8
  21. data/lib/tcell_agent/policies/headers_policy.rb +2 -2
  22. data/lib/tcell_agent/policies/patches_policy.rb +8 -4
  23. data/lib/tcell_agent/policies/policies_manager.rb +1 -0
  24. data/lib/tcell_agent/policies/policy_polling.rb +4 -3
  25. data/lib/tcell_agent/rails/auth/authlogic.rb +49 -44
  26. data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
  27. data/lib/tcell_agent/rails/auth/devise.rb +103 -102
  28. data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
  29. data/lib/tcell_agent/rails/auth/doorkeeper.rb +54 -57
  30. data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
  31. data/lib/tcell_agent/rails/better_ip.rb +7 -19
  32. data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
  33. data/lib/tcell_agent/rails/dlp/process_request.rb +5 -0
  34. data/lib/tcell_agent/rails/dlp.rb +58 -56
  35. data/lib/tcell_agent/rails/dlp_handler.rb +9 -10
  36. data/lib/tcell_agent/rails/js_agent_insert.rb +2 -3
  37. data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -1
  38. data/lib/tcell_agent/rails/middleware/global_middleware.rb +3 -4
  39. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +1 -0
  40. data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
  41. data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
  42. data/lib/tcell_agent/rails/routes/grape.rb +5 -12
  43. data/lib/tcell_agent/rails/routes.rb +6 -9
  44. data/lib/tcell_agent/rails/settings_reporter.rb +3 -6
  45. data/lib/tcell_agent/rails/tcell_body_proxy.rb +4 -7
  46. data/lib/tcell_agent/routes/table.rb +3 -0
  47. data/lib/tcell_agent/rust/agent_config.rb +62 -33
  48. data/lib/tcell_agent/rust/{libtcellagent-4.14.0.so → libtcellagent-alpine.so} +0 -0
  49. data/lib/tcell_agent/rust/{libtcellagent-4.14.0.dylib → libtcellagent-x64.dll} +0 -0
  50. data/lib/tcell_agent/rust/{libtcellagent-alpine-4.14.0.so → libtcellagent.dylib} +0 -0
  51. data/lib/tcell_agent/rust/libtcellagent.so +0 -0
  52. data/lib/tcell_agent/rust/models.rb +9 -0
  53. data/lib/tcell_agent/rust/native_agent.rb +61 -51
  54. data/lib/tcell_agent/rust/native_library.rb +8 -10
  55. data/lib/tcell_agent/sensor_events/server_agent.rb +3 -100
  56. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +1 -0
  57. data/lib/tcell_agent/servers/puma.rb +30 -13
  58. data/lib/tcell_agent/servers/rack_puma_handler.rb +33 -0
  59. data/lib/tcell_agent/servers/rails_server.rb +4 -4
  60. data/lib/tcell_agent/servers/unicorn.rb +1 -1
  61. data/lib/tcell_agent/servers/webrick.rb +12 -3
  62. data/lib/tcell_agent/settings_reporter.rb +0 -93
  63. data/lib/tcell_agent/sinatra.rb +1 -0
  64. data/lib/tcell_agent/tcell_context.rb +16 -7
  65. data/lib/tcell_agent/utils/headers.rb +0 -1
  66. data/lib/tcell_agent/utils/strings.rb +2 -2
  67. data/lib/tcell_agent/version.rb +1 -1
  68. data/lib/tcell_agent.rb +8 -16
  69. data/spec/cruby_spec_helper.rb +26 -0
  70. data/spec/lib/tcell_agent/configuration_spec.rb +62 -212
  71. data/spec/lib/tcell_agent/instrument_servers_spec.rb +95 -0
  72. data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +2 -2
  73. data/spec/lib/tcell_agent/{cmdi_spec.rb → instrumentation/cmdi_spec.rb} +50 -0
  74. data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +211 -272
  75. data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +213 -223
  76. data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +95 -61
  77. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +120 -2
  78. data/spec/lib/tcell_agent/patches_spec.rb +2 -1
  79. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +1 -2
  80. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +5 -6
  81. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +21 -2
  82. data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +1 -1
  83. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +13 -8
  84. data/spec/lib/tcell_agent/rails/better_ip_spec.rb +9 -11
  85. data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +6 -6
  86. data/spec/lib/tcell_agent/rails/dlp_spec.rb +1 -0
  87. data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +10 -2
  88. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +2 -1
  89. data/spec/lib/tcell_agent/rails/routes/route_id_spec.rb +4 -4
  90. data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
  91. data/spec/lib/tcell_agent/settings_reporter_spec.rb +2 -89
  92. data/spec/lib/tcell_agent/tcell_context_spec.rb +6 -5
  93. data/spec/spec_helper.rb +9 -1
  94. data/spec/support/builders.rb +8 -7
  95. data/spec/support/server_mocks/passenger_mock.rb +7 -0
  96. data/spec/support/server_mocks/puma_mock.rb +21 -0
  97. data/spec/support/server_mocks/rails_mock.rb +7 -0
  98. data/spec/support/server_mocks/thin_mock.rb +7 -0
  99. data/spec/support/server_mocks/unicorn_mock.rb +11 -0
  100. data/spec/support/shared_spec.rb +29 -0
  101. data/tcell_agent.gemspec +14 -14
  102. metadata +46 -29
  103. data/Rakefile +0 -18
  104. data/lib/tcell_agent/authlogic.rb +0 -23
  105. data/lib/tcell_agent/config/unknown_options.rb +0 -119
  106. data/lib/tcell_agent/devise.rb +0 -33
  107. data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +0 -25
  108. data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +0 -123
  109. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +0 -159
  110. data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
  111. data/lib/tcell_agent/rust/tcellagent-4.14.0.dll +0 -0
  112. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -195
@@ -1,8 +1,5 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
- require 'tcell_agent/authlogic' if defined?(Authlogic)
4
- require 'tcell_agent/devise' if defined?(Devise)
5
-
6
3
  require 'rails'
7
4
  require 'uri'
8
5
  require 'tcell_agent/agent'
@@ -21,7 +18,6 @@ require 'tcell_agent/rails/settings_reporter'
21
18
 
22
19
  require 'tcell_agent/instrumentation'
23
20
 
24
- require 'tcell_agent/userinfo'
25
21
  require 'cgi'
26
22
  require 'thread'
27
23
 
@@ -84,6 +80,7 @@ module TCellAgent
84
80
  normalized_column_names[namespaced_column_name] = column_name
85
81
 
86
82
  next unless column_name && (!namespace || namespace == table_name)
83
+
87
84
  rules = dlp_policy.get_actions_for_table(
88
85
  database_name,
89
86
  '*',
@@ -194,6 +191,7 @@ module TCellAgent
194
191
  results[0...TCellAgent.configuration.max_data_ex_db_records_per_request].each do |record|
195
192
  column_name_to_rules.each do |column_name, rules|
196
193
  next unless rules
194
+
197
195
  rules.each do |rule|
198
196
  tcell_context.add_response_db_filter(
199
197
  record[column_name.to_sym],
@@ -228,9 +226,15 @@ module TCellAgent
228
226
  )
229
227
  tcell_data = request_env[TCellAgent::Instrumentation::TCELL_ID]
230
228
  if tcell_data && result.is_a?(ActiveRecord::StatementInvalid)
231
- tcell_data.sql_exceptions.push(
232
- { 'exception_name' => result.class.name, 'exception_payload' => message }
233
- )
229
+ if message.is_a? Hash
230
+ tcell_data.sql_exceptions.push(
231
+ { 'exception_name' => result.class.name, 'exception_payload' => message[:message] }
232
+ )
233
+ else
234
+ tcell_data.sql_exceptions.push(
235
+ { 'exception_name' => result.class.name, 'exception_payload' => message }
236
+ )
237
+ end
234
238
  end
235
239
  end
236
240
  end
@@ -253,7 +257,7 @@ module TCellAgent
253
257
  end
254
258
 
255
259
  ActiveRecord::Querying.module_eval do
256
- if ::Rails::VERSION::MAJOR == 5
260
+ if ::Rails::VERSION::MAJOR >= 5
257
261
  alias_method :tcell_find_by_sql, :find_by_sql
258
262
  def find_by_sql(*args)
259
263
  results = tcell_find_by_sql(*args)
@@ -299,31 +303,29 @@ module TCellAgent
299
303
  def log_enforce(tcell_context, sanitize_string)
300
304
  if TCellAgent.configuration.should_instrument? &&
301
305
  TCellAgent.configuration.should_intercept_requests?
302
- if tcell_context && tcell_context.session_id
303
- session_id_actions = get_actions_for_session_id
304
- if session_id_actions
305
- send_event = false
306
- sanitize_string.gsub!(tcell_context.session_id) do |m|
307
- if session_id_actions.log_redact
308
- send_event = true
309
- m = '[session_id]'
310
- elsif session_id_actions.log_hash
311
- send_event = true
312
- m = '[hash]'
313
- elsif session_id_actions.log_event
314
- send_event = true
315
- end
316
- m
317
- end
318
- if send_event
319
- TCellAgent.send_event(
320
- TCellAgent::SensorEvents::DlpEvent.new(
321
- tcell_context.route_id,
322
- tcell_context.uri,
323
- TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG
324
- ).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
325
- )
306
+ session_id_actions = get_actions_for_session_id
307
+ if tcell_context && tcell_context.session_id && session_id_actions
308
+ send_event = false
309
+ sanitize_string.gsub!(tcell_context.session_id) do |m|
310
+ if session_id_actions.log_redact
311
+ send_event = true
312
+ m = '[session_id]'
313
+ elsif session_id_actions.log_hash
314
+ send_event = true
315
+ m = '[hash]'
316
+ elsif session_id_actions.log_event
317
+ send_event = true
326
318
  end
319
+ m
320
+ end
321
+ if send_event
322
+ TCellAgent.send_event(
323
+ TCellAgent::SensorEvents::DlpEvent.new(
324
+ tcell_context.route_id,
325
+ tcell_context.uri,
326
+ TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG
327
+ ).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
328
+ )
327
329
  end
328
330
  end
329
331
  end
@@ -334,32 +336,32 @@ module TCellAgent
334
336
  def response_body_enforce(tcell_context, sanitize_string)
335
337
  if TCellAgent.configuration.should_instrument? &&
336
338
  TCellAgent.configuration.should_intercept_requests?
337
- if tcell_context && tcell_context.session_id
338
- session_id_actions = get_actions_for_session_id
339
- if session_id_actions
340
- send_event = false
341
- sanitize_string.gsub!(tcell_context.session_id) do |m|
342
- if session_id_actions.body_redact
343
- # m = "[session_id]"
344
- send_event = true
345
- elsif session_id_actions.body_hash
346
- # m = "[hash]"
347
- send_event = true
348
- elsif session_id_actions.body_event
349
- send_event = true
350
- end
351
- m
339
+ session_id_actions = get_actions_for_session_id
340
+ if tcell_context && tcell_context.session_id && session_id_actions
341
+ send_event = false
342
+ sanitize_string.gsub!(tcell_context.session_id) do |m|
343
+ # rubocop:disable Lint/DuplicateBranch
344
+ if session_id_actions.body_redact
345
+ # m = "[session_id]"
346
+ send_event = true
347
+ elsif session_id_actions.body_hash
348
+ # m = "[hash]"
349
+ send_event = true
350
+ elsif session_id_actions.body_event
351
+ send_event = true
352
352
  end
353
+ # rubocop:enable Lint/DuplicateBranch
354
+ m
353
355
  end
354
- if send_event
355
- TCellAgent.send_event(
356
- TCellAgent::SensorEvents::DlpEvent.new(
357
- tcell_context.route_id,
358
- tcell_context.uri,
359
- TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY
360
- ).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
361
- )
362
- end
356
+ end
357
+ if send_event
358
+ TCellAgent.send_event(
359
+ TCellAgent::SensorEvents::DlpEvent.new(
360
+ tcell_context.route_id,
361
+ tcell_context.uri,
362
+ TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY
363
+ ).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
364
+ )
363
365
  end
364
366
  end
365
367
 
@@ -39,19 +39,18 @@ module TCellAgent
39
39
 
40
40
  TCellAgent::Instrumentation.safe_block('DLP Handler get handler and context') do
41
41
  if TCellAgent.configuration.should_instrument? &&
42
- TCellAgent.configuration.should_intercept_requests?
42
+ TCellAgent.configuration.should_intercept_requests? &&
43
+ TCellAgent::Utils::Rails.processable_response?(response_headers)
43
44
 
44
45
  # do all this work so that dlp doesn't run at all unless it's on and there
45
46
  # are rules to run
46
- if TCellAgent::Utils::Rails.processable_response?(response_headers)
47
- dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DATALOSS)
48
- if dlp_policy && dlp_policy.get_actions_for_session_id
49
- tcell_context = request.env[TCellAgent::Instrumentation::TCELL_ID]
50
- if tcell_context && tcell_context.session_id
51
- dlp_handler = proc { |tc, resp|
52
- handle_dlp!(tc, resp)
53
- }
54
- end
47
+ dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DATALOSS)
48
+ if dlp_policy && dlp_policy.get_actions_for_session_id
49
+ tcell_context = request.env[TCellAgent::Instrumentation::TCELL_ID]
50
+ if tcell_context && tcell_context.session_id
51
+ dlp_handler = proc { |tc, resp|
52
+ handle_dlp!(tc, resp)
53
+ }
55
54
  end
56
55
  end
57
56
  end
@@ -4,8 +4,7 @@ module TCellAgent
4
4
  module Instrumentation
5
5
  module Rails
6
6
  module JSAgent
7
- HEAD_SEARCH_REGEX = /<head>/
8
-
7
+ HEAD_SEARCH_REGEX = Regexp.new('(<head>|<head( |\n).*?>)', Regexp::IGNORECASE)
9
8
  def self.insert_now(js_agent_handler, script_insert, rack_body, content_length)
10
9
  TCellAgent::Instrumentation.safe_block('Handling JSAgent Insert Now') do
11
10
  if js_agent_handler
@@ -32,7 +31,7 @@ module TCellAgent
32
31
  TCellAgent::Instrumentation.safe_block('Handling JSAgent insert') do
33
32
  new_response = response.sub(
34
33
  TCellAgent::Instrumentation::Rails::JSAgent::HEAD_SEARCH_REGEX,
35
- "<head>#{script_insert}"
34
+ "\\1#{script_insert}"
36
35
  )
37
36
  end
38
37
 
@@ -26,7 +26,8 @@ module TCellAgent
26
26
  env[TCellAgent::Instrumentation::TCELL_ID].path = request.path
27
27
  env[TCellAgent::Instrumentation::TCELL_ID].user_agent = request.user_agent
28
28
  env[TCellAgent::Instrumentation::TCELL_ID].referrer = request.referrer
29
- env[TCellAgent::Instrumentation::TCELL_ID].remote_address = TCellAgent::Utils::Rails.better_ip(request)
29
+ env[TCellAgent::Instrumentation::TCELL_ID].remote_address = request.ip
30
+ env[TCellAgent::Instrumentation::TCELL_ID].reverse_proxy_header_value = TCellAgent::Utils::Rails.reverse_proxy_header(request)
30
31
  if request.request_method
31
32
  env[TCellAgent::Instrumentation::TCELL_ID].request_method = request.request_method
32
33
  end
@@ -7,7 +7,7 @@ require 'tcell_agent/sensor_events/sensor'
7
7
  require 'tcell_agent/sensor_events/server_agent'
8
8
  require 'tcell_agent/sensor_events/util/sanitizer_utilities'
9
9
 
10
- require 'tcell_agent/userinfo'
10
+ require 'tcell_agent/rails/auth/userinfo'
11
11
  require 'cgi'
12
12
 
13
13
  require 'tcell_agent/instrumentation'
@@ -24,6 +24,7 @@ module TCellAgent
24
24
  def call(env)
25
25
  if TCellAgent.configuration.should_intercept_requests?
26
26
  request = Rack::Request.new(env)
27
+
27
28
  TCellAgent::Instrumentation.safe_block('Setting session_id & user_id') do
28
29
  if request.session
29
30
  env[TCellAgent::Instrumentation::TCELL_ID].session_id =
@@ -41,9 +42,7 @@ module TCellAgent
41
42
  end
42
43
  end
43
44
 
44
- response = @app.call(env)
45
-
46
- response
45
+ @app.call(env)
47
46
  end
48
47
  end
49
48
  end
@@ -39,6 +39,7 @@ module TCellAgent
39
39
  TCellAgent::Instrumentation.safe_block('Handling headers') do
40
40
  headers_policy = TCellAgent.policy(TCellAgent::PolicyTypes::HEADERS)
41
41
  policy_headers = headers_policy.get_headers(
42
+ headers['Content-Type'],
42
43
  request.env[TCellAgent::Instrumentation::TCELL_ID]
43
44
  )
44
45
  policy_headers.each do |header_info|
@@ -2,36 +2,21 @@
2
2
 
3
3
  require 'rails'
4
4
 
5
- require 'tcell_agent/rails/routes'
6
-
7
5
  require 'tcell_agent/rails/middleware/global_middleware'
8
6
  require 'tcell_agent/rails/middleware/body_filter_middleware'
9
7
  require 'tcell_agent/rails/middleware/headers_middleware'
10
8
  require 'tcell_agent/rails/middleware/context_middleware'
11
9
 
10
+ require 'tcell_agent/rails/routes'
12
11
  require 'tcell_agent/rails/settings_reporter'
13
12
  require 'tcell_agent/rails/dlp'
14
13
  require 'tcell_agent/rails/csrf_exception'
15
14
 
16
- require 'tcell_agent/userinfo'
17
15
  require 'cgi'
18
16
  require 'thread'
19
17
 
20
18
  module TCellAgent
21
19
  class TCellAgentStartupRailtie < Rails::Railtie
22
- # TCellAgent config can be specified thru
23
- # Rails initializer's (https://guides.rubyonrails.org/v2.3/configuring.html#using-initializers)
24
- # so those need to run first since this relies on configuration
25
- initializer :tcell_instrument_auth_frameworks, :after => :load_config_initializers do |_app|
26
- next unless TCellAgent.configuration.should_instrument?
27
-
28
- require 'tcell_agent/devise'
29
- require 'tcell_agent/rails/auth/devise'
30
- require 'tcell_agent/authlogic'
31
- require 'tcell_agent/rails/auth/authlogic'
32
- require 'tcell_agent/rails/auth/doorkeeper'
33
- end
34
-
35
20
  initializer :tcell_insert_middleware, :before => :build_middleware_stack do |app|
36
21
  app.config.middleware.insert_before(0, TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware)
37
22
  app.config.middleware.insert_after(0, TCellAgent::Instrumentation::Rails::Middleware::HeadersMiddleware)
@@ -39,4 +24,12 @@ module TCellAgent
39
24
  app.config.middleware.use TCellAgent::Instrumentation::Rails::Middleware::GlobalMiddleware
40
25
  end
41
26
  end
27
+
28
+ class TCellAgentCSRFRailtie < Rails::Railtie
29
+ initializer 'tcell.sensors' do |_app|
30
+ ActiveSupport.on_load :action_controller do
31
+ ActionController::Base.send(:include, TCellAgent::CsrfExceptionReporter)
32
+ end
33
+ end
34
+ end
42
35
  end
@@ -0,0 +1,8 @@
1
+ module TCellAgent
2
+ class TCellAgentStartupRailtie < Rails::Railtie
3
+ initializer :start_tcell_agent,
4
+ :after => :load_config_initializers do |_app|
5
+ TCellAgent.thread_agent.start('Unicorn')
6
+ end
7
+ end
8
+ end
@@ -5,16 +5,11 @@ module TCellAgent
5
5
  def self.grape_route?(route)
6
6
  if defined?(Grape::API)
7
7
  begin
8
- if ::Rails::VERSION::MAJOR == 4 && ::Rails::VERSION::MINOR < 2
9
- # does app inherit from Grape::API?
10
- route.app < Grape::API
11
- else
12
- # does app inherit from Grape::API?
13
- route.app.app < Grape::API
14
- end
8
+ return route.app < Grape::API if ::Rails::VERSION::MAJOR == 4 &&
9
+ ::Rails::VERSION::MINOR < 2
15
10
 
16
- return true
17
- rescue StandardError # rubocop:disable Lint/HandleExceptions
11
+ return route.app.app < Grape::API
12
+ rescue StandardError
18
13
  # do nothing
19
14
  end
20
15
  end
@@ -76,9 +71,7 @@ module TCellAgent
76
71
  Grape::Endpoint.class_eval do
77
72
  alias_method :tcell_call!, :call!
78
73
  def call!(env)
79
- if TCellAgent.configuration.should_instrument? &&
80
- TCellAgent.configuration.should_intercept_requests?
81
-
74
+ if TCellAgent.configuration.should_intercept_requests?
82
75
  TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
83
76
  tcell_context = env[TCellAgent::Instrumentation::TCELL_ID]
84
77
  if tcell_context && tcell_context.grape_mount_endpoint && respond_to?(:routes)
@@ -77,7 +77,7 @@ module TCellAgent
77
77
  end
78
78
 
79
79
  def self.create_tcell_route(route)
80
- return TCellRoute5.new(route) if route && ::Rails::VERSION::MAJOR == 5
80
+ return TCellRoute5.new(route) if route && ::Rails::VERSION::MAJOR >= 5
81
81
  return TCellRoute4.new(route) if route && ::Rails::VERSION::MAJOR < 5
82
82
 
83
83
  TCellRoute.new
@@ -136,8 +136,7 @@ module TCellAgent
136
136
  prepend_around_filter :tcell_around_filter_routes
137
137
  end
138
138
  def tcell_around_filter_routes
139
- if TCellAgent.configuration.should_instrument? &&
140
- TCellAgent.configuration.should_intercept_requests?
139
+ if TCellAgent.configuration.should_intercept_requests?
141
140
  TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
142
141
  _match, parameters, route = ::Rails.application.routes.router.recognize(request) { |r, _| r }.first
143
142
 
@@ -173,7 +172,7 @@ module TCellAgent
173
172
  end
174
173
  end
175
174
 
176
- if ::Rails::VERSION::MAJOR == 5
175
+ if ::Rails::VERSION::MAJOR >= 5
177
176
  ActionDispatch::Journey::Routes.class_eval do
178
177
  alias_method :tcell_add_route, :add_route
179
178
  def add_route(name, mapping)
@@ -188,12 +187,11 @@ module TCellAgent
188
187
  end
189
188
  end
190
189
 
191
- if ::Rails::VERSION::MAJOR == 5 || (::Rails::VERSION::MAJOR == 4 && ::Rails::VERSION::MINOR >= 2)
190
+ if ::Rails::VERSION::MAJOR >= 5 || (::Rails::VERSION::MAJOR == 4 && ::Rails::VERSION::MINOR >= 2)
192
191
  ActionDispatch::Journey::Router.class_eval do
193
192
  alias_method :tcell_serve, :serve
194
193
  def serve(req)
195
- if TCellAgent.configuration.should_instrument? &&
196
- TCellAgent.configuration.should_intercept_requests?
194
+ if TCellAgent.configuration.should_intercept_requests?
197
195
  TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
198
196
  _match, parameters, route = find_routes(req).first
199
197
 
@@ -220,8 +218,7 @@ module TCellAgent
220
218
  def call(env)
221
219
  env['PATH_INFO'] = ActionDispatch::Journey::Router::Utils.normalize_path(env['PATH_INFO'])
222
220
 
223
- if TCellAgent.configuration.should_instrument? &&
224
- TCellAgent.configuration.should_intercept_requests?
221
+ if TCellAgent.configuration.should_intercept_requests?
225
222
  TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
226
223
  _match, parameters, route = find_routes(env).first
227
224
 
@@ -6,12 +6,9 @@ require 'tcell_agent/sensor_events/server_agent'
6
6
  module TCellAgent
7
7
  module Instrumentation
8
8
  module Rails
9
- def self.send_framework_info
10
- TCellAgent.send_event(
11
- TCellAgent::SensorEvents::ServerAgentAppFrameworkEvent.new(
12
- 'Rails', ::Rails.version
13
- )
14
- )
9
+ def self.framework_details
10
+ { 'app_framework' => 'Rails',
11
+ 'app_framework_version' => ::Rails.version }
15
12
  end
16
13
 
17
14
  def self.send_settings
@@ -31,7 +31,6 @@ module TCellAgent
31
31
  TCellAgent::Instrumentation.safe_block('Running AppSensor deferred due to streaming') do
32
32
  if @meta_data
33
33
  @meta_data.response_content_bytes_len = @content_length
34
-
35
34
  appfirewall_policy = TCellAgent.policy(TCellAgent::PolicyTypes::APPSENSOR)
36
35
  appfirewall_policy.check_appfirewall_injections(@meta_data)
37
36
  end
@@ -54,18 +53,16 @@ module TCellAgent
54
53
  @body.respond_to?(method_name, include_all)
55
54
  end
56
55
 
57
- def method_missing(method_name, *args, &block) # rubocop:disable Style/MethodMissing
56
+ def method_missing(method_name, *args, &block)
58
57
  @body.__send__(method_name, *args, &block)
59
58
  end
60
59
 
61
60
  def process_body(body)
62
61
  TCellAgent::Instrumentation.safe_block('Processing tcell body proxy body') do
63
62
  chunked_response_match = nil
64
- if body.class.name == 'String'
65
- if body =~ /^([[:xdigit:]]+)(;.+)?\r\n/
66
- chunked_response_match = Regexp.last_match(1)
67
- @content_length += chunked_response_match.to_i(16)
68
- end
63
+ if body.class.name == 'String' && body =~ /^([[:xdigit:]]+)(;.+)?\r\n/
64
+ chunked_response_match = Regexp.last_match(1)
65
+ @content_length += chunked_response_match.to_i(16)
69
66
  end
70
67
 
71
68
  new_body = body
@@ -2,6 +2,7 @@ module TCellAgent
2
2
  module Routes
3
3
  class FieldEndpoint
4
4
  attr_accessor :discovered
5
+
5
6
  def initialize
6
7
  super()
7
8
  @discovered = false
@@ -11,6 +12,7 @@ module TCellAgent
11
12
  class RouteEndpoint
12
13
  attr_accessor :database
13
14
  attr_accessor :database_queries_discovered
15
+
14
16
  def initialize
15
17
  @database_queries_discovered = {}
16
18
  @database = Hash.new do |d_h, d_k| # Database
@@ -27,6 +29,7 @@ module TCellAgent
27
29
 
28
30
  class RouteTable
29
31
  attr_accessor :routes
32
+
30
33
  def initialize
31
34
  @routes = Hash.new { |h, k| h[k] = RouteEndpoint.new }
32
35
  end
@@ -1,48 +1,77 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tcell_agent/version'
4
+ require 'tcell_agent/rust/models'
2
5
 
3
6
  module TCellAgent
4
7
  module Rust
5
8
  class AgentConfig < Hash
6
9
  def initialize(configuration)
7
- send_mode = 'Normal'
8
- send_mode = 'Demo' if configuration.demomode
9
-
10
- logging_options = configuration.clean_logging_options
11
- unless configuration.js_agent_api_base_url
12
- parsed_uri = URI.parse(configuration.tcell_api_url)
13
- api_url = [parsed_uri.scheme, '://', parsed_uri.host]
14
- api_url.push(":#{parsed_uri.port}") unless [80, 443].include?(parsed_uri.port)
15
- configuration.js_agent_api_base_url = "#{api_url.join('')}/api/v1"
16
- end
17
-
18
- self['disable_event_sending'] = !configuration.should_start_event_manager?
19
- self['send_mode'] = send_mode
20
10
  self['agent_type'] = 'Ruby'
21
11
  self['agent_version'] = TCellAgent::VERSION
22
- self['diagnostics_enabled'] = false
23
- self['application'] = {
12
+ self['default_cache_dir'] = File.join(Dir.getwd, 'tcell/cache')
13
+ self['default_config_file_dir'] = File.join(Dir.getwd, 'config')
14
+ self['default_log_dir'] = File.join(Dir.getwd, 'tcell/logs')
15
+ self['default_preload_policy_file_dir'] = Dir.getwd
16
+
17
+ if defined?(ConfigInitializer)
18
+ overrides = Models.clean_nils(AgentConfigOverrides.new(configuration))
19
+ self['overrides'] = overrides
20
+ else
21
+ self['overrides'] = { 'applications' => [{ :enable_json_body_inspection => true }],
22
+ 'config_file_path' => configuration.get_config_file_path }
23
+ end
24
+
25
+ set_agent_details
26
+ end
27
+
28
+ def set_agent_details
29
+ framework_details = if defined?(Rails)
30
+ TCellAgent::Instrumentation::Rails.framework_details
31
+ else
32
+ {}
33
+ end
34
+
35
+ self['agent_details'] = { 'language' => 'Ruby',
36
+ 'language_version' => RUBY_VERSION,
37
+ 'app_framework' => framework_details['app_framework'],
38
+ 'app_framework_version' => framework_details['app_framework_version'] }
39
+ end
40
+ end
41
+
42
+ class AgentConfigOverrides < Hash
43
+ def initialize(configuration)
44
+ applications = {
45
+ :allow_payloads => configuration.allow_payloads,
46
+ :api_key => configuration.api_key,
24
47
  :app_id => configuration.app_id,
25
- :api_key => configuration.api_key,
26
- :tcell_api_url => configuration.tcell_api_url,
27
- :tcell_input_url => configuration.tcell_input_url,
48
+ :enable_json_body_inspection => true,
28
49
  :hmac_key => configuration.hmac_key,
50
+ :max_header_size => configuration.max_csp_header_bytes,
29
51
  :password_hmac_key => configuration.password_hmac_key,
30
- :allow_payloads => configuration.allow_payloads,
31
- :js_agent_api_base_url => configuration.js_agent_api_base_url,
32
- :js_agent_url => configuration.js_agent_url,
33
- :cache_dir => configuration.cache_folder,
34
- :log_dir => configuration.agent_log_dir,
35
- :logging_options => logging_options,
36
- :host_identifier => configuration.host_identifier,
37
- :reverse_proxy_ip_address_header => configuration.reverse_proxy_ip_address_header,
38
- :fetch_policies_from_tcell => configuration.should_start_policy_poll?,
39
- :preload_policy_filename => configuration.preload_policy_filename
52
+ :reverse_proxy => configuration.reverse_proxy,
53
+ :reverse_proxy_ip_address_header => configuration.reverse_proxy_ip_address_header
40
54
  }
41
- self['appfirewall'] = {
42
- :enable_body_json_inspection => true,
43
- :allow_log_payloads => true
44
- }
45
- self['max_header_size'] = configuration.max_csp_header_bytes || (1024 * 1024)
55
+
56
+ self['api_url'] = configuration.tcell_api_url
57
+ self['applications'] = [Models.clean_nils(applications)]
58
+ self['config_file_path'] = configuration.get_config_file_path
59
+ self['disabled_instrumentation'] = configuration.disabled_instrumentation
60
+ self['enabled'] = configuration.enabled
61
+ self['host_identifier'] = configuration.host_identifier
62
+ self['input_url'] = configuration.tcell_input_url
63
+ self['instrument'] = configuration.instrument
64
+ self['js_agent_api_url'] = configuration.js_agent_api_base_url
65
+ self['js_agent_url'] = configuration.js_agent_url
66
+ self['log_destination'] = configuration.logging_options[:destination]
67
+ self['log_dir'] = configuration.log_dir
68
+ self['log_enabled'] = configuration.logging_options[:enabled]
69
+ self['log_filename'] = configuration.logging_options[:log_filename]
70
+ self['log_level'] = configuration.logging_options[:level]
71
+ self['proxy_url'] = configuration.proxy_url
72
+ self['proxy_username'] = configuration.proxy_username
73
+ self['proxy_password'] = configuration.proxy_password
74
+ self['update_policy'] = configuration.fetch_policies_from_tcell
46
75
  end
47
76
  end
48
77
  end
@@ -13,6 +13,15 @@ module TCellAgent
13
13
 
14
14
  flattened_params
15
15
  end
16
+
17
+ def self.clean_nils(hash)
18
+ if hash.respond_to?(:compact!)
19
+ hash.compact!
20
+ else
21
+ hash.delete_if { |_, v| v.nil? }
22
+ end
23
+ hash
24
+ end
16
25
  end
17
26
  end
18
27
  end