tcell_agent 2.0.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
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