tcell_agent 0.2.2 → 0.2.4
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 +97 -32
- data/lib/tcell_agent.rb +4 -4
- data/lib/tcell_agent/agent.rb +68 -13
- data/lib/tcell_agent/agent/event_processor.rb +256 -79
- data/lib/tcell_agent/agent/fork_pipe_manager.rb +114 -0
- data/lib/tcell_agent/agent/policy_manager.rb +28 -16
- data/lib/tcell_agent/agent/policy_types.rb +3 -4
- data/lib/tcell_agent/agent/route_manager.rb +45 -0
- data/lib/tcell_agent/agent/static_agent.rb +48 -10
- data/lib/tcell_agent/api.rb +0 -2
- data/lib/tcell_agent/appsensor/path_traversal.rb +1 -1
- data/lib/tcell_agent/configuration.rb +19 -6
- data/lib/tcell_agent/instrumentation.rb +123 -0
- data/lib/tcell_agent/logger.rb +4 -1
- data/lib/tcell_agent/policies/content_security_policy.rb +44 -8
- data/lib/tcell_agent/policies/dataloss_policy.rb +122 -65
- data/lib/tcell_agent/rails.rb +19 -10
- data/{config/initializers/authlogic_auth.rb → lib/tcell_agent/rails/auth/authlogic.rb} +1 -0
- data/{config/initializers/devise_auth.rb → lib/tcell_agent/rails/auth/devise.rb} +2 -81
- data/lib/tcell_agent/rails/dlp.rb +40 -36
- data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +2 -2
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +8 -2
- data/lib/tcell_agent/rails/routes.rb +15 -19
- data/lib/tcell_agent/routes/table.rb +35 -0
- data/lib/tcell_agent/sensor_events/app_sensor.rb +22 -33
- data/lib/tcell_agent/sensor_events/discovery.rb +30 -0
- data/lib/tcell_agent/sensor_events/dlp.rb +9 -4
- data/lib/tcell_agent/sensor_events/sensor.rb +3 -0
- data/lib/tcell_agent/sensor_events/server_agent.rb +30 -6
- data/lib/tcell_agent/sensor_events/util/utils.rb +5 -1
- data/lib/tcell_agent/start_background_thread.rb +27 -22
- data/lib/tcell_agent/utils/queue_with_timeout.rb +65 -1
- data/lib/tcell_agent/version.rb +1 -1
- data/spec/lib/tcell_agent/instrumentation_spec.rb +198 -0
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +37 -2
- data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +81 -8
- data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +3 -3
- data/spec/spec_helper.rb +16 -0
- metadata +11 -11
- data/config/initializers/init.rb +0 -8
- data/lib/tcell_agent/dataloss.rb +0 -0
- data/lib/tcell_agent/policies/add_script_tag_policy.rb +0 -47
- data/lib/tcell_agent/rails/devise.rb +0 -0
- data/spec/lib/tcell_agent/policies/add_script_tag_policy_spec.rb +0 -37
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'thread'
|
|
4
|
+
require "tcell_agent/logger"
|
|
5
|
+
|
|
6
|
+
module TCellAgent
|
|
7
|
+
class Agent
|
|
8
|
+
class ForkPipeManager
|
|
9
|
+
attr_accessor :readp
|
|
10
|
+
attr_accessor :writep
|
|
11
|
+
|
|
12
|
+
@@parent_id = Process.pid
|
|
13
|
+
def initialize(&block)
|
|
14
|
+
begin
|
|
15
|
+
@readp, @writep = IO.pipe('ASCII-8BIT', 'ASCII-8BIT', binmode: true)
|
|
16
|
+
if defined?(::Encoding::ASCII_8BIT)
|
|
17
|
+
@writep.set_encoding(::Encoding::ASCII_8BIT)
|
|
18
|
+
end
|
|
19
|
+
if is_parent?
|
|
20
|
+
self.start_listener(&block)
|
|
21
|
+
end
|
|
22
|
+
rescue Exception=>init_exception
|
|
23
|
+
TCellAgent.logger.error("Could not start listener for pipe to forks")
|
|
24
|
+
TCellAgent.logger.error(init_exception.message)
|
|
25
|
+
TCellAgent.logger.debug(init_exception.backtrace)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
def is_parent?
|
|
29
|
+
@@parent_id == Process.pid
|
|
30
|
+
end
|
|
31
|
+
def start_listener(&block)
|
|
32
|
+
Thread.new {
|
|
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
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
def send_to_parent(event)
|
|
52
|
+
if is_parent?
|
|
53
|
+
#puts "Sending in pipe the wrong way"
|
|
54
|
+
return
|
|
55
|
+
else
|
|
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
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
@@event_pipe_manager = ForkPipeManager.new { |event|
|
|
69
|
+
begin
|
|
70
|
+
TCellAgent.send_event(event)
|
|
71
|
+
rescue Exception=>block_exception
|
|
72
|
+
TCellAgent.logger.error("Could handle send_event_block")
|
|
73
|
+
TCellAgent.logger.error(block_exception.message)
|
|
74
|
+
TCellAgent.logger.debug(block_exception.backtrace)
|
|
75
|
+
end
|
|
76
|
+
}
|
|
77
|
+
@@metrics_pipe_manager = ForkPipeManager.new { |val|
|
|
78
|
+
begin
|
|
79
|
+
switch_on = val.fetch("_type","")
|
|
80
|
+
case switch_on
|
|
81
|
+
when "increment_route"
|
|
82
|
+
TCellAgent.increment_route(
|
|
83
|
+
val.fetch("route_id",nil),
|
|
84
|
+
val.fetch("response_time",nil)
|
|
85
|
+
)
|
|
86
|
+
when "discover_database_fields"
|
|
87
|
+
TCellAgent.discover_database_fields(
|
|
88
|
+
val.fetch("route_id",nil),
|
|
89
|
+
val.fetch("database",nil),
|
|
90
|
+
val.fetch("schema",nil),
|
|
91
|
+
val.fetch("table",nil),
|
|
92
|
+
val.fetch("fields",nil)
|
|
93
|
+
)
|
|
94
|
+
else
|
|
95
|
+
# Log this?
|
|
96
|
+
end
|
|
97
|
+
rescue Exception=>block_exception
|
|
98
|
+
TCellAgent.logger.error("Could handle metrics_pipe_block")
|
|
99
|
+
TCellAgent.logger.error(block_exception.message)
|
|
100
|
+
TCellAgent.logger.debug(block_exception.backtrace)
|
|
101
|
+
end
|
|
102
|
+
}
|
|
103
|
+
def self.is_parent_process?
|
|
104
|
+
@@event_pipe_manager.is_parent?
|
|
105
|
+
end
|
|
106
|
+
def self.send_to_metrics_pipe(hash_value)
|
|
107
|
+
@@metrics_pipe_manager.send_to_parent(hash_value)
|
|
108
|
+
end
|
|
109
|
+
def self.send_to_event_pipe(event)
|
|
110
|
+
@@event_pipe_manager.send_to_parent(event)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
# See the file "LICENSE" for the full license governing this code.
|
|
2
4
|
|
|
3
5
|
require "tcell_agent/logger"
|
|
@@ -14,7 +16,6 @@ require "tcell_agent/policies/http_redirect_policy"
|
|
|
14
16
|
require "tcell_agent/policies/secure_headers_policy"
|
|
15
17
|
require "tcell_agent/policies/honeytokens_policy"
|
|
16
18
|
require "tcell_agent/policies/appsensor_policy"
|
|
17
|
-
require "tcell_agent/policies/add_script_tag_policy"
|
|
18
19
|
|
|
19
20
|
require "tcell_agent/sensor_events/server_agent"
|
|
20
21
|
|
|
@@ -28,21 +29,32 @@ require 'json'
|
|
|
28
29
|
module TCellAgent
|
|
29
30
|
class Agent
|
|
30
31
|
|
|
32
|
+
def ensure_policy_polling_running
|
|
33
|
+
return if policy_polling_running?
|
|
34
|
+
@policy_polling_worker_mutex.synchronize do
|
|
35
|
+
return if policy_polling_running?
|
|
36
|
+
start_policy_polling
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def policy_polling_running?
|
|
41
|
+
@policy_polling_thread && @policy_polling_thread.alive?
|
|
42
|
+
end
|
|
43
|
+
|
|
31
44
|
def start_policy_polling
|
|
32
45
|
if TCellAgent.configuration.fetch_policies_from_tcell == true
|
|
33
46
|
TCellAgent.logger.debug("starting background polling thread")
|
|
34
|
-
@
|
|
47
|
+
@policy_polling_thread = Thread.new do
|
|
35
48
|
last_poll_time = 0
|
|
36
|
-
tapi = TCellApi.new
|
|
37
49
|
last_run = Time.now
|
|
38
50
|
loop do
|
|
39
51
|
begin
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
policy_jsons = @@policy_tapi.pollAPI(last_poll_time)
|
|
53
|
+
if policy_jsons == nil
|
|
54
|
+
TCellAgent.logger.error("Policy was nil")
|
|
55
|
+
sleep(10.0)
|
|
56
|
+
next
|
|
57
|
+
elsif policy_jsons.key?("last_timestamp")
|
|
46
58
|
if policy_jsons["last_timestamp"] != 0
|
|
47
59
|
last_poll_time = policy_jsons["last_timestamp"]
|
|
48
60
|
end
|
|
@@ -53,20 +65,19 @@ module TCellAgent
|
|
|
53
65
|
end
|
|
54
66
|
processPolicyJson(policy_jsons)
|
|
55
67
|
rescue Exception => e
|
|
56
|
-
TCellAgent.logger.error("
|
|
68
|
+
TCellAgent.logger.error("exception while handling connection: #{e.message}")
|
|
57
69
|
TCellAgent.logger.debug(e.backtrace)
|
|
58
|
-
TCellAgent.logger.debug("Sleeping
|
|
59
|
-
sleep(
|
|
70
|
+
TCellAgent.logger.debug("Sleeping 30 seconds because the tCell.io request failed...")
|
|
71
|
+
sleep(30) #wait a minute before trying again
|
|
60
72
|
end
|
|
61
|
-
# A little rate limiting
|
|
62
73
|
if (Time.now - last_run) < 1
|
|
63
|
-
TCellAgent.logger.debug("Rate limiting: sleeping
|
|
64
|
-
sleep(
|
|
74
|
+
TCellAgent.logger.debug("Rate limiting: sleeping 10 seconds")
|
|
75
|
+
sleep(10)
|
|
65
76
|
end
|
|
66
77
|
last_run = Time.now
|
|
67
78
|
end
|
|
68
79
|
end
|
|
69
|
-
end
|
|
80
|
+
end
|
|
70
81
|
end
|
|
71
82
|
|
|
72
83
|
def processPolicyJson(policy_jsons, cache_the_policy=true)
|
|
@@ -97,6 +108,7 @@ module TCellAgent
|
|
|
97
108
|
|
|
98
109
|
def cache(policy_name, policy)
|
|
99
110
|
cache_filename = TCellAgent.configuration.cache_filename
|
|
111
|
+
FileUtils.mkdir_p(File.dirname(cache_filename))
|
|
100
112
|
if TCellAgent.configuration.app_id
|
|
101
113
|
cache_filename = cache_filename + '.' + TCellAgent.configuration.app_id
|
|
102
114
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
# See the file "LICENSE" for the full license governing this code.
|
|
2
4
|
|
|
3
5
|
require "tcell_agent/policies/content_security_policy"
|
|
@@ -8,7 +10,6 @@ require "tcell_agent/policies/http_redirect_policy"
|
|
|
8
10
|
require "tcell_agent/policies/secure_headers_policy"
|
|
9
11
|
require "tcell_agent/policies/honeytokens_policy"
|
|
10
12
|
require "tcell_agent/policies/appsensor_policy"
|
|
11
|
-
require "tcell_agent/policies/add_script_tag_policy"
|
|
12
13
|
require "tcell_agent/policies/login_fraud_policy"
|
|
13
14
|
require "tcell_agent/policies/dataloss_policy"
|
|
14
15
|
|
|
@@ -20,9 +21,8 @@ module TCellAgent
|
|
|
20
21
|
HttpTx = "http-tx"
|
|
21
22
|
HttpRedirect = "http-redirect"
|
|
22
23
|
AppSensor = "appsensor"
|
|
23
|
-
AddScriptTag = "add-jsagent-script-tag"
|
|
24
24
|
HoneyTokens = "exp-honeytokens"
|
|
25
|
-
LoginFraud = "
|
|
25
|
+
LoginFraud = "login"
|
|
26
26
|
DataLoss = "dlp"
|
|
27
27
|
|
|
28
28
|
ClassMap = {
|
|
@@ -32,7 +32,6 @@ module TCellAgent
|
|
|
32
32
|
HttpTx=>TCellAgent::Policies::HttpTxPolicy,
|
|
33
33
|
HttpRedirect=>TCellAgent::Policies::HttpRedirectPolicy,
|
|
34
34
|
AppSensor=>TCellAgent::Policies::AppSensorPolicy,
|
|
35
|
-
AddScriptTag=>TCellAgent::Policies::AddScriptTagPolicy,
|
|
36
35
|
HoneyTokens=>TCellAgent::Policies::HoneytokensPolicy,
|
|
37
36
|
LoginFraud=>TCellAgent::Policies::LoginFraudPolicy,
|
|
38
37
|
DataLoss=>TCellAgent::Policies::DataLossPolicy
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# See the file "LICENSE" for the full license governing this code.
|
|
4
|
+
|
|
5
|
+
require "tcell_agent/logger"
|
|
6
|
+
require "tcell_agent/version"
|
|
7
|
+
require "tcell_agent/api"
|
|
8
|
+
require "tcell_agent/configuration"
|
|
9
|
+
|
|
10
|
+
require "tcell_agent/routes/table"
|
|
11
|
+
require "tcell_agent/sensor_events/discovery"
|
|
12
|
+
require "tcell_agent"
|
|
13
|
+
|
|
14
|
+
module TCellAgent
|
|
15
|
+
class Agent
|
|
16
|
+
def discover_database_field(route_id, database, schema, table, field)
|
|
17
|
+
if (@route_table.routes[route_id].database[database][schema][table][field].discovered != true)
|
|
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
|
|
22
|
+
end
|
|
23
|
+
def discover_database_fields(route_id, database, schema, table, fields)
|
|
24
|
+
if TCellAgent::Agent.is_parent_process? == false
|
|
25
|
+
TCellAgent.queue_metric({"_type"=>"discover_database_fields",
|
|
26
|
+
"route_id"=>route_id,
|
|
27
|
+
"database"=>database,
|
|
28
|
+
"schema"=>schema,
|
|
29
|
+
"table"=>table,
|
|
30
|
+
"fields"=>fields})
|
|
31
|
+
return
|
|
32
|
+
end
|
|
33
|
+
discovered_fields = fields.select { |field|
|
|
34
|
+
@route_table.routes[route_id].database[database][schema][table][field].discovered != true
|
|
35
|
+
}
|
|
36
|
+
if (discovered_fields.length > 0)
|
|
37
|
+
discovered_fields.each { |field|
|
|
38
|
+
@route_table.routes[route_id].database[database][schema][table][field].discovered = true
|
|
39
|
+
}
|
|
40
|
+
event = (TCellAgent::SensorEvents::DiscoveryEvent.new(route_id)).for_database_fields(database, schema, table, fields)
|
|
41
|
+
TCellAgent.send_event(event)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -1,22 +1,60 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
1
3
|
# See the file "LICENSE" for the full license governing this code.
|
|
2
4
|
require 'tcell_agent/sensor_events/metrics'
|
|
5
|
+
require 'monitor'
|
|
3
6
|
|
|
4
7
|
module TCellAgent
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
@@instance_lock = Mutex.new
|
|
9
|
+
@@my_thread_agent = nil
|
|
10
|
+
|
|
11
|
+
def self.thread_agent
|
|
12
|
+
if(self.thread_agent_defined? == false)
|
|
13
|
+
@@instance_lock.synchronize do
|
|
14
|
+
if(self.thread_agent_defined? == false)
|
|
15
|
+
@@my_thread_agent= TCellAgent::Agent.new(Process.pid)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
@@my_thread_agent
|
|
7
20
|
end
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
21
|
+
|
|
22
|
+
def self.thread_agent_defined?
|
|
23
|
+
@@my_thread_agent != nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# setter
|
|
27
|
+
def self.thread_agent=some_agent
|
|
28
|
+
@@instance_lock.synchronize do
|
|
29
|
+
@@my_thread_agent = some_agent
|
|
11
30
|
end
|
|
12
31
|
end
|
|
32
|
+
|
|
33
|
+
#class << self
|
|
34
|
+
# attr_accessor :thread_agent
|
|
35
|
+
#end
|
|
36
|
+
def self.send_event(event)
|
|
37
|
+
self.thread_agent.queueSensorEvent(event)
|
|
38
|
+
end
|
|
39
|
+
def self.queue_metric(event)
|
|
40
|
+
self.thread_agent._queue_metric(event)
|
|
41
|
+
end
|
|
13
42
|
def self.policy(policy_type)
|
|
14
|
-
|
|
15
|
-
self.thread_agent.policies.fetch(policy_type, nil)
|
|
16
|
-
end
|
|
43
|
+
self.thread_agent.policies.fetch(policy_type, nil)
|
|
17
44
|
end
|
|
18
45
|
def self.increment_route(route_id, response_time)
|
|
19
|
-
|
|
20
|
-
|
|
46
|
+
self.thread_agent.increment_route(route_id, response_time)
|
|
47
|
+
end
|
|
48
|
+
def self.discover_database_field(route_id, database, schema, table, field)
|
|
49
|
+
self.thread_agent.discover_database_field(route_id, database, schema, table, field)
|
|
50
|
+
end
|
|
51
|
+
def self.discover_database_fields(route_id, database, schema, table, fields)
|
|
52
|
+
self.thread_agent.discover_database_fields(route_id, database, schema, table, fields)
|
|
53
|
+
end
|
|
54
|
+
def self.stop_agent
|
|
55
|
+
self.thread_agent.stop_agent = true
|
|
56
|
+
end
|
|
57
|
+
def self.ensure_event_processor_running
|
|
58
|
+
self.thread_agent.ensure_event_processor_running
|
|
21
59
|
end
|
|
22
60
|
end
|
data/lib/tcell_agent/api.rb
CHANGED
|
@@ -30,7 +30,6 @@ module TCellAgent
|
|
|
30
30
|
TCellAgent.logger.debug("tCell.io Could not add agent string: " + e.message)
|
|
31
31
|
end
|
|
32
32
|
response = RestClient.get full_url,request_headers
|
|
33
|
-
new_timestamp = last_timestamp
|
|
34
33
|
TCellAgent.logger.debug "tCell.io API Response: " + response
|
|
35
34
|
response_json = JSON.parse(response)
|
|
36
35
|
if (response_json && response_json.has_key?("result"))
|
|
@@ -50,7 +49,6 @@ module TCellAgent
|
|
|
50
49
|
if (last_timestamp && last_timestamp != "")
|
|
51
50
|
full_url = full_url + "?last_timestamp=" + last_timestamp.to_s
|
|
52
51
|
end
|
|
53
|
-
TCellAgent.logger.debug("tCell.io Old API Request: " + full_url)
|
|
54
52
|
response = RestClient.get full_url
|
|
55
53
|
TCellAgent.logger.debug "tCell.io API Response: " + response
|
|
56
54
|
response_json = JSON.parse(response)
|
|
@@ -11,7 +11,7 @@ require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
|
|
11
11
|
module TCellAgent
|
|
12
12
|
class AppSensor
|
|
13
13
|
PATH_TRAVERSAL_REGEXES = [
|
|
14
|
-
Regexp.new("(?:(?:\\\/|\\\\)?\\.+(\\\/|\\\\)(
|
|
14
|
+
Regexp.new("(?:(?:\\\/|\\\\)?\\.+(\\\/|\\\\)(?:\\.*))|(?:\\w+\\.exe\\??\\s)|(?:;\\s*\\w+\\s*\\\/[\\w*-]+\\\/)|(?:\\d\\.\\dx\\|)|(?:%(?:c0\\.|af\\.|5c\\.))|(?:\\\/(?:%2e){2})"),
|
|
15
15
|
Regexp.new("(?:%c0%ae\\\/)|(?:(?:\\\/|\\\\)(home|conf|usr|etc|proc|opt|s?bin|local|dev|tmp|kern|[br]oot|sys|system|windows|winnt|program|%[a-z_-]{3,}%)(?:\\\/|\\\\))|(?:(?:\\\/|\\\\)inetpub|localstart\\.asp|boot\\.ini)"),
|
|
16
16
|
Regexp.new("(?:etc\\\/\\W*passwd)")
|
|
17
17
|
]
|
|
@@ -37,13 +37,17 @@ module TCellAgent
|
|
|
37
37
|
def initialize(filename="config/tcell_agent.config", useapp=nil)
|
|
38
38
|
@version = 0
|
|
39
39
|
@exp_config_settings = true
|
|
40
|
-
|
|
40
|
+
@demomode = false
|
|
41
41
|
|
|
42
42
|
@fetch_policies_from_tcell = true
|
|
43
43
|
@instrument_for_events = true
|
|
44
44
|
@enabled = true
|
|
45
|
-
@cache_filename = "tcell/tcell_agent.cache"
|
|
46
|
-
@default_log_filename = "tcell/tcell_agent.log"
|
|
45
|
+
@cache_filename = "tcell/cache/tcell_agent.cache"
|
|
46
|
+
@default_log_filename = "tcell/logs/tcell_agent.log"
|
|
47
|
+
|
|
48
|
+
@event_batch_size_limit = 25
|
|
49
|
+
@event_time_limit_seconds = 55
|
|
50
|
+
|
|
47
51
|
read_config_using_env
|
|
48
52
|
read_config_from_file(filename)
|
|
49
53
|
|
|
@@ -51,8 +55,6 @@ module TCellAgent
|
|
|
51
55
|
@tcell_input_url ||= "https://input.tcell.io/api/v1"
|
|
52
56
|
@js_agent_api_base_url ||= nil
|
|
53
57
|
@js_agent_url ||= "https://api.tcell.io/tcellagent.min.js"
|
|
54
|
-
@event_batch_size_limit = 25
|
|
55
|
-
@event_time_limit_seconds = 30
|
|
56
58
|
|
|
57
59
|
begin
|
|
58
60
|
@host_identifier = (Socket.gethostname() || "localhost")
|
|
@@ -74,6 +76,11 @@ module TCellAgent
|
|
|
74
76
|
@hmac_key = ENV["TCELL_HMAC_KEY"]
|
|
75
77
|
@tcell_api_url = ENV["TCELL_API_URL"]
|
|
76
78
|
@tcell_input_url = ENV["TCELL_INPUT_URL"]
|
|
79
|
+
@demomode = ENV["TCELL_DEMOMODE"] || @demomode
|
|
80
|
+
if @demomode
|
|
81
|
+
@event_batch_size_limit = 2
|
|
82
|
+
@event_time_limit_seconds = 5
|
|
83
|
+
end
|
|
77
84
|
end
|
|
78
85
|
def read_config_from_file(filename)
|
|
79
86
|
if File.file?(filename)
|
|
@@ -127,7 +134,13 @@ module TCellAgent
|
|
|
127
134
|
# Causes old event url to be used
|
|
128
135
|
@company = app_data["company"]
|
|
129
136
|
|
|
130
|
-
|
|
137
|
+
if @demomode != true
|
|
138
|
+
@demomode = app_data.fetch('demomode', false)
|
|
139
|
+
end
|
|
140
|
+
if @demomode
|
|
141
|
+
@event_batch_size_limit = 2
|
|
142
|
+
@event_time_limit_seconds = 5
|
|
143
|
+
end
|
|
131
144
|
else
|
|
132
145
|
puts " ********* ********* ********* *********"
|
|
133
146
|
puts "* tCell.io *"
|
|
@@ -16,6 +16,129 @@ module TCellAgent
|
|
|
16
16
|
attr_accessor :user_id
|
|
17
17
|
attr_accessor :route_id
|
|
18
18
|
attr_accessor :uri
|
|
19
|
+
attr_accessor :database_filters
|
|
20
|
+
def self.filterx(sanitize_string, event_flag, replace_flag, term)
|
|
21
|
+
send_event = false
|
|
22
|
+
sanitize_string.gsub!(term) {|m|
|
|
23
|
+
if replace_flag
|
|
24
|
+
m = "[redacted]"
|
|
25
|
+
send_event = true
|
|
26
|
+
elsif event_flag
|
|
27
|
+
# m = "[hash]"
|
|
28
|
+
send_event = true
|
|
29
|
+
end
|
|
30
|
+
m
|
|
31
|
+
}
|
|
32
|
+
return send_event
|
|
33
|
+
end
|
|
34
|
+
def initialize
|
|
35
|
+
@database_filters = Hash.new{|h,k| h[k] = Set.new}
|
|
36
|
+
end
|
|
37
|
+
def add_response_db_filter(term, action_obj, database, schema, table, field)
|
|
38
|
+
if (term != nil and term != '')
|
|
39
|
+
self.database_filters[term].add([database, schema, table, field, action_obj])
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
def filter_body(body)
|
|
43
|
+
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
|
44
|
+
if dlp_policy and self.session_id
|
|
45
|
+
session_id_actions = dlp_policy.get_actions_for_session_id
|
|
46
|
+
if session_id_actions
|
|
47
|
+
send_flag = TCellData.filterx(body, session_id_actions.body_event, session_id_actions.body_redact, self.session_id)
|
|
48
|
+
if send_flag
|
|
49
|
+
TCellAgent.send_event(
|
|
50
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
|
51
|
+
self.route_id,
|
|
52
|
+
self.uri,
|
|
53
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY
|
|
54
|
+
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
self.database_filters.sort_by {|term,properties| -term.length }.each do |term, properties|
|
|
60
|
+
action_infos = self.database_filters[term]
|
|
61
|
+
replace_actions = (action_infos.select {|action_info| action_info[4].body_redact == true })
|
|
62
|
+
event_actions = (action_infos.select {|action_info| (action_info[4].body_redact != true && action_info[4].body_event == true) })
|
|
63
|
+
send_flag = TCellData.filterx(body, event_actions.length > 0, replace_actions.length > 0, term)
|
|
64
|
+
if send_flag
|
|
65
|
+
replace_actions.each do |action_info|
|
|
66
|
+
database, schema, table, field, action_obj = action_info
|
|
67
|
+
TCellAgent.send_event(
|
|
68
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
|
69
|
+
self.route_id,
|
|
70
|
+
self.uri,
|
|
71
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY,
|
|
72
|
+
action_obj.action_id
|
|
73
|
+
).for_database(database, schema, table, field)
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
event_actions.each do |action_info|
|
|
77
|
+
database, schema, table, field, action_obj = action_info
|
|
78
|
+
TCellAgent.send_event(
|
|
79
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
|
80
|
+
self.route_id,
|
|
81
|
+
self.uri,
|
|
82
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_BODY,
|
|
83
|
+
action_obj.action_id
|
|
84
|
+
).for_database(database, schema, table, field)
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
return body
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def filter_log(log_msg)
|
|
93
|
+
dlp_policy = TCellAgent.policy(TCellAgent::PolicyTypes::DataLoss)
|
|
94
|
+
if dlp_policy and self.session_id
|
|
95
|
+
session_id_actions = dlp_policy.get_actions_for_session_id
|
|
96
|
+
if session_id_actions
|
|
97
|
+
send_flag = TCellData.filterx(log_msg, session_id_actions.log_event, session_id_actions.log_redact, self.session_id)
|
|
98
|
+
if send_flag
|
|
99
|
+
TCellAgent.send_event(
|
|
100
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
|
101
|
+
self.route_id,
|
|
102
|
+
self.uri,
|
|
103
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG
|
|
104
|
+
).for_framework(TCellAgent::SensorEvents::DlpEvent::FRAMEWORK_VARIABLE_SESSION_ID)
|
|
105
|
+
)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
self.database_filters.sort_by {|term,properties| -term.length }.each do |term, properties|
|
|
110
|
+
action_infos = self.database_filters[term]
|
|
111
|
+
replace_actions = (action_infos.select {|action_info| action_info[4].log_redact == true })
|
|
112
|
+
event_actions = (action_infos.select {|action_info| (action_info[4].log_redact != true && action_info[4].log_event == true) })
|
|
113
|
+
send_flag = TCellData.filterx(log_msg, event_actions.length > 0, replace_actions.length > 0, term)
|
|
114
|
+
if send_flag
|
|
115
|
+
replace_actions.each do |action_info|
|
|
116
|
+
database, schema, table, field, action_obj = action_info
|
|
117
|
+
TCellAgent.send_event(
|
|
118
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
|
119
|
+
self.route_id,
|
|
120
|
+
self.uri,
|
|
121
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG,
|
|
122
|
+
action_obj.action_id
|
|
123
|
+
).for_database(database, schema, table, field)
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
event_actions.each do |action_info|
|
|
127
|
+
database, schema, table, field, action_obj = action_info
|
|
128
|
+
TCellAgent.send_event(
|
|
129
|
+
TCellAgent::SensorEvents::DlpEvent.new(
|
|
130
|
+
self.route_id,
|
|
131
|
+
self.uri,
|
|
132
|
+
TCellAgent::SensorEvents::DlpEvent::FOUND_IN_LOG,
|
|
133
|
+
action_obj.action_id
|
|
134
|
+
).for_database(database, schema, table, field)
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
return log_msg
|
|
140
|
+
end
|
|
141
|
+
|
|
19
142
|
end
|
|
20
143
|
|
|
21
144
|
def self.instrument_frameworks
|