tcell_agent 2.1.0 → 2.3.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/bin/tcell_agent +42 -146
  3. data/lib/tcell_agent.rb +8 -16
  4. data/lib/tcell_agent/agent.rb +76 -46
  5. data/lib/tcell_agent/config_initializer.rb +66 -0
  6. data/lib/tcell_agent/configuration.rb +72 -267
  7. data/lib/tcell_agent/instrument_servers.rb +14 -18
  8. data/lib/tcell_agent/instrumentation/cmdi.rb +15 -15
  9. data/lib/tcell_agent/instrumentation/lfi.rb +16 -5
  10. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +39 -100
  11. data/lib/tcell_agent/logger.rb +1 -2
  12. data/lib/tcell_agent/rails/auth/authlogic.rb +49 -44
  13. data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
  14. data/lib/tcell_agent/rails/auth/devise.rb +103 -102
  15. data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
  16. data/lib/tcell_agent/rails/auth/doorkeeper.rb +54 -58
  17. data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
  18. data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
  19. data/lib/tcell_agent/rails/dlp.rb +0 -4
  20. data/lib/tcell_agent/rails/middleware/global_middleware.rb +4 -1
  21. data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
  22. data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
  23. data/lib/tcell_agent/rails/routes.rb +3 -6
  24. data/lib/tcell_agent/rails/routes/grape.rb +4 -12
  25. data/lib/tcell_agent/rails/tcell_body_proxy.rb +0 -1
  26. data/lib/tcell_agent/rust/agent_config.rb +43 -32
  27. data/lib/tcell_agent/rust/{libtcellagent-4.17.1.dylib → libtcellagent-6.2.1.dylib} +0 -0
  28. data/lib/tcell_agent/rust/{libtcellagent-4.17.1.so → libtcellagent-6.2.1.so} +0 -0
  29. data/lib/tcell_agent/rust/{libtcellagent-alpine-4.17.1.so → libtcellagent-alpine-6.2.1.so} +0 -0
  30. data/lib/tcell_agent/rust/models.rb +9 -0
  31. data/lib/tcell_agent/rust/native_agent.rb +18 -0
  32. data/lib/tcell_agent/rust/native_library.rb +2 -1
  33. data/lib/tcell_agent/rust/{tcellagent-4.17.1.dll → tcellagent-6.2.1.dll} +0 -0
  34. data/lib/tcell_agent/servers/puma.rb +7 -7
  35. data/lib/tcell_agent/servers/rack_puma_handler.rb +23 -0
  36. data/lib/tcell_agent/servers/rails_server.rb +4 -4
  37. data/lib/tcell_agent/servers/unicorn.rb +1 -1
  38. data/lib/tcell_agent/servers/webrick.rb +0 -1
  39. data/lib/tcell_agent/settings_reporter.rb +0 -79
  40. data/lib/tcell_agent/tcell_context.rb +1 -1
  41. data/lib/tcell_agent/version.rb +1 -1
  42. data/spec/lib/tcell_agent/configuration_spec.rb +62 -212
  43. data/spec/lib/tcell_agent/instrument_servers_spec.rb +95 -0
  44. data/spec/lib/tcell_agent/instrumentation/cmdi_spec.rb +46 -4
  45. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +47 -2
  46. data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
  47. data/spec/lib/tcell_agent/settings_reporter_spec.rb +0 -73
  48. data/spec/spec_helper.rb +6 -0
  49. data/spec/support/builders.rb +6 -6
  50. data/spec/support/server_mocks/passenger_mock.rb +7 -0
  51. data/spec/support/server_mocks/puma_mock.rb +17 -0
  52. data/spec/support/server_mocks/rails_mock.rb +7 -0
  53. data/spec/support/server_mocks/thin_mock.rb +7 -0
  54. data/spec/support/server_mocks/unicorn_mock.rb +11 -0
  55. metadata +27 -14
  56. data/lib/tcell_agent/authlogic.rb +0 -23
  57. data/lib/tcell_agent/config/unknown_options.rb +0 -119
  58. data/lib/tcell_agent/devise.rb +0 -33
  59. data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
  60. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -195
@@ -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
@@ -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
 
@@ -192,8 +191,7 @@ module TCellAgent
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
 
@@ -5,15 +5,9 @@ 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
15
-
16
- return true
8
+ return route.app < Grape::API if ::Rails::VERSION::MAJOR == 4 &&
9
+ ::Rails::VERSION::MINOR < 2
10
+ return route.app.app < Grape::API
17
11
  rescue StandardError # rubocop:disable Lint/HandleExceptions
18
12
  # do nothing
19
13
  end
@@ -76,9 +70,7 @@ module TCellAgent
76
70
  Grape::Endpoint.class_eval do
77
71
  alias_method :tcell_call!, :call!
78
72
  def call!(env)
79
- if TCellAgent.configuration.should_instrument? &&
80
- TCellAgent.configuration.should_intercept_requests?
81
-
73
+ if TCellAgent.configuration.should_intercept_requests?
82
74
  TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
83
75
  tcell_context = env[TCellAgent::Instrumentation::TCELL_ID]
84
76
  if tcell_context && tcell_context.grape_mount_endpoint && respond_to?(:routes)
@@ -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
@@ -1,48 +1,59 @@
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
10
+ self['agent_type'] = 'Ruby'
11
+ self['agent_version'] = TCellAgent::VERSION
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
9
16
 
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"
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 }
16
23
  end
24
+ end
25
+ end
17
26
 
18
- self['disable_event_sending'] = !configuration.should_start_event_manager?
19
- self['send_mode'] = send_mode
20
- self['agent_type'] = 'Ruby'
21
- self['agent_version'] = TCellAgent::VERSION
22
- self['diagnostics_enabled'] = false
23
- self['application'] = {
27
+ class AgentConfigOverrides < Hash
28
+ def initialize(configuration)
29
+ applications = {
30
+ :allow_payloads => configuration.allow_payloads,
31
+ :api_key => configuration.api_key,
24
32
  :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,
33
+ :enable_json_body_inspection => true,
28
34
  :hmac_key => configuration.hmac_key,
35
+ :max_header_size => configuration.max_csp_header_bytes,
29
36
  :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
40
- }
41
- self['appfirewall'] = {
42
- :enable_body_json_inspection => true,
43
- :allow_log_payloads => true
37
+ :reverse_proxy => configuration.reverse_proxy,
38
+ :reverse_proxy_ip_address_header => configuration.reverse_proxy_ip_address_header
44
39
  }
45
- self['max_header_size'] = configuration.max_csp_header_bytes || (1024 * 1024)
40
+
41
+ self['api_url'] = configuration.tcell_api_url
42
+ self['applications'] = [Models.clean_nils(applications)]
43
+ self['config_file_path'] = configuration.get_config_file_path
44
+ self['disabled_instrumentation'] = configuration.disabled_instrumentation
45
+ self['enabled'] = configuration.enabled
46
+ self['host_identifier'] = configuration.host_identifier
47
+ self['input_url'] = configuration.tcell_input_url
48
+ self['instrument'] = configuration.instrument
49
+ self['js_agent_api_url'] = configuration.js_agent_api_base_url
50
+ self['js_agent_url'] = configuration.js_agent_url
51
+ self['log_destination'] = configuration.logging_options[:destination]
52
+ self['log_dir'] = configuration.log_dir
53
+ self['log_enabled'] = configuration.logging_options[:enabled]
54
+ self['log_filename'] = configuration.logging_options[:log_filename]
55
+ self['log_level'] = configuration.logging_options[:level]
56
+ self['update_policy'] = configuration.fetch_policies_from_tcell
46
57
  end
47
58
  end
48
59
  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
@@ -58,6 +58,20 @@ module TCellAgent
58
58
  response.errors
59
59
  end
60
60
 
61
+ def self.test_agent(config)
62
+ agent_config = TCellAgent::Rust::AgentConfig.new(config)
63
+
64
+ config_pointer = FFI::MemoryPointer.from_string(
65
+ JSON.dump(agent_config)
66
+ )
67
+
68
+ buf = FFI::MemoryPointer.new(:uint8, 1024 * 8)
69
+ # config_pointer.size - 1: strips null terminator
70
+ TCellAgent::Rust::NativeLibrary.test_agent(
71
+ config_pointer, config_pointer.size - 1, buf, buf.size
72
+ )
73
+ end
74
+
61
75
  def self.free_agent(agent_ptr)
62
76
  if TCellAgent::Rust::NativeLibrary.common_lib_available? &&
63
77
  agent_ptr
@@ -88,6 +102,9 @@ module TCellAgent
88
102
  return nil
89
103
  end
90
104
 
105
+ return unless response['config'] && response['agent_enabled']
106
+
107
+ TCellAgent.configuration.populate_configuration(response['config'])
91
108
  NativeAgent.new(response['agent_ptr'])
92
109
  end
93
110
 
@@ -209,6 +226,7 @@ module TCellAgent
209
226
  :user_id => tcell_context.user_id,
210
227
  :full_uri => tcell_context.uri
211
228
  }
229
+
212
230
  command_pointer = FFI::MemoryPointer.from_string(
213
231
  JSON.dump(command_info)
214
232
  )
@@ -6,7 +6,7 @@ module TCellAgent
6
6
  require 'ffi'
7
7
  extend FFI::Library
8
8
 
9
- VERSION = '4.17.1'.freeze
9
+ VERSION = '6.2.1'.freeze
10
10
  prefix = 'lib'
11
11
  extension = '.so'
12
12
  variant = ''
@@ -50,6 +50,7 @@ module TCellAgent
50
50
  attach_function :update_policies, %i[pointer pointer size_t pointer size_t], :int
51
51
  attach_function :test_event_sender, %i[pointer size_t pointer size_t], :int
52
52
  attach_function :test_policies, %i[pointer size_t pointer size_t], :int
53
+ attach_function :test_agent, %i[pointer size_t pointer size_t], :int
53
54
 
54
55
  def self.common_lib_available?
55
56
  true
@@ -4,21 +4,21 @@ if defined?(Puma.cli_config)
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
7
- alias_method :original_start_server, :start_server
7
+ alias_method :tcell_original_start_server, :start_server
8
8
  def start_server
9
- TCellAgent.thread_agent.start('Puma Single Mode')
9
+ TCellAgent.thread_agent.start('Puma')
10
10
 
11
- original_start_server
11
+ tcell_original_start_server
12
12
  end
13
13
  end
14
14
 
15
15
  else
16
16
  Puma::Server.class_eval do
17
- alias_method :original_run, :run
17
+ alias_method :tcell_original_run, :run
18
18
  def run(background = true)
19
19
  TCellAgent.thread_agent.start('Puma Cluster Mode (Worker)')
20
20
 
21
- original_run(background)
21
+ tcell_original_run(background)
22
22
  end
23
23
  end
24
24
  end
@@ -28,11 +28,11 @@ if defined?(Puma.cli_config)
28
28
  # Instrumentation will run for each worker but there's
29
29
  # nothing we can do about that (Unicorn's preload_app behaves the same way)
30
30
  Puma::Server.class_eval do
31
- alias_method :original_run, :run
31
+ alias_method :tcell_original_run, :run
32
32
  def run(background = true)
33
33
  TCellAgent.thread_agent.start('Puma Cluster Mode (Worker)')
34
34
 
35
- original_run(background)
35
+ tcell_original_run(background)
36
36
  end
37
37
  end
38
38
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rack::Handler::Puma.class_eval do
4
+ class << self
5
+ alias_method :tcell_original_config, :config
6
+ def config(app, options = {})
7
+ conf = tcell_original_config(app, options)
8
+
9
+ if defined?(Puma::Server) && !Puma::Server.instance_methods.include?(:tcell_original_run)
10
+ Puma::Server.class_eval do
11
+ alias_method :tcell_original_run, :run
12
+ def run(background = true)
13
+ TCellAgent.thread_agent.start('Puma')
14
+
15
+ tcell_original_run(background)
16
+ end
17
+ end
18
+ end
19
+
20
+ conf
21
+ end
22
+ end
23
+ end
@@ -5,17 +5,17 @@
5
5
  Rails::Server.class_eval do
6
6
  alias_method :tcell_build_app, :build_app
7
7
  def build_app(app)
8
+ require('tcell_agent/servers/rack_puma_handler') if defined?(Rack::Handler::Puma)
8
9
  require('tcell_agent/servers/unicorn') if defined?(Unicorn::HttpServer)
9
10
  require('tcell_agent/servers/webrick') if defined?(Rack::Handler::WEBrick)
10
11
  require('tcell_agent/servers/thin') if defined?(Thin::Server)
11
12
 
12
13
  if defined?(Puma::Server)
13
14
  Puma::Server.class_eval do
14
- alias_method :original_run, :run
15
+ alias_method :tcell_original_run, :run
15
16
  def run(background = true)
16
- TCellAgent.thread_agent.start('Puma Single Mode')
17
-
18
- original_run(background)
17
+ TCellAgent.thread_agent.start('Puma')
18
+ tcell_original_run(background)
19
19
  end
20
20
  end
21
21
  end
@@ -3,7 +3,7 @@ Unicorn::HttpServer.class_eval do
3
3
  # - This check also ensures that a server is running as opposed to a different command such
4
4
  # as `bundle exec rails runner User.count`.
5
5
  unless Unicorn::HttpServer::START_CTX && Unicorn::HttpServer::START_CTX[0]
6
- require 'tcell_agent/rails/start_agent_after_initializers'
6
+ require 'tcell_agent/rails/railties/tcell_agent_unicorn_railties'
7
7
  end
8
8
 
9
9
  # This only gets instrumented when preload_app is true
@@ -3,7 +3,6 @@ Rack::Handler::WEBrick.class_eval do
3
3
  alias_method :original_run, :run
4
4
  def run(app, options = {})
5
5
  TCellAgent.thread_agent.start('WEBrick')
6
-
7
6
  original_run(app, options)
8
7
  end
9
8
  end
@@ -37,85 +37,6 @@ module TCellAgent
37
37
  )
38
38
  end
39
39
 
40
- TCellAgent::Instrumentation.safe_block('Instrumenting Initial Config') do
41
- TCellAgent.send_event(
42
- TCellAgent::SensorEvents::AgentSettingEvent.new(
43
- 'allow_payloads',
44
- (!!TCellAgent.configuration.allow_payloads).to_s # rubocop:disable Style/DoubleNegation
45
- )
46
- )
47
-
48
- TCellAgent.send_event(
49
- TCellAgent::SensorEvents::AgentSettingEvent.new(
50
- 'reverse_proxy',
51
- (!!TCellAgent.configuration.reverse_proxy).to_s # rubocop:disable Style/DoubleNegation
52
- )
53
- )
54
-
55
- # Because of all the diff ways to initialize the agent
56
- # some some of the following vars might not be set until
57
- # we call this method, so call this method to set all
58
- # the variables
59
- TCellAgent.configuration.log_filename
60
-
61
- TCellAgent.send_event(
62
- TCellAgent::SensorEvents::AgentSettingEvent.new(
63
- 'config_filename',
64
- TCellAgent.configuration.config_filename
65
- )
66
- )
67
- TCellAgent.send_event(
68
- TCellAgent::SensorEvents::AgentSettingEvent.new(
69
- 'logging_directory',
70
- TCellAgent.configuration.agent_log_dir
71
- )
72
- )
73
-
74
- TCellAgent.send_event(
75
- TCellAgent::SensorEvents::AgentSettingEvent.new(
76
- 'agent_home_directory',
77
- TCellAgent.configuration.agent_home_dir
78
- )
79
- )
80
-
81
- logging_options = TCellAgent.configuration.logging_options || {}
82
- use_default_setting = !logging_options.key?(:enabled) && !logging_options.key?('enabled')
83
- if use_default_setting || logging_options[:enabled] || logging_options['enabled']
84
- TCellAgent.send_event(
85
- TCellAgent::SensorEvents::AgentSettingEvent.new('logging_enabled', 'true')
86
- )
87
-
88
- TCellAgent.send_event(
89
- TCellAgent::SensorEvents::AgentSettingEvent.new(
90
- 'logging_level',
91
- logging_options[:level] || logging_options['level'] || 'INFO'
92
- )
93
- )
94
- else
95
- TCellAgent.send_event(
96
- TCellAgent::SensorEvents::AgentSettingEvent.new('logging_enabled', 'false')
97
- )
98
- end
99
-
100
- if TCellAgent.configuration.hmac_key
101
- TCellAgent.send_event(
102
- TCellAgent::SensorEvents::AgentSettingEvent.new(
103
- 'hmac_key_present',
104
- (!!TCellAgent.configuration.hmac_key).to_s # rubocop:disable Style/DoubleNegation
105
- )
106
- )
107
- end
108
-
109
- if TCellAgent.configuration.reverse_proxy
110
- TCellAgent.send_event(
111
- TCellAgent::SensorEvents::AgentSettingEvent.new(
112
- 'reverse_proxy_ip_address_header',
113
- TCellAgent.configuration.reverse_proxy_ip_address_header
114
- )
115
- )
116
- end
117
- end
118
-
119
40
  if defined?(::Rails)
120
41
  TCellAgent::Instrumentation.safe_block('Instrumenting routes') do
121
42
  TCellAgent::Instrumentation::Rails.instrument_routes
@@ -40,7 +40,7 @@ module TCellAgent
40
40
  tcell_context.request_method,
41
41
  tcell_context.remote_address,
42
42
  tcell_context.route_id,
43
- tcell_context.hmac_session_id,
43
+ tcell_context.session_id,
44
44
  tcell_context.user_id,
45
45
  tcell_context.transaction_id,
46
46
  tcell_context.uri