tcell_agent 0.2.7 → 0.2.8
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/bin/tcell_agent +22 -0
- data/lib/tcell_agent/agent/event_processor.rb +7 -0
- data/lib/tcell_agent/agent/fork_pipe_manager.rb +29 -29
- data/lib/tcell_agent/agent/policy_manager.rb +2 -1
- data/lib/tcell_agent/agent/route_manager.rb +35 -15
- data/lib/tcell_agent/configuration.rb +42 -2
- data/lib/tcell_agent/instrumentation.rb +4 -1
- data/lib/tcell_agent/logger.rb +1 -1
- data/lib/tcell_agent/rails.rb +12 -18
- data/lib/tcell_agent/rails/auth/authlogic.rb +2 -2
- data/lib/tcell_agent/rails/auth/devise.rb +1 -1
- data/lib/tcell_agent/rails/dlp.rb +133 -123
- data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +2 -1
- data/lib/tcell_agent/rails/on_start.rb +67 -69
- data/lib/tcell_agent/rails/routes.rb +91 -86
- data/lib/tcell_agent/rails/settings_reporter.rb +10 -0
- data/lib/tcell_agent/routes/table.rb +2 -0
- data/lib/tcell_agent/sensor_events/server_agent.rb +10 -0
- data/lib/tcell_agent/servers/thin.rb +1 -0
- data/lib/tcell_agent/servers/webrick.rb +0 -1
- data/lib/tcell_agent/start_background_thread.rb +44 -45
- data/lib/tcell_agent/system_info.rb +10 -0
- data/lib/tcell_agent/version.rb +1 -1
- data/spec/lib/tcell_agent/agent/fork_pipe_manager_spec.rb +99 -0
- data/spec/lib/tcell_agent/api/api_spec.rb +2 -2
- data/spec/lib/tcell_agent/instrumentation_spec.rb +176 -176
- data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +32 -32
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +63 -63
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +93 -93
- data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +222 -222
- data/spec/lib/tcell_agent/policies/honeytokens_policy_spec.rb +17 -17
- data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +57 -57
- data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +17 -17
- data/spec/lib/tcell_agent/policies/login_policy_spec.rb +3 -3
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +59 -59
- data/spec/lib/tcell_agent/rails/logger_spec.rb +148 -0
- data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +7 -7
- data/spec/lib/tcell_agent/rails_spec.rb +2 -2
- data/spec/lib/tcell_agent/sensor_events/dlp_spec.rb +9 -9
- data/spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb +20 -20
- data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +52 -52
- data/spec/lib/tcell_agent_spec.rb +17 -17
- data/spec/spec_helper.rb +1 -0
- data/spec/support/resources/normal_config.json +5 -5
- data/tcell_agent.gemspec +4 -4
- metadata +31 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38bd348af6afc0394baa2b21028297f52c8bd869
|
4
|
+
data.tar.gz: 3a0cd72fe8d1c792a13a4a73492da78d2b773b13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd5eb354fe88c5822692bb5e74194d56f67645d92910e14f24d07d27c128735b5750d84a567e7a9dd4a2558c5af1b71f41ec92c47c9db1e5f4e1efc6c731d7f2
|
7
|
+
data.tar.gz: c570a523bdb36c1aebe4fcf457ececc053e3395cb56bc7f3fbc59d8100897fcda06a8a4fe0447f62acdee239ca4fba601c93892b92ea3d4a1a7c9f952915c9cb
|
data/bin/tcell_agent
CHANGED
@@ -14,6 +14,8 @@ Commonly used command are:
|
|
14
14
|
setup : Setup new config file
|
15
15
|
test : Run diagnostics classes and config
|
16
16
|
loglevel : Set the loglevel of the tcell agent
|
17
|
+
enable : Enable the agent
|
18
|
+
disable : Disable the agent
|
17
19
|
|
18
20
|
See 'tcell_agent COMMAND --help' for more information on a specific command.
|
19
21
|
|
@@ -69,6 +71,12 @@ subcommands = {
|
|
69
71
|
options[:off] = v
|
70
72
|
end
|
71
73
|
end,
|
74
|
+
'enable' => OptionParser.new do |opts|
|
75
|
+
opts.banner = "Usage: enable"
|
76
|
+
end,
|
77
|
+
'disable' => OptionParser.new do |opts|
|
78
|
+
opts.banner = "Usage: disable"
|
79
|
+
end,
|
72
80
|
'test' => OptionParser.new do |opts|
|
73
81
|
opts.banner = "Usage: test"
|
74
82
|
#opts.on("-q", "--[no-]quiet", "quietly run ") do |v|
|
@@ -165,6 +173,20 @@ elsif (command == 'preload')
|
|
165
173
|
File.open(CONFIG_FILE, 'w'){|f| f.puts JSON.pretty_generate(config_hash) }
|
166
174
|
puts "done."
|
167
175
|
|
176
|
+
elsif (command == 'enable')
|
177
|
+
file = File.read(CONFIG_FILE)
|
178
|
+
config_hash = JSON.parse(file)
|
179
|
+
config_hash["applications"][0].delete("enabled")
|
180
|
+
File.open(CONFIG_FILE, 'w'){|f| f.puts JSON.pretty_generate(config_hash) }
|
181
|
+
puts "Enabled, you will need to restart the server."
|
182
|
+
|
183
|
+
elsif (command == 'disable')
|
184
|
+
file = File.read(CONFIG_FILE)
|
185
|
+
config_hash = JSON.parse(file)
|
186
|
+
config_hash["applications"][0]["enabled"] = false
|
187
|
+
File.open(CONFIG_FILE, 'w'){|f| f.puts JSON.pretty_generate(config_hash) }
|
188
|
+
puts "Disabled, you will need to restart the server."
|
189
|
+
|
168
190
|
elsif (command == 'demomode')
|
169
191
|
file = File.read(CONFIG_FILE)
|
170
192
|
config_hash = JSON.parse(file)
|
@@ -34,6 +34,7 @@ module TCellAgent
|
|
34
34
|
|
35
35
|
def ensure_event_processor_running
|
36
36
|
return if event_processor_running?
|
37
|
+
return if TCellAgent.configuration.should_start_event_manager? == false
|
37
38
|
@worker_mutex.synchronize do
|
38
39
|
return if event_processor_running?
|
39
40
|
if self.is_parent_process? == false
|
@@ -51,6 +52,8 @@ module TCellAgent
|
|
51
52
|
end
|
52
53
|
|
53
54
|
def start_event_processor(send_empties=true)
|
55
|
+
return if TCellAgent.configuration.should_start_event_manager? == false
|
56
|
+
|
54
57
|
if TCellAgent::Agent.is_parent_process? == false
|
55
58
|
return
|
56
59
|
end
|
@@ -245,6 +248,7 @@ module TCellAgent
|
|
245
248
|
end
|
246
249
|
|
247
250
|
def start_metrics_event_thread
|
251
|
+
return if TCellAgent.configuration.should_consume_event? == false
|
248
252
|
@metrics_event_thread = Thread.new do
|
249
253
|
begin
|
250
254
|
loop do
|
@@ -264,6 +268,7 @@ module TCellAgent
|
|
264
268
|
end
|
265
269
|
|
266
270
|
def _queue_metric(event)
|
271
|
+
return if TCellAgent.configuration.should_consume_event? == false
|
267
272
|
begin
|
268
273
|
self.ensure_metrics_event_thread_running
|
269
274
|
if (@metrics_event_queue.length() > 100)
|
@@ -277,6 +282,7 @@ module TCellAgent
|
|
277
282
|
end
|
278
283
|
|
279
284
|
def queueSensorEvent(event)
|
285
|
+
return if TCellAgent.configuration.should_consume_event? == false
|
280
286
|
begin
|
281
287
|
if TCellAgent::Agent.is_parent_process? == false
|
282
288
|
self.queue_forked_event(event)
|
@@ -299,6 +305,7 @@ module TCellAgent
|
|
299
305
|
end
|
300
306
|
|
301
307
|
def increment_session_info(hmac_session_id, user_id, ip_address, user_agent)
|
308
|
+
|
302
309
|
TCellAgent::Instrumentation.safe_block("Incrementing session info") do
|
303
310
|
|
304
311
|
if TCellAgent::Agent.is_parent_process? == false
|
@@ -17,9 +17,9 @@ module TCellAgent
|
|
17
17
|
@writep.set_encoding(::Encoding::ASCII_8BIT)
|
18
18
|
end
|
19
19
|
if is_parent?
|
20
|
-
|
20
|
+
self.start_listener(&block)
|
21
21
|
end
|
22
|
-
rescue Exception=>init_exception
|
22
|
+
rescue Exception => init_exception
|
23
23
|
TCellAgent.logger.error("Could not start listener for pipe to forks")
|
24
24
|
TCellAgent.logger.error(init_exception.message)
|
25
25
|
TCellAgent.logger.debug(init_exception.backtrace)
|
@@ -30,38 +30,38 @@ module TCellAgent
|
|
30
30
|
end
|
31
31
|
def start_listener(&block)
|
32
32
|
Thread.new {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
33
|
+
while true do
|
34
|
+
begin
|
35
|
+
packed_bytes = @readp.read(4)
|
36
|
+
event_length = packed_bytes.unpack("L>").first
|
37
|
+
packed_event = @readp.read(event_length)
|
38
|
+
event = Marshal.load(packed_event)
|
39
|
+
if block
|
40
|
+
block.call(event)
|
41
|
+
end
|
42
|
+
rescue Exception=>block_exception
|
43
|
+
TCellAgent.logger.error("Could not decode block")
|
44
|
+
TCellAgent.logger.error(block_exception.message)
|
45
|
+
TCellAgent.logger.debug(block_exception.backtrace)
|
46
|
+
sleep 0.5
|
48
47
|
end
|
48
|
+
end
|
49
49
|
}
|
50
50
|
end
|
51
51
|
def send_to_parent(event)
|
52
52
|
if is_parent?
|
53
|
-
|
54
|
-
|
53
|
+
#puts "Sending in pipe the wrong way"
|
54
|
+
return
|
55
55
|
else
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
56
|
+
begin
|
57
|
+
packed_event = Marshal.dump(event)
|
58
|
+
packed_bytes = [packed_event.bytesize].pack("L>")
|
59
|
+
@writep.write(packed_bytes+packed_event)
|
60
|
+
rescue Exception => block_exception
|
61
|
+
TCellAgent.logger.error("Could not write to pipe")
|
62
|
+
TCellAgent.logger.error(block_exception.message)
|
63
|
+
TCellAgent.logger.debug(block_exception.backtrace)
|
64
|
+
end
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
@@ -69,7 +69,7 @@ module TCellAgent
|
|
69
69
|
@@event_pipe_manager = ForkPipeManager.new { |event|
|
70
70
|
begin
|
71
71
|
TCellAgent.send_event(event)
|
72
|
-
rescue Exception=>block_exception
|
72
|
+
rescue Exception => block_exception
|
73
73
|
TCellAgent.logger.error("Could handle send_event_block")
|
74
74
|
TCellAgent.logger.error(block_exception.message)
|
75
75
|
TCellAgent.logger.debug(block_exception.backtrace)
|
@@ -31,6 +31,7 @@ module TCellAgent
|
|
31
31
|
|
32
32
|
def ensure_policy_polling_running
|
33
33
|
return if policy_polling_running?
|
34
|
+
return if TCellAgent.configuration.should_start_policy_poll? == false
|
34
35
|
@policy_polling_worker_mutex.synchronize do
|
35
36
|
return if policy_polling_running?
|
36
37
|
start_policy_polling
|
@@ -42,7 +43,7 @@ module TCellAgent
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def start_policy_polling
|
45
|
-
if TCellAgent.configuration.
|
46
|
+
if TCellAgent.configuration.should_start_policy_poll? == true
|
46
47
|
TCellAgent.logger.debug("Starting policy polling thread")
|
47
48
|
@policy_polling_thread = Thread.new do
|
48
49
|
last_poll_time = 0
|
@@ -13,14 +13,27 @@ require "tcell_agent"
|
|
13
13
|
|
14
14
|
module TCellAgent
|
15
15
|
class Agent
|
16
|
+
def self.get_database_discovery_identifier(database, schema, table, fields)
|
17
|
+
[
|
18
|
+
database,
|
19
|
+
schema,
|
20
|
+
table,
|
21
|
+
fields.join(",")
|
22
|
+
].join(",").hash
|
23
|
+
end
|
24
|
+
|
16
25
|
def discover_database_field(route_id, database, schema, table, field)
|
17
|
-
|
18
|
-
@route_table.routes[route_id].database[database][schema][table][field].discovered = true
|
19
|
-
event = (TCellAgent::SensorEvents::DiscoveryEvent.new(route_id)).for_database(database, schema, table, field)
|
20
|
-
TCellAgent.send_event(event)
|
21
|
-
end
|
26
|
+
discover_database_fields(route_id, database, schema, table, [field])
|
22
27
|
end
|
28
|
+
|
23
29
|
def discover_database_fields(route_id, database, schema, table, fields)
|
30
|
+
if (route_id == nil ||
|
31
|
+
database == nil ||
|
32
|
+
schema == nil ||
|
33
|
+
table == nil ||
|
34
|
+
fields == nil)
|
35
|
+
return
|
36
|
+
end
|
24
37
|
if TCellAgent::Agent.is_parent_process? == false
|
25
38
|
TCellAgent.queue_metric({"_type"=>"discover_database_fields",
|
26
39
|
"route_id"=>route_id,
|
@@ -30,16 +43,23 @@ module TCellAgent
|
|
30
43
|
"fields"=>fields})
|
31
44
|
return
|
32
45
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
46
|
+
query_hash = TCellAgent::Agent.get_database_discovery_identifier(database, schema, table, fields)
|
47
|
+
if (@route_table.routes[route_id].database_queries_discovered.fetch(query_hash, false) == false)
|
48
|
+
@route_table.routes[route_id].database_queries_discovered[query_hash] = true
|
49
|
+
event = (TCellAgent::SensorEvents::DiscoveryEvent.new(route_id)).for_database_fields(database, schema, table, fields)
|
50
|
+
TCellAgent.send_event(event)
|
51
|
+
end
|
52
|
+
#discovered_fields = fields.select { |field|
|
53
|
+
# @route_table.routes[route_id].database_queries_discoverd[database][schema][table][field].discovered != true
|
54
|
+
#}
|
55
|
+
#if (discovered_fields.length > 0)
|
56
|
+
# discovered_fields.each { |field|
|
57
|
+
# @route_table.routes[route_id].database[database][schema][table][field].discovered = true
|
58
|
+
# }
|
59
|
+
# event = (TCellAgent::SensorEvents::DiscoveryEvent.new(route_id)).for_database_fields(database, schema, table, fields)
|
60
|
+
# TCellAgent.send_event(event)
|
61
|
+
#end
|
43
62
|
end
|
63
|
+
|
44
64
|
end
|
45
65
|
end
|
@@ -17,7 +17,7 @@ module TCellAgent
|
|
17
17
|
class Configuration
|
18
18
|
attr_accessor :version, :app_id, :api_key, :hmac_key,
|
19
19
|
:tcell_api_url, :tcell_input_url,
|
20
|
-
:
|
20
|
+
:logging_options,
|
21
21
|
:fetch_policies_from_tcell, :instrument_for_events,
|
22
22
|
:preload_policy_filename,
|
23
23
|
:proxy_host, :proxy_port, :proxy_username, :proxy_password,
|
@@ -33,8 +33,35 @@ module TCellAgent
|
|
33
33
|
:raise_exceptions,
|
34
34
|
:allow_unencrypted_appsensor_payloads
|
35
35
|
|
36
|
+
attr_accessor :enabled,
|
37
|
+
:enable_event_manager, # false = Do not start the even manager
|
38
|
+
:enable_event_consumer, # false = Do not consume events, drop them
|
39
|
+
:enable_policy_polling, # false = Do not poll for policies
|
40
|
+
:enable_instrumentation, # false = Do not add instrumentation
|
41
|
+
:enable_intercept_requests # false = Do not insert middleware
|
42
|
+
|
36
43
|
attr_accessor :exp_config_settings
|
37
44
|
|
45
|
+
def should_start_event_manager?
|
46
|
+
@enabled && @enable_event_manager
|
47
|
+
end
|
48
|
+
|
49
|
+
def should_consume_event?
|
50
|
+
@enabled && @enable_event_manager && @enable_event_consumer
|
51
|
+
end
|
52
|
+
|
53
|
+
def should_start_policy_poll?
|
54
|
+
@enabled && @enable_policy_polling && @fetch_policies_from_tcell # fetch_policies_from_tcel = legacy
|
55
|
+
end
|
56
|
+
|
57
|
+
def should_instrument?
|
58
|
+
@enabled && @enable_instrumentation && @instrument_for_events # instrument_for_events = legacy
|
59
|
+
end
|
60
|
+
|
61
|
+
def should_intercept_requests?
|
62
|
+
@enabled && @enable_instrumentation && @enable_intercept_requests
|
63
|
+
end
|
64
|
+
|
38
65
|
def initialize(filename="config/tcell_agent.config", useapp=nil)
|
39
66
|
@version = 0
|
40
67
|
@exp_config_settings = true
|
@@ -44,7 +71,14 @@ module TCellAgent
|
|
44
71
|
|
45
72
|
@fetch_policies_from_tcell = true
|
46
73
|
@instrument_for_events = true
|
74
|
+
|
47
75
|
@enabled = true
|
76
|
+
@enable_event_manager = true
|
77
|
+
@enable_event_consumer = true
|
78
|
+
@enable_policy_polling = true
|
79
|
+
@enable_instrumentation = true
|
80
|
+
@enable_intercept_requests = true
|
81
|
+
|
48
82
|
@cache_filename = "tcell/cache/tcell_agent.cache"
|
49
83
|
@default_log_filename = "tcell/logs/tcell_agent.log"
|
50
84
|
|
@@ -107,8 +141,14 @@ module TCellAgent
|
|
107
141
|
@api_key ||= app_data["api_key"]
|
108
142
|
|
109
143
|
# Optional
|
110
|
-
@enabled = app_data.fetch("enabled", true)
|
111
144
|
@preload_policy_filename = app_data.fetch("preload_policy_filename", nil)
|
145
|
+
|
146
|
+
@enabled = app_data.fetch("enabled", @enabled)
|
147
|
+
@enable_event_manager = app_data.fetch("enable_event_manager", @enable_event_manager)
|
148
|
+
@enable_event_consumer = app_data.fetch("enable_event_consumer", @enable_event_consumer)
|
149
|
+
@enable_policy_polling = app_data.fetch("enable_policy_polling", @enable_policy_polling)
|
150
|
+
@enable_instrumentation = app_data.fetch("enable_instrumentation", @enable_instrumentation)
|
151
|
+
@enable_intercept_requests = app_data.fetch("enable_intercept_requests", @enable_intercept_requests)
|
112
152
|
@fetch_policies_from_tcell = app_data.fetch("fetch_policies_from_tcell", @fetch_policies_from_tcell)
|
113
153
|
@instrument_for_events = app_data.fetch("instrument_for_events", @instrument_for_events)
|
114
154
|
|
data/lib/tcell_agent/logger.rb
CHANGED
@@ -41,7 +41,7 @@ module TCellAgent
|
|
41
41
|
@logger.formatter = proc do |severity, datetime, progname, msg|
|
42
42
|
# ISO 8601 format
|
43
43
|
date_format = datetime.strftime("%Y-%m-%d %H:%M:%S,%L%z")
|
44
|
-
"[#{date_format}] #{severity}[#{@logger_pid}]: #{msg}\n"
|
44
|
+
"[#{date_format}] [#{TCellAgent::VERSION}] #{severity}[#{@logger_pid}]: #{msg}\n"
|
45
45
|
end
|
46
46
|
|
47
47
|
return @logger
|
data/lib/tcell_agent/rails.rb
CHANGED
@@ -24,27 +24,21 @@ require 'tcell_agent/userinfo'
|
|
24
24
|
require 'cgi'
|
25
25
|
require 'thread'
|
26
26
|
|
27
|
-
# ensure ActiveRecord's version has been required already
|
28
|
-
module TCellAgent
|
29
|
-
class MyRailtie < Rails::Railtie
|
30
|
-
initializer 'activeservice.autoload', :after => :set_autoload_paths do |app|
|
31
|
-
if (TCellAgent.configuration.enabled)
|
32
|
-
Rails.application.config.to_prepare do
|
33
|
-
end
|
34
|
-
Rails.application.config.after_initialize do
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
27
|
module TCellAgent
|
42
28
|
class Railtie < Rails::Railtie
|
43
29
|
initializer "tcell_agent.insert_middleware" do |app|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
30
|
+
if TCellAgent.configuration.should_intercept_requests?
|
31
|
+
app.config.to_prepare do
|
32
|
+
require 'tcell_agent/devise' if defined?(Devise)
|
33
|
+
require 'tcell_agent/rails/auth/devise' if defined?(Devise)
|
34
|
+
require 'tcell_agent/authlogic' if defined?(Authlogic)
|
35
|
+
require 'tcell_agent/rails/auth/authlogic' if defined?(Authlogic)
|
36
|
+
end
|
37
|
+
app.config.middleware.insert_before(0, "TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware")
|
38
|
+
app.config.middleware.insert_after(0, "TCellAgent::Instrumentation::Rails::Middleware::HeadersMiddleware")
|
39
|
+
app.config.middleware.use "TCellAgent::Instrumentation::Rails::Middleware::BodyFilterMiddleware"
|
40
|
+
app.config.middleware.use "TCellAgent::Instrumentation::Rails::Middleware::GlobalMiddleware"
|
41
|
+
end
|
48
42
|
end
|
49
43
|
end
|
50
44
|
end
|
@@ -6,8 +6,8 @@ require 'tcell_agent/instrumentation'
|
|
6
6
|
|
7
7
|
module TCellAgent
|
8
8
|
if defined?(Authlogic)
|
9
|
-
TCellAgent.
|
10
|
-
|
9
|
+
if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
|
10
|
+
TCellAgent.logger.debug("Instrumenting Authlogic")
|
11
11
|
require 'tcell_agent/agent'
|
12
12
|
require 'tcell_agent/sensor_events/login_fraud'
|
13
13
|
Authlogic::Session::Base.class_eval do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module TCellAgent
|
2
2
|
if defined?(Devise)
|
3
|
-
if (TCellAgent.configuration.enabled && TCellAgent.configuration.
|
3
|
+
if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
|
4
4
|
TCellAgent.logger.debug("Instrumenting Devise")
|
5
5
|
|
6
6
|
require 'tcell_agent/agent'
|
@@ -51,31 +51,35 @@ require 'thread'
|
|
51
51
|
# end
|
52
52
|
# end
|
53
53
|
|
54
|
+
require 'tcell_agent/configuration'
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
if
|
66
|
-
|
67
|
-
if
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
action_objs.
|
78
|
-
|
56
|
+
if TCellAgent.configuration.enabled && TCellAgent.configuration.should_instrument? && TCellAgent.configuration.should_intercept_requests?
|
57
|
+
|
58
|
+
class ActiveRecord::Base
|
59
|
+
# after_initialize do |user|
|
60
|
+
# puts "You have initialized an object!"
|
61
|
+
# puts "ASDF"
|
62
|
+
# end
|
63
|
+
after_find do |record|
|
64
|
+
database_name = self.class.connection_config().fetch(:database,"*").split('/').last
|
65
|
+
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
66
|
+
if dlp_policy
|
67
|
+
request_env = TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS.fetch(Thread.current.object_id, nil)
|
68
|
+
if request_env
|
69
|
+
tcell_context = request_env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
|
70
|
+
if tcell_context
|
71
|
+
model = record.class
|
72
|
+
column_names = model.columns.map { |col| col.name }
|
73
|
+
if (dlp_policy.database_discovery_enabled)
|
74
|
+
TCellAgent.discover_database_fields(tcell_context.route_id, database_name,"*",model.table_name, column_names)
|
75
|
+
end
|
76
|
+
model.columns.each do |col|
|
77
|
+
#puts "#{model.table_name} .. #{col.name}"
|
78
|
+
action_objs = dlp_policy.get_actions_for_table(database_name, "*", model.table_name, col.name, tcell_context.route_id)
|
79
|
+
if action_objs
|
80
|
+
action_objs.each do |action_obj|
|
81
|
+
tcell_context.add_response_db_filter(record[col.name.to_sym], action_obj, database_name, "*", model.table_name, col.name)
|
82
|
+
end
|
79
83
|
end
|
80
84
|
end
|
81
85
|
end
|
@@ -83,126 +87,132 @@ class ActiveRecord::Base
|
|
83
87
|
end
|
84
88
|
end
|
85
89
|
end
|
86
|
-
end
|
87
90
|
|
88
|
-
# - Request
|
89
|
-
# - Session Id event
|
90
|
-
# - Session Id redact
|
91
|
-
# - Session Id hash
|
92
|
-
# - Session Id mask
|
93
|
-
# - Database-Stuff - [event, redact]
|
94
|
-
#
|
95
|
-
# - Log
|
96
|
-
#
|
97
|
-
|
98
|
-
module TCellAgent
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
91
|
+
# - Request
|
92
|
+
# - Session Id event
|
93
|
+
# - Session Id redact
|
94
|
+
# - Session Id hash
|
95
|
+
# - Session Id mask
|
96
|
+
# - Database-Stuff - [event, redact]
|
97
|
+
#
|
98
|
+
# - Log
|
99
|
+
#
|
100
|
+
|
101
|
+
module TCellAgent
|
102
|
+
module Policies
|
103
|
+
class DataLossPolicy
|
104
|
+
def log_enforce(tcell_context, sanitize_string)
|
105
|
+
if (tcell_context && tcell_context.session_id)
|
106
|
+
session_id_actions = self.get_actions_for_session_id
|
107
|
+
if session_id_actions
|
108
|
+
send_event = false
|
109
|
+
sanitize_string.gsub!(tcell_context.session_id) {|m|
|
110
|
+
if session_id_actions.log_redact
|
111
|
+
send_event = true
|
112
|
+
m = "[session_id]"
|
113
|
+
elsif session_id_actions.log_hash
|
114
|
+
send_event = true
|
115
|
+
m = "[hash]"
|
116
|
+
elsif session_id_actions.log_event
|
117
|
+
send_event = true
|
118
|
+
end
|
119
|
+
m
|
120
|
+
}
|
121
|
+
if send_event
|
122
|
+
TCellAgent.send_event(
|
123
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
124
|
+
tcell_context.route_id,
|
125
|
+
tcell_context.uri,
|
126
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG
|
127
|
+
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
128
|
+
)
|
115
129
|
end
|
116
|
-
|
117
|
-
|
130
|
+
end
|
131
|
+
end
|
132
|
+
sanitize_string
|
133
|
+
end
|
134
|
+
def response_body_enforce(tcell_context, sanitize_string)
|
135
|
+
if (tcell_context && tcell_context.session_id)
|
136
|
+
session_id_actions = self.get_actions_for_session_id
|
137
|
+
if session_id_actions
|
138
|
+
send_event = false
|
139
|
+
sanitize_string.gsub!(tcell_context.session_id) {|m|
|
140
|
+
if session_id_actions.body_redact
|
141
|
+
# m = "[session_id]"
|
142
|
+
send_event = true
|
143
|
+
elsif session_id_actions.body_hash
|
144
|
+
# m = "[hash]"
|
145
|
+
send_event = true
|
146
|
+
elsif session_id_actions.body_event
|
147
|
+
send_event = true
|
148
|
+
end
|
149
|
+
m
|
150
|
+
}
|
151
|
+
end
|
118
152
|
if send_event
|
119
153
|
TCellAgent.send_event(
|
120
154
|
TCellAgent::SensorEvents::DlpEvent.new(
|
121
155
|
tcell_context.route_id,
|
122
156
|
tcell_context.uri,
|
123
|
-
TCellAgent::SensorEvents::DlpEvent::
|
157
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY
|
124
158
|
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
125
159
|
)
|
126
160
|
end
|
127
161
|
end
|
162
|
+
sanitize_string
|
128
163
|
end
|
129
|
-
sanitize_string
|
130
|
-
end
|
131
|
-
def response_body_enforce(tcell_context, sanitize_string)
|
132
|
-
if (tcell_context && tcell_context.session_id)
|
133
|
-
session_id_actions = self.get_actions_for_session_id
|
134
|
-
if session_id_actions
|
135
|
-
send_event = false
|
136
|
-
sanitize_string.gsub!(tcell_context.session_id) {|m|
|
137
|
-
if session_id_actions.body_redact
|
138
|
-
# m = "[session_id]"
|
139
|
-
send_event = true
|
140
|
-
elsif session_id_actions.body_hash
|
141
|
-
# m = "[hash]"
|
142
|
-
send_event = true
|
143
|
-
elsif session_id_actions.body_event
|
144
|
-
send_event = true
|
145
|
-
end
|
146
|
-
m
|
147
|
-
}
|
148
|
-
end
|
149
|
-
if send_event
|
150
|
-
TCellAgent.send_event(
|
151
|
-
TCellAgent::SensorEvents::DlpEvent.new(
|
152
|
-
tcell_context.route_id,
|
153
|
-
tcell_context.uri,
|
154
|
-
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY
|
155
|
-
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
156
|
-
)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
sanitize_string
|
160
164
|
end
|
161
165
|
end
|
162
166
|
end
|
163
|
-
end
|
164
167
|
|
165
|
-
module TCellAgent
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
168
|
+
module TCellAgent
|
169
|
+
ActiveSupport.on_load(:action_controller) do
|
170
|
+
ActionController::Base.class_eval do
|
171
|
+
around_filter :global_request_logging
|
172
|
+
def global_request_logging
|
173
|
+
begin
|
174
|
+
yield
|
175
|
+
TCellAgent::Instrumentation.safe_block("Running DLP Logging Filters") {
|
176
|
+
tcell_context = request.env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
|
177
|
+
if tcell_context
|
178
|
+
response.body = tcell_context.filter_body(response.body)
|
179
|
+
end
|
180
|
+
}
|
181
|
+
end
|
178
182
|
end
|
179
183
|
end
|
180
184
|
end
|
181
|
-
|
182
|
-
|
185
|
+
end
|
186
|
+
|
187
|
+
class Logger
|
188
|
+
alias_method :tcell_old_add, :add
|
189
|
+
def add(severity, message = nil, progname = nil, &block)
|
190
|
+
if severity < self.level
|
191
|
+
tcell_old_add(severity, message, progname)
|
183
192
|
|
184
|
-
class Logger
|
185
|
-
alias_method :tcell_old_add, :add
|
186
|
-
def add(severity, message = nil, progname = nil, &block)
|
187
|
-
progname ||= @progname
|
188
|
-
if message.nil?
|
189
|
-
if block_given?
|
190
|
-
message = yield
|
191
193
|
else
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
tcell_context = request_env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
|
201
|
-
if tcell_context
|
202
|
-
tcell_context.filter_log(message)
|
194
|
+
progname ||= @progname
|
195
|
+
if message.nil?
|
196
|
+
if block_given?
|
197
|
+
message = yield
|
198
|
+
else
|
199
|
+
message = progname
|
200
|
+
progname = @progname
|
201
|
+
end
|
203
202
|
end
|
203
|
+
|
204
|
+
TCellAgent::Instrumentation.safe_block_no_log("Handling JSAgent add") {
|
205
|
+
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
206
|
+
request_env = TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS.fetch(Thread.current.object_id, nil)
|
207
|
+
if message && dlp_policy && request_env
|
208
|
+
tcell_context = request_env[TCellAgent::Instrumentation::Rails::Middleware::TCELL_ID]
|
209
|
+
if tcell_context
|
210
|
+
tcell_context.filter_log(message)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
}
|
214
|
+
tcell_old_add(severity, message, progname)
|
204
215
|
end
|
205
|
-
|
206
|
-
tcell_old_add(severity, message, progname)
|
216
|
+
end
|
207
217
|
end
|
208
|
-
end
|
218
|
+
end
|