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,25 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  tcell_server = ENV['TCELL_AGENT_SERVER']
2
4
 
3
- if TCellAgent.configuration.should_instrument?
4
- unless tcell_server && tcell_server == 'mock'
5
- if (tcell_server && tcell_server == 'webrick') || defined?(Rails::Server)
6
- require('tcell_agent/servers/rails_server')
5
+ TCellAgent.thread_agent.instrument_built_ins if tcell_server &&
6
+ tcell_server == 'mock'
7
7
 
8
- elsif (tcell_server && tcell_server == 'thin') || defined?(Thin)
9
- require('tcell_agent/servers/thin')
8
+ require('tcell_agent/servers/rails_server') if (tcell_server && tcell_server == 'webrick') ||
9
+ defined?(Rails::Server)
10
10
 
11
- elsif (tcell_server && tcell_server == 'puma') || defined?(Puma)
12
- require('tcell_agent/servers/puma')
11
+ require('tcell_agent/servers/thin') if (tcell_server && tcell_server == 'thin') ||
12
+ defined?(Thin)
13
13
 
14
- elsif (tcell_server && tcell_server == 'unicorn') || defined?(Unicorn)
15
- require('tcell_agent/servers/unicorn')
14
+ require('tcell_agent/servers/puma') if (tcell_server && tcell_server == 'puma') ||
15
+ defined?(Puma)
16
16
 
17
- elsif (tcell_server && tcell_server == 'passenger') || defined?(PhusionPassenger)
18
- require('tcell_agent/servers/passenger')
19
- end
20
- end
17
+ require('tcell_agent/servers/unicorn') if (tcell_server && tcell_server == 'unicorn') ||
18
+ defined?(Unicorn)
21
19
 
22
- elsif (tcell_server && tcell_server == 'unicorn') || defined?(Unicorn)
23
- # unicorn is always instrumented to support rolling restarts
24
- require('tcell_agent/servers/unicorn')
25
- end
20
+ require('tcell_agent/servers/passenger') if (tcell_server && tcell_server == 'passenger') ||
21
+ defined?(PhusionPassenger)
@@ -25,18 +25,18 @@ module TCellAgent
25
25
  cmd = ''
26
26
 
27
27
  TCellAgent::Instrumentation.safe_block('CMDI Parsing *args') do
28
- unless args.empty?
29
- args_copy = Array.new(args)
30
- args_copy.shift if args_copy.first.is_a?(Hash)
31
- args_copy.pop if args_copy.last.is_a?(Hash)
32
-
33
- if args_copy.first.is_a?(Array)
34
- cmd_n_argv0 = args_copy.shift
35
- args_copy.unshift(cmd_n_argv0.first)
36
- end
28
+ return cmd if args.nil? || args.empty?
29
+
30
+ args_copy = Array.new(args)
31
+ args_copy.shift if args_copy.first.is_a?(Hash)
32
+ args_copy.pop if args_copy.last.is_a?(Hash)
37
33
 
38
- cmd = args_copy.join(' ')
34
+ if args_copy.first.is_a?(Array)
35
+ cmd_n_argv0 = args_copy.shift
36
+ args_copy.unshift(cmd_n_argv0.first)
39
37
  end
38
+
39
+ cmd = args_copy.join(' ')
40
40
  end
41
41
 
42
42
  cmd
@@ -46,12 +46,12 @@ module TCellAgent
46
46
  cmd = ''
47
47
 
48
48
  TCellAgent::Instrumentation.safe_block('CMDI Parsing *args') do
49
- unless args.empty?
50
- args_copy = Array.new(args)
51
- first_arg = args_copy.shift
49
+ return cmd if args.nil? || args.empty?
52
50
 
53
- cmd = first_arg[1..-1] if first_arg && (first_arg.is_a? String) && first_arg[0] == '|'
54
- end
51
+ args_copy = Array.new(args)
52
+ first_arg = args_copy.shift
53
+
54
+ cmd = first_arg[1..-1] if first_arg && (first_arg.is_a? String) && first_arg[0] == '|'
55
55
  end
56
56
 
57
57
  cmd
@@ -26,15 +26,23 @@ module TCellAgent
26
26
  path = ''
27
27
  mode = ''
28
28
 
29
- return ['', ''] if args.empty?
30
-
31
29
  TCellAgent::Instrumentation.safe_block('LFI Parsing *args') do
30
+ return ['', ''] if args.nil? || args.empty?
31
+
32
32
  args_copy = Array.new(args)
33
33
  path = args_copy.shift
34
34
  mode = args_copy.shift || 'r'
35
35
 
36
36
  if path && path.to_s[0] != '|'
37
- [File.expand_path(path).to_s, convert_mode(mode)]
37
+ path = File.expand_path(path.to_s)
38
+
39
+ mode = if mode && mode.is_a?(Hash)
40
+ convert_mode(mode[:mode])
41
+ else
42
+ convert_mode(mode)
43
+ end
44
+
45
+ [path, mode]
38
46
  else
39
47
  ['', '']
40
48
  end
@@ -53,8 +61,11 @@ module TCellAgent
53
61
  path = ARGF.filename
54
62
  end
55
63
 
56
- path = File.expand_path(path) unless path.nil?
57
- [path.to_s, mode]
64
+ if path && path.to_s[0] != '|'
65
+ [File.expand_path(path.to_s), mode]
66
+ else
67
+ ['', '']
68
+ end
58
69
  end
59
70
  end
60
71
 
@@ -1,76 +1,52 @@
1
1
  module Kernel
2
- class << self
3
- alias_method :tcell_original_1_open, :open
4
- def open(*args, &block)
5
- path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
6
-
7
- if !path.strip.empty? && TCellAgent::Instrumentation::Lfi.block_file_access?(path, mode)
8
- raise IOError, "tCell.io Agent: Attempted access to file #{path} with mode #{mode} denied"
9
- end
10
-
11
- if path.empty?
12
- cmd = TCellAgent::Cmdi.parse_command_from_open(*args)
13
- if cmd && TCellAgent::Cmdi.block_command?(cmd)
14
- raise "tCell.io Agent: Command not allowed by policy: #{cmd}"
15
- end
16
- end
2
+ private
17
3
 
18
- tcell_original_1_open(*args, &block)
19
- end
20
-
21
- alias_method :tcell_original_1_gets, :gets
22
- def gets(*args, &block)
23
- path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode_argf
24
-
25
- if TCellAgent::Instrumentation::Lfi.block_file_access?(path, mode)
26
- raise IOError, "tCell.io Agent: Attempted access to file #{path} with mode #{mode} denied"
27
- end
28
-
29
- tcell_original_1_gets(*args, &block)
30
- end
4
+ alias_method :tcell_original_backtick, :`
5
+ alias_method :tcell_original_exec, :exec
6
+ alias_method :tcell_original_open, :open
7
+ alias_method :tcell_original_gets, :gets
8
+ alias_method :tcell_original_readline, :readline
9
+ alias_method :tcell_original_spawn, :spawn
10
+ alias_method :tcell_original_system, :system
31
11
 
12
+ class << self
13
+ alias_method :tcell_original_exec, :exec
14
+ alias_method :tcell_original_open, :open
15
+ alias_method :tcell_original_gets, :gets
32
16
  alias_method :tcell_original_readline, :readline
33
- def readline(*args, &block)
34
- path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode_argf
35
-
36
- if TCellAgent::Instrumentation::Lfi.block_file_access?(path, mode)
37
- raise IOError, "tCell.io Agent: Attempted access to file #{path} with mode #{mode} denied"
38
- end
17
+ alias_method :tcell_original_spawn, :spawn
18
+ alias_method :tcell_original_system, :system
19
+ end
39
20
 
40
- tcell_original_readline(*args, &block)
21
+ def `(cmd)
22
+ if TCellAgent::Cmdi.block_command?(cmd)
23
+ raise "tCell.io Agent: Command not allowed by policy: #{cmd}"
41
24
  end
42
25
 
43
- alias_method :tcell_original_1_spawn, :spawn
44
- def spawn(*args)
45
- cmd = TCellAgent::Cmdi.parse_command(*args)
46
- if TCellAgent::Cmdi.block_command?(cmd)
47
- raise "tCell.io Agent: Command not allowed by policy: #{cmd}"
48
- end
49
-
50
- tcell_original_1_spawn(*args)
51
- end
26
+ tcell_original_backtick(cmd)
27
+ end
52
28
 
53
- alias_method :tcell_original_1_system, :system
54
- def system(*args)
29
+ if TCellAgent.configuration.should_instrument?('kernel_exec')
30
+ def exec(*args)
55
31
  cmd = TCellAgent::Cmdi.parse_command(*args)
56
32
  if TCellAgent::Cmdi.block_command?(cmd)
57
33
  raise "tCell.io Agent: Command not allowed by policy: #{cmd}"
58
34
  end
59
35
 
60
- tcell_original_1_system(*args)
36
+ tcell_original_exec(*args)
61
37
  end
62
38
  end
63
39
 
64
- alias_method :tcell_original_backtick, :`
65
- def `(cmd)
66
- if TCellAgent::Cmdi.block_command?(cmd)
67
- raise "tCell.io Agent: Command not allowed by policy: #{cmd}"
40
+ def gets(*args, &block)
41
+ path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode_argf
42
+
43
+ if TCellAgent::Instrumentation::Lfi.block_file_access?(path, mode)
44
+ raise IOError, "tCell.io Agent: Attempted access to file #{path} with mode #{mode} denied"
68
45
  end
69
46
 
70
- tcell_original_backtick(cmd)
47
+ tcell_original_gets(*args, &block)
71
48
  end
72
49
 
73
- alias_method :tcell_original_2_open, :open
74
50
  def open(*args, &block)
75
51
  path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode(*args)
76
52
 
@@ -85,21 +61,9 @@ module Kernel
85
61
  end
86
62
  end
87
63
 
88
- tcell_original_2_open(*args, &block)
64
+ tcell_original_open(*args, &block)
89
65
  end
90
66
 
91
- alias_method :tcell_original_2_gets, :gets
92
- def gets(*args, &block)
93
- path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode_argf
94
-
95
- if TCellAgent::Instrumentation::Lfi.block_file_access?(path, mode)
96
- raise IOError, "tCell.io Agent: Attempted access to file #{path} with mode #{mode} denied"
97
- end
98
-
99
- tcell_original_2_gets(*args, &block)
100
- end
101
-
102
- alias_method :tcell_original_readline, :readline
103
67
  def readline(*args, &block)
104
68
  path, mode = TCellAgent::Instrumentation::Lfi.extract_path_mode_argf
105
69
 
@@ -110,54 +74,29 @@ module Kernel
110
74
  tcell_original_readline(*args, &block)
111
75
  end
112
76
 
113
- alias_method :tcell_original_2_spawn, :spawn
114
77
  def spawn(*args)
115
78
  cmd = TCellAgent::Cmdi.parse_command(*args)
116
79
  if TCellAgent::Cmdi.block_command?(cmd)
117
80
  raise "tCell.io Agent: Command not allowed by policy: #{cmd}"
118
81
  end
119
82
 
120
- tcell_original_2_spawn(*args)
83
+ tcell_original_spawn(*args)
121
84
  end
122
85
 
123
- alias_method :tcell_original_2_system, :system
124
86
  def system(*args)
125
87
  cmd = TCellAgent::Cmdi.parse_command(*args)
126
88
  if TCellAgent::Cmdi.block_command?(cmd)
127
89
  raise "tCell.io Agent: Command not allowed by policy: #{cmd}"
128
90
  end
129
91
 
130
- tcell_original_2_system(*args)
92
+ tcell_original_system(*args)
131
93
  end
132
- end
133
-
134
- if TCellAgent.configuration.should_instrument_cmdi_exec?
135
- module Kernel
136
- class << self
137
- alias_method :tcell_original_exec, :exec
138
- def exec(*args)
139
- cmd = TCellAgent::Cmdi.parse_command(*args)
140
- if TCellAgent::Cmdi.block_command?(cmd)
141
- raise "tCell.io Agent: Command not allowed by policy: #{cmd}"
142
- end
143
-
144
- tcell_original_exec(*args)
145
- end
146
- end
147
-
148
- alias_method :tcell_original_exec, :exec
149
-
150
- private
151
-
152
- def exec(*args)
153
- cmd = TCellAgent::Cmdi.parse_command(*args)
154
- if TCellAgent::Cmdi.block_command?(cmd)
155
- raise "tCell.io Agent: Command not allowed by policy: #{cmd}"
156
- end
157
94
 
158
- tcell_original_exec(*args)
159
- end
160
- end
161
- else
162
- TCellAgent.logger.debug('Disabling cmdi Kernel::exec instrumentation', 'TCellAgent::Cmdi')
95
+ module_function :`
96
+ module_function :exec
97
+ module_function :gets
98
+ module_function :open
99
+ module_function :readline
100
+ module_function :spawn
101
+ module_function :system
163
102
  end
@@ -14,7 +14,6 @@ module TCellAgent
14
14
  def initialize(logger, module_name)
15
15
  @logger = logger
16
16
  @module_name = module_name
17
- @module_name = "#{TCellAgent.configuration.log_tag} #{module_name}" if TCellAgent.configuration.log_tag
18
17
  end
19
18
 
20
19
  %i[exception debug info warn error].each do |method_name|
@@ -80,7 +79,7 @@ module TCellAgent
80
79
  @native_logger
81
80
  end
82
81
 
83
- def self.native_agent=(native_agent)
82
+ def self.native_logger=(native_agent)
84
83
  @native_logger = NativeLogger.new(native_agent)
85
84
  end
86
85
  end
@@ -1,56 +1,61 @@
1
- if TCellAgent.configuration.should_instrument_authlogic? && defined?(Authlogic)
1
+ # frozen_string_literal: true
2
2
 
3
- require 'tcell_agent/configuration'
4
- require 'tcell_agent/instrumentation'
3
+ require 'tcell_agent/configuration'
4
+ require 'tcell_agent/instrumentation'
5
5
 
6
- module TCellAgent
7
- require 'tcell_agent/agent'
6
+ module TCellAgent
7
+ require 'tcell_agent/agent'
8
8
 
9
- Authlogic::Session::Base.class_eval do
10
- alias_method :tcell_save, :save
11
- def save(&block)
12
- return tcell_save(&block) unless TCellAgent.configuration.should_intercept_requests?
9
+ Authlogic::Session::Base.class_eval do
10
+ alias_method :tcell_save, :save
11
+ def save(&block)
12
+ return tcell_save(&block) unless TCellAgent.configuration.should_intercept_requests?
13
13
 
14
- user_logged_in_before = !user.nil?
15
- success = tcell_save(&block)
16
- user_logged_in_after = !user.nil?
14
+ user_logged_in_before = !user.nil?
15
+ success = tcell_save(&block)
16
+ user_logged_in_after = !user.nil?
17
17
 
18
- TCellAgent::Instrumentation.safe_block('Authlogic login info') do
19
- user_id = nil
20
- password = nil
21
- user_valid = nil
22
- TCellAgent::Instrumentation.safe_block('getting userid for login form') do
23
- user_id = send(self.class.login_field.to_sym)
24
- end
18
+ TCellAgent::Instrumentation.safe_block('Authlogic login info') do
19
+ user_id = nil
20
+ password = nil
21
+ user_valid = nil
22
+ TCellAgent::Instrumentation.safe_block('getting userid for login form') do
23
+ user_id = send(self.class.login_field.to_sym)
24
+ end
25
+
26
+ request = Authlogic::Session::Base.controller.request
27
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
28
+
29
+ return success unless tcell_data
30
+
31
+ login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
32
+ if user_logged_in_before && user_logged_in_after
33
+ # password changed or logged in as another user
34
+ elsif !user_logged_in_before && !user_logged_in_after
35
+ TCellAgent::Instrumentation.safe_block('checking if user is valid') do
36
+ error_messages = errors.messages[login_field]
25
37
 
26
- request = Authlogic::Session::Base.controller.request
27
- tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
28
-
29
- return success unless tcell_data
30
-
31
- login_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LOGINFRAUD)
32
- if user_logged_in_before && user_logged_in_after
33
- # password changed or logged in as another user
34
- elsif !user_logged_in_before && !user_logged_in_after
35
- login_policy.report_login_failure(
36
- user_id,
37
- password,
38
- request.env,
39
- user_valid,
40
- tcell_data
41
- )
42
- elsif !user_logged_in_before && user_logged_in_after
43
- login_policy.report_login_success(
44
- user_id,
45
- request.env,
46
- tcell_data
47
- )
38
+ user_valid = error_messages.empty?
48
39
  end
49
- end
50
40
 
51
- success
41
+ login_policy.report_login_failure(
42
+ user_id,
43
+ password,
44
+ request.env,
45
+ user_valid,
46
+ tcell_data
47
+ )
48
+ elsif !user_logged_in_before && user_logged_in_after
49
+ tcell_data.user_id = user_id if user_id && tcell_data.user_id.nil?
50
+ login_policy.report_login_success(
51
+ user_id,
52
+ request.env,
53
+ tcell_data
54
+ )
55
+ end
52
56
  end
57
+
58
+ success
53
59
  end
54
60
  end
55
-
56
61
  end
@@ -0,0 +1,20 @@
1
+ require 'tcell_agent/rails/auth/userinfo'
2
+
3
+ module TCellAgent
4
+ TCellAgent::UserInformation.class_eval do
5
+ class << self
6
+ alias_method :original_get_user_from_request, :get_user_from_request
7
+ def get_user_from_request(request)
8
+ orig_user_id = original_get_user_from_request(request)
9
+ begin
10
+ if request.session && request.session.key?('user_credentials_id')
11
+ return request.session['user_credentials_id'].to_s
12
+ end
13
+ rescue StandardError
14
+ return orig_user_id
15
+ end
16
+ orig_user_id
17
+ end
18
+ end
19
+ end
20
+ end