tcell_agent 2.1.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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