tcell_agent 1.1.6 → 1.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 268481d9cc436a4f01caf780f929dc045ca3162c1869fe52426d3587d16e78e6
4
- data.tar.gz: a2705e57d4662a154306226c700fd2531961d82c329697f5f3c2c8367cf5e3f3
3
+ metadata.gz: f6f920526272f2ae748d733a485ce838edbf04ce6ec7641265791fd115d9c2a2
4
+ data.tar.gz: 7c80dc4ff7592443f2d4b9d82a776f9e82f2bc2acb1587890d292d8a0c166a1a
5
5
  SHA512:
6
- metadata.gz: 545ad44a5d2d830e57858c6d4e96378bfd6dcb708e7cf8e184d1a33d265c3005c760afa8249fddddf634f5c6270180249eebb42fde7e75f13777a777954dd894
7
- data.tar.gz: 6d103258c4749bafb3048942d7f98a4ba34632f19510e76c335021eb60d9299b7979fa440381d48ca5445fcd5cfee7ca0b8cbdf08825a036f1d4a12dcdbc16d1
6
+ metadata.gz: a4c8bea678eb530fb55f9ddeffd0105ad184138c0f77302bc610eee74da467d0de5583b09a1d578c1549cee9730b708d6223ec6d07404c6f9e53b92e4ef9e8b3
7
+ data.tar.gz: 32035b9d1703f0b08da77c8621ba19f2741486e90c02e8db886e686f4ac8dd39cf6ac38ad011374d6ed8c1c269b6e5ac20f550f71b4da29dd35e9e1d496d8ac8
@@ -32,8 +32,14 @@ module TCellAgent
32
32
  end
33
33
 
34
34
  def ensure_event_processor_running
35
- return if event_processor_running?
36
- return if TCellAgent.configuration.should_start_event_manager? == false
35
+ if event_processor_running?
36
+ TCellAgent.logger.debug('[Agent::ensure_event_processor_running] Event processor already running, no need to start')
37
+ return
38
+ end
39
+ if TCellAgent.configuration.should_start_event_manager? == false
40
+ TCellAgent.logger.debug('[Agent::ensure_event_processor_running] TCellAgent.configuration.should_start_event_manager? is false, no need to start')
41
+ return
42
+ end
37
43
  @worker_mutex.synchronize do
38
44
  return if event_processor_running?
39
45
  initialize_processor_variables if parent_process? == false
@@ -42,7 +48,10 @@ module TCellAgent
42
48
  end
43
49
 
44
50
  def event_processor_running?
45
- return true if TCellAgent::Agent.parent_process? == false
51
+ if TCellAgent::Agent.parent_process? == false
52
+ TCellAgent.logger.debug('[Agent::event_processor_running?] Not a parent process, so returning true')
53
+ return true
54
+ end
46
55
  @event_processor_thread && @event_processor_thread.alive?
47
56
  end
48
57
 
@@ -87,9 +96,17 @@ module TCellAgent
87
96
  def start_event_processor(send_empties = true)
88
97
  return if TCellAgent.configuration.should_start_event_manager? == false
89
98
 
90
- return if TCellAgent::Agent.parent_process? == false
99
+ if TCellAgent.configuration.should_start_event_manager_in_child_processes?
100
+ TCellAgent.logger.debug('Enabling event manager in child processes')
101
+ require('tcell_agent/config/child_process_events')
102
+ end
91
103
 
92
- TCellAgent.logger.debug('Starting event processor thread')
104
+ if TCellAgent::Agent.parent_process? == false
105
+ TCellAgent.logger.debug('[Agent::start_event_processor] Not a parent process, so not starting event processor thread')
106
+ return
107
+ end
108
+
109
+ TCellAgent.logger.debug('[Agent::start_event_processor] Starting event processor thread')
93
110
  @events_send_empties = send_empties
94
111
  Thread.abort_on_exception = true
95
112
  @event_processor_thread = Thread.new do
@@ -147,6 +164,7 @@ module TCellAgent
147
164
  end
148
165
 
149
166
  def ensure_fork_event_thread_running
167
+ TCellAgent.logger.debug('[Agent::ensure_fork_event_thread_running] Ensuring the fork event thread is running')
150
168
  return if event_fork_thread_running?
151
169
  @fork_event_thread_mutex.synchronize do
152
170
  return if event_fork_thread_running?
@@ -155,11 +173,15 @@ module TCellAgent
155
173
  end
156
174
 
157
175
  def event_fork_thread_running?
158
- return true if TCellAgent::Agent.parent_process?
176
+ if TCellAgent::Agent.parent_process?
177
+ TCellAgent.logger.debug('[Agent::event_fork_thread_running?] Parent process, so returning true')
178
+ return true
179
+ end
159
180
  @fork_event_thread && @fork_event_thread.alive?
160
181
  end
161
182
 
162
183
  def start_fork_event_thread
184
+ TCellAgent.logger.debug('[Agent::start_fork_event_thread] Starting event fork thread')
163
185
  @fork_event_thread = Thread.new do
164
186
  loop do
165
187
  begin
@@ -0,0 +1,8 @@
1
+ # Forces event manager to start in child processes
2
+ # Conditionally loaded based on config
3
+ class << TCellAgent::Agent
4
+ alias_method :tcell_parent_process?, :parent_process?
5
+ def parent_process?
6
+ true
7
+ end
8
+ end
@@ -26,7 +26,6 @@ module TCellAgent
26
26
  :app_id,
27
27
  :api_key,
28
28
  :hmac_key,
29
- :tcell_api_url,
30
29
  :tcell_input_url,
31
30
  :logging_options,
32
31
  :logger,
@@ -54,22 +53,36 @@ module TCellAgent
54
53
  :allow_payloads,
55
54
  :password_hmac_key
56
55
 
56
+ attr_reader :tcell_api_url
57
+
57
58
  attr_accessor :disable_all,
58
59
  :enabled,
59
60
  :enable_event_manager, # false = Do not start the even manager
60
61
  :enable_event_consumer, # false = Do not consume events, drop them
61
62
  :enable_policy_polling, # false = Do not poll for policies
62
63
  :enable_instrumentation, # false = Do not add instrumentation
63
- :enable_intercept_requests # false = Do not insert middleware
64
+ :enable_intercept_requests, # false = Do not insert middleware
65
+ :enable_child_process_events # true = Start an event processor on all processes, even children
64
66
 
65
67
  attr_accessor :enabled_instrumentations
66
68
 
67
69
  attr_accessor :exp_config_settings
68
70
 
71
+ attr_accessor :disable_cmdi_exec_instrumentation # true = disable cmdi Kernel::exec instrumentation
72
+
73
+ def tcell_api_url=(value)
74
+ @tcell_api_url = value
75
+ @tcell_api_url = compose_api_url!
76
+ end
77
+
69
78
  def should_start_event_manager?
70
79
  @enabled && @enable_event_manager
71
80
  end
72
81
 
82
+ def should_start_event_manager_in_child_processes?
83
+ @enabled && @enable_event_manager && @enable_child_process_events
84
+ end
85
+
73
86
  def should_consume_event?
74
87
  @enabled && @enable_event_manager && @enable_event_consumer
75
88
  end
@@ -110,6 +123,10 @@ module TCellAgent
110
123
  end
111
124
  end
112
125
 
126
+ def should_instrument_cmdi_exec?
127
+ !@disable_cmdi_exec_instrumentation
128
+ end
129
+
113
130
  def initialize(filename = 'config/tcell_agent.config', _useapp = nil)
114
131
  # These will be set when the agent starts up, to give rails initializers
115
132
  # a chance to run
@@ -134,6 +151,7 @@ module TCellAgent
134
151
  @enable_policy_polling = true
135
152
  @enable_instrumentation = true
136
153
  @enable_intercept_requests = true
154
+ @enable_child_process_events = false
137
155
 
138
156
  @enabled_instrumentations = {
139
157
  :doorkeeper => true,
@@ -141,6 +159,8 @@ module TCellAgent
141
159
  :authlogic => true
142
160
  }
143
161
 
162
+ @disable_cmdi_exec_instrumentation = false
163
+
144
164
  @log_file_name = 'tcell_agent.log'
145
165
 
146
166
  @event_batch_size_limit = 50
@@ -254,6 +274,8 @@ module TCellAgent
254
274
 
255
275
  @agent_home_owner = ENV['TCELL_AGENT_HOME_OWNER'] || @agent_home_owner
256
276
  @agent_log_dir = ENV['TCELL_AGENT_LOG_DIR'] || @agent_log_dir
277
+
278
+ @disable_cmdi_exec_instrumentation = ENV['TCELL_CMDI_EXEC_DISABLED'] || @disable_cmdi_exec_instrumentation
257
279
  end
258
280
 
259
281
  def read_config_from_file(filename)
@@ -288,6 +310,7 @@ module TCellAgent
288
310
  @enable_intercept_requests = app_data.fetch('enable_intercept_requests', @enable_intercept_requests)
289
311
  @fetch_policies_from_tcell = app_data.fetch('fetch_policies_from_tcell', @fetch_policies_from_tcell)
290
312
  @instrument_for_events = app_data.fetch('instrument_for_events', @instrument_for_events)
313
+ @enable_child_process_events = app_data.fetch('enable_child_process_events', @enable_child_process_events)
291
314
 
292
315
  @agent_home_owner = app_data.fetch('agent_home_owner', @agent_home_owner)
293
316
 
@@ -0,0 +1,56 @@
1
+ require 'tcell_agent/agent/policy_types'
2
+ require 'tcell_agent/utils/strings'
3
+ require 'tcell_agent/configuration'
4
+
5
+ module TCellAgent
6
+ module Cmdi
7
+ def self.block_command?(cmd)
8
+ TCellAgent::Instrumentation.safe_block('Checking Command Injection Policy') do
9
+ if TCellAgent::Utils::Strings.present?(cmd)
10
+ rust_policies = TCellAgent.policy(TCellAgent::PolicyTypes::RUST)
11
+ if rust_policies && rust_policies.cmdi_enabled
12
+ request_env = TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS.fetch(
13
+ Thread.current.object_id, {}
14
+ )
15
+ tcell_context = request_env[TCellAgent::Instrumentation::TCELL_ID]
16
+ return rust_policies.block_command?(cmd, tcell_context)
17
+ end
18
+ end
19
+ end
20
+
21
+ false
22
+ end
23
+
24
+ def self.parse_command(*args)
25
+ cmd = ''
26
+
27
+ TCellAgent::Instrumentation.safe_block('CMDI Parsing *args') do
28
+ unless args.empty?
29
+ args_copy = Array.new(args)
30
+ args_copy.shift if args_copy.first.is_a?(Hash)
31
+ args_copy.pop if args_copy.last.is_a?(Hash)
32
+
33
+ if args_copy.first.is_a?(Array)
34
+ cmd_n_argv0 = args_copy.shift
35
+ args_copy.unshift(cmd_n_argv0.first)
36
+ end
37
+
38
+ cmd = args_copy.join(' ')
39
+ end
40
+ end
41
+
42
+ cmd
43
+ end
44
+ end
45
+ end
46
+
47
+ if TCellAgent.configuration.should_instrument_cmdi_exec?
48
+ require('tcell_agent/instrumentation/cmdi/exec')
49
+ else
50
+ TCellAgent.logger.debug('Disabling cmdi Kernel::exec instrumentation')
51
+ end
52
+
53
+ require('tcell_agent/instrumentation/cmdi/backtick')
54
+ require('tcell_agent/instrumentation/cmdi/system')
55
+ require('tcell_agent/instrumentation/cmdi/spawn')
56
+ require('tcell_agent/instrumentation/cmdi/popen')
@@ -0,0 +1,10 @@
1
+ module Kernel
2
+ alias_method :tcell_original_backtick, :`
3
+ def `(cmd)
4
+ if TCellAgent::Cmdi.block_command?(cmd)
5
+ raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
6
+ end
7
+
8
+ tcell_original_backtick(cmd)
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Kernel
2
+ alias_method :tcell_original_exec, :exec
3
+ def exec(*args)
4
+ cmd = TCellAgent::Cmdi.parse_command(*args)
5
+ if TCellAgent::Cmdi.block_command?(cmd)
6
+ raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
7
+ end
8
+
9
+ tcell_original_exec(*args)
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ class IO
2
+ class << self
3
+ alias_method :tcell_original_popen, :popen
4
+ def popen(*args, &block)
5
+ unless args.empty?
6
+ cmd = ''
7
+
8
+ TCellAgent::Instrumentation.safe_block('CMDI Parsing popen *args') do
9
+ args_copy = Array.new(args)
10
+ args_copy.shift if args_copy.first.is_a?(Hash)
11
+ args_copy.pop if args_copy.last.is_a?(Hash)
12
+
13
+ cmd = if args_copy.first.is_a?(String)
14
+ args_copy.shift
15
+ else
16
+ TCellAgent::Cmdi.parse_command(*args_copy.shift)
17
+ end
18
+ end
19
+
20
+ if TCellAgent::Cmdi.block_command?(cmd)
21
+ raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
22
+ end
23
+ end
24
+
25
+ tcell_original_popen(*args, &block)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ module Kernel
2
+ alias_method :tcell_original_spawn, :spawn
3
+ def spawn(*args)
4
+ cmd = TCellAgent::Cmdi.parse_command(*args)
5
+ if TCellAgent::Cmdi.block_command?(cmd)
6
+ raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
7
+ end
8
+
9
+ tcell_original_spawn(*args)
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Kernel
2
+ alias_method :tcell_original_system, :system
3
+ def system(*args)
4
+ cmd = TCellAgent::Cmdi.parse_command(*args)
5
+ if TCellAgent::Cmdi.block_command?(cmd)
6
+ raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
7
+ end
8
+
9
+ tcell_original_system(*args)
10
+ end
11
+ end
@@ -92,9 +92,17 @@ if TCellAgent.configuration.should_instrument_devise? && defined?(Devise)
92
92
  alias_method :tcell_validate, :validate
93
93
  def validate(resource, &block)
94
94
  is_valid = tcell_validate(resource, &block)
95
+ send_event = is_valid
96
+
97
+ # gets the first entry in the current backtrace
98
+ # syntax suggested by rubocop to improve performance
99
+ if caller(1..1).first.include? 'two_factor_authenticatable'
100
+ TCellAgent.logger.debug('Not sending login success event for Devise::Strategies::TwoFactorAuthenticatable since 2fa is unsupported')
101
+ send_event = false
102
+ end
95
103
 
96
104
  TCellAgent::Instrumentation.safe_block('Devise Authenticatable Validate') do
97
- if is_valid && TCellAgent.configuration.enabled &&
105
+ if send_event && TCellAgent.configuration.enabled &&
98
106
  TCellAgent.configuration.should_intercept_requests?
99
107
  username = nil
100
108
  (authentication_keys || []).each do |auth_key|
@@ -9,7 +9,7 @@ unless TCellAgent.configuration.disable_all
9
9
  module TCellAgent
10
10
  # require 'tcell_agent/sinatra' if defined?(Sinatra)
11
11
  require 'tcell_agent/rails' if defined?(Rails)
12
- require 'tcell_agent/cmdi'
12
+ require 'tcell_agent/instrumentation/cmdi'
13
13
 
14
14
  def self.run_instrumentation(server_name, send_startup_events = true)
15
15
  require 'tcell_agent/hooks/login_fraud'
@@ -1,5 +1,5 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
3
  module TCellAgent
4
- VERSION = '1.1.6'.freeze
4
+ VERSION = '1.1.7'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tcell_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.6
4
+ version: 1.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafael
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-28 00:00:00.000000000 Z
11
+ date: 2019-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -118,12 +118,18 @@ files:
118
118
  - lib/tcell_agent/api.rb
119
119
  - lib/tcell_agent/appsensor/injections_reporter.rb
120
120
  - lib/tcell_agent/authlogic.rb
121
- - lib/tcell_agent/cmdi.rb
121
+ - lib/tcell_agent/config/child_process_events.rb
122
122
  - lib/tcell_agent/config/unknown_options.rb
123
123
  - lib/tcell_agent/configuration.rb
124
124
  - lib/tcell_agent/devise.rb
125
125
  - lib/tcell_agent/hooks/login_fraud.rb
126
126
  - lib/tcell_agent/instrumentation.rb
127
+ - lib/tcell_agent/instrumentation/cmdi.rb
128
+ - lib/tcell_agent/instrumentation/cmdi/backtick.rb
129
+ - lib/tcell_agent/instrumentation/cmdi/exec.rb
130
+ - lib/tcell_agent/instrumentation/cmdi/popen.rb
131
+ - lib/tcell_agent/instrumentation/cmdi/spawn.rb
132
+ - lib/tcell_agent/instrumentation/cmdi/system.rb
127
133
  - lib/tcell_agent/logger.rb
128
134
  - lib/tcell_agent/patches.rb
129
135
  - lib/tcell_agent/policies/dataloss_policy.rb
@@ -1,114 +0,0 @@
1
- require 'tcell_agent/agent/policy_types'
2
- require 'tcell_agent/utils/strings'
3
-
4
- module TCellAgent
5
- module Cmdi
6
- def self.block_command?(cmd)
7
- TCellAgent::Instrumentation.safe_block('Checking Command Injection Policy') do
8
- if TCellAgent::Utils::Strings.present?(cmd)
9
- rust_policies = TCellAgent.policy(TCellAgent::PolicyTypes::RUST)
10
- if rust_policies && rust_policies.cmdi_enabled
11
- request_env = TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware::THREADS.fetch(
12
- Thread.current.object_id, {}
13
- )
14
- tcell_context = request_env[TCellAgent::Instrumentation::TCELL_ID]
15
- return rust_policies.block_command?(cmd, tcell_context)
16
- end
17
- end
18
- end
19
-
20
- false
21
- end
22
-
23
- def self.parse_command(*args)
24
- cmd = ''
25
-
26
- TCellAgent::Instrumentation.safe_block('CMDI Parsing *args') do
27
- unless args.empty?
28
- args_copy = Array.new(args)
29
- args_copy.shift if args_copy.first.is_a?(Hash)
30
- args_copy.pop if args_copy.last.is_a?(Hash)
31
-
32
- if args_copy.first.is_a?(Array)
33
- cmd_n_argv0 = args_copy.shift
34
- args_copy.unshift(cmd_n_argv0.first)
35
- end
36
-
37
- cmd = args_copy.join(' ')
38
- end
39
- end
40
-
41
- cmd
42
- end
43
- end
44
- end
45
-
46
- module Kernel
47
- alias_method :tcell_original_backtick, :`
48
- def `(cmd)
49
- if TCellAgent::Cmdi.block_command?(cmd)
50
- raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
51
- end
52
-
53
- tcell_original_backtick(cmd)
54
- end
55
-
56
- alias_method :tcell_original_exec, :exec
57
- def exec(*args)
58
- cmd = TCellAgent::Cmdi.parse_command(*args)
59
- if TCellAgent::Cmdi.block_command?(cmd)
60
- raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
61
- end
62
-
63
- tcell_original_exec(*args)
64
- end
65
-
66
- alias_method :tcell_original_system, :system
67
- def system(*args)
68
- cmd = TCellAgent::Cmdi.parse_command(*args)
69
- if TCellAgent::Cmdi.block_command?(cmd)
70
- raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
71
- end
72
-
73
- tcell_original_system(*args)
74
- end
75
-
76
- alias_method :tcell_original_spawn, :spawn
77
- def spawn(*args)
78
- cmd = TCellAgent::Cmdi.parse_command(*args)
79
- if TCellAgent::Cmdi.block_command?(cmd)
80
- raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
81
- end
82
-
83
- tcell_original_spawn(*args)
84
- end
85
- end
86
-
87
- class IO
88
- class << self
89
- alias_method :tcell_original_popen, :popen
90
- def popen(*args, &block)
91
- unless args.empty?
92
- cmd = ''
93
-
94
- TCellAgent::Instrumentation.safe_block('CMDI Parsing popen *args') do
95
- args_copy = Array.new(args)
96
- args_copy.shift if args_copy.first.is_a?(Hash)
97
- args_copy.pop if args_copy.last.is_a?(Hash)
98
-
99
- cmd = if args_copy.first.is_a?(String)
100
- args_copy.shift
101
- else
102
- TCellAgent::Cmdi.parse_command(*args_copy.shift)
103
- end
104
- end
105
-
106
- if TCellAgent::Cmdi.block_command?(cmd)
107
- raise Errno::ENOENT, "tCell.io Agent: Command not allowed by policy: #{cmd}"
108
- end
109
- end
110
-
111
- tcell_original_popen(*args, &block)
112
- end
113
- end
114
- end