tcell_agent 2.1.2 → 2.2.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 (47) 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 -16
  8. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +1 -1
  9. data/lib/tcell_agent/logger.rb +1 -2
  10. data/lib/tcell_agent/rails/auth/authlogic.rb +46 -50
  11. data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
  12. data/lib/tcell_agent/rails/auth/devise.rb +101 -103
  13. data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
  14. data/lib/tcell_agent/rails/auth/doorkeeper.rb +55 -58
  15. data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
  16. data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
  17. data/lib/tcell_agent/rails/dlp.rb +0 -4
  18. data/lib/tcell_agent/rails/middleware/global_middleware.rb +1 -1
  19. data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
  20. data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
  21. data/lib/tcell_agent/rails/routes.rb +3 -6
  22. data/lib/tcell_agent/rails/routes/grape.rb +1 -3
  23. data/lib/tcell_agent/rails/tcell_body_proxy.rb +0 -1
  24. data/lib/tcell_agent/rust/agent_config.rb +43 -32
  25. data/lib/tcell_agent/rust/{libtcellagent-4.18.0.dylib → libtcellagent-5.0.2.dylib} +0 -0
  26. data/lib/tcell_agent/rust/{libtcellagent-4.18.0.so → libtcellagent-5.0.2.so} +0 -0
  27. data/lib/tcell_agent/rust/{libtcellagent-alpine-4.18.0.so → libtcellagent-alpine-5.0.2.so} +0 -0
  28. data/lib/tcell_agent/rust/models.rb +9 -0
  29. data/lib/tcell_agent/rust/native_agent.rb +18 -0
  30. data/lib/tcell_agent/rust/native_library.rb +2 -1
  31. data/lib/tcell_agent/rust/{tcellagent-4.18.0.dll → tcellagent-5.0.2.dll} +0 -0
  32. data/lib/tcell_agent/servers/rails_server.rb +0 -1
  33. data/lib/tcell_agent/servers/unicorn.rb +1 -1
  34. data/lib/tcell_agent/servers/webrick.rb +0 -1
  35. data/lib/tcell_agent/settings_reporter.rb +0 -79
  36. data/lib/tcell_agent/version.rb +1 -1
  37. data/spec/lib/tcell_agent/configuration_spec.rb +56 -211
  38. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +2 -2
  39. data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
  40. data/spec/lib/tcell_agent/settings_reporter_spec.rb +0 -73
  41. data/spec/support/builders.rb +5 -6
  42. metadata +14 -14
  43. data/lib/tcell_agent/authlogic.rb +0 -23
  44. data/lib/tcell_agent/config/unknown_options.rb +0 -119
  45. data/lib/tcell_agent/devise.rb +0 -33
  46. data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
  47. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -195
@@ -1,65 +1,32 @@
1
- if TCellAgent.configuration.should_instrument_doorkeeper? && defined?(Doorkeeper)
1
+ require 'tcell_agent/agent'
2
+ require 'tcell_agent/sensor_events/login_fraud'
2
3
 
3
- require 'tcell_agent/agent'
4
- require 'tcell_agent/sensor_events/login_fraud'
4
+ module TCellAgent
5
+ module DoorkeeperInstrumentation
6
+ Doorkeeper::TokensController.class_eval do
7
+ alias_method :tcell_authorize_response, :authorize_response
8
+ def authorize_response
9
+ result = tcell_authorize_response
5
10
 
6
- module TCellAgent
7
- module DoorkeeperInstrumentation
8
- Doorkeeper::TokensController.class_eval do
9
- alias_method :tcell_authorize_response, :authorize_response
10
- def authorize_response
11
- result = tcell_authorize_response
11
+ TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
12
+ return result unless TCellAgent.configuration.should_intercept_requests?
12
13
 
13
- TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
14
- return result unless TCellAgent.configuration.should_intercept_requests?
14
+ login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
15
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
15
16
 
16
- login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
17
- tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
17
+ return unless tcell_data
18
+ headers = request.env
18
19
 
19
- return unless tcell_data
20
- headers = request.env
21
-
22
- if result.is_a?(Doorkeeper::OAuth::TokenResponse)
23
- user_id = result.token.resource_owner_id
24
- login_policy.report_login_success(
25
- user_id,
26
- headers,
27
- tcell_data
28
- )
29
- elsif result.is_a?(Doorkeeper::OAuth::ErrorResponse)
30
- user_id = request.POST['client_id']
31
- password = nil
32
- user_valid = nil
33
- login_policy.report_login_failure(
34
- user_id,
35
- password,
36
- headers,
37
- user_valid,
38
- tcell_data
39
- )
40
- end
41
- end
42
-
43
- result
44
- end
45
- end
46
-
47
- module TCellAuthorizationsNew
48
- def new
49
- super if defined?(super)
50
-
51
- TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
52
- return unless TCellAgent.configuration.should_intercept_requests?
53
- return unless pre_auth.error
54
-
55
- login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
56
- tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
57
-
58
- return unless tcell_data
59
-
60
- user_id = current_resource_owner.id
20
+ if result.is_a?(Doorkeeper::OAuth::TokenResponse)
21
+ user_id = result.token.resource_owner_id
22
+ login_policy.report_login_success(
23
+ user_id,
24
+ headers,
25
+ tcell_data
26
+ )
27
+ elsif result.is_a?(Doorkeeper::OAuth::ErrorResponse)
28
+ user_id = request.POST['client_id']
61
29
  password = nil
62
- headers = request.env
63
30
  user_valid = nil
64
31
  login_policy.report_login_failure(
65
32
  user_id,
@@ -70,10 +37,40 @@ if TCellAgent.configuration.should_instrument_doorkeeper? && defined?(Doorkeeper
70
37
  )
71
38
  end
72
39
  end
40
+
41
+ result
73
42
  end
43
+ end
44
+
45
+ module TCellAuthorizationsNew
46
+ def new
47
+ super if defined?(super)
48
+
49
+ TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
50
+ return unless TCellAgent.configuration.should_intercept_requests?
51
+ return unless pre_auth.error
74
52
 
75
- # prepend is ruby 2+ feature
76
- Doorkeeper::AuthorizationsController.send(:prepend, TCellAuthorizationsNew)
53
+ login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
54
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
55
+
56
+ return unless tcell_data
57
+
58
+ user_id = current_resource_owner.id
59
+ password = nil
60
+ headers = request.env
61
+ user_valid = nil
62
+ login_policy.report_login_failure(
63
+ user_id,
64
+ password,
65
+ headers,
66
+ user_valid,
67
+ tcell_data
68
+ )
69
+ end
70
+ end
77
71
  end
72
+
73
+ # prepend is ruby 2+ feature
74
+ Doorkeeper::AuthorizationsController.send(:prepend, TCellAuthorizationsNew)
78
75
  end
79
76
  end
@@ -16,12 +16,4 @@ module TCellAgent
16
16
  super if defined?(super)
17
17
  end
18
18
  end
19
-
20
- class MyRailtie < Rails::Railtie
21
- initializer 'tcell.sensors' do |_app|
22
- ActiveSupport.on_load :action_controller do
23
- ActionController::Base.send(:include, TCellAgent::CsrfExceptionReporter)
24
- end
25
- end
26
- end
27
19
  end
@@ -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
 
@@ -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'
@@ -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
@@ -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
 
@@ -70,9 +70,7 @@ module TCellAgent
70
70
  Grape::Endpoint.class_eval do
71
71
  alias_method :tcell_call!, :call!
72
72
  def call!(env)
73
- if TCellAgent.configuration.should_instrument? &&
74
- TCellAgent.configuration.should_intercept_requests?
75
-
73
+ if TCellAgent.configuration.should_intercept_requests?
76
74
  TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
77
75
  tcell_context = env[TCellAgent::Instrumentation::TCELL_ID]
78
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_dir' => configuration.get_config_file_dir }
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_dir'] = configuration.get_config_file_dir
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.18.0'.freeze
9
+ VERSION = '5.0.2'.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