tcell_agent 1.1.6 → 1.1.7

Sign up to get free protection for your applications and to get access to all the features.
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