tcell_agent 2.0.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) 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 +21 -10
  10. data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +20 -12
  11. data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +45 -102
  12. data/lib/tcell_agent/logger.rb +1 -2
  13. data/lib/tcell_agent/policies/command_injection_policy.rb +1 -1
  14. data/lib/tcell_agent/rails/auth/authlogic.rb +49 -44
  15. data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
  16. data/lib/tcell_agent/rails/auth/devise.rb +103 -102
  17. data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
  18. data/lib/tcell_agent/rails/auth/doorkeeper.rb +54 -58
  19. data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
  20. data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
  21. data/lib/tcell_agent/rails/dlp.rb +10 -8
  22. data/lib/tcell_agent/rails/middleware/global_middleware.rb +4 -1
  23. data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
  24. data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
  25. data/lib/tcell_agent/rails/routes.rb +6 -9
  26. data/lib/tcell_agent/rails/routes/grape.rb +4 -12
  27. data/lib/tcell_agent/rails/tcell_body_proxy.rb +0 -1
  28. data/lib/tcell_agent/rust/agent_config.rb +43 -32
  29. data/lib/tcell_agent/rust/{libtcellagent-4.14.0.dylib → libtcellagent-5.0.2.dylib} +0 -0
  30. data/lib/tcell_agent/rust/{libtcellagent-4.14.0.so → libtcellagent-5.0.2.so} +0 -0
  31. data/lib/tcell_agent/rust/{libtcellagent-alpine-4.14.0.so → libtcellagent-alpine-5.0.2.so} +0 -0
  32. data/lib/tcell_agent/rust/models.rb +9 -0
  33. data/lib/tcell_agent/rust/native_agent.rb +18 -0
  34. data/lib/tcell_agent/rust/native_library.rb +2 -1
  35. data/lib/tcell_agent/rust/{tcellagent-4.14.0.dll → tcellagent-5.0.2.dll} +0 -0
  36. data/lib/tcell_agent/servers/puma.rb +7 -7
  37. data/lib/tcell_agent/servers/rack_puma_handler.rb +23 -0
  38. data/lib/tcell_agent/servers/rails_server.rb +4 -4
  39. data/lib/tcell_agent/servers/unicorn.rb +1 -1
  40. data/lib/tcell_agent/servers/webrick.rb +0 -1
  41. data/lib/tcell_agent/settings_reporter.rb +0 -79
  42. data/lib/tcell_agent/tcell_context.rb +1 -1
  43. data/lib/tcell_agent/version.rb +1 -1
  44. data/spec/lib/tcell_agent/configuration_spec.rb +62 -212
  45. data/spec/lib/tcell_agent/instrument_servers_spec.rb +95 -0
  46. data/spec/lib/tcell_agent/{cmdi_spec.rb → instrumentation/cmdi_spec.rb} +50 -0
  47. data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +6 -0
  48. data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +19 -4
  49. data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +47 -2
  50. data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
  51. data/spec/lib/tcell_agent/settings_reporter_spec.rb +0 -73
  52. data/spec/spec_helper.rb +6 -0
  53. data/spec/support/builders.rb +6 -6
  54. data/spec/support/server_mocks/passenger_mock.rb +7 -0
  55. data/spec/support/server_mocks/puma_mock.rb +17 -0
  56. data/spec/support/server_mocks/rails_mock.rb +7 -0
  57. data/spec/support/server_mocks/thin_mock.rb +7 -0
  58. data/spec/support/server_mocks/unicorn_mock.rb +11 -0
  59. metadata +29 -16
  60. data/lib/tcell_agent/authlogic.rb +0 -23
  61. data/lib/tcell_agent/config/unknown_options.rb +0 -119
  62. data/lib/tcell_agent/devise.rb +0 -33
  63. data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
  64. data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -195
@@ -37,85 +37,6 @@ module TCellAgent
37
37
  )
38
38
  end
39
39
 
40
- TCellAgent::Instrumentation.safe_block('Instrumenting Initial Config') do
41
- TCellAgent.send_event(
42
- TCellAgent::SensorEvents::AgentSettingEvent.new(
43
- 'allow_payloads',
44
- (!!TCellAgent.configuration.allow_payloads).to_s # rubocop:disable Style/DoubleNegation
45
- )
46
- )
47
-
48
- TCellAgent.send_event(
49
- TCellAgent::SensorEvents::AgentSettingEvent.new(
50
- 'reverse_proxy',
51
- (!!TCellAgent.configuration.reverse_proxy).to_s # rubocop:disable Style/DoubleNegation
52
- )
53
- )
54
-
55
- # Because of all the diff ways to initialize the agent
56
- # some some of the following vars might not be set until
57
- # we call this method, so call this method to set all
58
- # the variables
59
- TCellAgent.configuration.log_filename
60
-
61
- TCellAgent.send_event(
62
- TCellAgent::SensorEvents::AgentSettingEvent.new(
63
- 'config_filename',
64
- TCellAgent.configuration.config_filename
65
- )
66
- )
67
- TCellAgent.send_event(
68
- TCellAgent::SensorEvents::AgentSettingEvent.new(
69
- 'logging_directory',
70
- TCellAgent.configuration.agent_log_dir
71
- )
72
- )
73
-
74
- TCellAgent.send_event(
75
- TCellAgent::SensorEvents::AgentSettingEvent.new(
76
- 'agent_home_directory',
77
- TCellAgent.configuration.agent_home_dir
78
- )
79
- )
80
-
81
- logging_options = TCellAgent.configuration.logging_options || {}
82
- use_default_setting = !logging_options.key?(:enabled) && !logging_options.key?('enabled')
83
- if use_default_setting || logging_options[:enabled] || logging_options['enabled']
84
- TCellAgent.send_event(
85
- TCellAgent::SensorEvents::AgentSettingEvent.new('logging_enabled', 'true')
86
- )
87
-
88
- TCellAgent.send_event(
89
- TCellAgent::SensorEvents::AgentSettingEvent.new(
90
- 'logging_level',
91
- logging_options[:level] || logging_options['level'] || 'INFO'
92
- )
93
- )
94
- else
95
- TCellAgent.send_event(
96
- TCellAgent::SensorEvents::AgentSettingEvent.new('logging_enabled', 'false')
97
- )
98
- end
99
-
100
- if TCellAgent.configuration.hmac_key
101
- TCellAgent.send_event(
102
- TCellAgent::SensorEvents::AgentSettingEvent.new(
103
- 'hmac_key_present',
104
- (!!TCellAgent.configuration.hmac_key).to_s # rubocop:disable Style/DoubleNegation
105
- )
106
- )
107
- end
108
-
109
- if TCellAgent.configuration.reverse_proxy
110
- TCellAgent.send_event(
111
- TCellAgent::SensorEvents::AgentSettingEvent.new(
112
- 'reverse_proxy_ip_address_header',
113
- TCellAgent.configuration.reverse_proxy_ip_address_header
114
- )
115
- )
116
- end
117
- end
118
-
119
40
  if defined?(::Rails)
120
41
  TCellAgent::Instrumentation.safe_block('Instrumenting routes') do
121
42
  TCellAgent::Instrumentation::Rails.instrument_routes
@@ -40,7 +40,7 @@ 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
46
  tcell_context.uri
@@ -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.2.1'.freeze
5
5
  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?(: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