tcell_agent 2.0.0 → 2.5.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +2 -2
  3. data/bin/tcell_agent +41 -150
  4. data/lib/tcell_agent/agent.rb +87 -52
  5. data/lib/tcell_agent/config_initializer.rb +63 -0
  6. data/lib/tcell_agent/configuration.rb +72 -267
  7. data/lib/tcell_agent/hooks/login_fraud.rb +1 -1
  8. data/lib/tcell_agent/instrument_servers.rb +14 -18
  9. data/lib/tcell_agent/instrumentation/cmdi.rb +47 -15
  10. data/lib/tcell_agent/instrumentation/lfi.rb +72 -15
  11. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/file.rb +21 -0
  12. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/io.rb +75 -0
  13. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/kernel.rb +80 -0
  14. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/file.rb +21 -0
  15. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/io.rb +75 -0
  16. data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/kernel.rb +80 -0
  17. data/lib/tcell_agent/instrumentation.rb +14 -6
  18. data/lib/tcell_agent/logger.rb +3 -4
  19. data/lib/tcell_agent/policies/command_injection_policy.rb +1 -1
  20. data/lib/tcell_agent/policies/dataloss_policy.rb +15 -8
  21. data/lib/tcell_agent/policies/headers_policy.rb +2 -2
  22. data/lib/tcell_agent/policies/patches_policy.rb +8 -4
  23. data/lib/tcell_agent/policies/policies_manager.rb +1 -0
  24. data/lib/tcell_agent/policies/policy_polling.rb +4 -3
  25. data/lib/tcell_agent/rails/auth/authlogic.rb +49 -44
  26. data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
  27. data/lib/tcell_agent/rails/auth/devise.rb +103 -102
  28. data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
  29. data/lib/tcell_agent/rails/auth/doorkeeper.rb +54 -57
  30. data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
  31. data/lib/tcell_agent/rails/better_ip.rb +7 -19
  32. data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
  33. data/lib/tcell_agent/rails/dlp/process_request.rb +5 -0
  34. data/lib/tcell_agent/rails/dlp.rb +58 -56
  35. data/lib/tcell_agent/rails/dlp_handler.rb +9 -10
  36. data/lib/tcell_agent/rails/js_agent_insert.rb +2 -3
  37. data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -1
  38. data/lib/tcell_agent/rails/middleware/global_middleware.rb +3 -4
  39. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +1 -0
  40. data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
  41. data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
  42. data/lib/tcell_agent/rails/routes/grape.rb +5 -12
  43. data/lib/tcell_agent/rails/routes.rb +6 -9
  44. data/lib/tcell_agent/rails/settings_reporter.rb +3 -6
  45. data/lib/tcell_agent/rails/tcell_body_proxy.rb +4 -7
  46. data/lib/tcell_agent/routes/table.rb +3 -0
  47. data/lib/tcell_agent/rust/agent_config.rb +62 -33
  48. data/lib/tcell_agent/rust/{libtcellagent-4.14.0.so → libtcellagent-alpine.so} +0 -0
  49. data/lib/tcell_agent/rust/{libtcellagent-4.14.0.dylib → libtcellagent-x64.dll} +0 -0
  50. data/lib/tcell_agent/rust/{libtcellagent-alpine-4.14.0.so → libtcellagent.dylib} +0 -0
  51. data/lib/tcell_agent/rust/libtcellagent.so +0 -0
  52. data/lib/tcell_agent/rust/models.rb +9 -0
  53. data/lib/tcell_agent/rust/native_agent.rb +61 -51
  54. data/lib/tcell_agent/rust/native_library.rb +8 -10
  55. data/lib/tcell_agent/sensor_events/server_agent.rb +3 -100
  56. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +1 -0
  57. data/lib/tcell_agent/servers/puma.rb +30 -13
  58. data/lib/tcell_agent/servers/rack_puma_handler.rb +33 -0
  59. data/lib/tcell_agent/servers/rails_server.rb +4 -4
  60. data/lib/tcell_agent/servers/unicorn.rb +1 -1
  61. data/lib/tcell_agent/servers/webrick.rb +12 -3
  62. data/lib/tcell_agent/settings_reporter.rb +0 -93
  63. data/lib/tcell_agent/sinatra.rb +1 -0
  64. data/lib/tcell_agent/tcell_context.rb +16 -7
  65. data/lib/tcell_agent/utils/headers.rb +0 -1
  66. data/lib/tcell_agent/utils/strings.rb +2 -2
  67. data/lib/tcell_agent/version.rb +1 -1
  68. data/lib/tcell_agent.rb +8 -16
  69. data/spec/cruby_spec_helper.rb +26 -0
  70. data/spec/lib/tcell_agent/configuration_spec.rb +62 -212
  71. data/spec/lib/tcell_agent/instrument_servers_spec.rb +95 -0
  72. data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +2 -2
  73. data/spec/lib/tcell_agent/{cmdi_spec.rb → instrumentation/cmdi_spec.rb} +50 -0
  74. data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +211 -272
  75. data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +213 -223
  76. data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +95 -61
  77. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +120 -2
  78. data/spec/lib/tcell_agent/patches_spec.rb +2 -1
  79. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +1 -2
  80. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +5 -6
  81. data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +21 -2
  82. data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +1 -1
  83. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +13 -8
  84. data/spec/lib/tcell_agent/rails/better_ip_spec.rb +9 -11
  85. data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +6 -6
  86. data/spec/lib/tcell_agent/rails/dlp_spec.rb +1 -0
  87. data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +10 -2
  88. data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +2 -1
  89. data/spec/lib/tcell_agent/rails/routes/route_id_spec.rb +4 -4
  90. data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
  91. data/spec/lib/tcell_agent/settings_reporter_spec.rb +2 -89
  92. data/spec/lib/tcell_agent/tcell_context_spec.rb +6 -5
  93. data/spec/spec_helper.rb +9 -1
  94. data/spec/support/builders.rb +8 -7
  95. data/spec/support/server_mocks/passenger_mock.rb +7 -0
  96. data/spec/support/server_mocks/puma_mock.rb +21 -0
  97. data/spec/support/server_mocks/rails_mock.rb +7 -0
  98. data/spec/support/server_mocks/thin_mock.rb +7 -0
  99. data/spec/support/server_mocks/unicorn_mock.rb +11 -0
  100. data/spec/support/shared_spec.rb +29 -0
  101. data/tcell_agent.gemspec +14 -14
  102. metadata +46 -29
  103. data/Rakefile +0 -18
  104. data/lib/tcell_agent/authlogic.rb +0 -23
  105. data/lib/tcell_agent/config/unknown_options.rb +0 -119
  106. data/lib/tcell_agent/devise.rb +0 -33
  107. data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +0 -25
  108. data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +0 -123
  109. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +0 -159
  110. data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
  111. data/lib/tcell_agent/rust/tcellagent-4.14.0.dll +0 -0
  112. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -195
@@ -16,6 +16,7 @@ module TCellAgent
16
16
  TCellAgent::Instrumentation.safe_block('Setting Headers') do
17
17
  headers_policy = TCellAgent.policy(TCellAgent::PolicyTypes::HEADERS)
18
18
  policy_headers = headers_policy.get_headers(
19
+ headers['Content-Type'],
19
20
  request.env[TCellAgent::Instrumentation::TCELL_ID]
20
21
  )
21
22
  policy_headers.each do |header_info|
@@ -40,10 +40,11 @@ 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
- tcell_context.uri
46
+ tcell_context.uri,
47
+ tcell_context.reverse_proxy_header_value
47
48
  )
48
49
  meta_data.path = tcell_context.path
49
50
 
@@ -70,7 +71,8 @@ module TCellAgent
70
71
  :response_headers,
71
72
  :csrf_exception_name,
72
73
  :sql_exceptions,
73
- :database_result_sizes
74
+ :database_result_sizes,
75
+ :reverse_proxy_header_value
74
76
 
75
77
  attr_reader :flattened_get_dict,
76
78
  :flattened_cookie_dict,
@@ -85,7 +87,8 @@ module TCellAgent
85
87
  session_id,
86
88
  user_id,
87
89
  transaction_id,
88
- location)
90
+ location,
91
+ reverse_proxy_header_value)
89
92
  @method = method
90
93
  @remote_address = remote_address
91
94
  @route_id = route_id
@@ -93,7 +96,7 @@ module TCellAgent
93
96
  @user_id = user_id
94
97
  @transaction_id = transaction_id
95
98
  @location = location
96
- @path = path
99
+ @reverse_proxy_header_value = reverse_proxy_header_value
97
100
 
98
101
  @flattened_get_dict = {}
99
102
  @flattened_cookie_dict = {}
@@ -148,6 +151,7 @@ module TCellAgent
148
151
  if !content_length.nil? && content_length > TCELL_MAX_BODY_LENGTH || request.content_type.nil?
149
152
  return nil
150
153
  end
154
+
151
155
  raw_post_data = nil
152
156
  # Positions strio to the beginning of input, resetting lineno to zero.
153
157
  # rails 4.1 seems to read the stringIO directly and so body.gets is empty
@@ -171,10 +175,15 @@ module TCellAgent
171
175
  self.get_dict = request.GET
172
176
  self.cookie_dict = request.cookies
173
177
 
174
- self.post_dict = if @content_type.start_with?('application/json', 'application/xml')
178
+ self.post_dict = if @content_type.start_with?('application/json', 'application/xml') ||
179
+ (@content_type.start_with?('multipart/form-data') && @request_content_bytes_len == 0)
175
180
  {}
176
181
  else
177
- request.POST
182
+ begin
183
+ request.POST
184
+ rescue EOFError
185
+ {}
186
+ end
178
187
  end
179
188
 
180
189
  self.headers_dict = request.env
@@ -1,4 +1,3 @@
1
-
2
1
  module TCellAgent
3
2
  module Utils
4
3
  module Headers
@@ -1,10 +1,10 @@
1
1
  module TCellAgent
2
2
  module Utils
3
3
  module Strings
4
- BLANK_RE = /\A[[:space:]]*\z/
4
+ BLANK_RE = /\A[[:space:]]*\z/.freeze
5
5
 
6
6
  def self.blank?(str)
7
- str.nil? || str.empty? || BLANK_RE === str # rubocop:disable Style/CaseEquality
7
+ str.nil? || str.empty? || BLANK_RE === str
8
8
  end
9
9
 
10
10
  def self.present?(str)
@@ -1,5 +1,5 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
3
  module TCellAgent
4
- VERSION = '2.0.0'.freeze
4
+ VERSION = '2.5.0'.freeze
5
5
  end
data/lib/tcell_agent.rb CHANGED
@@ -1,26 +1,18 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
-
3
- require 'tcell_agent/logger'
4
- require 'tcell_agent/utils/strings'
5
2
  require 'tcell_agent/configuration'
6
3
 
7
- require 'tcell_agent/agent'
8
-
9
- require 'tcell_agent/sensor_events/util/sanitizer_utilities'
10
-
11
- require 'tcell_agent/instrumentation'
4
+ unless TCellAgent.configuration.disable_all
5
+ require 'tcell_agent/logger'
6
+ require 'tcell_agent/utils/strings'
7
+ require 'tcell_agent/agent'
12
8
 
13
- require 'tcell_agent/instrument_servers'
9
+ require 'tcell_agent/sensor_events/util/sanitizer_utilities'
14
10
 
15
- if !TCellAgent.configuration.disable_all && TCellAgent.configuration.should_instrument?
16
- require 'tcell_agent/instrumentation/cmdi'
17
- require 'tcell_agent/instrumentation/lfi'
18
- require 'tcell_agent/instrumentation/monkey_patches/io'
19
- require 'tcell_agent/instrumentation/monkey_patches/file'
20
- require 'tcell_agent/instrumentation/monkey_patches/kernel'
11
+ require 'tcell_agent/instrumentation'
21
12
 
13
+ require 'tcell_agent/instrument_servers'
22
14
  require 'tcell_agent/hooks/login_fraud'
23
- require 'tcell_agent/rails/on_start' if defined?(Rails)
15
+ require 'tcell_agent/rails/railties/tcell_agent_railties' if defined?(Rails)
24
16
  # sinatra used to be supported, but dropped support due to no customers using it
25
17
  # require 'tcell_agent/sinatra' if defined?(Sinatra)
26
18
  end
@@ -0,0 +1,26 @@
1
+ require 'tcell_agent'
2
+
3
+ TCellAgent.configuration.enabled = true
4
+ TCellAgent.configuration.instrument = true
5
+ TCellAgent.configuration.enable_intercept_requests = true
6
+ TCellAgent.configuration.disabled_instrumentation = []
7
+ TCellAgent.thread_agent.instrument_built_ins
8
+
9
+ # This monkey patch turns off blocking for LFI/CMDI when run in CRuby specs/
10
+ # test suite. The original method also depends on a Rails installation,
11
+ # which CRuby does not have installed.
12
+ module TCellAgent
13
+ module Instrumentation
14
+ module Lfi
15
+ def self.block_file_access?(_path, _mode)
16
+ false
17
+ end
18
+ end
19
+ end
20
+
21
+ module Cmdi
22
+ def self.block_command?(_cmd)
23
+ false
24
+ end
25
+ end
26
+ end
@@ -2,228 +2,78 @@ require 'spec_helper'
2
2
 
3
3
  module TCellAgent
4
4
  describe Configuration do
5
- describe '#agent_home_dir' do
6
- context 'no TCELL_AGENT_HOME defined' do
7
- it 'should set cache file, config, and log file to defaults' do
8
- configuration = Configuration.new
5
+ describe 'should_instrument?' do
6
+ context 'with the agent disabled' do
7
+ it 'should return false' do
8
+ config = Configuration.new
9
+ config.enabled = false
9
10
 
10
- expect(configuration.log_filename).to eq(
11
- File.join(Dir.getwd, 'tcell/logs/tcell_agent.log')
12
- )
13
- expect(configuration.config_filename).to eq(
14
- File.join(Dir.getwd, 'config/tcell_agent.config')
15
- )
11
+ expect(config.should_instrument?).to be_falsey
16
12
  end
17
13
  end
18
-
19
- context 'TCELL_AGENT_HOME defined' do
20
- it 'should set config filename to default, cache file and log file are updated' do
21
- old_tcell_agent_home = ENV['TCELL_AGENT_HOME']
22
-
23
- ENV['TCELL_AGENT_HOME'] = 'spec_tcell_home'
24
-
25
- configuration = Configuration.new
26
-
27
- expect(configuration.log_filename).to eq(
28
- 'spec_tcell_home/logs/tcell_agent.log'
29
- )
30
- expect(configuration.config_filename).to eq(
31
- File.join(Dir.getwd, 'config/tcell_agent.config')
32
- )
33
-
34
- ENV['TCELL_AGENT_HOME'] = old_tcell_agent_home
35
- end
36
- end
37
-
38
- context 'TCELL_AGENT_HOME and TCELL_AGENT_LOG_DIR defined' do
39
- it 'should set config filename to default, cache file and log file are updated' do
40
- old_tcell_agent_home = ENV['TCELL_AGENT_HOME']
41
- old_tcell_agent_log_dir = ENV['TCELL_AGENT_LOG_DIR']
42
-
43
- ENV['TCELL_AGENT_HOME'] = 'spec_tcell_home'
44
- ENV['TCELL_AGENT_LOG_DIR'] = 'spec_tcell_log_dir'
45
-
46
- configuration = Configuration.new
47
-
48
- expect(configuration.log_filename).to eq(
49
- 'spec_tcell_log_dir/tcell_agent.log'
50
- )
51
- expect(configuration.config_filename).to eq(
52
- File.join(Dir.getwd, 'config/tcell_agent.config')
53
- )
54
-
55
- ENV['TCELL_AGENT_HOME'] = old_tcell_agent_home
56
- ENV['TCELL_AGENT_LOG_DIR'] = old_tcell_agent_log_dir
57
- end
58
- end
59
-
60
- context 'TCELL_AGENT_HOME, TCELL_AGENT_LOG_DIR, and TCELL_AGENT_CONFIG defined ' do
61
- it 'should update config filename, cache file, and log file' do
62
- old_tcell_agent_home = ENV['TCELL_AGENT_HOME']
63
- old_tcell_agent_log_dir = ENV['TCELL_AGENT_LOG_DIR']
64
- old_config_filename = ENV['TCELL_AGENT_CONFIG']
65
-
66
- ENV['TCELL_AGENT_HOME'] = 'spec_tcell_home'
67
- ENV['TCELL_AGENT_LOG_DIR'] = 'spec_tcell_log_dir'
68
- ENV['TCELL_AGENT_CONFIG'] = 'spec_config/tcell_agent.config'
69
-
70
- configuration = Configuration.new
71
-
72
- expect(configuration.log_filename).to eq(
73
- 'spec_tcell_log_dir/tcell_agent.log'
74
- )
75
- expect(configuration.config_filename).to eq(
76
- 'spec_config/tcell_agent.config'
77
- )
78
-
79
- ENV['TCELL_AGENT_HOME'] = old_tcell_agent_home
80
- ENV['TCELL_AGENT_LOG_DIR'] = old_tcell_agent_log_dir
81
- ENV['TCELL_AGENT_CONFIG'] = old_config_filename
82
- end
83
- end
84
- end
85
-
86
- describe '#data_exposure' do
87
- context 'no data_exposure defined' do
88
- it 'should set max_data_ex_db_records_per_request to default' do
89
- no_data_ex = double(
90
- 'no_data_ex',
91
- :read => {
92
- :version => 1,
93
- :applications => [
94
- :app_id => 'app_id',
95
- :name => 'test',
96
- :api_key => 'api_key'
97
- ]
98
- }.to_json
99
- )
100
- expect(File).to receive(:file?).with(
101
- File.join(Dir.getwd, 'no_data_ex.config')
102
- ).and_return(true)
103
- expect(File).to receive(:open).with(
104
- File.join(Dir.getwd, 'no_data_ex.config')
105
- ).and_return(no_data_ex)
106
- configuration = Configuration.new('no_data_ex.config')
107
-
108
- expect(configuration.max_data_ex_db_records_per_request).to eq(1000)
109
- end
110
- end
111
-
112
- context 'data_exposure is empty' do
113
- it 'should set max_data_ex_db_records_per_request to default' do
114
- no_data_ex = double(
115
- 'no_data_ex',
116
- :read => {
117
- :version => 1,
118
- :applications => [
119
- :app_id => 'app_id',
120
- :name => 'test',
121
- :api_key => 'api_key',
122
- :data_exposure => {}
123
- ]
124
- }.to_json
125
- )
126
- expect(File).to receive(:file?).with(
127
- File.join(Dir.getwd, 'no_data_ex.config')
128
- ).and_return(true)
129
- expect(File).to receive(:open).with(
130
- File.join(Dir.getwd, 'no_data_ex.config')
131
- ).and_return(no_data_ex)
132
- configuration = Configuration.new('no_data_ex.config')
133
-
134
- expect(configuration.max_data_ex_db_records_per_request).to eq(1000)
14
+ context 'with the agent enabled' do
15
+ context 'with all instrumentation enabled' do
16
+ context 'with no parameters' do
17
+ it 'should return true' do
18
+ config = Configuration.new
19
+ config.enabled = true
20
+ config.instrument = true
21
+
22
+ expect(config.should_instrument?).to be_truthy
23
+ end
24
+ end
25
+ context 'with parameters' do
26
+ it 'should return true' do
27
+ config = Configuration.new
28
+ config.enabled = true
29
+ config.instrument = true
30
+ config.disabled_instrumentation = Set.new
31
+
32
+ expect(config.should_instrument?('devise')).to be_truthy
33
+ end
34
+ end
135
35
  end
136
- end
36
+ context 'with auth frameworks disabled' do
37
+ it 'should return false' do
38
+ config = Configuration.new
39
+ config.disabled_instrumentation = Set.new(%w[authlogic devise doorkeeper])
137
40
 
138
- context 'data_exposure contains an override' do
139
- it 'should set max_data_ex_db_records_per_request to override' do
140
- no_data_ex = double(
141
- 'no_data_ex',
142
- :read => {
143
- :version => 1,
144
- :applications => [
145
- :app_id => 'app_id',
146
- :name => 'test',
147
- :api_key => 'api_key',
148
- :data_exposure => {
149
- :max_data_ex_db_records_per_request => 5000
150
- }
151
- ]
152
- }.to_json
153
- )
154
- expect(File).to receive(:file?).with(
155
- File.join(Dir.getwd, 'no_data_ex.config')
156
- ).and_return(true)
157
- expect(File).to receive(:open).with(
158
- File.join(Dir.getwd, 'no_data_ex.config')
159
- ).and_return(no_data_ex)
160
- configuration = Configuration.new('no_data_ex.config')
161
-
162
- expect(configuration.max_data_ex_db_records_per_request).to eq(5000)
41
+ expect(config.should_instrument?('devise')).to be_falsey
42
+ end
163
43
  end
164
44
  end
165
45
  end
166
-
167
- describe '#allow_payloads' do
168
- context 'setting it via config' do
169
- context 'using allow_payloads' do
170
- it 'should be false' do
171
- allow_payloads_enabled = double(
172
- 'no_data_ex',
173
- :read => {
174
- :version => 1,
175
- :applications => [
176
- :app_id => 'app_id',
177
- :api_key => 'api_key',
178
- :allow_payloads => false
179
- ]
180
- }.to_json
181
- )
182
- expect(File).to receive(:file?).with(
183
- File.join(Dir.getwd, 'config/tcell_agent.config')
184
- ).and_return(true)
185
- expect(File).to receive(:open).with(
186
- File.join(Dir.getwd, 'config/tcell_agent.config')
187
- ).and_return(allow_payloads_enabled)
188
-
189
- configuration = Configuration.new
190
-
191
- expect(configuration.allow_payloads).to eq(false)
192
- end
46
+ describe 'populate_configuration' do
47
+ context 'with a poor native_agent_config_response' do
48
+ it 'should not throw an error' do
49
+ native_agent_config_response = {}
50
+
51
+ config = Configuration.new
52
+ expect do
53
+ config.populate_configuration(native_agent_config_response)
54
+ end.not_to raise_error
193
55
  end
194
56
  end
195
-
196
- context 'setting it via env var' do
197
- context 'TCELL_AGENT_ALLOW_PAYLOADS overrides everything else' do
198
- it 'should be false' do
199
- old_tcell_agent_allow_payloads = ENV['TCELL_AGENT_ALLOW_PAYLOADS']
200
-
201
- ENV['TCELL_AGENT_ALLOW_PAYLOADS'] = 'false'
202
-
203
- allow_payloads_enabled = double(
204
- 'no_data_ex',
205
- :read => {
206
- :version => 1,
207
- :applications => [
208
- :app_id => 'app_id',
209
- :api_key => 'api_key',
210
- :allow_payloads => true
211
- ]
212
- }.to_json
213
- )
214
- expect(File).to receive(:file?).with(
215
- File.join(Dir.getwd, 'config/tcell_agent.config')
216
- ).and_return(true)
217
- expect(File).to receive(:open).with(
218
- File.join(Dir.getwd, 'config/tcell_agent.config')
219
- ).and_return(allow_payloads_enabled)
220
-
221
- configuration = Configuration.new
222
-
223
- ENV['TCELL_AGENT_ALLOW_PAYLOADS'] = old_tcell_agent_allow_payloads
224
-
225
- expect(configuration.allow_payloads).to eq(false)
226
- end
57
+ context 'with an elaborate native_agent_config_response' do
58
+ it 'should set all the correct configurations' do
59
+ native_agent_config_response = { 'enabled' => true,
60
+ 'disabled_instrumentation' => %w[devise doorkeeper],
61
+ 'update_policy' => 'true',
62
+ 'applications' => { 'first' => { 'app_id' => 'app_id_placeholder',
63
+ 'api_key' => 'api_key_paceholder',
64
+ 'hmac_key' => 'hmac_key_placeholder',
65
+ 'password_hmac_key' => 'password_hmac_key_placeholder',
66
+ 'proxy_config' => { 'reverse_proxy' => true,
67
+ 'reverse_proxy_ip_address_header' => 'X-Forwarded-For' } } },
68
+ 'endpoint_config' => { 'api_url' => 'https://us.agent.tcell.insight.rapid7.com/api/v1' },
69
+ 'ruby_config' => { 'enable_policy_polling' => true } }
70
+
71
+ config = Configuration.new
72
+ config.populate_configuration(native_agent_config_response)
73
+
74
+ expect(config.disabled_instrumentation).to be_a(Set)
75
+ expect(config.disabled_instrumentation).to include('devise', 'doorkeeper')
76
+ expect(config.enable_intercept_requests).to be_truthy
227
77
  end
228
78
  end
229
79
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ def test_rails
4
+ expect(Rails::Server.instance_methods.include?(:tcell_build_app)).to be_truthy
5
+ end
6
+
7
+ def test_thin
8
+ expect(Thin::Server.instance_methods.include?(:original_start)).to be_truthy
9
+ end
10
+
11
+ def test_unicorn
12
+ expect(Unicorn::HttpServer::START_CTX[0]).to be_falsy
13
+ expect(Unicorn::HttpServer.instance_methods.include?(:tcell_init_worker_process)).to be_truthy
14
+ expect(Unicorn::HttpServer.instance_methods.include?(:tcell_load_config!)).to be_truthy
15
+ end
16
+
17
+ def test_passenger
18
+ expect(PhusionPassenger::LoaderSharedHelpers.instance_methods.include?(:tcell_before_handling_requests))
19
+ end
20
+
21
+ def test_puma
22
+ expect(Puma.cli_config.options[:preload_app]).to be_falsey
23
+ expect(Puma::Server.instance_methods.include?(:tcell_original_run)).to be_truthy
24
+ end
25
+
26
+ def test_server(filenames, funcs)
27
+ fork do
28
+ filenames.each do |file|
29
+ load file
30
+ end
31
+
32
+ load 'tcell_agent/instrument_servers.rb'
33
+
34
+ funcs.each do |func|
35
+ method(func).call
36
+ end
37
+ end
38
+ end
39
+
40
+ describe 'instrument_servers' do
41
+ context 'with single server dependency' do
42
+ context 'with webrick server' do
43
+ it 'should instrument Webrick' do
44
+ mocks = ['spec/support/server_mocks/rails_mock.rb']
45
+ tests = [:test_rails]
46
+ test_server(mocks, tests)
47
+ end
48
+ end
49
+
50
+ context 'with Thin server' do
51
+ it 'should instrument Thin' do
52
+ mocks = ['spec/support/server_mocks/thin_mock.rb']
53
+ tests = [:test_thin]
54
+ test_server(mocks, tests)
55
+ end
56
+ end
57
+
58
+ context 'with Puma server' do
59
+ it 'should instrument Puma' do
60
+ mocks = ['spec/support/server_mocks/puma_mock.rb']
61
+ tests = [:test_puma]
62
+ test_server(mocks, tests)
63
+ end
64
+ end
65
+
66
+ context 'with Unicorn server' do
67
+ it 'should instrument Unicorn' do
68
+ mocks = ['spec/support/server_mocks/unicorn_mock.rb']
69
+ tests = [:test_unicorn]
70
+ test_server(mocks, tests)
71
+ end
72
+ end
73
+
74
+ context 'with Passenger server' do
75
+ it 'should instrument Unicorn' do
76
+ mocks = ['spec/support/server_mocks/passenger_mock.rb']
77
+ tests = [:test_passenger]
78
+ test_server(mocks, tests)
79
+ end
80
+ end
81
+ end
82
+ context 'with multiple server dependencies' do
83
+ it 'should instrument all servers available' do
84
+ mocks = ['spec/support/server_mocks/rails_mock.rb',
85
+ 'spec/support/server_mocks/thin_mock.rb',
86
+ 'spec/support/server_mocks/puma_mock.rb',
87
+ 'spec/support/server_mocks/unicorn_mock.rb',
88
+ 'spec/support/server_mocks/passenger_mock.rb']
89
+
90
+ tests = %i[test_rails test_thin test_puma test_unicorn test_passenger]
91
+
92
+ test_server(mocks, tests)
93
+ end
94
+ end
95
+ end
@@ -262,10 +262,10 @@ describe IO do
262
262
  IO.popen(@env, %w[echo test], 'w+', :unsetenv_others => true)
263
263
 
264
264
  expect(TCellAgent::Cmdi).to receive(:block_command?).with('echo test')
265
- IO.popen([@env, 'echo', 'test', :unsetenv_others => true], 'w+')
265
+ IO.popen([@env, 'echo', 'test', { :unsetenv_others => true }], 'w+')
266
266
 
267
267
  expect(TCellAgent::Cmdi).to receive(:block_command?).with('echo test')
268
- IO.popen(@env, [@env, 'echo', 'test', :unsetenv_others => true], 'w+', :err => %i[child out])
268
+ IO.popen(@env, [@env, 'echo', 'test', { :unsetenv_others => true }], 'w+', :err => %i[child out])
269
269
  end
270
270
  end
271
271
  end
@@ -147,5 +147,55 @@ module TCellAgent
147
147
  end
148
148
  end
149
149
  end
150
+ describe '.parse_command_from_open' do
151
+ context 'with empty parameters' do
152
+ it 'should not return a command' do
153
+ cmd = TCellAgent::Cmdi.parse_command_from_open
154
+ expect(cmd).to eq('')
155
+ end
156
+ end
157
+ context 'with empty array' do
158
+ it 'should not return a command' do
159
+ args = []
160
+ cmd = TCellAgent::Cmdi.parse_command_from_open(*args)
161
+ expect(cmd).to eq('')
162
+ end
163
+ end
164
+ context 'with a string command' do
165
+ context 'with an empty string' do
166
+ it 'should return an empty string' do
167
+ cmd = TCellAgent::Cmdi.parse_command_from_open('')
168
+ expect(cmd).to eq('')
169
+ end
170
+ end
171
+ context 'with an empty command' do
172
+ it 'should return an empty string' do
173
+ cmd = TCellAgent::Cmdi.parse_command_from_open('|')
174
+ expect(cmd).to eq('')
175
+ end
176
+ end
177
+ context 'with a non-empty command' do
178
+ it 'should parse the command properly' do
179
+ cmd = TCellAgent::Cmdi.parse_command_from_open('|echo')
180
+ expect(cmd).to eq('echo')
181
+
182
+ cmd = TCellAgent::Cmdi.parse_command_from_open('|ls -l /tmp')
183
+ expect(cmd).to eq('ls -l /tmp')
184
+ end
185
+ end
186
+ end
187
+ context 'with a filename argument' do
188
+ it 'should not return a command' do
189
+ cmd = TCellAgent::Cmdi.parse_command_from_open('/tmp')
190
+ expect(cmd).to eq('')
191
+ end
192
+ end
193
+ context 'with a non-string first argument' do
194
+ it 'should return an empty string' do
195
+ cmd = TCellAgent::Cmdi.parse_command_from_open({})
196
+ expect(cmd).to eq('')
197
+ end
198
+ end
199
+ end
150
200
  end
151
201
  end