tcell_agent 2.3.0 → 2.5.1

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +2 -2
  3. data/bin/tcell_agent +6 -11
  4. data/lib/tcell_agent/agent.rb +18 -13
  5. data/lib/tcell_agent/config_initializer.rb +2 -5
  6. data/lib/tcell_agent/configuration.rb +4 -4
  7. data/lib/tcell_agent/hooks/login_fraud.rb +1 -1
  8. data/lib/tcell_agent/instrumentation/cmdi.rb +32 -0
  9. data/lib/tcell_agent/instrumentation/lfi.rb +55 -9
  10. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/file.rb +21 -0
  11. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/io.rb +75 -0
  12. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/kernel.rb +80 -0
  13. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/file.rb +21 -0
  14. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/io.rb +75 -0
  15. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/kernel.rb +80 -0
  16. data/lib/tcell_agent/instrumentation.rb +14 -6
  17. data/lib/tcell_agent/logger.rb +2 -2
  18. data/lib/tcell_agent/policies/dataloss_policy.rb +15 -8
  19. data/lib/tcell_agent/policies/headers_policy.rb +2 -2
  20. data/lib/tcell_agent/policies/patches_policy.rb +8 -4
  21. data/lib/tcell_agent/policies/policies_manager.rb +1 -0
  22. data/lib/tcell_agent/policies/policy_polling.rb +4 -3
  23. data/lib/tcell_agent/rails/auth/doorkeeper.rb +1 -0
  24. data/lib/tcell_agent/rails/better_ip.rb +7 -19
  25. data/lib/tcell_agent/rails/dlp/process_request.rb +5 -0
  26. data/lib/tcell_agent/rails/dlp.rb +48 -48
  27. data/lib/tcell_agent/rails/dlp_handler.rb +9 -10
  28. data/lib/tcell_agent/rails/js_agent_insert.rb +2 -3
  29. data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -1
  30. data/lib/tcell_agent/rails/middleware/global_middleware.rb +1 -5
  31. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +1 -0
  32. data/lib/tcell_agent/rails/routes/grape.rb +2 -1
  33. data/lib/tcell_agent/rails/settings_reporter.rb +3 -6
  34. data/lib/tcell_agent/rails/tcell_body_proxy.rb +4 -6
  35. data/lib/tcell_agent/routes/table.rb +3 -0
  36. data/lib/tcell_agent/rust/agent_config.rb +18 -0
  37. data/lib/tcell_agent/rust/{libtcellagent-alpine-6.2.1.so → libtcellagent-alpine.so} +0 -0
  38. data/lib/tcell_agent/rust/{tcellagent-6.2.1.dll → libtcellagent-x64.dll} +0 -0
  39. data/lib/tcell_agent/rust/{libtcellagent-6.2.1.dylib → libtcellagent.dylib} +0 -0
  40. data/lib/tcell_agent/rust/{libtcellagent-6.2.1.so → libtcellagent.so} +0 -0
  41. data/lib/tcell_agent/rust/native_agent.rb +51 -59
  42. data/lib/tcell_agent/rust/native_library.rb +7 -10
  43. data/lib/tcell_agent/sensor_events/server_agent.rb +3 -100
  44. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +1 -0
  45. data/lib/tcell_agent/servers/puma.rb +25 -8
  46. data/lib/tcell_agent/servers/rack_puma_handler.rb +13 -3
  47. data/lib/tcell_agent/servers/webrick.rb +14 -4
  48. data/lib/tcell_agent/settings_reporter.rb +0 -14
  49. data/lib/tcell_agent/sinatra.rb +1 -0
  50. data/lib/tcell_agent/tcell_context.rb +15 -6
  51. data/lib/tcell_agent/utils/headers.rb +0 -1
  52. data/lib/tcell_agent/utils/strings.rb +2 -2
  53. data/lib/tcell_agent/version.rb +1 -1
  54. data/spec/cruby_spec_helper.rb +26 -0
  55. data/spec/lib/tcell_agent/instrument_servers_spec.rb +42 -7
  56. data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +2 -2
  57. data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +211 -272
  58. data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +207 -223
  59. data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +89 -70
  60. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +73 -0
  61. data/spec/lib/tcell_agent/patches_spec.rb +2 -1
  62. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +1 -2
  63. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +5 -6
  64. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +21 -2
  65. data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +1 -1
  66. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +13 -8
  67. data/spec/lib/tcell_agent/rails/better_ip_spec.rb +9 -11
  68. data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +6 -6
  69. data/spec/lib/tcell_agent/rails/dlp_spec.rb +1 -0
  70. data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +10 -2
  71. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +2 -1
  72. data/spec/lib/tcell_agent/rails/routes/route_id_spec.rb +4 -4
  73. data/spec/lib/tcell_agent/settings_reporter_spec.rb +2 -16
  74. data/spec/lib/tcell_agent/tcell_context_spec.rb +6 -5
  75. data/spec/spec_helper.rb +3 -1
  76. data/spec/support/builders.rb +2 -1
  77. data/spec/support/server_mocks/{puma_mock.rb → puma_mock_1.rb} +5 -1
  78. data/spec/support/server_mocks/puma_mock_2.rb +26 -0
  79. data/spec/support/server_mocks/puma_mock_3.rb +22 -0
  80. data/spec/support/shared_spec.rb +29 -0
  81. data/tcell_agent.gemspec +14 -14
  82. metadata +29 -21
  83. data/Rakefile +0 -18
  84. data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +0 -25
  85. data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +0 -131
  86. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +0 -102
@@ -9,55 +9,6 @@ require 'tcell_agent/utils/headers'
9
9
  module TCellAgent
10
10
  module Rust
11
11
  class NativeAgent # rubocop:disable Metrics/ClassLength
12
- def self.test_event_sender(events)
13
- config = TCellAgent.configuration
14
- event_sender = {
15
- :uuid => config.uuid,
16
- :hostname => config.host_identifier,
17
- :agent_type => 'Ruby',
18
- :agent_version => TCellAgent::VERSION,
19
- :app_id => config.app_id,
20
- :api_key => config.api_key,
21
- :tcell_input_url => config.tcell_input_url,
22
- :events => events
23
- }
24
- event_sender_pointer = FFI::MemoryPointer.from_string(
25
- JSON.dump(event_sender)
26
- )
27
-
28
- buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
29
- # config_pointer.size - 1: strips null terminator
30
- result_size = TCellAgent::Rust::NativeLibrary.test_event_sender(
31
- event_sender_pointer, event_sender_pointer.size - 1, buf, buf.size
32
- )
33
-
34
- response = NativeAgentResponse.new('test_event_sender', buf, result_size)
35
-
36
- response.errors
37
- end
38
-
39
- def self.test_policies
40
- config = TCellAgent.configuration
41
- policies_info = {
42
- :app_id => config.app_id,
43
- :api_key => config.api_key,
44
- :tcell_api_url => config.tcell_api_url
45
- }
46
- policies_info_pointer = FFI::MemoryPointer.from_string(
47
- JSON.dump(policies_info)
48
- )
49
-
50
- buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
51
- # config_pointer.size - 1: strips null terminator
52
- result_size = TCellAgent::Rust::NativeLibrary.test_policies(
53
- policies_info_pointer, policies_info_pointer.size - 1, buf, buf.size
54
- )
55
-
56
- response = NativeAgentResponse.new('test_event_sender', buf, result_size)
57
-
58
- response.errors
59
- end
60
-
61
12
  def self.test_agent(config)
62
13
  agent_config = TCellAgent::Rust::AgentConfig.new(config)
63
14
 
@@ -133,6 +84,7 @@ module TCellAgent
133
84
  :headers => header_params,
134
85
  :cookies => cookie_params,
135
86
  :path_params => path_params,
87
+ :reverse_proxy_header_value => appsensor_meta.reverse_proxy_header_value,
136
88
  :remote_address => appsensor_meta.remote_address,
137
89
  :full_uri => appsensor_meta.location,
138
90
  :session_id => appsensor_meta.session_id,
@@ -143,7 +95,6 @@ module TCellAgent
143
95
  :content_type => appsensor_meta.content_type,
144
96
  :request_body => appsensor_meta.raw_request_body
145
97
  }
146
-
147
98
  request_response_json[:sql_exceptions] = appsensor_meta.sql_exceptions if appsensor_meta.sql_exceptions
148
99
  request_response_json[:database_result_sizes] = appsensor_meta.database_result_sizes if appsensor_meta.database_result_sizes
149
100
 
@@ -184,13 +135,15 @@ module TCellAgent
184
135
  :method => appsensor_meta.method,
185
136
  :path => appsensor_meta.path,
186
137
  :remote_address => appsensor_meta.remote_address,
138
+ :reverse_proxy_header_value => appsensor_meta.reverse_proxy_header_value,
187
139
  :request_bytes_length => appsensor_meta.request_content_bytes_len,
188
140
  :query_params => query_params,
189
- :post_params => post_params,
141
+ :post_params => post_params,
190
142
  :headers => header_params,
191
143
  :cookies => cookie_params,
192
144
  :content_type => appsensor_meta.content_type,
193
- :full_uri => appsensor_meta.location
145
+ :full_uri => appsensor_meta.location,
146
+ :request_body => appsensor_meta.raw_request_body
194
147
  }
195
148
 
196
149
  patches_request_pointer = FFI::MemoryPointer.from_string(
@@ -213,6 +166,37 @@ module TCellAgent
213
166
  response.response
214
167
  end
215
168
 
169
+ def apply_suspicious_quick_check(appsensor_meta)
170
+ return {} unless appsensor_meta
171
+
172
+ sus_quick_check_request_json = {
173
+ :reverse_proxy_header_value => appsensor_meta.reverse_proxy_header_value,
174
+ :method => appsensor_meta.method,
175
+ :path => appsensor_meta.path,
176
+ :full_uri => appsensor_meta.location,
177
+ :request_bytes_length => appsensor_meta.request_content_bytes_len
178
+ }
179
+
180
+ if appsensor_meta.reverse_proxy_header_value.nil?
181
+ sus_quick_check_request_json.merge(
182
+ {
183
+ :client_ip_override => appsensor_meta.remote_address
184
+ }
185
+ )
186
+ end
187
+
188
+ sus_quick_check_request_ptr = FFI::MemoryPointer.from_string(
189
+ JSON.dump(sus_quick_check_request_json)
190
+ )
191
+
192
+ # sus_quick_check_request_ptr.size - 1: strips null terminator
193
+ TCellAgent::Rust::NativeLibrary.suspicious_quick_check_apply(
194
+ FFI::Pointer.new(@agent_ptr),
195
+ sus_quick_check_request_ptr,
196
+ sus_quick_check_request_ptr.size - 1
197
+ )
198
+ end
199
+
216
200
  def apply_cmdi(command, tcell_context)
217
201
  return unless TCellAgent::Utils::Strings.present?(command)
218
202
 
@@ -220,6 +204,7 @@ module TCellAgent
220
204
  :command => command,
221
205
  :method => tcell_context.request_method,
222
206
  :path => tcell_context.path,
207
+ :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
223
208
  :remote_address => tcell_context.remote_address,
224
209
  :route_id => tcell_context.route_id,
225
210
  :session_id => tcell_context.session_id,
@@ -247,10 +232,11 @@ module TCellAgent
247
232
  response.response
248
233
  end
249
234
 
250
- def get_headers(tcell_context)
235
+ def get_headers(content_type, tcell_context)
251
236
  return unless tcell_context
252
237
 
253
238
  headers_request = {
239
+ :content_type => content_type,
254
240
  :method => tcell_context.request_method,
255
241
  :path => tcell_context.path,
256
242
  :route_id => tcell_context.route_id.to_s,
@@ -288,8 +274,9 @@ module TCellAgent
288
274
  :status_code => status_code,
289
275
  :method => tcell_context.request_method,
290
276
  :path => tcell_context.path,
277
+ :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
291
278
  :remote_addr => tcell_context.remote_address,
292
- :full_uri => tcell_context.fullpath,
279
+ :full_uri => tcell_context.uri,
293
280
  :route_id => tcell_context.route_id,
294
281
  :session_id => tcell_context.session_id,
295
282
  :user_id => tcell_context.user_id
@@ -353,11 +340,12 @@ module TCellAgent
353
340
  :event_name => event_name,
354
341
  :user_id => user_id,
355
342
  :user_agent => tcell_context.user_agent,
343
+ :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
356
344
  :remote_address => tcell_context.remote_address,
357
345
  :header_keys => header_keys,
358
- :passsword => password,
346
+ :password => password,
359
347
  :session_id => tcell_context.session_id,
360
- :full_uri => tcell_context.fullpath,
348
+ :full_uri => tcell_context.uri,
361
349
  :referrer => tcell_context.referrer,
362
350
  :user_valid => user_valid
363
351
  }
@@ -395,11 +383,14 @@ module TCellAgent
395
383
  if tcell_context
396
384
  file_access_info = file_access_info.merge(
397
385
  {
398
- :full_uri => tcell_context.fullpath,
386
+ :full_uri => tcell_context.uri,
387
+ :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
399
388
  :remote_address => tcell_context.remote_address,
400
389
  :route_id => tcell_context.route_id,
401
390
  :session_id => tcell_context.session_id,
402
- :user_id => tcell_context.user_id
391
+ :user_id => tcell_context.user_id,
392
+ :method => tcell_context.request_method,
393
+ :request_path => tcell_context.path
403
394
  }
404
395
  )
405
396
  end
@@ -471,6 +462,7 @@ module TCellAgent
471
462
  :session_id => tcell_context && tcell_context.session_id,
472
463
  :user_id => tcell_context && tcell_context.user_id,
473
464
  :user_agent => tcell_context && tcell_context.user_agent,
465
+ :reverse_proxy_header_value => tcell_context.reverse_proxy_header_value,
474
466
  :remote_address => tcell_context && tcell_context.remote_address
475
467
  }
476
468
  message_pointer = FFI::MemoryPointer.from_string(
@@ -522,7 +514,7 @@ module TCellAgent
522
514
  end
523
515
  end
524
516
 
525
- # Note: for tests
517
+ # NOTE: for tests
526
518
  def update_policies(policies)
527
519
  return {} unless TCellAgent::Utils::Strings.present?(policies)
528
520
 
@@ -6,22 +6,20 @@ module TCellAgent
6
6
  require 'ffi'
7
7
  extend FFI::Library
8
8
 
9
- VERSION = '6.2.1'.freeze
10
- prefix = 'lib'
11
9
  extension = '.so'
12
10
  variant = ''
13
11
  if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
12
+ variant = '-x64'
14
13
  extension = '.dll'
15
- prefix = ''
16
14
  elsif /darwin/ =~ RUBY_PLATFORM
17
15
  extension = '.dylib'
18
16
  elsif /musl/ =~ RUBY_PLATFORM
19
- variant = 'alpine-'
17
+ variant = '-alpine'
20
18
  end
21
19
 
22
20
  begin
23
21
  ffi_lib File.join(File.dirname(__FILE__),
24
- "#{prefix}tcellagent-#{variant}#{VERSION}#{extension}")
22
+ "libtcellagent#{variant}#{extension}")
25
23
 
26
24
  # All the rust library calls have the following response api:
27
25
  #
@@ -36,6 +34,7 @@ module TCellAgent
36
34
  attach_function :poll_new_policies, %i[pointer pointer size_t], :int
37
35
  attach_function :appfirewall_apply, %i[pointer pointer size_t pointer size_t], :int
38
36
  attach_function :patches_apply, %i[pointer pointer size_t pointer size_t], :int
37
+ attach_function :suspicious_quick_check_apply, %i[pointer pointer size_t], :int
39
38
  attach_function :cmdi_apply, %i[pointer pointer size_t pointer size_t], :int
40
39
  attach_function :get_headers, %i[pointer pointer size_t pointer size_t], :int
41
40
  attach_function :get_js_agent_script_tag, %i[pointer pointer size_t pointer size_t], :int
@@ -48,17 +47,15 @@ module TCellAgent
48
47
  attach_function :log_message, %i[pointer pointer size_t pointer size_t], :int
49
48
 
50
49
  attach_function :update_policies, %i[pointer pointer size_t pointer size_t], :int
51
- attach_function :test_event_sender, %i[pointer size_t pointer size_t], :int
52
- attach_function :test_policies, %i[pointer size_t pointer size_t], :int
53
50
  attach_function :test_agent, %i[pointer size_t pointer size_t], :int
54
51
 
55
52
  def self.common_lib_available?
56
53
  true
57
54
  end
58
- rescue LoadError => load_error
55
+ rescue LoadError => e
59
56
  logger = TCellAgent::ModuleLogger.new(TCellAgent::RubyLogger.new, name)
60
- logger.error("Failed loading agent library. #{load_error.message}")
61
- logger.exception(load_error)
57
+ logger.error("Failed loading agent library. #{e.message}")
58
+ logger.exception(e)
62
59
 
63
60
  def self.common_lib_available? # rubocop:disable Lint/DuplicateMethods
64
61
  false
@@ -7,59 +7,6 @@ require 'etc'
7
7
 
8
8
  module TCellAgent
9
9
  module SensorEvents
10
- class ServerAgentDetailsSensorEvent < TCellSensorEvent
11
- include TCellAgent::ModuleLoggerAccess
12
-
13
- def initialize
14
- super('server_agent_details')
15
- @flush = true
16
- @ensure = true
17
-
18
- self['user'] = 'unknown'
19
- self['group'] = 'unknown'
20
-
21
- begin
22
- login = Etc.getlogin
23
- if login
24
- self['user'] = login
25
- begin
26
- info = Etc.getpwnam(login)
27
- self['group'] = info.gid.to_s
28
- rescue StandardError => te
29
- module_logger.debug("Could not get group id: #{te.message}")
30
- module_logger.exception(te)
31
- end
32
- end
33
- rescue StandardError => to
34
- module_logger.debug("Could not get user & group: #{to.message}")
35
- module_logger.exception(te)
36
- end
37
-
38
- module_logger.debug("User #{self['user']}")
39
- module_logger.debug("Group #{self['group']}")
40
- end
41
- end
42
-
43
- class ServerAgentDetailsLanguageEvent < TCellSensorEvent
44
- def initialize(language, language_version)
45
- super('server_agent_details')
46
- @flush = true
47
- @ensure = true
48
- self['language'] = language
49
- self['language_version'] = language_version
50
- end
51
- end
52
-
53
- class ServerAgentAppFrameworkEvent < TCellSensorEvent
54
- def initialize(framework_name, framework_version)
55
- super('server_agent_details')
56
- @flush = true
57
- @ensure = true
58
- self['app_framework'] = framework_name
59
- self['app_framework_version'] = framework_version
60
- end
61
- end
62
-
63
10
  class ServerAgentPackagesSensorEvent < TCellSensorEvent
64
11
  include TCellAgent::ModuleLoggerAccess
65
12
 
@@ -75,59 +22,15 @@ module TCellAgent
75
22
  packages.push(package)
76
23
  module_logger.debug("Adding packages #{x.name}")
77
24
  end
78
- rescue StandardError => te
79
- module_logger.error("Exception adding package: #{te.message}")
80
- module_logger.exception(te)
25
+ rescue StandardError => e
26
+ module_logger.error("Exception adding package: #{e.message}")
27
+ module_logger.exception(e)
81
28
  end
82
29
  end
83
30
  self['packages'] = packages
84
31
  end
85
32
  end
86
33
 
87
- class AppFramework < TCellSensorEvent
88
- def initialize(name, version)
89
- super('appserver_framework')
90
- @flush = false
91
- @ensure = true
92
- self['n'] = name
93
- self['v'] = version
94
- end
95
- end
96
-
97
- class AppAuthFramework < TCellSensorEvent
98
- def initialize(name, version)
99
- super('appserver_auth_framework')
100
- @flush = false
101
- @ensure = true
102
- self['n'] = name
103
- self['v'] = version
104
- end
105
- end
106
-
107
- class AppFrameworkSetting < TCellSensorEvent
108
- def initialize(framework_name, setting, value)
109
- super('appserver_framework_setting')
110
- @flush = false
111
- @ensure = true
112
- self['framework'] = framework_name
113
- self['s'] = setting
114
- self['v'] = value
115
- end
116
- end
117
-
118
- class AppCookie < TCellSensorEvent
119
- def initialize(name, value, secure, http_only, session)
120
- super('appserver_framework_setting')
121
- @flush = false
122
- @ensure = true
123
- self['n'] = name
124
- self['v'] = value
125
- self['http_only'] = http_only
126
- self['secure'] = secure
127
- self['session'] = session
128
- end
129
- end
130
-
131
34
  class AppRoutesSensorEvent < TCellSensorEvent
132
35
  def initialize(uri, method, route_id, params = nil, destination = nil)
133
36
  super('appserver_routes')
@@ -19,6 +19,7 @@ module TCellAgent
19
19
  params = CGI.parse(query)
20
20
  params.each do |param_name, param_values|
21
21
  next if param_values.nil? || param_values.empty?
22
+
22
23
  params[param_name] = ['']
23
24
  end
24
25
  params.map { |k, v| "#{k}=#{v.join(',')}" }.join('&')
@@ -1,6 +1,6 @@
1
1
  if defined?(Puma.cli_config)
2
2
  if Puma.cli_config.options[:preload_app]
3
- if Puma.cli_config.options[:workers] == 0 # rubocop:disable Style/NumericPredicate
3
+ if Puma.cli_config.options[:workers] == 0
4
4
  # Puma is running in single mode, so run both the initial instrumentation and
5
5
  # start the agent
6
6
  Puma::Runner.class_eval do
@@ -15,24 +15,41 @@ if defined?(Puma.cli_config)
15
15
  else
16
16
  Puma::Server.class_eval do
17
17
  alias_method :tcell_original_run, :run
18
- def run(background = true)
19
- TCellAgent.thread_agent.start('Puma Cluster Mode (Worker)')
20
18
 
21
- tcell_original_run(background)
19
+ if defined?(Gem::Version) &&
20
+ defined?(Puma::Const::PUMA_VERSION) &&
21
+ (Gem::Version.new(Puma::Const::PUMA_VERSION) < Gem::Version.new('5.1.0'))
22
+ def run(background = true)
23
+ TCellAgent.thread_agent.start('Puma')
24
+ tcell_original_run(background)
25
+ end
26
+ else
27
+ def run(background = true, thread_name: 'server')
28
+ TCellAgent.thread_agent.start('Puma')
29
+ tcell_original_run(background, :thread_name => thread_name)
30
+ end
22
31
  end
23
32
  end
24
33
  end
25
-
26
34
  else
27
35
  # this ensures instrumentation runs for preload_app = false.
28
36
  # Instrumentation will run for each worker but there's
29
37
  # nothing we can do about that (Unicorn's preload_app behaves the same way)
30
38
  Puma::Server.class_eval do
31
39
  alias_method :tcell_original_run, :run
32
- def run(background = true)
33
- TCellAgent.thread_agent.start('Puma Cluster Mode (Worker)')
34
40
 
35
- tcell_original_run(background)
41
+ if defined?(Gem::Version) &&
42
+ defined?(Puma::Const::PUMA_VERSION) &&
43
+ (Gem::Version.new(Puma::Const::PUMA_VERSION) < Gem::Version.new('5.1.0'))
44
+ def run(background = true)
45
+ TCellAgent.thread_agent.start('Puma')
46
+ tcell_original_run(background)
47
+ end
48
+ else
49
+ def run(background = true, thread_name: 'server')
50
+ TCellAgent.thread_agent.start('Puma')
51
+ tcell_original_run(background, :thread_name => thread_name)
52
+ end
36
53
  end
37
54
  end
38
55
  end
@@ -9,10 +9,20 @@ Rack::Handler::Puma.class_eval do
9
9
  if defined?(Puma::Server) && !Puma::Server.instance_methods.include?(:tcell_original_run)
10
10
  Puma::Server.class_eval do
11
11
  alias_method :tcell_original_run, :run
12
- def run(background = true)
13
- TCellAgent.thread_agent.start('Puma')
14
12
 
15
- tcell_original_run(background)
13
+ if defined?(Gem::Version) &&
14
+ defined?(Puma::Const::PUMA_VERSION) &&
15
+ (Gem::Version.new(Puma::Const::PUMA_VERSION) >= Gem::Version.new('5.1.0'))
16
+ def run(background = true, thread_name: 'server')
17
+ TCellAgent.thread_agent.start('Puma')
18
+ tcell_original_run(background, :thread_name => thread_name)
19
+ end
20
+ else
21
+ def run(background = true)
22
+ TCellAgent.thread_agent.start('Puma')
23
+
24
+ tcell_original_run(background)
25
+ end
16
26
  end
17
27
  end
18
28
  end
@@ -1,9 +1,19 @@
1
1
  Rack::Handler::WEBrick.class_eval do
2
2
  class << self
3
- alias_method :original_run, :run
4
- def run(app, options = {})
5
- TCellAgent.thread_agent.start('WEBrick')
6
- original_run(app, options)
3
+ alias_method :tcell_original_run, :run
4
+
5
+ if defined?(Gem::Version) &&
6
+ defined?(Rack.release) &&
7
+ Gem::Version.new(Rack.release) < Gem::Version.new('2.2.0')
8
+ def run(app, options = {})
9
+ TCellAgent.thread_agent.start('WEBrick')
10
+ tcell_original_run(app, options)
11
+ end
12
+ else
13
+ def run(app, **options)
14
+ TCellAgent.thread_agent.start('WEBrick')
15
+ tcell_original_run(app, **options)
16
+ end
7
17
  end
8
18
  end
9
19
  end
@@ -7,25 +7,11 @@ require 'thread'
7
7
  module TCellAgent
8
8
  def self.report_settings
9
9
  Thread.new do
10
- TCellAgent::Instrumentation.safe_block('Instrumenting Agent Details') do
11
- event = TCellAgent::SensorEvents::ServerAgentDetailsSensorEvent.new
12
- TCellAgent.send_event(event)
13
- end
14
-
15
10
  TCellAgent::Instrumentation.safe_block('Instrumenting Server Packages') do
16
11
  event = TCellAgent::SensorEvents::ServerAgentPackagesSensorEvent.new
17
12
  TCellAgent.send_event(event)
18
13
  end
19
14
 
20
- TCellAgent::Instrumentation.safe_block('Instrumenting Language Info') do
21
- TCellAgent.send_event(
22
- TCellAgent::SensorEvents::ServerAgentDetailsLanguageEvent.new(
23
- 'Ruby',
24
- RUBY_VERSION
25
- )
26
- )
27
- end
28
-
29
15
  TCellAgent::Instrumentation.safe_block('Instrumenting Native Lib Status') do
30
16
  require 'tcell_agent/rust/native_agent'
31
17
 
@@ -16,6 +16,7 @@ module TCellAgent
16
16
  TCellAgent::Instrumentation.safe_block('Setting Headers') do
17
17
  headers_policy = TCellAgent.policy(TCellAgent::PolicyTypes::HEADERS)
18
18
  policy_headers = headers_policy.get_headers(
19
+ headers['Content-Type'],
19
20
  request.env[TCellAgent::Instrumentation::TCELL_ID]
20
21
  )
21
22
  policy_headers.each do |header_info|
@@ -43,7 +43,8 @@ module TCellAgent
43
43
  tcell_context.session_id,
44
44
  tcell_context.user_id,
45
45
  tcell_context.transaction_id,
46
- tcell_context.uri
46
+ tcell_context.uri,
47
+ tcell_context.reverse_proxy_header_value
47
48
  )
48
49
  meta_data.path = tcell_context.path
49
50
 
@@ -70,7 +71,8 @@ module TCellAgent
70
71
  :response_headers,
71
72
  :csrf_exception_name,
72
73
  :sql_exceptions,
73
- :database_result_sizes
74
+ :database_result_sizes,
75
+ :reverse_proxy_header_value
74
76
 
75
77
  attr_reader :flattened_get_dict,
76
78
  :flattened_cookie_dict,
@@ -85,7 +87,8 @@ module TCellAgent
85
87
  session_id,
86
88
  user_id,
87
89
  transaction_id,
88
- location)
90
+ location,
91
+ reverse_proxy_header_value)
89
92
  @method = method
90
93
  @remote_address = remote_address
91
94
  @route_id = route_id
@@ -93,7 +96,7 @@ module TCellAgent
93
96
  @user_id = user_id
94
97
  @transaction_id = transaction_id
95
98
  @location = location
96
- @path = path
99
+ @reverse_proxy_header_value = reverse_proxy_header_value
97
100
 
98
101
  @flattened_get_dict = {}
99
102
  @flattened_cookie_dict = {}
@@ -148,6 +151,7 @@ module TCellAgent
148
151
  if !content_length.nil? && content_length > TCELL_MAX_BODY_LENGTH || request.content_type.nil?
149
152
  return nil
150
153
  end
154
+
151
155
  raw_post_data = nil
152
156
  # Positions strio to the beginning of input, resetting lineno to zero.
153
157
  # rails 4.1 seems to read the stringIO directly and so body.gets is empty
@@ -171,10 +175,15 @@ module TCellAgent
171
175
  self.get_dict = request.GET
172
176
  self.cookie_dict = request.cookies
173
177
 
174
- self.post_dict = if @content_type.start_with?('application/json', 'application/xml')
178
+ self.post_dict = if @content_type.start_with?('application/json', 'application/xml') ||
179
+ (@content_type.start_with?('multipart/form-data') && @request_content_bytes_len == 0)
175
180
  {}
176
181
  else
177
- request.POST
182
+ begin
183
+ request.POST
184
+ rescue EOFError
185
+ {}
186
+ end
178
187
  end
179
188
 
180
189
  self.headers_dict = request.env
@@ -1,4 +1,3 @@
1
-
2
1
  module TCellAgent
3
2
  module Utils
4
3
  module Headers
@@ -1,10 +1,10 @@
1
1
  module TCellAgent
2
2
  module Utils
3
3
  module Strings
4
- BLANK_RE = /\A[[:space:]]*\z/
4
+ BLANK_RE = /\A[[:space:]]*\z/.freeze
5
5
 
6
6
  def self.blank?(str)
7
- str.nil? || str.empty? || BLANK_RE === str # rubocop:disable Style/CaseEquality
7
+ str.nil? || str.empty? || BLANK_RE === str
8
8
  end
9
9
 
10
10
  def self.present?(str)
@@ -1,5 +1,5 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
3
  module TCellAgent
4
- VERSION = '2.3.0'.freeze
4
+ VERSION = '2.5.1'.freeze
5
5
  end
@@ -0,0 +1,26 @@
1
+ require 'tcell_agent'
2
+
3
+ TCellAgent.configuration.enabled = true
4
+ TCellAgent.configuration.instrument = true
5
+ TCellAgent.configuration.enable_intercept_requests = true
6
+ TCellAgent.configuration.disabled_instrumentation = []
7
+ TCellAgent.thread_agent.instrument_built_ins
8
+
9
+ # This monkey patch turns off blocking for LFI/CMDI when run in CRuby specs/
10
+ # test suite. The original method also depends on a Rails installation,
11
+ # which CRuby does not have installed.
12
+ module TCellAgent
13
+ module Instrumentation
14
+ module Lfi
15
+ def self.block_file_access?(_path, _mode)
16
+ false
17
+ end
18
+ end
19
+ end
20
+
21
+ module Cmdi
22
+ def self.block_command?(_cmd)
23
+ false
24
+ end
25
+ end
26
+ end