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
@@ -1,127 +1,128 @@
1
- if TCellAgent.configuration.should_instrument_devise? && defined?(Devise)
2
- module TCellAgent
3
- require 'base64'
4
- require 'tcell_agent/agent'
5
-
6
- module DeviseInstrumentation
7
- module TCellFailureAppRespond
8
- def respond
9
- TCellAgent::Instrumentation.safe_block('Devise Failure App Respond') do
10
- if TCellAgent.configuration.should_intercept_requests?
11
- tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
12
- if tcell_data
13
- # in the case of http auth, user_id is set in
14
- # Devise::Strategies::Authenticatable.valid_for_http_auth?
15
- user_id = tcell_data.user_id
16
- user_id ||= _get_tcell_username
17
-
18
- # in the case of http auth, password is set in
19
- # Devise::Strategies::Authenticatable.valid_for_http_auth?
20
- password = tcell_data.password
21
- password ||= _get_tcell_password
22
-
23
- user_valid = nil
24
- login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
25
- login_policy.report_login_failure(
26
- user_id,
27
- password,
28
- request.env,
29
- user_valid,
30
- tcell_data
31
- )
32
- end
1
+ module TCellAgent
2
+ require 'base64'
3
+ require 'tcell_agent/agent'
4
+
5
+ module DeviseInstrumentation
6
+ module TCellFailureAppRespond
7
+ def respond
8
+ TCellAgent::Instrumentation.safe_block('Devise Failure App Respond') do
9
+ if TCellAgent.configuration.should_intercept_requests?
10
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
11
+ if tcell_data
12
+ # in the case of http auth, user_id is set in
13
+ # Devise::Strategies::Authenticatable.valid_for_http_auth?
14
+ user_id = tcell_data.user_id
15
+ user_id ||= _get_tcell_username
16
+
17
+ # in the case of http auth, password is set in
18
+ # Devise::Strategies::Authenticatable.valid_for_http_auth?
19
+ password = tcell_data.password
20
+ password ||= _get_tcell_password
21
+
22
+ user_valid = warden_message != :not_found_in_database if defined?(warden_message)
23
+
24
+ login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
25
+ login_policy.report_login_failure(
26
+ user_id,
27
+ password,
28
+ request.env,
29
+ user_valid,
30
+ tcell_data
31
+ )
33
32
  end
34
33
  end
35
-
36
- super if defined?(super)
37
34
  end
38
35
 
39
- def _get_tcell_username
40
- tcell_username = nil
41
- TCellAgent::Instrumentation.safe_block('Devise Get TCell Username') do
42
- keys = scope_class.authentication_keys.dup
43
- user_params = request.POST.fetch('user', {})
44
- keys.each do |key|
45
- next_usename = user_params.fetch(key, nil)
46
- if next_usename
47
- tcell_username ||= ''
48
- tcell_username += next_usename
49
- end
36
+ super if defined?(super)
37
+ end
38
+
39
+ def _get_tcell_username
40
+ tcell_username = nil
41
+ TCellAgent::Instrumentation.safe_block('Devise Get TCell Username') do
42
+ keys = scope_class.authentication_keys.dup
43
+ user_params = request.POST.fetch('user', {})
44
+ keys.each do |key|
45
+ next_usename = user_params.fetch(key, nil)
46
+ if next_usename
47
+ tcell_username ||= ''
48
+ tcell_username += next_usename
50
49
  end
51
50
  end
52
- tcell_username
53
51
  end
52
+ tcell_username
53
+ end
54
54
 
55
- def _get_tcell_password
56
- tcell_password = nil
57
- TCellAgent::Instrumentation.safe_block('Devise Get TCell Password') do
58
- user_params = request.POST.fetch('user', {})
59
- tcell_password = user_params['password']
60
- end
61
- tcell_password
55
+ def _get_tcell_password
56
+ tcell_password = nil
57
+ TCellAgent::Instrumentation.safe_block('Devise Get TCell Password') do
58
+ user_params = request.POST.fetch('user', {})
59
+ tcell_password = user_params['password']
62
60
  end
61
+ tcell_password
63
62
  end
64
63
  end
64
+ end
65
65
 
66
- # prepend is ruby 2+ feature
67
- Devise::FailureApp.send(:prepend, DeviseInstrumentation::TCellFailureAppRespond)
66
+ # prepend is ruby 2+ feature
67
+ Devise::FailureApp.send(:prepend, DeviseInstrumentation::TCellFailureAppRespond)
68
+
69
+ Devise::Strategies::Authenticatable.class_eval do
70
+ alias_method :tcell_valid_for_http_auth?, :valid_for_http_auth?
71
+ def valid_for_http_auth?
72
+ is_valid = tcell_valid_for_http_auth?
73
+
74
+ TCellAgent::Instrumentation.safe_block('Devise set username for http basic auth') do
75
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
76
+ if http_auth_hash && tcell_data
77
+ username = http_auth_hash[http_authentication_key]
78
+ password = http_auth_hash[:password]
79
+ tcell_data.user_id = username if username && !tcell_data.user_id
80
+ tcell_data.password = password if password && !tcell_data.password
81
+ end
82
+ end
68
83
 
69
- Devise::Strategies::Authenticatable.class_eval do
70
- alias_method :tcell_valid_for_http_auth?, :valid_for_http_auth?
71
- def valid_for_http_auth?
72
- is_valid = tcell_valid_for_http_auth?
84
+ is_valid
85
+ end
73
86
 
74
- TCellAgent::Instrumentation.safe_block('Devise set username for http basic auth') do
75
- tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
76
- if http_auth_hash && tcell_data
77
- username = http_auth_hash[http_authentication_key]
78
- password = http_auth_hash[:password]
79
- tcell_data.user_id = username if username && !tcell_data.user_id
80
- tcell_data.password = password if password && !tcell_data.password
81
- end
82
- end
87
+ alias_method :tcell_validate, :validate
88
+ def validate(resource, &block)
89
+ is_valid = tcell_validate(resource, &block)
90
+ send_event = is_valid
83
91
 
84
- is_valid
92
+ # gets the first entry in the current backtrace
93
+ # syntax suggested by rubocop to improve performance
94
+ if caller(1..1).first.include? 'two_factor_authenticatable'
95
+ TCellAgent.logger.debug('Not sending login success event for Devise::Strategies::TwoFactorAuthenticatable since 2fa is unsupported', 'TCellAgent::DeviseInstrumentation')
96
+ send_event = false
85
97
  end
86
98
 
87
- alias_method :tcell_validate, :validate
88
- def validate(resource, &block)
89
- is_valid = tcell_validate(resource, &block)
90
- send_event = is_valid
91
-
92
- # gets the first entry in the current backtrace
93
- # syntax suggested by rubocop to improve performance
94
- if caller(1..1).first.include? 'two_factor_authenticatable'
95
- TCellAgent.logger.debug('Not sending login success event for Devise::Strategies::TwoFactorAuthenticatable since 2fa is unsupported', 'TCellAgent::DeviseInstrumentation')
96
- send_event = false
97
- end
99
+ TCellAgent::Instrumentation.safe_block('Devise Authenticatable Validate') do
100
+ if send_event && TCellAgent.configuration.should_intercept_requests?
101
+ username = nil
102
+ (authentication_keys || []).each do |auth_key|
103
+ attr = authentication_hash[auth_key] unless authentication_hash.nil?
98
104
 
99
- TCellAgent::Instrumentation.safe_block('Devise Authenticatable Validate') do
100
- if send_event && TCellAgent.configuration.enabled &&
101
- TCellAgent.configuration.should_intercept_requests?
102
- username = nil
103
- (authentication_keys || []).each do |auth_key|
104
- attr = authentication_hash[auth_key]
105
- if attr
106
- username ||= ''
107
- username += attr
108
- end
105
+ if attr
106
+ username ||= ''
107
+ username += attr
109
108
  end
110
-
111
- tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
112
- return is_valid unless tcell_data
113
-
114
- login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
115
- login_policy.report_login_success(
116
- username,
117
- request.env,
118
- tcell_data
119
- )
120
109
  end
121
- end
122
110
 
123
- is_valid
111
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
112
+ return is_valid unless tcell_data
113
+
114
+ tcell_data.user_id = username if username && tcell_data.user_id.nil?
115
+
116
+ login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
117
+ login_policy.report_login_success(
118
+ username,
119
+ request.env,
120
+ tcell_data
121
+ )
122
+ end
124
123
  end
124
+
125
+ is_valid
125
126
  end
126
127
  end
127
128
  end
@@ -0,0 +1,29 @@
1
+ require 'devise'
2
+ require 'devise/rails'
3
+ require 'devise/strategies/database_authenticatable'
4
+ require 'tcell_agent/rails/auth/userinfo'
5
+
6
+ module TCellAgent
7
+ TCellAgent::UserInformation.class_eval do
8
+ class << self
9
+ alias_method :original_get_user_from_request, :get_user_from_request
10
+ def get_user_from_request(request)
11
+ orig_user_id = original_get_user_from_request(request)
12
+ begin
13
+ if request.session && request.session.key?('warden.user.user.key')
14
+ userkey = request.session['warden.user.user.key']
15
+ user_id = if userkey.length == 2
16
+ userkey[0][0]
17
+ else
18
+ userkey[1][0]
19
+ end
20
+ return user_id.to_s if user_id.is_a? Integer
21
+ end
22
+ rescue StandardError
23
+ return orig_user_id
24
+ end
25
+ orig_user_id
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,65 +1,31 @@
1
- if TCellAgent.configuration.should_instrument_doorkeeper? && defined?(Doorkeeper)
1
+ require 'tcell_agent/agent'
2
2
 
3
- require 'tcell_agent/agent'
4
- require 'tcell_agent/sensor_events/login_fraud'
3
+ module TCellAgent
4
+ module DoorkeeperInstrumentation
5
+ Doorkeeper::TokensController.class_eval do
6
+ alias_method :tcell_authorize_response, :authorize_response
7
+ def authorize_response
8
+ result = tcell_authorize_response
5
9
 
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
10
+ TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
11
+ return result unless TCellAgent.configuration.should_intercept_requests?
12
12
 
13
- TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
14
- return result unless TCellAgent.configuration.should_intercept_requests?
13
+ login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
14
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
15
15
 
16
- login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
17
- tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
16
+ return unless tcell_data
17
+ headers = request.env
18
18
 
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
19
+ if result.is_a?(Doorkeeper::OAuth::TokenResponse)
20
+ user_id = result.token.resource_owner_id
21
+ login_policy.report_login_success(
22
+ user_id,
23
+ headers,
24
+ tcell_data
25
+ )
26
+ elsif result.is_a?(Doorkeeper::OAuth::ErrorResponse)
27
+ user_id = request.POST['client_id']
61
28
  password = nil
62
- headers = request.env
63
29
  user_valid = nil
64
30
  login_policy.report_login_failure(
65
31
  user_id,
@@ -70,10 +36,40 @@ if TCellAgent.configuration.should_instrument_doorkeeper? && defined?(Doorkeeper
70
36
  )
71
37
  end
72
38
  end
39
+
40
+ result
73
41
  end
42
+ end
43
+
44
+ module TCellAuthorizationsNew
45
+ def new
46
+ super if defined?(super)
47
+
48
+ TCellAgent::Instrumentation.safe_block('Doorkeeper Token Authorize') do
49
+ return unless TCellAgent.configuration.should_intercept_requests?
50
+ return unless pre_auth.error
74
51
 
75
- # prepend is ruby 2+ feature
76
- Doorkeeper::AuthorizationsController.send(:prepend, TCellAuthorizationsNew)
52
+ login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
53
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
54
+
55
+ return unless tcell_data
56
+
57
+ user_id = current_resource_owner.id
58
+ password = nil
59
+ headers = request.env
60
+ user_valid = nil
61
+ login_policy.report_login_failure(
62
+ user_id,
63
+ password,
64
+ headers,
65
+ user_valid,
66
+ tcell_data
67
+ )
68
+ end
69
+ end
77
70
  end
71
+
72
+ # prepend is ruby 2+ feature
73
+ Doorkeeper::AuthorizationsController.send(:prepend, TCellAuthorizationsNew)
78
74
  end
79
75
  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'
@@ -24,6 +24,9 @@ module TCellAgent
24
24
  def call(env)
25
25
  if TCellAgent.configuration.should_intercept_requests?
26
26
  request = Rack::Request.new(env)
27
+
28
+ request['init'] = true
29
+
27
30
  TCellAgent::Instrumentation.safe_block('Setting session_id & user_id') do
28
31
  if request.session
29
32
  env[TCellAgent::Instrumentation::TCELL_ID].session_id =
@@ -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