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.
- checksums.yaml +4 -4
- data/LICENSE +2 -2
- data/bin/tcell_agent +41 -150
- data/lib/tcell_agent/agent.rb +87 -52
- data/lib/tcell_agent/config_initializer.rb +63 -0
- data/lib/tcell_agent/configuration.rb +72 -267
- data/lib/tcell_agent/hooks/login_fraud.rb +1 -1
- data/lib/tcell_agent/instrument_servers.rb +14 -18
- data/lib/tcell_agent/instrumentation/cmdi.rb +47 -15
- data/lib/tcell_agent/instrumentation/lfi.rb +72 -15
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/file.rb +21 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/io.rb +75 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_2/kernel.rb +80 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/file.rb +21 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/io.rb +75 -0
- data/lib/tcell_agent/instrumentation/monkey_patches/ruby_3/kernel.rb +80 -0
- data/lib/tcell_agent/instrumentation.rb +14 -6
- data/lib/tcell_agent/logger.rb +3 -4
- data/lib/tcell_agent/policies/command_injection_policy.rb +1 -1
- data/lib/tcell_agent/policies/dataloss_policy.rb +15 -8
- data/lib/tcell_agent/policies/headers_policy.rb +2 -2
- data/lib/tcell_agent/policies/patches_policy.rb +8 -4
- data/lib/tcell_agent/policies/policies_manager.rb +1 -0
- data/lib/tcell_agent/policies/policy_polling.rb +4 -3
- data/lib/tcell_agent/rails/auth/authlogic.rb +49 -44
- data/lib/tcell_agent/rails/auth/authlogic_helper.rb +20 -0
- data/lib/tcell_agent/rails/auth/devise.rb +103 -102
- data/lib/tcell_agent/rails/auth/devise_helper.rb +29 -0
- data/lib/tcell_agent/rails/auth/doorkeeper.rb +54 -57
- data/lib/tcell_agent/{userinfo.rb → rails/auth/userinfo.rb} +0 -0
- data/lib/tcell_agent/rails/better_ip.rb +7 -19
- data/lib/tcell_agent/rails/csrf_exception.rb +0 -8
- data/lib/tcell_agent/rails/dlp/process_request.rb +5 -0
- data/lib/tcell_agent/rails/dlp.rb +58 -56
- data/lib/tcell_agent/rails/dlp_handler.rb +9 -10
- data/lib/tcell_agent/rails/js_agent_insert.rb +2 -3
- data/lib/tcell_agent/rails/middleware/context_middleware.rb +2 -1
- data/lib/tcell_agent/rails/middleware/global_middleware.rb +3 -4
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +1 -0
- data/lib/tcell_agent/rails/{on_start.rb → railties/tcell_agent_railties.rb} +9 -16
- data/lib/tcell_agent/rails/railties/tcell_agent_unicorn_railties.rb +8 -0
- data/lib/tcell_agent/rails/routes/grape.rb +5 -12
- data/lib/tcell_agent/rails/routes.rb +6 -9
- data/lib/tcell_agent/rails/settings_reporter.rb +3 -6
- data/lib/tcell_agent/rails/tcell_body_proxy.rb +4 -7
- data/lib/tcell_agent/routes/table.rb +3 -0
- data/lib/tcell_agent/rust/agent_config.rb +62 -33
- data/lib/tcell_agent/rust/{libtcellagent-4.14.0.so → libtcellagent-alpine.so} +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-4.14.0.dylib → libtcellagent-x64.dll} +0 -0
- data/lib/tcell_agent/rust/{libtcellagent-alpine-4.14.0.so → libtcellagent.dylib} +0 -0
- data/lib/tcell_agent/rust/libtcellagent.so +0 -0
- data/lib/tcell_agent/rust/models.rb +9 -0
- data/lib/tcell_agent/rust/native_agent.rb +61 -51
- data/lib/tcell_agent/rust/native_library.rb +8 -10
- data/lib/tcell_agent/sensor_events/server_agent.rb +3 -100
- data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +1 -0
- data/lib/tcell_agent/servers/puma.rb +30 -13
- data/lib/tcell_agent/servers/rack_puma_handler.rb +33 -0
- data/lib/tcell_agent/servers/rails_server.rb +4 -4
- data/lib/tcell_agent/servers/unicorn.rb +1 -1
- data/lib/tcell_agent/servers/webrick.rb +12 -3
- data/lib/tcell_agent/settings_reporter.rb +0 -93
- data/lib/tcell_agent/sinatra.rb +1 -0
- data/lib/tcell_agent/tcell_context.rb +16 -7
- data/lib/tcell_agent/utils/headers.rb +0 -1
- data/lib/tcell_agent/utils/strings.rb +2 -2
- data/lib/tcell_agent/version.rb +1 -1
- data/lib/tcell_agent.rb +8 -16
- data/spec/cruby_spec_helper.rb +26 -0
- data/spec/lib/tcell_agent/configuration_spec.rb +62 -212
- data/spec/lib/tcell_agent/instrument_servers_spec.rb +95 -0
- data/spec/lib/tcell_agent/instrumentation/cmdi/io_cmdi_spec.rb +2 -2
- data/spec/lib/tcell_agent/{cmdi_spec.rb → instrumentation/cmdi_spec.rb} +50 -0
- data/spec/lib/tcell_agent/instrumentation/lfi/file_lfi_spec.rb +211 -272
- data/spec/lib/tcell_agent/instrumentation/lfi/io_lfi_spec.rb +213 -223
- data/spec/lib/tcell_agent/instrumentation/lfi/kernel_lfi_spec.rb +95 -61
- data/spec/lib/tcell_agent/instrumentation/lfi_spec.rb +120 -2
- data/spec/lib/tcell_agent/patches_spec.rb +2 -1
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +1 -2
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +5 -6
- data/spec/lib/tcell_agent/policies/patches_policy_spec.rb +21 -2
- data/spec/lib/tcell_agent/policies/policies_manager_spec.rb +1 -1
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +13 -8
- data/spec/lib/tcell_agent/rails/better_ip_spec.rb +9 -11
- data/spec/lib/tcell_agent/rails/csrf_exception_spec.rb +6 -6
- data/spec/lib/tcell_agent/rails/dlp_spec.rb +1 -0
- data/spec/lib/tcell_agent/rails/js_agent_insert_spec.rb +10 -2
- data/spec/lib/tcell_agent/rails/middleware/tcell_body_proxy_spec.rb +2 -1
- data/spec/lib/tcell_agent/rails/routes/route_id_spec.rb +4 -4
- data/spec/lib/tcell_agent/rust/agent_config_spec.rb +27 -0
- data/spec/lib/tcell_agent/settings_reporter_spec.rb +2 -89
- data/spec/lib/tcell_agent/tcell_context_spec.rb +6 -5
- data/spec/spec_helper.rb +9 -1
- data/spec/support/builders.rb +8 -7
- data/spec/support/server_mocks/passenger_mock.rb +7 -0
- data/spec/support/server_mocks/puma_mock.rb +21 -0
- data/spec/support/server_mocks/rails_mock.rb +7 -0
- data/spec/support/server_mocks/thin_mock.rb +7 -0
- data/spec/support/server_mocks/unicorn_mock.rb +11 -0
- data/spec/support/shared_spec.rb +29 -0
- data/tcell_agent.gemspec +14 -14
- metadata +46 -29
- data/Rakefile +0 -18
- data/lib/tcell_agent/authlogic.rb +0 -23
- data/lib/tcell_agent/config/unknown_options.rb +0 -119
- data/lib/tcell_agent/devise.rb +0 -33
- data/lib/tcell_agent/instrumentation/monkey_patches/file.rb +0 -25
- data/lib/tcell_agent/instrumentation/monkey_patches/io.rb +0 -123
- data/lib/tcell_agent/instrumentation/monkey_patches/kernel.rb +0 -159
- data/lib/tcell_agent/rails/start_agent_after_initializers.rb +0 -12
- data/lib/tcell_agent/rust/tcellagent-4.14.0.dll +0 -0
- data/spec/lib/tcell_agent/config/unknown_options_spec.rb +0 -195
|
@@ -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
|
|
|
@@ -84,6 +80,7 @@ module TCellAgent
|
|
|
84
80
|
normalized_column_names[namespaced_column_name] = column_name
|
|
85
81
|
|
|
86
82
|
next unless column_name && (!namespace || namespace == table_name)
|
|
83
|
+
|
|
87
84
|
rules = dlp_policy.get_actions_for_table(
|
|
88
85
|
database_name,
|
|
89
86
|
'*',
|
|
@@ -194,6 +191,7 @@ module TCellAgent
|
|
|
194
191
|
results[0...TCellAgent.configuration.max_data_ex_db_records_per_request].each do |record|
|
|
195
192
|
column_name_to_rules.each do |column_name, rules|
|
|
196
193
|
next unless rules
|
|
194
|
+
|
|
197
195
|
rules.each do |rule|
|
|
198
196
|
tcell_context.add_response_db_filter(
|
|
199
197
|
record[column_name.to_sym],
|
|
@@ -228,9 +226,15 @@ module TCellAgent
|
|
|
228
226
|
)
|
|
229
227
|
tcell_data = request_env[TCellAgent::Instrumentation::TCELL_ID]
|
|
230
228
|
if tcell_data && result.is_a?(ActiveRecord::StatementInvalid)
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
229
|
+
if message.is_a? Hash
|
|
230
|
+
tcell_data.sql_exceptions.push(
|
|
231
|
+
{ 'exception_name' => result.class.name, 'exception_payload' => message[:message] }
|
|
232
|
+
)
|
|
233
|
+
else
|
|
234
|
+
tcell_data.sql_exceptions.push(
|
|
235
|
+
{ 'exception_name' => result.class.name, 'exception_payload' => message }
|
|
236
|
+
)
|
|
237
|
+
end
|
|
234
238
|
end
|
|
235
239
|
end
|
|
236
240
|
end
|
|
@@ -253,7 +257,7 @@ module TCellAgent
|
|
|
253
257
|
end
|
|
254
258
|
|
|
255
259
|
ActiveRecord::Querying.module_eval do
|
|
256
|
-
if ::Rails::VERSION::MAJOR
|
|
260
|
+
if ::Rails::VERSION::MAJOR >= 5
|
|
257
261
|
alias_method :tcell_find_by_sql, :find_by_sql
|
|
258
262
|
def find_by_sql(*args)
|
|
259
263
|
results = tcell_find_by_sql(*args)
|
|
@@ -299,31 +303,29 @@ module TCellAgent
|
|
|
299
303
|
def log_enforce(tcell_context, sanitize_string)
|
|
300
304
|
if TCellAgent.configuration.should_instrument? &&
|
|
301
305
|
TCellAgent.configuration.should_intercept_requests?
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
send_event = true
|
|
315
|
-
end
|
|
316
|
-
m
|
|
317
|
-
end
|
|
318
|
-
if send_event
|
|
319
|
-
TCellAgent.send_event(
|
|
320
|
-
TCellAgent::SensorEvents::DlpEvent.new(
|
|
321
|
-
tcell_context.route_id,
|
|
322
|
-
tcell_context.uri,
|
|
323
|
-
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG
|
|
324
|
-
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
|
325
|
-
)
|
|
306
|
+
session_id_actions = get_actions_for_session_id
|
|
307
|
+
if tcell_context && tcell_context.session_id && session_id_actions
|
|
308
|
+
send_event = false
|
|
309
|
+
sanitize_string.gsub!(tcell_context.session_id) do |m|
|
|
310
|
+
if session_id_actions.log_redact
|
|
311
|
+
send_event = true
|
|
312
|
+
m = '[session_id]'
|
|
313
|
+
elsif session_id_actions.log_hash
|
|
314
|
+
send_event = true
|
|
315
|
+
m = '[hash]'
|
|
316
|
+
elsif session_id_actions.log_event
|
|
317
|
+
send_event = true
|
|
326
318
|
end
|
|
319
|
+
m
|
|
320
|
+
end
|
|
321
|
+
if send_event
|
|
322
|
+
TCellAgent.send_event(
|
|
323
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
|
324
|
+
tcell_context.route_id,
|
|
325
|
+
tcell_context.uri,
|
|
326
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG
|
|
327
|
+
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
|
328
|
+
)
|
|
327
329
|
end
|
|
328
330
|
end
|
|
329
331
|
end
|
|
@@ -334,32 +336,32 @@ module TCellAgent
|
|
|
334
336
|
def response_body_enforce(tcell_context, sanitize_string)
|
|
335
337
|
if TCellAgent.configuration.should_instrument? &&
|
|
336
338
|
TCellAgent.configuration.should_intercept_requests?
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
end
|
|
351
|
-
m
|
|
339
|
+
session_id_actions = get_actions_for_session_id
|
|
340
|
+
if tcell_context && tcell_context.session_id && session_id_actions
|
|
341
|
+
send_event = false
|
|
342
|
+
sanitize_string.gsub!(tcell_context.session_id) do |m|
|
|
343
|
+
# rubocop:disable Lint/DuplicateBranch
|
|
344
|
+
if session_id_actions.body_redact
|
|
345
|
+
# m = "[session_id]"
|
|
346
|
+
send_event = true
|
|
347
|
+
elsif session_id_actions.body_hash
|
|
348
|
+
# m = "[hash]"
|
|
349
|
+
send_event = true
|
|
350
|
+
elsif session_id_actions.body_event
|
|
351
|
+
send_event = true
|
|
352
352
|
end
|
|
353
|
+
# rubocop:enable Lint/DuplicateBranch
|
|
354
|
+
m
|
|
353
355
|
end
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
)
|
|
362
|
-
|
|
356
|
+
end
|
|
357
|
+
if send_event
|
|
358
|
+
TCellAgent.send_event(
|
|
359
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
|
360
|
+
tcell_context.route_id,
|
|
361
|
+
tcell_context.uri,
|
|
362
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY
|
|
363
|
+
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
|
364
|
+
)
|
|
363
365
|
end
|
|
364
366
|
end
|
|
365
367
|
|
|
@@ -39,19 +39,18 @@ module TCellAgent
|
|
|
39
39
|
|
|
40
40
|
TCellAgent::Instrumentation.safe_block('DLP Handler get handler and context') do
|
|
41
41
|
if TCellAgent.configuration.should_instrument? &&
|
|
42
|
-
TCellAgent.configuration.should_intercept_requests?
|
|
42
|
+
TCellAgent.configuration.should_intercept_requests? &&
|
|
43
|
+
TCellAgent::Utils::Rails.processable_response?(response_headers)
|
|
43
44
|
|
|
44
45
|
# do all this work so that dlp doesn't run at all unless it's on and there
|
|
45
46
|
# are rules to run
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
end
|
|
47
|
+
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DATALOSS)
|
|
48
|
+
if dlp_policy && dlp_policy.get_actions_for_session_id
|
|
49
|
+
tcell_context = request.env[TCellAgent::Instrumentation::TCELL_ID]
|
|
50
|
+
if tcell_context && tcell_context.session_id
|
|
51
|
+
dlp_handler = proc { |tc, resp|
|
|
52
|
+
handle_dlp!(tc, resp)
|
|
53
|
+
}
|
|
55
54
|
end
|
|
56
55
|
end
|
|
57
56
|
end
|
|
@@ -4,8 +4,7 @@ module TCellAgent
|
|
|
4
4
|
module Instrumentation
|
|
5
5
|
module Rails
|
|
6
6
|
module JSAgent
|
|
7
|
-
HEAD_SEARCH_REGEX =
|
|
8
|
-
|
|
7
|
+
HEAD_SEARCH_REGEX = Regexp.new('(<head>|<head( |\n).*?>)', Regexp::IGNORECASE)
|
|
9
8
|
def self.insert_now(js_agent_handler, script_insert, rack_body, content_length)
|
|
10
9
|
TCellAgent::Instrumentation.safe_block('Handling JSAgent Insert Now') do
|
|
11
10
|
if js_agent_handler
|
|
@@ -32,7 +31,7 @@ module TCellAgent
|
|
|
32
31
|
TCellAgent::Instrumentation.safe_block('Handling JSAgent insert') do
|
|
33
32
|
new_response = response.sub(
|
|
34
33
|
TCellAgent::Instrumentation::Rails::JSAgent::HEAD_SEARCH_REGEX,
|
|
35
|
-
"
|
|
34
|
+
"\\1#{script_insert}"
|
|
36
35
|
)
|
|
37
36
|
end
|
|
38
37
|
|
|
@@ -26,7 +26,8 @@ module TCellAgent
|
|
|
26
26
|
env[TCellAgent::Instrumentation::TCELL_ID].path = request.path
|
|
27
27
|
env[TCellAgent::Instrumentation::TCELL_ID].user_agent = request.user_agent
|
|
28
28
|
env[TCellAgent::Instrumentation::TCELL_ID].referrer = request.referrer
|
|
29
|
-
env[TCellAgent::Instrumentation::TCELL_ID].remote_address =
|
|
29
|
+
env[TCellAgent::Instrumentation::TCELL_ID].remote_address = request.ip
|
|
30
|
+
env[TCellAgent::Instrumentation::TCELL_ID].reverse_proxy_header_value = TCellAgent::Utils::Rails.reverse_proxy_header(request)
|
|
30
31
|
if request.request_method
|
|
31
32
|
env[TCellAgent::Instrumentation::TCELL_ID].request_method = request.request_method
|
|
32
33
|
end
|
|
@@ -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,7 @@ module TCellAgent
|
|
|
24
24
|
def call(env)
|
|
25
25
|
if TCellAgent.configuration.should_intercept_requests?
|
|
26
26
|
request = Rack::Request.new(env)
|
|
27
|
+
|
|
27
28
|
TCellAgent::Instrumentation.safe_block('Setting session_id & user_id') do
|
|
28
29
|
if request.session
|
|
29
30
|
env[TCellAgent::Instrumentation::TCELL_ID].session_id =
|
|
@@ -41,9 +42,7 @@ module TCellAgent
|
|
|
41
42
|
end
|
|
42
43
|
end
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
response
|
|
45
|
+
@app.call(env)
|
|
47
46
|
end
|
|
48
47
|
end
|
|
49
48
|
end
|
|
@@ -39,6 +39,7 @@ module TCellAgent
|
|
|
39
39
|
TCellAgent::Instrumentation.safe_block('Handling headers') do
|
|
40
40
|
headers_policy = TCellAgent.policy(TCellAgent::PolicyTypes::HEADERS)
|
|
41
41
|
policy_headers = headers_policy.get_headers(
|
|
42
|
+
headers['Content-Type'],
|
|
42
43
|
request.env[TCellAgent::Instrumentation::TCELL_ID]
|
|
43
44
|
)
|
|
44
45
|
policy_headers.each do |header_info|
|
|
@@ -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
|
|
@@ -5,16 +5,11 @@ module TCellAgent
|
|
|
5
5
|
def self.grape_route?(route)
|
|
6
6
|
if defined?(Grape::API)
|
|
7
7
|
begin
|
|
8
|
-
if ::Rails::VERSION::MAJOR == 4 &&
|
|
9
|
-
|
|
10
|
-
route.app < Grape::API
|
|
11
|
-
else
|
|
12
|
-
# does app inherit from Grape::API?
|
|
13
|
-
route.app.app < Grape::API
|
|
14
|
-
end
|
|
8
|
+
return route.app < Grape::API if ::Rails::VERSION::MAJOR == 4 &&
|
|
9
|
+
::Rails::VERSION::MINOR < 2
|
|
15
10
|
|
|
16
|
-
return
|
|
17
|
-
rescue StandardError
|
|
11
|
+
return route.app.app < Grape::API
|
|
12
|
+
rescue StandardError
|
|
18
13
|
# do nothing
|
|
19
14
|
end
|
|
20
15
|
end
|
|
@@ -76,9 +71,7 @@ module TCellAgent
|
|
|
76
71
|
Grape::Endpoint.class_eval do
|
|
77
72
|
alias_method :tcell_call!, :call!
|
|
78
73
|
def call!(env)
|
|
79
|
-
if TCellAgent.configuration.
|
|
80
|
-
TCellAgent.configuration.should_intercept_requests?
|
|
81
|
-
|
|
74
|
+
if TCellAgent.configuration.should_intercept_requests?
|
|
82
75
|
TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
|
|
83
76
|
tcell_context = env[TCellAgent::Instrumentation::TCELL_ID]
|
|
84
77
|
if tcell_context && tcell_context.grape_mount_endpoint && respond_to?(:routes)
|
|
@@ -77,7 +77,7 @@ module TCellAgent
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def self.create_tcell_route(route)
|
|
80
|
-
return TCellRoute5.new(route) if route && ::Rails::VERSION::MAJOR
|
|
80
|
+
return TCellRoute5.new(route) if route && ::Rails::VERSION::MAJOR >= 5
|
|
81
81
|
return TCellRoute4.new(route) if route && ::Rails::VERSION::MAJOR < 5
|
|
82
82
|
|
|
83
83
|
TCellRoute.new
|
|
@@ -136,8 +136,7 @@ module TCellAgent
|
|
|
136
136
|
prepend_around_filter :tcell_around_filter_routes
|
|
137
137
|
end
|
|
138
138
|
def tcell_around_filter_routes
|
|
139
|
-
if TCellAgent.configuration.
|
|
140
|
-
TCellAgent.configuration.should_intercept_requests?
|
|
139
|
+
if TCellAgent.configuration.should_intercept_requests?
|
|
141
140
|
TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
|
|
142
141
|
_match, parameters, route = ::Rails.application.routes.router.recognize(request) { |r, _| r }.first
|
|
143
142
|
|
|
@@ -173,7 +172,7 @@ module TCellAgent
|
|
|
173
172
|
end
|
|
174
173
|
end
|
|
175
174
|
|
|
176
|
-
if ::Rails::VERSION::MAJOR
|
|
175
|
+
if ::Rails::VERSION::MAJOR >= 5
|
|
177
176
|
ActionDispatch::Journey::Routes.class_eval do
|
|
178
177
|
alias_method :tcell_add_route, :add_route
|
|
179
178
|
def add_route(name, mapping)
|
|
@@ -188,12 +187,11 @@ module TCellAgent
|
|
|
188
187
|
end
|
|
189
188
|
end
|
|
190
189
|
|
|
191
|
-
if ::Rails::VERSION::MAJOR
|
|
190
|
+
if ::Rails::VERSION::MAJOR >= 5 || (::Rails::VERSION::MAJOR == 4 && ::Rails::VERSION::MINOR >= 2)
|
|
192
191
|
ActionDispatch::Journey::Router.class_eval do
|
|
193
192
|
alias_method :tcell_serve, :serve
|
|
194
193
|
def serve(req)
|
|
195
|
-
if TCellAgent.configuration.
|
|
196
|
-
TCellAgent.configuration.should_intercept_requests?
|
|
194
|
+
if TCellAgent.configuration.should_intercept_requests?
|
|
197
195
|
TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
|
|
198
196
|
_match, parameters, route = find_routes(req).first
|
|
199
197
|
|
|
@@ -220,8 +218,7 @@ module TCellAgent
|
|
|
220
218
|
def call(env)
|
|
221
219
|
env['PATH_INFO'] = ActionDispatch::Journey::Router::Utils.normalize_path(env['PATH_INFO'])
|
|
222
220
|
|
|
223
|
-
if TCellAgent.configuration.
|
|
224
|
-
TCellAgent.configuration.should_intercept_requests?
|
|
221
|
+
if TCellAgent.configuration.should_intercept_requests?
|
|
225
222
|
TCellAgent::Instrumentation.safe_block('Determining Rails Route ID') do
|
|
226
223
|
_match, parameters, route = find_routes(env).first
|
|
227
224
|
|
|
@@ -6,12 +6,9 @@ require 'tcell_agent/sensor_events/server_agent'
|
|
|
6
6
|
module TCellAgent
|
|
7
7
|
module Instrumentation
|
|
8
8
|
module Rails
|
|
9
|
-
def self.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'Rails', ::Rails.version
|
|
13
|
-
)
|
|
14
|
-
)
|
|
9
|
+
def self.framework_details
|
|
10
|
+
{ 'app_framework' => 'Rails',
|
|
11
|
+
'app_framework_version' => ::Rails.version }
|
|
15
12
|
end
|
|
16
13
|
|
|
17
14
|
def self.send_settings
|
|
@@ -31,7 +31,6 @@ module TCellAgent
|
|
|
31
31
|
TCellAgent::Instrumentation.safe_block('Running AppSensor deferred due to streaming') do
|
|
32
32
|
if @meta_data
|
|
33
33
|
@meta_data.response_content_bytes_len = @content_length
|
|
34
|
-
|
|
35
34
|
appfirewall_policy = TCellAgent.policy(TCellAgent::PolicyTypes::APPSENSOR)
|
|
36
35
|
appfirewall_policy.check_appfirewall_injections(@meta_data)
|
|
37
36
|
end
|
|
@@ -54,18 +53,16 @@ module TCellAgent
|
|
|
54
53
|
@body.respond_to?(method_name, include_all)
|
|
55
54
|
end
|
|
56
55
|
|
|
57
|
-
def method_missing(method_name, *args, &block)
|
|
56
|
+
def method_missing(method_name, *args, &block)
|
|
58
57
|
@body.__send__(method_name, *args, &block)
|
|
59
58
|
end
|
|
60
59
|
|
|
61
60
|
def process_body(body)
|
|
62
61
|
TCellAgent::Instrumentation.safe_block('Processing tcell body proxy body') do
|
|
63
62
|
chunked_response_match = nil
|
|
64
|
-
if body.class.name == 'String'
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@content_length += chunked_response_match.to_i(16)
|
|
68
|
-
end
|
|
63
|
+
if body.class.name == 'String' && body =~ /^([[:xdigit:]]+)(;.+)?\r\n/
|
|
64
|
+
chunked_response_match = Regexp.last_match(1)
|
|
65
|
+
@content_length += chunked_response_match.to_i(16)
|
|
69
66
|
end
|
|
70
67
|
|
|
71
68
|
new_body = body
|
|
@@ -2,6 +2,7 @@ module TCellAgent
|
|
|
2
2
|
module Routes
|
|
3
3
|
class FieldEndpoint
|
|
4
4
|
attr_accessor :discovered
|
|
5
|
+
|
|
5
6
|
def initialize
|
|
6
7
|
super()
|
|
7
8
|
@discovered = false
|
|
@@ -11,6 +12,7 @@ module TCellAgent
|
|
|
11
12
|
class RouteEndpoint
|
|
12
13
|
attr_accessor :database
|
|
13
14
|
attr_accessor :database_queries_discovered
|
|
15
|
+
|
|
14
16
|
def initialize
|
|
15
17
|
@database_queries_discovered = {}
|
|
16
18
|
@database = Hash.new do |d_h, d_k| # Database
|
|
@@ -27,6 +29,7 @@ module TCellAgent
|
|
|
27
29
|
|
|
28
30
|
class RouteTable
|
|
29
31
|
attr_accessor :routes
|
|
32
|
+
|
|
30
33
|
def initialize
|
|
31
34
|
@routes = Hash.new { |h, k| h[k] = RouteEndpoint.new }
|
|
32
35
|
end
|
|
@@ -1,48 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'tcell_agent/version'
|
|
4
|
+
require 'tcell_agent/rust/models'
|
|
2
5
|
|
|
3
6
|
module TCellAgent
|
|
4
7
|
module Rust
|
|
5
8
|
class AgentConfig < Hash
|
|
6
9
|
def initialize(configuration)
|
|
7
|
-
send_mode = 'Normal'
|
|
8
|
-
send_mode = 'Demo' if configuration.demomode
|
|
9
|
-
|
|
10
|
-
logging_options = configuration.clean_logging_options
|
|
11
|
-
unless configuration.js_agent_api_base_url
|
|
12
|
-
parsed_uri = URI.parse(configuration.tcell_api_url)
|
|
13
|
-
api_url = [parsed_uri.scheme, '://', parsed_uri.host]
|
|
14
|
-
api_url.push(":#{parsed_uri.port}") unless [80, 443].include?(parsed_uri.port)
|
|
15
|
-
configuration.js_agent_api_base_url = "#{api_url.join('')}/api/v1"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
self['disable_event_sending'] = !configuration.should_start_event_manager?
|
|
19
|
-
self['send_mode'] = send_mode
|
|
20
10
|
self['agent_type'] = 'Ruby'
|
|
21
11
|
self['agent_version'] = TCellAgent::VERSION
|
|
22
|
-
self['
|
|
23
|
-
self['
|
|
12
|
+
self['default_cache_dir'] = File.join(Dir.getwd, 'tcell/cache')
|
|
13
|
+
self['default_config_file_dir'] = File.join(Dir.getwd, 'config')
|
|
14
|
+
self['default_log_dir'] = File.join(Dir.getwd, 'tcell/logs')
|
|
15
|
+
self['default_preload_policy_file_dir'] = Dir.getwd
|
|
16
|
+
|
|
17
|
+
if defined?(ConfigInitializer)
|
|
18
|
+
overrides = Models.clean_nils(AgentConfigOverrides.new(configuration))
|
|
19
|
+
self['overrides'] = overrides
|
|
20
|
+
else
|
|
21
|
+
self['overrides'] = { 'applications' => [{ :enable_json_body_inspection => true }],
|
|
22
|
+
'config_file_path' => configuration.get_config_file_path }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
set_agent_details
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def set_agent_details
|
|
29
|
+
framework_details = if defined?(Rails)
|
|
30
|
+
TCellAgent::Instrumentation::Rails.framework_details
|
|
31
|
+
else
|
|
32
|
+
{}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
self['agent_details'] = { 'language' => 'Ruby',
|
|
36
|
+
'language_version' => RUBY_VERSION,
|
|
37
|
+
'app_framework' => framework_details['app_framework'],
|
|
38
|
+
'app_framework_version' => framework_details['app_framework_version'] }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class AgentConfigOverrides < Hash
|
|
43
|
+
def initialize(configuration)
|
|
44
|
+
applications = {
|
|
45
|
+
:allow_payloads => configuration.allow_payloads,
|
|
46
|
+
:api_key => configuration.api_key,
|
|
24
47
|
:app_id => configuration.app_id,
|
|
25
|
-
:
|
|
26
|
-
:tcell_api_url => configuration.tcell_api_url,
|
|
27
|
-
:tcell_input_url => configuration.tcell_input_url,
|
|
48
|
+
:enable_json_body_inspection => true,
|
|
28
49
|
:hmac_key => configuration.hmac_key,
|
|
50
|
+
:max_header_size => configuration.max_csp_header_bytes,
|
|
29
51
|
:password_hmac_key => configuration.password_hmac_key,
|
|
30
|
-
:
|
|
31
|
-
:
|
|
32
|
-
:js_agent_url => configuration.js_agent_url,
|
|
33
|
-
:cache_dir => configuration.cache_folder,
|
|
34
|
-
:log_dir => configuration.agent_log_dir,
|
|
35
|
-
:logging_options => logging_options,
|
|
36
|
-
:host_identifier => configuration.host_identifier,
|
|
37
|
-
:reverse_proxy_ip_address_header => configuration.reverse_proxy_ip_address_header,
|
|
38
|
-
:fetch_policies_from_tcell => configuration.should_start_policy_poll?,
|
|
39
|
-
:preload_policy_filename => configuration.preload_policy_filename
|
|
52
|
+
:reverse_proxy => configuration.reverse_proxy,
|
|
53
|
+
:reverse_proxy_ip_address_header => configuration.reverse_proxy_ip_address_header
|
|
40
54
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
self['
|
|
55
|
+
|
|
56
|
+
self['api_url'] = configuration.tcell_api_url
|
|
57
|
+
self['applications'] = [Models.clean_nils(applications)]
|
|
58
|
+
self['config_file_path'] = configuration.get_config_file_path
|
|
59
|
+
self['disabled_instrumentation'] = configuration.disabled_instrumentation
|
|
60
|
+
self['enabled'] = configuration.enabled
|
|
61
|
+
self['host_identifier'] = configuration.host_identifier
|
|
62
|
+
self['input_url'] = configuration.tcell_input_url
|
|
63
|
+
self['instrument'] = configuration.instrument
|
|
64
|
+
self['js_agent_api_url'] = configuration.js_agent_api_base_url
|
|
65
|
+
self['js_agent_url'] = configuration.js_agent_url
|
|
66
|
+
self['log_destination'] = configuration.logging_options[:destination]
|
|
67
|
+
self['log_dir'] = configuration.log_dir
|
|
68
|
+
self['log_enabled'] = configuration.logging_options[:enabled]
|
|
69
|
+
self['log_filename'] = configuration.logging_options[:log_filename]
|
|
70
|
+
self['log_level'] = configuration.logging_options[:level]
|
|
71
|
+
self['proxy_url'] = configuration.proxy_url
|
|
72
|
+
self['proxy_username'] = configuration.proxy_username
|
|
73
|
+
self['proxy_password'] = configuration.proxy_password
|
|
74
|
+
self['update_policy'] = configuration.fetch_policies_from_tcell
|
|
46
75
|
end
|
|
47
76
|
end
|
|
48
77
|
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|