tcell_agent 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +4 -0
- data/README.md +43 -0
- data/Rakefile +7 -0
- data/bin/tcell_agent +171 -0
- data/config/initializers/authlogic_auth.rb +51 -0
- data/config/initializers/devise_auth.rb +167 -0
- data/config/initializers/init.rb +8 -0
- data/lib/tcell_agent.rb +33 -0
- data/lib/tcell_agent/agent.rb +79 -0
- data/lib/tcell_agent/agent/event_processor.rb +133 -0
- data/lib/tcell_agent/agent/policy_manager.rb +138 -0
- data/lib/tcell_agent/agent/policy_types.rb +42 -0
- data/lib/tcell_agent/agent/static_agent.rb +22 -0
- data/lib/tcell_agent/api.rb +101 -0
- data/lib/tcell_agent/appsensor.rb +42 -0
- data/lib/tcell_agent/appsensor/cmdi.rb +32 -0
- data/lib/tcell_agent/appsensor/path_traversal.rb +33 -0
- data/lib/tcell_agent/appsensor/sqli.rb +55 -0
- data/lib/tcell_agent/appsensor/xss.rb +40 -0
- data/lib/tcell_agent/authlogic.rb +26 -0
- data/lib/tcell_agent/configuration.rb +148 -0
- data/lib/tcell_agent/dataloss.rb +0 -0
- data/lib/tcell_agent/devise.rb +83 -0
- data/lib/tcell_agent/instrumentation.rb +44 -0
- data/lib/tcell_agent/logger.rb +46 -0
- data/lib/tcell_agent/policies/add_script_tag_policy.rb +47 -0
- data/lib/tcell_agent/policies/appsensor_policy.rb +76 -0
- data/lib/tcell_agent/policies/clickjacking_policy.rb +113 -0
- data/lib/tcell_agent/policies/content_security_policy.rb +119 -0
- data/lib/tcell_agent/policies/dataloss_policy.rb +175 -0
- data/lib/tcell_agent/policies/honeytokens_policy.rb +67 -0
- data/lib/tcell_agent/policies/http_redirect_policy.rb +84 -0
- data/lib/tcell_agent/policies/http_tx_policy.rb +60 -0
- data/lib/tcell_agent/policies/login_fraud_policy.rb +42 -0
- data/lib/tcell_agent/policies/secure_headers_policy.rb +64 -0
- data/lib/tcell_agent/rails.rb +146 -0
- data/lib/tcell_agent/rails/devise.rb +0 -0
- data/lib/tcell_agent/rails/dlp.rb +204 -0
- data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +69 -0
- data/lib/tcell_agent/rails/middleware/context_middleware.rb +50 -0
- data/lib/tcell_agent/rails/middleware/global_middleware.rb +53 -0
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +176 -0
- data/lib/tcell_agent/rails/routes.rb +130 -0
- data/lib/tcell_agent/rails/settings_reporter.rb +40 -0
- data/lib/tcell_agent/sensor_events/app_config.rb +16 -0
- data/lib/tcell_agent/sensor_events/app_sensor.rb +240 -0
- data/lib/tcell_agent/sensor_events/dlp.rb +58 -0
- data/lib/tcell_agent/sensor_events/honeytokens.rb +16 -0
- data/lib/tcell_agent/sensor_events/login_fraud.rb +43 -0
- data/lib/tcell_agent/sensor_events/metrics.rb +24 -0
- data/lib/tcell_agent/sensor_events/sensor.rb +85 -0
- data/lib/tcell_agent/sensor_events/server_agent.rb +101 -0
- data/lib/tcell_agent/sensor_events/util/redirect_utils.rb +22 -0
- data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +153 -0
- data/lib/tcell_agent/sensor_events/util/utils.rb +21 -0
- data/lib/tcell_agent/sinatra.rb +41 -0
- data/lib/tcell_agent/start_background_thread.rb +63 -0
- data/lib/tcell_agent/userinfo.rb +8 -0
- data/lib/tcell_agent/utils/queue_with_timeout.rb +60 -0
- data/lib/tcell_agent/version.rb +5 -0
- data/spec/controllers/application_controller.rb +12 -0
- data/spec/lib/tcell_agent/api/api_spec.rb +36 -0
- data/spec/lib/tcell_agent/appsensor_spec.rb +66 -0
- data/spec/lib/tcell_agent/policies/add_script_tag_policy_spec.rb +37 -0
- data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +40 -0
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +71 -0
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +71 -0
- data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +88 -0
- data/spec/lib/tcell_agent/policies/honeytokens_policy_spec.rb +22 -0
- data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +62 -0
- data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +22 -0
- data/spec/lib/tcell_agent/policies/login_policy_spec.rb +42 -0
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +67 -0
- data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +187 -0
- data/spec/lib/tcell_agent/rails_spec.rb +57 -0
- data/spec/lib/tcell_agent/sensor_events/dlp_spec.rb +14 -0
- data/spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb +25 -0
- data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +57 -0
- data/spec/lib/tcell_agent_spec.rb +22 -0
- data/spec/resources/normal_config.json +13 -0
- data/spec/spec_helper.rb +4 -0
- data/tcell_agent.gemspec +29 -0
- metadata +249 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'tcell_agent/authlogic' if defined?(Authlogic)
|
4
|
+
require 'tcell_agent/devise' if defined?(Devise)
|
5
|
+
|
6
|
+
require 'rails'
|
7
|
+
require 'uri'
|
8
|
+
require 'tcell_agent/logger'
|
9
|
+
require 'tcell_agent/agent'
|
10
|
+
require 'tcell_agent/sensor_events/sensor'
|
11
|
+
require 'tcell_agent/sensor_events/app_sensor'
|
12
|
+
require 'tcell_agent/sensor_events/server_agent'
|
13
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
14
|
+
require 'tcell_agent/sensor_events/util/redirect_utils'
|
15
|
+
|
16
|
+
require 'tcell_agent/rails/middleware/global_middleware'
|
17
|
+
require 'tcell_agent/rails/middleware/body_filter_middleware'
|
18
|
+
require 'tcell_agent/rails/middleware/headers_middleware'
|
19
|
+
require 'tcell_agent/rails/middleware/context_middleware'
|
20
|
+
|
21
|
+
require 'tcell_agent/rails/routes'
|
22
|
+
require 'tcell_agent/rails/settings_reporter'
|
23
|
+
require 'tcell_agent/rails/dlp'
|
24
|
+
|
25
|
+
require 'rails/all'
|
26
|
+
|
27
|
+
require 'tcell_agent/userinfo'
|
28
|
+
require 'cgi'
|
29
|
+
require 'thread'
|
30
|
+
|
31
|
+
# ensure ActiveRecord's version has been required already
|
32
|
+
|
33
|
+
module TCellAgent
|
34
|
+
class Railtie < Rails::Railtie
|
35
|
+
initializer "tcell_agent.insert_middleware" do |app|
|
36
|
+
app.config.middleware.insert_before(0, "TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware")
|
37
|
+
app.config.middleware.insert_after(0, "TCellAgent::Instrumentation::Rails::Middleware::HeadersMiddleware")
|
38
|
+
app.config.middleware.use "TCellAgent::Instrumentation::Rails::Middleware::BodyFilterMiddleware"
|
39
|
+
app.config.middleware.use "TCellAgent::Instrumentation::Rails::Middleware::GlobalMiddleware"
|
40
|
+
end
|
41
|
+
config.after_initialize do
|
42
|
+
TCellAgent::Instrumentation::Rails.send_framework_info
|
43
|
+
TCellAgent::Instrumentation::Rails.send_settings(Rails.application)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
class Engine < Rails::Engine
|
47
|
+
config.after_initialize do
|
48
|
+
TCellAgent::Instrumentation::Rails.get_routes()
|
49
|
+
end
|
50
|
+
end
|
51
|
+
# # if (Rails::VERSION::MAJOR == 3)
|
52
|
+
# # config.after_initialize do
|
53
|
+
# # Rails.application.reload_routes!
|
54
|
+
# # Rails.application.routes.routes.each do |route|
|
55
|
+
# # methods = ['GET','POST','PUT','DELETE','HEAD',
|
56
|
+
# # 'PATCH','TRACE','CONNECT','OPTIONS']
|
57
|
+
# # if (route.constraints.has_key? :request_method)
|
58
|
+
# # route_path = "#{route.path.spec}"
|
59
|
+
# # if (route_path.end_with?("(.:format)"))
|
60
|
+
# # route_path = route_path.chomp("(.:format)")
|
61
|
+
# # end
|
62
|
+
# # route_destination = route.defaults.to_s
|
63
|
+
# # route_params = route.path.required_names
|
64
|
+
# # route_methods = methods.select {|x| route.verb.match(x) }
|
65
|
+
# # route_methods.each { |route_method|
|
66
|
+
# # #puts "#{route_path}, #{route_method.downcase}"
|
67
|
+
# # TCellAgent::AgentThread.sendEvent(
|
68
|
+
# # TCellAgent::SensorEvents::AppRoutesSensorEvent.new(
|
69
|
+
# # route_path, route_method, nil, "#{route_destination}"
|
70
|
+
# # )
|
71
|
+
# # )
|
72
|
+
# # }
|
73
|
+
# # end
|
74
|
+
# # end
|
75
|
+
# # end
|
76
|
+
# # end
|
77
|
+
# ActionDispatch::Request.class_eval do
|
78
|
+
# attr_accessor :_tcell_transaction_id
|
79
|
+
# end
|
80
|
+
# config.after_initialize do
|
81
|
+
# puts "Framework"
|
82
|
+
# puts "Rails"
|
83
|
+
# puts Rails.version
|
84
|
+
# puts Rails.application.config.session_options
|
85
|
+
# if defined?(Devise)
|
86
|
+
# puts "Devise"
|
87
|
+
# puts "ominauth"
|
88
|
+
# puts Devise.password_length
|
89
|
+
# puts Devise.remember_for
|
90
|
+
# puts Devise.expire_all_remember_me_on_sign_out
|
91
|
+
# puts Devise.maximum_attempts
|
92
|
+
# puts Devise.unlock_in
|
93
|
+
# puts Devise.paranoid
|
94
|
+
# puts Devise.token_generator
|
95
|
+
# puts "warden"
|
96
|
+
# puts Devise.warden_config
|
97
|
+
# end
|
98
|
+
# end
|
99
|
+
# if (Rails::VERSION::MAJOR == 4)
|
100
|
+
# ActionDispatch::Journey::Routes.class_eval do
|
101
|
+
# alias_method :original_add_route, :add_route
|
102
|
+
# def add_route(app, path, conditions, defaults, name = nil)
|
103
|
+
# route = original_add_route(app, path, conditions, defaults, name)
|
104
|
+
# methods = ['GET','POST','PUT','DELETE','HEAD',
|
105
|
+
# 'PATCH','TRACE','CONNECT','OPTIONS']
|
106
|
+
# if (route.constraints.has_key? :request_method)
|
107
|
+
# route_path = "#{route.path.spec}"
|
108
|
+
# if (route_path.end_with?("(.:format)"))
|
109
|
+
# route_path = route_path.chomp("(.:format)")
|
110
|
+
# end
|
111
|
+
# route_destination = route.defaults.to_s
|
112
|
+
# route_params = route.path.required_names
|
113
|
+
# route_methods = methods.select {|x| route.verb.match(x) }
|
114
|
+
# route_methods.each { |route_method|
|
115
|
+
# #puts "#{route_path}, #{route_method.downcase}"
|
116
|
+
# TCellAgent.send_event(
|
117
|
+
# TCellAgent::SensorEvents::AppRoutesSensorEvent.new(
|
118
|
+
# route_path, route_method, nil, "#{route_destination}"
|
119
|
+
# )
|
120
|
+
# )
|
121
|
+
# }
|
122
|
+
# end
|
123
|
+
# route
|
124
|
+
# end
|
125
|
+
# end
|
126
|
+
# end
|
127
|
+
# ActiveSupport.on_load(:action_controller) do
|
128
|
+
# ActionController::Base.class_eval do
|
129
|
+
# #around_filter :global_request_logging
|
130
|
+
# # def _tcell_route_name
|
131
|
+
# # begin
|
132
|
+
# # route = Rails.application.routes.router.recognize(request) { |route, _| route }.first
|
133
|
+
# # route_path = "#{route[2].path.spec}"
|
134
|
+
# # if (route_path.end_with?("(.:format)"))
|
135
|
+
# # route_path = route_path.chomp("(.:format)")
|
136
|
+
# # end
|
137
|
+
# # #puts "#{route_path}, #{request.method.downcase}"
|
138
|
+
# # TCellAgent::SensorEvents::Util.calculateRouteId(request.method.downcase, route_path)
|
139
|
+
# # rescue Exception => inner_excetion
|
140
|
+
# # TCellAgent.logger.debug("Could not figure out path #{inner_excetion.message}")
|
141
|
+
# # end
|
142
|
+
# # end #def global
|
143
|
+
# end #ac classeval
|
144
|
+
# end #as onload
|
145
|
+
# end #class
|
146
|
+
end #module
|
File without changes
|
@@ -0,0 +1,204 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'tcell_agent/authlogic' if defined?(Authlogic)
|
4
|
+
require 'tcell_agent/devise' if defined?(Devise)
|
5
|
+
|
6
|
+
require 'rails'
|
7
|
+
require 'uri'
|
8
|
+
require 'tcell_agent/logger'
|
9
|
+
require 'tcell_agent/agent'
|
10
|
+
require 'tcell_agent/sensor_events/sensor'
|
11
|
+
require 'tcell_agent/sensor_events/app_sensor'
|
12
|
+
require 'tcell_agent/sensor_events/server_agent'
|
13
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
14
|
+
require 'tcell_agent/sensor_events/util/redirect_utils'
|
15
|
+
|
16
|
+
require 'tcell_agent/sensor_events/dlp'
|
17
|
+
|
18
|
+
require 'tcell_agent/rails/middleware/global_middleware'
|
19
|
+
require 'tcell_agent/rails/middleware/body_filter_middleware'
|
20
|
+
require 'tcell_agent/rails/middleware/headers_middleware'
|
21
|
+
require 'tcell_agent/rails/middleware/context_middleware'
|
22
|
+
|
23
|
+
require 'tcell_agent/rails/routes'
|
24
|
+
require 'tcell_agent/rails/settings_reporter'
|
25
|
+
require 'tcell_agent/rails/dlp'
|
26
|
+
|
27
|
+
require 'rails/all'
|
28
|
+
|
29
|
+
require 'tcell_agent/userinfo'
|
30
|
+
require 'cgi'
|
31
|
+
require 'thread'
|
32
|
+
|
33
|
+
# if defined?(SQLite3)
|
34
|
+
# require 'active_record/connection_adapters/sqlite3_adapter'
|
35
|
+
# ActiveRecord::ConnectionAdapters::SQLite3Adapter.class_eval do
|
36
|
+
# alias_method :original_exec, :exec_query
|
37
|
+
# def exec_query(sql, name = nil, binds = [])
|
38
|
+
# puts "----v----"
|
39
|
+
# puts sql
|
40
|
+
# puts name
|
41
|
+
# puts binds
|
42
|
+
# puts "----^----"
|
43
|
+
# result = original_exec(sql, name, binds)
|
44
|
+
# puts result.inspect
|
45
|
+
# puts ";-----------------------;"
|
46
|
+
# result
|
47
|
+
# end
|
48
|
+
# def postgresql_version
|
49
|
+
# 80200
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
|
54
|
+
# class ActiveRecord::Base
|
55
|
+
# after_initialize do |user|
|
56
|
+
# puts "You have initialized an object!"
|
57
|
+
# puts user
|
58
|
+
# end
|
59
|
+
|
60
|
+
# after_find do |record|
|
61
|
+
# dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
62
|
+
# if dlp_policy
|
63
|
+
# request_env = TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS.fetch(Thread.current.object_id, nil)
|
64
|
+
# if request_env
|
65
|
+
# model = record.class
|
66
|
+
# model.columns.each do |col|
|
67
|
+
# #puts "#{model.table_name} .. #{col.name}"
|
68
|
+
# actions = dlp_policy.get_actions_for(model.table_name, col.name)
|
69
|
+
# if (actions.include?("body_redact"))
|
70
|
+
# (request_env["filter_body_set"] ||= Set.new).add(record[col.name.to_sym])
|
71
|
+
# #request_env["filter_body_set"].add()
|
72
|
+
# end
|
73
|
+
# if (actions.include?("log_redact"))
|
74
|
+
# (request_env["filter_log_set"] ||= Set.new).add(record[col.name.to_sym])
|
75
|
+
# #request_env["filter_log_set"].add(record[col.name.to_sym])
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
# end
|
82
|
+
|
83
|
+
# - Request
|
84
|
+
# - Session Id event
|
85
|
+
# - Session Id redact
|
86
|
+
# - Session Id hash
|
87
|
+
# - Session Id mask
|
88
|
+
# - Database-Stuff - [event, redact]
|
89
|
+
#
|
90
|
+
# - Log
|
91
|
+
#
|
92
|
+
|
93
|
+
module TCellAgent
|
94
|
+
module Policies
|
95
|
+
class DataLossPolicy
|
96
|
+
def log_enforce(tcell_context, sanitize_string)
|
97
|
+
if (tcell_context && tcell_context.session_id)
|
98
|
+
session_id_actions = self.get_actions_for_session_id
|
99
|
+
if session_id_actions
|
100
|
+
send_event = false
|
101
|
+
sanitize_string.gsub!(tcell_context.session_id) {|m|
|
102
|
+
if session_id_actions.log_redact
|
103
|
+
send_event = true
|
104
|
+
m = "[session_id]"
|
105
|
+
elsif session_id_actions.log_hash
|
106
|
+
send_event = true
|
107
|
+
m = "[hash]"
|
108
|
+
elsif session_id_actions.log_event
|
109
|
+
send_event = true
|
110
|
+
end
|
111
|
+
m
|
112
|
+
}
|
113
|
+
if send_event
|
114
|
+
TCellAgent.send_event(
|
115
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
116
|
+
tcell_context.route_id,
|
117
|
+
tcell_context.uri,
|
118
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG
|
119
|
+
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
120
|
+
)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
sanitize_string
|
125
|
+
end
|
126
|
+
def response_body_enforce(tcell_context, sanitize_string)
|
127
|
+
if (tcell_context && tcell_context.session_id)
|
128
|
+
session_id_actions = self.get_actions_for_session_id
|
129
|
+
if session_id_actions
|
130
|
+
send_event = false
|
131
|
+
sanitize_string.gsub!(tcell_context.session_id) {|m|
|
132
|
+
if session_id_actions.body_redact
|
133
|
+
# m = "[session_id]"
|
134
|
+
send_event = true
|
135
|
+
elsif session_id_actions.body_hash
|
136
|
+
# m = "[hash]"
|
137
|
+
send_event = true
|
138
|
+
elsif session_id_actions.body_event
|
139
|
+
send_event = true
|
140
|
+
end
|
141
|
+
m
|
142
|
+
}
|
143
|
+
end
|
144
|
+
if send_event
|
145
|
+
TCellAgent.send_event(
|
146
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
147
|
+
tcell_context.route_id,
|
148
|
+
tcell_context.uri,
|
149
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY
|
150
|
+
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
151
|
+
)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
sanitize_string
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
module TCellAgent
|
161
|
+
class Engine < Rails::Engine
|
162
|
+
ActiveSupport.on_load(:action_controller) do
|
163
|
+
ActionController::Base.class_eval do
|
164
|
+
around_filter :global_request_logging
|
165
|
+
def global_request_logging
|
166
|
+
begin
|
167
|
+
yield
|
168
|
+
TCellAgent::Instrumentation.safe_block("Handling JSAgent add") {
|
169
|
+
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
170
|
+
if dlp_policy
|
171
|
+
tcell_context = request.env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
|
172
|
+
response.body = dlp_policy.response_body_enforce(tcell_context, response.body)
|
173
|
+
end
|
174
|
+
}
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
class Logger
|
183
|
+
alias_method :tcell_old_add, :add
|
184
|
+
def add(severity, message = nil, progname = nil, &block)
|
185
|
+
progname ||= @progname
|
186
|
+
if message.nil?
|
187
|
+
if block_given?
|
188
|
+
message = yield
|
189
|
+
else
|
190
|
+
message = progname
|
191
|
+
progname = @progname
|
192
|
+
end
|
193
|
+
end
|
194
|
+
TCellAgent::Instrumentation.safe_block_no_log("Handling JSAgent add") {
|
195
|
+
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
196
|
+
request_env = TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS.fetch(Thread.current.object_id, nil)
|
197
|
+
if message && dlp_policy && request_env
|
198
|
+
tcell_context = request_env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
|
199
|
+
dlp_policy.log_enforce(tcell_context, message)
|
200
|
+
end
|
201
|
+
}
|
202
|
+
tcell_old_add(severity, message, progname)
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
require 'uri'
|
5
|
+
require 'tcell_agent/logger'
|
6
|
+
require 'tcell_agent/agent'
|
7
|
+
require 'tcell_agent/sensor_events/sensor'
|
8
|
+
require 'tcell_agent/sensor_events/app_sensor'
|
9
|
+
require 'tcell_agent/sensor_events/server_agent'
|
10
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
11
|
+
require 'tcell_agent/sensor_events/util/redirect_utils'
|
12
|
+
|
13
|
+
require 'tcell_agent/instrumentation'
|
14
|
+
|
15
|
+
module TCellAgent
|
16
|
+
module Instrumentation
|
17
|
+
module Rails
|
18
|
+
module Middleware
|
19
|
+
class BodyFilterMiddleware
|
20
|
+
HEAD_SEARCH_REGEX=/<head>/
|
21
|
+
def initialize(app)
|
22
|
+
@app = app
|
23
|
+
end
|
24
|
+
def call(env)
|
25
|
+
request = Rack::Request.new(env)
|
26
|
+
orig = (Time.now.to_f * 1000).to_i
|
27
|
+
response = @app.call(env)
|
28
|
+
response_time = (Time.now.to_f * 1000).to_i - orig
|
29
|
+
TCellAgent::Instrumentation.safe_block("Handling Route Time") {
|
30
|
+
route_id = env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID].route_id
|
31
|
+
if route_id
|
32
|
+
TCellAgent.increment_route(route_id, response_time)
|
33
|
+
else
|
34
|
+
TCellAgent.increment_route("", response_time)
|
35
|
+
end
|
36
|
+
}
|
37
|
+
response = self._handle_js_agent_add(request, response)
|
38
|
+
response
|
39
|
+
end
|
40
|
+
def replace_in_body(script_tag_policy, body)
|
41
|
+
base_url_vars = ""
|
42
|
+
if (script_tag_policy.js_agent_api_base_url)
|
43
|
+
base_url_vars = " tcellbaseurl=\"#{script_tag_policy.js_agent_api_base_url}\""
|
44
|
+
end
|
45
|
+
script_insert = "\n<script src=\"#{script_tag_policy.js_agent_url}\" tcellapikey=\"#{script_tag_policy.js_agent_api_key}\" tcellappid=\"#{script_tag_policy.js_agent_app_id}\"#{base_url_vars}></script>\n"
|
46
|
+
body.sub!(BodyFilterMiddleware::HEAD_SEARCH_REGEX,"<head>#{script_insert}")
|
47
|
+
end
|
48
|
+
def _handle_js_agent_add(request, response)
|
49
|
+
TCellAgent::Instrumentation.safe_block("Handling JSAgent add") {
|
50
|
+
status, headers, rack_body = response
|
51
|
+
if (headers.fetch("Content-Type","").start_with?'text/html')
|
52
|
+
script_tag_policy = TCellAgent.policy(TCellAgent::PolicyTypes::AddScriptTag)
|
53
|
+
if (script_tag_policy &&
|
54
|
+
script_tag_policy.enabled)
|
55
|
+
newbody = []
|
56
|
+
rack_body.each { |str|
|
57
|
+
newbody << self.replace_in_body(script_tag_policy, str)
|
58
|
+
}
|
59
|
+
response = [status, headers, newbody]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
}
|
63
|
+
response
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
require 'uri'
|
5
|
+
require 'tcell_agent/logger'
|
6
|
+
require 'tcell_agent/agent'
|
7
|
+
require 'tcell_agent/sensor_events/sensor'
|
8
|
+
require 'tcell_agent/sensor_events/app_sensor'
|
9
|
+
require 'tcell_agent/sensor_events/server_agent'
|
10
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
11
|
+
require 'tcell_agent/sensor_events/util/redirect_utils'
|
12
|
+
|
13
|
+
require 'tcell_agent/rails/routes'
|
14
|
+
|
15
|
+
require 'tcell_agent/userinfo'
|
16
|
+
require 'cgi'
|
17
|
+
|
18
|
+
require 'tcell_agent/instrumentation'
|
19
|
+
require 'thread'
|
20
|
+
|
21
|
+
module TCellAgent
|
22
|
+
module Instrumentation
|
23
|
+
module Rails
|
24
|
+
module Middleware
|
25
|
+
TCELL_ID = "tcell.request_data"
|
26
|
+
|
27
|
+
class ContextMiddleware
|
28
|
+
THREADS = {}
|
29
|
+
def initialize(app)
|
30
|
+
@app = app
|
31
|
+
end
|
32
|
+
|
33
|
+
def call(env)
|
34
|
+
env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID] = TCellAgent::Instrumentation::TCellData.new
|
35
|
+
TCellAgent::Instrumentation.safe_block("Setting transaction_id") {
|
36
|
+
env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID].transaction_id = SecureRandom.uuid
|
37
|
+
request = Rack::Request.new(env)
|
38
|
+
env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID].uri = request.fullpath
|
39
|
+
}
|
40
|
+
env["filter_body_set"] = Set.new
|
41
|
+
ContextMiddleware::THREADS[Thread.current.object_id] = env
|
42
|
+
response = @app.call(env)
|
43
|
+
ContextMiddleware::THREADS.delete(Thread.current.object_id)
|
44
|
+
response
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|