tcell_agent 0.2.24 → 0.2.25

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
  SHA1:
3
- metadata.gz: 13c88a7582aa8c65921222ed524e8000e8d8872a
4
- data.tar.gz: 2bf2b713872f81e2950994f56f8d431698410224
3
+ metadata.gz: 92307eb548621a9832e41c4966bf2aac64933d43
4
+ data.tar.gz: b0fb089fcbf1967b74ae58538e37425bdb74f466
5
5
  SHA512:
6
- metadata.gz: 40078c7ef5481e0364eff69549a8a3d3fc4197ad7ebb903958443e1f7eaaf8c7310d77cb1ba9d752a2b34a4a2bec748755311e8c58ff10b5570c9c8b02c58e07
7
- data.tar.gz: 4469f30d67cce86ae944efd69dabd92f681cbe9d7cbe1878a1f5155d3f464d1962871c5229570c764c5ef416eb9601f0db11dce3809ac73ba96add1e3e21b57f
6
+ metadata.gz: 7b411099b2c2525530594416c52ef0801eb9e6fa33d7c07dde867b22e381a9edffe00f497512cab7fe2751543264aaa57f7a1629071fedbb65f57f0aafe5bd46
7
+ data.tar.gz: 18a19efaf4d730e0165521c6c7da3f189adb13ae0975de945e1954bd392157c9441d5c33823f3fcdef3f50cc2f10d177172366bda909e70c5234ba297a24d157
data/README.md CHANGED
@@ -41,3 +41,4 @@ Or run the helper command
41
41
  Or if running from the repo:
42
42
 
43
43
  $ bundle exec <path to repo>/rubyagent-tcell/bin/tcell_agent
44
+
@@ -57,6 +57,8 @@ module TCellAgent
57
57
  :enable_instrumentation, # false = Do not add instrumentation
58
58
  :enable_intercept_requests # false = Do not insert middleware
59
59
 
60
+ attr_accessor :enabled_instrumentations
61
+
60
62
  attr_accessor :exp_config_settings
61
63
 
62
64
  def should_start_event_manager?
@@ -79,6 +81,30 @@ module TCellAgent
79
81
  @enabled && @enable_instrumentation && @enable_intercept_requests
80
82
  end
81
83
 
84
+ def should_instrument_doorkeeper?
85
+ if @enabled_instrumentations.has_key?('doorkeeper') || @enabled_instrumentations.has_key?(:doorkeeper)
86
+ !!(@enabled_instrumentations['doorkeeper'] || @enabled_instrumentations[:doorkeeper])
87
+ else
88
+ true
89
+ end
90
+ end
91
+
92
+ def should_instrument_devise?
93
+ if @enabled_instrumentations.has_key?('devise') || @enabled_instrumentations.has_key?(:devise)
94
+ !!(@enabled_instrumentations['devise'] || @enabled_instrumentations[:devise])
95
+ else
96
+ true
97
+ end
98
+ end
99
+
100
+ def should_instrument_authlogic?
101
+ if @enabled_instrumentations.has_key?('authlogic') || @enabled_instrumentations.has_key?(:authlogic)
102
+ !!(@enabled_instrumentations['authlogic'] || @enabled_instrumentations[:authlogic])
103
+ else
104
+ true
105
+ end
106
+ end
107
+
82
108
  def initialize(filename="config/tcell_agent.config", useapp=nil)
83
109
  # These will be set when the agent starts up, to give rails initializers
84
110
  # a chance to run
@@ -104,6 +130,11 @@ module TCellAgent
104
130
  @enable_instrumentation = true
105
131
  @enable_intercept_requests = true
106
132
 
133
+ @enabled_instrumentations = {
134
+ doorkeeper: true,
135
+ devise: true,
136
+ authlogic: true
137
+ }
107
138
 
108
139
  @agent_home_dir = File.join(Dir.getwd, "tcell")
109
140
  @config_filename = File.join(Dir.getwd, filename)
@@ -240,6 +271,8 @@ module TCellAgent
240
271
  data_exposure = app_data.fetch('data_exposure', {})
241
272
  @max_data_ex_db_records_per_request = data_exposure.fetch('max_data_ex_db_records_per_request', @max_data_ex_db_records_per_request)
242
273
 
274
+ @enabled_instrumentations = app_data.fetch('enabled_instrumentations', {})
275
+
243
276
  @reverse_proxy = app_data.fetch('reverse_proxy', @reverse_proxy)
244
277
  @reverse_proxy_ip_address_header = app_data.fetch('reverse_proxy_ip_address_header', @reverse_proxy_ip_address_header)
245
278
 
@@ -293,6 +326,7 @@ module TCellAgent
293
326
  @agent_log_dir ||= File.join(@agent_home_dir, "logs")
294
327
  File.join(@agent_log_dir, "tcell_agent_payloads.log")
295
328
  end
329
+
296
330
  end # class
297
331
 
298
332
  TCellAgent.configuration ||= TCellAgent::Configuration.new
@@ -5,12 +5,6 @@ require 'devise/rails'
5
5
  require 'devise/strategies/database_authenticatable'
6
6
  require 'tcell_agent/userinfo'
7
7
  require 'tcell_agent/logger'
8
- #Warden::Manager.after_authentication do |user,auth,opts|
9
- # p "<M>M>M>M>M>M>M>M>M>M>M>M>M>M>M>M>M>M>M"
10
- # p user
11
- # # do something with user
12
- #end
13
-
14
8
  require 'tcell_agent/sensor_events/honeytokens'
15
9
 
16
10
  module TCellAgent
@@ -39,45 +33,5 @@ module TCellAgent
39
33
  end
40
34
  end
41
35
  end
42
- # Devise::Strategies::DatabaseAuthenticatable.class_eval do
43
- # alias_method :original_authenticate!, :authenticate!
44
- # def authenticate!
45
- # begin
46
- # tcell_background_worker = TCellAgent.thread_agent
47
- # # if (tcell_background_worker && tcell_background_worker.honeytokens_policy)
48
- # # credstring = ""
49
- # # authentication_keys.each do |authentication_key|
50
- # # credstring = credstring + authentication_hash[authentication_key] + "::"
51
- # # end
52
- # # credstring = credstring + password[1..-3] # Chop off first and last 2 characters
53
- # # token_id = tcell_background_worker.honeytokens_policy.id_for_credentialstring(credstring)
54
- # # if token_id
55
- # # begin
56
- # # event = TCellAgent::SensorEvents::HoneytokensSensorEvent.new(request, token_id)
57
- # # TCellAgent.send_event(event)
58
- # # rescue
59
- # # #pass
60
- # # end
61
- # # return
62
- # # end
63
- # # end
64
- # rescue Exception => e
65
- # TCellAgent.logger.error("uncaught exception while processing honeytokens: #{e.message}")
66
- # end
67
- # original_authenticate!
68
- # end
69
- # end
70
36
  end
71
37
  end
72
- # module Devise
73
- # module Models
74
- # module Recoverable
75
- # extend ActiveSupport::Concern
76
- # alias_method :original_send_reset_password_instructions, :send_reset_password_instructions
77
- # def send_reset_password_instructions
78
- # x = original_send_reset_password_instructions
79
- # x
80
- # end
81
- # end
82
- # end
83
- # end
@@ -62,7 +62,7 @@ module TCellAgent
62
62
  class TCellData
63
63
  attr_accessor :transaction_id, :session_id, :hmac_session_id, :user_id, :route_id,
64
64
  :uri, :context_filters_by_term, :database_filters, :ip_address, :user_agent, :request_method,
65
- :path_parameters, :ip_blocking_triggered, :grape_mount_endpoint
65
+ :path_parameters, :ip_blocking_triggered, :grape_mount_endpoint, :referrer, :path
66
66
 
67
67
  def self.filterx(sanitize_string, event_flag, replace_flag, term)
68
68
  send_event = false
@@ -1,57 +1,63 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
- require 'tcell_agent/logger'
4
- require 'tcell_agent/configuration'
5
- require 'tcell_agent/instrumentation'
3
+ if TCellAgent.configuration.should_instrument_authlogic?
6
4
 
7
- module TCellAgent
8
- if defined?(Authlogic)
9
- TCellAgent.logger.debug("Instrumenting Authlogic")
10
- require 'tcell_agent/agent'
11
- require 'tcell_agent/sensor_events/login_fraud'
12
- Authlogic::Session::Base.class_eval do
13
- alias_method :original_save, :save
14
- def save(&block)
15
- if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
16
- user_logged_in_before = (user != nil)
17
- success = original_save
18
- user_logged_in_after = (user != nil)
19
- TCellAgent::Instrumentation.safe_block("Authlogic login info") {
5
+ require 'tcell_agent/logger'
6
+ require 'tcell_agent/configuration'
7
+ require 'tcell_agent/instrumentation'
20
8
 
21
- login_fraud_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LoginFraud)
22
- if (login_fraud_policy && login_fraud_policy.enabled)
23
- user_id = nil
24
- TCellAgent::Instrumentation.safe_block("getting userid for login form") {
25
- user_id = self.send(self.class.login_field.to_sym)
26
- }
27
- if (user_logged_in_before && user_logged_in_after)
28
- #password changed or logged in as another user
29
- elsif (!user_logged_in_before && !user_logged_in_after)
30
- if (login_fraud_policy.login_failed_enabled)
31
- request = Authlogic::Session::Base.controller.request
32
- response = Authlogic::Session::Base.controller.response
33
- hmac_session_id = request.env[TCellAgent::Instrumentation::TCELL_ID].hmac_session_id
34
- event = TCellAgent::SensorEvents::LoginFailure.new(request, response, user_id, hmac_session_id)
35
- TCellAgent.send_event(event)
36
- end
37
- elsif (!user_logged_in_before && user_logged_in_after)
38
- if (login_fraud_policy.login_success_enabled)
39
- request = Authlogic::Session::Base.controller.request
40
- response = Authlogic::Session::Base.controller.response
41
- hmac_session_id = request.env[TCellAgent::Instrumentation::TCELL_ID].hmac_session_id
42
- event = TCellAgent::SensorEvents::LoginSuccess.new(request, response, user_id, hmac_session_id)
43
- TCellAgent.send_event(event)
9
+ module TCellAgent
10
+ if defined?(Authlogic)
11
+ TCellAgent.logger.debug("Instrumenting Authlogic")
12
+ require 'tcell_agent/agent'
13
+ require 'tcell_agent/sensor_events/login_fraud'
14
+ Authlogic::Session::Base.class_eval do
15
+ alias_method :original_save, :save
16
+ def save(&block)
17
+ if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
18
+ user_logged_in_before = (user != nil)
19
+ success = original_save
20
+ user_logged_in_after = (user != nil)
21
+ TCellAgent::Instrumentation.safe_block("Authlogic login info") {
22
+
23
+ login_fraud_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LoginFraud)
24
+ if (login_fraud_policy && login_fraud_policy.enabled)
25
+ user_id = nil
26
+ TCellAgent::Instrumentation.safe_block("getting userid for login form") {
27
+ user_id = self.send(self.class.login_field.to_sym)
28
+ }
29
+ if (user_logged_in_before && user_logged_in_after)
30
+ #password changed or logged in as another user
31
+ elsif (!user_logged_in_before && !user_logged_in_after)
32
+ if (login_fraud_policy.login_failed_enabled)
33
+ request = Authlogic::Session::Base.controller.request
34
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
35
+ if tcell_data
36
+ event = TCellAgent::SensorEvents::LoginFailure.new(request.env, tcell_data, user_id)
37
+ TCellAgent.send_event(event)
38
+ end
39
+ end
40
+ elsif (!user_logged_in_before && user_logged_in_after)
41
+ if (login_fraud_policy.login_success_enabled)
42
+ request = Authlogic::Session::Base.controller.request
43
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
44
+ if tcell_data
45
+ event = TCellAgent::SensorEvents::LoginSuccess.new(request.env, tcell_data, user_id)
46
+ TCellAgent.send_event(event)
47
+ end
48
+ end
44
49
  end
45
50
  end
46
- end
47
- }
51
+ }
48
52
 
49
- success
53
+ success
50
54
 
51
- else
52
- original_save
53
- end # if instrument
55
+ else
56
+ original_save
57
+ end # if instrument
58
+ end
54
59
  end
55
- end
56
- end # if Authlogic
60
+ end # if Authlogic
61
+ end
62
+
57
63
  end
@@ -1,80 +1,112 @@
1
- module TCellAgent
2
- if defined?(Devise)
1
+ if TCellAgent.configuration.should_instrument_devise? && defined?(Devise)
2
+ module TCellAgent
3
3
 
4
+ require 'base64'
4
5
  require 'tcell_agent/agent'
5
6
  require 'tcell_agent/sensor_events/login_fraud'
6
7
  require 'tcell_agent/policies/appsensor_policy'
7
8
 
8
- Devise::SessionsController.class_eval do
9
+ module DeviseInstrumentation
10
+ def self.report_login_event(clazz, request_env, user_id)
11
+ if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
9
12
 
10
- if (::Rails::VERSION::MAJOR == 5)
11
- after_action :log_failed_login, :only => :new
12
- elsif (::Rails::VERSION::MAJOR < 5)
13
- after_filter :log_failed_login, :only => :new
14
- end
15
- alias_method :original_new, :new
16
- def new
17
- original_new
13
+ login_fraud_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LoginFraud)
14
+ if (login_fraud_policy && login_fraud_policy.enabled && login_fraud_policy.login_failed_enabled)
15
+ tcell_data = request_env[TCellAgent::Instrumentation::TCELL_ID]
16
+ if tcell_data
17
+ TCellAgent.send_event(clazz.new(request_env, tcell_data, user_id))
18
+ end
19
+ end
20
+ end
18
21
  end
19
22
 
20
- alias_method :original_create, :create
21
- def create(&block)
22
- results = original_create(&block)
23
+ module TCellFailureAppRespond
24
+ def respond
25
+ TCellAgent::Instrumentation.safe_block("Devise Failure App Respond") do
26
+ if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
27
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
28
+ if tcell_data
29
+ # in the case of http auth, the user_id is set in
30
+ # Devise::Strategies::Authenticatable.valid_for_http_auth?
31
+ user_id = tcell_data.user_id
32
+ user_id = _get_tcell_username unless user_id
33
+ TCellAgent::DeviseInstrumentation.report_login_event(
34
+ TCellAgent::SensorEvents::LoginFailure,
35
+ request.env,
36
+ user_id
37
+ )
38
+ end
23
39
 
24
- if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
25
- TCellAgent::Instrumentation.safe_block("Devise login successful") {
26
- tcell_username = _get_tcell_username
27
- login_fraud_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LoginFraud)
28
- if (login_fraud_policy && login_fraud_policy.enabled && login_fraud_policy.login_success_enabled)
29
- hmac_session_id = request.env[TCellAgent::Instrumentation::TCELL_ID].hmac_session_id
30
- request.env[TCellAgent::Instrumentation::TCELL_ID].user_id = TCellAgent::UserInformation.getUserFromRequest(request)
31
- user_id = tcell_username || request.env[TCellAgent::Instrumentation::TCELL_ID].user_id
32
- event = TCellAgent::SensorEvents::LoginSuccess.new(request, response, user_id, hmac_session_id)
33
- TCellAgent.send_event(event)
34
40
  end
35
- }
41
+ end
42
+
43
+ super if defined?(super)
36
44
  end
37
45
 
38
- results
46
+ def _get_tcell_username
47
+ _tcell_username = nil
48
+ TCellAgent::Instrumentation.safe_block("Devise Get TCell Username") {
49
+ keys = scope_class.authentication_keys.dup
50
+ user_params = request.POST.fetch("user",{})
51
+ keys.each do |key|
52
+ next_usename = user_params.fetch(key, nil)
53
+ if next_usename
54
+ _tcell_username ||= ""
55
+ _tcell_username += next_usename
56
+ end
57
+ end
58
+ }
59
+ _tcell_username
60
+ end
39
61
  end
62
+ end
40
63
 
41
- def _get_tcell_username
42
- _tcell_username = nil
43
- TCellAgent::Instrumentation.safe_block("devise login - get username") {
44
- keys = resource_class.authentication_keys.dup
45
- user_params = request.POST.fetch("user",{})
46
- keys.each do |key|
47
- next_usename = user_params.fetch(key, nil)
48
- if next_usename
49
- _tcell_username ||= ""
50
- _tcell_username += next_usename
51
- end
64
+ # prepend is ruby 2+ feature
65
+ Devise::FailureApp.send(:prepend, DeviseInstrumentation::TCellFailureAppRespond)
66
+
67
+ Devise::Strategies::Authenticatable.class_eval do
68
+ alias_method :tcell_valid_for_http_auth?, :valid_for_http_auth?
69
+ def valid_for_http_auth?
70
+ is_valid = tcell_valid_for_http_auth?
71
+
72
+ TCellAgent::Instrumentation.safe_block("Devise set username for http basic auth") do
73
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
74
+ if http_auth_hash && tcell_data
75
+ username = http_auth_hash[http_authentication_key]
76
+ tcell_data.user_id = username if username && !tcell_data.user_id
52
77
  end
53
- }
54
- _tcell_username
78
+ end
79
+
80
+ is_valid
55
81
  end
56
82
 
57
- private
58
- def log_failed_login
59
- if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
60
- TCellAgent::Instrumentation.safe_block("Devise login failed") {
61
- tcell_username = _get_tcell_username
62
- login_fraud_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LoginFraud)
63
- if (login_fraud_policy && login_fraud_policy.enabled && login_fraud_policy.login_failed_enabled)
64
- if failed_login?
65
- hmac_session_id = request.env[TCellAgent::Instrumentation::TCELL_ID].hmac_session_id
66
- event = TCellAgent::SensorEvents::LoginFailure.new(request, response, tcell_username, hmac_session_id)
67
- TCellAgent.send_event(event)
83
+ alias_method :tcell_validate, :validate
84
+ def validate(resource, &block)
85
+ is_valid = tcell_validate(resource, &block)
86
+
87
+ TCellAgent::Instrumentation.safe_block("Devise Authenticatable Validate") do
88
+ if (is_valid && TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
89
+ username = nil
90
+ (authentication_keys || []).each do |auth_key|
91
+ attr = authentication_hash[auth_key]
92
+ if attr
93
+ username ||= ""
94
+ username += attr
68
95
  end
69
96
  end
70
- }
97
+
98
+ TCellAgent::DeviseInstrumentation.report_login_event(
99
+ TCellAgent::SensorEvents::LoginSuccess,
100
+ request.env,
101
+ username
102
+ )
103
+ end
71
104
  end
72
- end
73
105
 
74
- def failed_login?
75
- (options = env["warden.options"]) && options[:action] == "unauthenticated"
106
+ is_valid
76
107
  end
108
+
77
109
  end
78
110
 
79
- end #if defined devise
111
+ end
80
112
  end
@@ -0,0 +1,72 @@
1
+ if TCellAgent.configuration.should_instrument_doorkeeper?
2
+
3
+ if defined?(Doorkeeper)
4
+ require 'tcell_agent/agent'
5
+ require 'tcell_agent/sensor_events/login_fraud'
6
+ require 'tcell_agent/policies/appsensor_policy'
7
+ require 'tcell_agent/sensor_events/login_fraud'
8
+
9
+ module TCellAgent
10
+ module DoorkeeperInstrumentation
11
+
12
+ Doorkeeper::TokensController.class_eval do
13
+ alias_method :tcell_authorize_response, :authorize_response
14
+ def authorize_response
15
+ result = tcell_authorize_response
16
+
17
+ TCellAgent::Instrumentation.safe_block("Doorkeeper Token Authorize") do
18
+ if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
19
+ login_fraud_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LoginFraud)
20
+ if (login_fraud_policy && login_fraud_policy.enabled && login_fraud_policy.login_failed_enabled)
21
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
22
+ if tcell_data
23
+ if result.is_a?(Doorkeeper::OAuth::TokenResponse)
24
+ TCellAgent.send_event(
25
+ TCellAgent::SensorEvents::LoginSuccess.new(request.env, tcell_data, result.token.resource_owner_id)
26
+ )
27
+ elsif result.is_a?(Doorkeeper::OAuth::ErrorResponse)
28
+ TCellAgent.send_event(
29
+ TCellAgent::SensorEvents::LoginFailure.new(request.env, tcell_data, request.POST['client_id'])
30
+ )
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ result
39
+ end
40
+ end
41
+
42
+ module TCellAuthorizationsNew
43
+ def new
44
+ super if defined?(super)
45
+
46
+ TCellAgent::Instrumentation.safe_block("Doorkeeper Token Authorize") do
47
+ if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
48
+ if pre_auth.error
49
+ login_fraud_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LoginFraud)
50
+ if (login_fraud_policy && login_fraud_policy.enabled && login_fraud_policy.login_failed_enabled)
51
+ tcell_data = request.env[TCellAgent::Instrumentation::TCELL_ID]
52
+ if tcell_data && pre_auth.error
53
+ TCellAgent.send_event(
54
+ TCellAgent::SensorEvents::LoginFailure.new(request.env, tcell_data, current_resource_owner.id)
55
+ )
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # prepend is ruby 2+ feature
65
+ Doorkeeper::AuthorizationsController.send(:prepend, TCellAuthorizationsNew)
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,79 @@
1
+ require 'tcell_agent/agent'
2
+ require 'tcell_agent/sensor_events/login_fraud'
3
+ require 'tcell_agent/policies/appsensor_policy'
4
+ require 'tcell_agent/sensor_events/login_fraud'
5
+
6
+ if defined?(TCellAgent::Hooks::V1::Frameworks::Rails::Login)
7
+ TCellAgent::Hooks::V1::Frameworks::Rails::Login.module_eval do
8
+ class << self
9
+ alias_method :tcell_register_login_event, :register_login_event
10
+ def register_login_event(status, rails_request, user_id, user_valid=nil)
11
+ TCellAgent::Instrumentation.safe_block("Rails Auth Hooks") do
12
+ if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
13
+ login_fraud_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LoginFraud)
14
+ if (login_fraud_policy && login_fraud_policy.enabled && login_fraud_policy.login_failed_enabled)
15
+ tcell_data = rails_request.env[TCellAgent::Instrumentation::TCELL_ID]
16
+ if tcell_data
17
+ if status == TCellAgent::Hooks::V1::Login::LOGIN_FAILURE
18
+ TCellAgent.send_event(
19
+ TCellAgent::SensorEvents::LoginFailure.new(rails_request.env, tcell_data, user_id)
20
+ )
21
+ elsif status == TCellAgent::Hooks::V1::Login::LOGIN_SUCCESS
22
+ TCellAgent.send_event(
23
+ TCellAgent::SensorEvents::LoginSuccess.new(rails_request.env, tcell_data, user_id)
24
+ )
25
+ else
26
+ TCellAgent.logger.error("Unkown login status: #{status}")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ if defined?(TCellAgent::Hooks::V1::Login)
38
+ TCellAgent::Hooks::V1::Login.module_eval do
39
+ class << self
40
+ alias_method :tcell_register_login_event, :register_login_event
41
+ def register_login_event(
42
+ status,
43
+ session_id,
44
+ user_agent,
45
+ referrer,
46
+ remote_address,
47
+ header_keys,
48
+ user_id,
49
+ document_uri,
50
+ user_valid=nil)
51
+ TCellAgent::Instrumentation.safe_block("Login Auth Hooks") do
52
+ if (TCellAgent.configuration.enabled && TCellAgent.configuration.should_intercept_requests?)
53
+ login_fraud_policy = TCellAgent.policy(TCellAgent::PolicyTypes::LoginFraud)
54
+ if (login_fraud_policy && login_fraud_policy.enabled && login_fraud_policy.login_failed_enabled)
55
+ tcell_data = TCellAgent::Instrumentation::TCellData.new
56
+ tcell_data.user_agent = user_agent
57
+ tcell_data.referrer = referrer
58
+ tcell_data.ip_address = remote_address
59
+ tcell_data.path = document_uri
60
+ tcell_data.hmac_session_id = TCellAgent::SensorEvents::Util.hmac(session_id)
61
+
62
+ if status == TCellAgent::Hooks::V1::Login::LOGIN_FAILURE
63
+ TCellAgent.send_event(
64
+ TCellAgent::SensorEvents::LoginFailure.new(header_keys, tcell_data, user_id)
65
+ )
66
+ elsif status == TCellAgent::Hooks::V1::Login::LOGIN_SUCCESS
67
+ TCellAgent.send_event(
68
+ TCellAgent::SensorEvents::LoginSuccess.new(header_keys, tcell_data, user_id)
69
+ )
70
+ else
71
+ TCellAgent.logger.error("Unkown login status: #{status}")
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -47,6 +47,8 @@ module TCellAgent
47
47
  TCellAgent::Instrumentation.safe_block("Setting and ip address user agent") {
48
48
  env[TCellAgent::Instrumentation::TCELL_ID].ip_address = TCellAgent::Utils::Rails.better_ip(request)
49
49
  env[TCellAgent::Instrumentation::TCELL_ID].user_agent = request.user_agent
50
+ env[TCellAgent::Instrumentation::TCELL_ID].path = request.path
51
+ env[TCellAgent::Instrumentation::TCELL_ID].referrer = request.referrer
50
52
  }
51
53
  end
52
54
 
@@ -26,6 +26,8 @@ else
26
26
  require 'tcell_agent/rails/auth/devise' if defined?(Devise)
27
27
  require 'tcell_agent/authlogic' if defined?(Authlogic)
28
28
  require 'tcell_agent/rails/auth/authlogic' if defined?(Authlogic)
29
+ require 'tcell_agent/rails/auth/doorkeeper'
30
+ require 'tcell_agent/rails/auth/hooks'
29
31
  end
30
32
 
31
33
  # TODO: will this get run ever?
@@ -31,6 +31,8 @@ module TCellAgent
31
31
  require 'tcell_agent/rails/auth/devise' if defined?(Devise)
32
32
  require 'tcell_agent/authlogic' if defined?(Authlogic)
33
33
  require 'tcell_agent/rails/auth/authlogic' if defined?(Authlogic)
34
+ require 'tcell_agent/rails/auth/doorkeeper'
35
+ require 'tcell_agent/rails/auth/hooks'
34
36
  end
35
37
  app.config.middleware.insert_before(0, TCellAgent::Instrumentation::Rails::Middleware::ContextMiddleware)
36
38
  app.config.middleware.insert_after(0, TCellAgent::Instrumentation::Rails::Middleware::HeadersMiddleware)
@@ -19,9 +19,9 @@ module TCellAgent
19
19
  pattern=nil)
20
20
  super("as")
21
21
  self["dp"] = detection_point
22
- self["param"] = param if param
23
- self["remote_addr"] = remote_addr if remote_addr
24
- self["m"] = method if method
22
+ self["param"] = param.to_s if param
23
+ self["remote_addr"] = remote_addr.to_s if remote_addr
24
+ self["m"] = method.to_s if method
25
25
  @raw_location = location
26
26
  @user_id = user_id
27
27
  @hmac_session_id = hmac_session_id
@@ -3,41 +3,52 @@
3
3
  require 'tcell_agent/sensor_events/util/sanitizer_utilities'
4
4
  require 'tcell_agent/sensor_events/sensor'
5
5
  require 'tcell_agent/sensor_events/util/sanitizer_utilities'
6
+
6
7
  module TCellAgent
7
- module SensorEvents
8
-
9
- class LoginFailure < TCellSensorEvent
10
- def initialize(request, response, user_id, hmac_session_id)
11
- super("login")
12
- headers = request.env.select {|k,v| k.start_with? 'HTTP_'}
13
- .collect {|k,v| k.sub(/^HTTP_/, '') }
14
- self["event_name"] = "login-failure"
15
- self["user_agent"] = request.env['HTTP_USER_AGENT']
16
- self["referrer"] = request.referer
17
- self["remote_addr"] = request.remote_ip
18
- self["header_keys"] = headers
19
- self["user_id"] = user_id
20
- self["document_uri"] = TCellAgent::SensorEvents::Util.strip_uri_values(request.path)
21
- self["session"] = hmac_session_id
22
- end
23
- end
8
+ module SensorEvents
9
+
10
+ class LoginEvent < TCellSensorEvent
11
+ def initialize(header_keys, tcell_data, user_id, user_valid)
12
+ super("login")
24
13
 
25
- class LoginSuccess < TCellSensorEvent
26
- attr_accessor :event_name
27
- def initialize(request, response, user_id, hmac_session_id)
28
- super("login")
29
- headers = request.env.select {|k,v| k.start_with? 'HTTP_'}
30
- .collect {|k,v| k.sub(/^HTTP_/, '') }
31
- self["event_name"] = "login-success"
32
- self["user_agent"] = request.env['HTTP_USER_AGENT']
33
- self["referrer"] = request.referer
34
- self["remote_addr"] = request.remote_ip
35
- self["header_keys"] = headers
36
- self["user_id"] = user_id
37
- self["document_uri"] = TCellAgent::SensorEvents::Util.strip_uri_values(request.path)
38
- self["session"] = hmac_session_id
39
- end
14
+ self["header_keys"] = header_keys
15
+
16
+ self["user_agent"] = tcell_data.user_agent.to_s if tcell_data.user_agent
17
+ self["referrer"] = tcell_data.referrer.to_s if tcell_data.referrer
18
+ self["remote_addr"] = tcell_data.ip_address.to_s if tcell_data.ip_address
19
+ self["user_id"] = user_id.to_s if user_id
20
+ self["document_uri"] = TCellAgent::SensorEvents::Util.strip_uri_values(tcell_data.path) if tcell_data.path
21
+ self["session"] = tcell_data.hmac_session_id if tcell_data.hmac_session_id
22
+ end
23
+
24
+ protected
25
+ def clean_header_keys(request_env_or_header_keys)
26
+ if request_env_or_header_keys.is_a?(Hash)
27
+ request_env_or_header_keys.select {|k,v| k.start_with? 'HTTP_'}.collect {|k,v| k.sub(/^HTTP_/, '') }
28
+ else
29
+ request_env_or_header_keys.map { |k| k.sub(/^HTTP_/, '') }
30
+ end
40
31
  end
32
+ end
33
+
34
+ class LoginFailure < LoginEvent
35
+ def initialize(request_env_or_header_keys, tcell_data, user_id, user_valid=nil)
36
+ header_keys = clean_header_keys(request_env_or_header_keys)
37
+
38
+ super(header_keys, tcell_data, user_id, user_valid)
39
+
40
+ self["event_name"] = "login-failure"
41
+ end
42
+ end
43
+
44
+ class LoginSuccess < LoginEvent
45
+ def initialize(request_env_or_header_keys, tcell_data, user_id, user_valid=nil)
46
+ header_keys = clean_header_keys(request_env_or_header_keys)
47
+
48
+ super(header_keys, tcell_data, user_id, user_valid)
41
49
 
50
+ self["event_name"] = "login-success"
51
+ end
42
52
  end
43
- end
53
+ end
54
+ end
@@ -10,19 +10,19 @@ Unicorn::HttpServer.class_eval do
10
10
  # this only runs when preload_app=true because when preload_app=false
11
11
  # the gems aren't loaded early enough for tcell to override
12
12
  # the class definitions
13
- alias_method :original_join, :join
14
- def join
13
+ alias_method :tcell_bind_new_listeners!, :bind_new_listeners!
14
+ def bind_new_listeners!
15
15
  TCellAgent.run_instrumentation("Unicorn")
16
16
 
17
- original_join
17
+ tcell_bind_new_listeners!
18
18
  end
19
19
 
20
20
  # This gets called when unicorn receives the HUP signal to reload its config.
21
21
  # Tcell also needs to ensure its config is reloaded and services are started
22
22
  # or stopped accordingly
23
- alias_method :original_load_config!, :load_config!
23
+ alias_method :tcell_load_config!, :load_config!
24
24
  def load_config!
25
- original_load_config!
25
+ tcell_load_config!
26
26
 
27
27
  TCellAgent::Instrumentation.safe_block("Reloading Tcell Config") do
28
28
  new_config = TCellAgent::Configuration.new
@@ -94,9 +94,9 @@ Unicorn::HttpServer.class_eval do
94
94
  # this only runs when preload_app=true because when preload_app=false
95
95
  # the gems aren't loaded early enough for tcell to override
96
96
  # the class definitions
97
- alias original_init_worker_process init_worker_process
97
+ alias tcell_init_worker_process init_worker_process
98
98
  def init_worker_process(work)
99
- start_process = original_init_worker_process(work)
99
+ start_process = tcell_init_worker_process(work)
100
100
 
101
101
  if TCellAgent.configuration.enabled && TCellAgent.configuration.should_instrument?
102
102
  begin
@@ -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 = "0.2.24"
4
+ VERSION = "0.2.25"
5
5
  end
@@ -0,0 +1,246 @@
1
+ require 'spec_helper'
2
+
3
+ module TCellAgent
4
+
5
+ module Hooks
6
+ module V1
7
+ module Frameworks
8
+ module Rails
9
+ module Login
10
+ def self.register_login_event(status, rails_request, user_id, user_valid=nil)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ module Hooks
19
+ module V1
20
+ module Login
21
+ LOGIN_SUCCESS = "success"
22
+ LOGIN_FAILURE = "failure"
23
+ def self.register_login_event(status, session_id, user_agent, referrer, remote_addr, header_keys, user_id, document_uri, user_valid=nil)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ describe "manually requiring auth hooks" do
30
+ before(:all) do
31
+ require 'tcell_agent/rails/auth/hooks'
32
+ end
33
+
34
+ describe "Using generic interface" do
35
+ context "with a login failure" do
36
+ it "should report the login failure" do
37
+ login_fraud = double("login_fraud", enabled: true, login_failed_enabled: true)
38
+
39
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::LoginFraud).and_return(
40
+ login_fraud
41
+ )
42
+ expect(TCellAgent).to receive(:send_event).with(
43
+ {
44
+ "event_type" => "login",
45
+ "header_keys" => ["USER_AGENT", "X_FORWARDED_FOR"],
46
+ "user_agent" => "user_agent",
47
+ "referrer" => "referrer",
48
+ "remote_addr" => "1.1.1.1",
49
+ "user_id" => "user_id",
50
+ "document_uri" => "http://tcell.tcell.io/login?param_name=",
51
+ "session" => "48c0ce7961d8d5d4bd57bd77976b3d38",
52
+ "event_name" => "login-failure"
53
+ }
54
+ )
55
+
56
+ status = Hooks::V1::Login::LOGIN_FAILURE
57
+ header_keys = ["HTTP_USER_AGENT", "HTTP_X_FORWARDED_FOR"]
58
+ document_uri = "http://tcell.tcell.io/login?param_name=param_value"
59
+
60
+ Hooks::V1::Login.register_login_event(
61
+ status, "session_id", "user_agent", "referrer", "1.1.1.1", header_keys, "user_id", document_uri
62
+ )
63
+ end
64
+ end
65
+
66
+ context "with a login success" do
67
+ it "should report the login success" do
68
+ login_fraud = double("login_fraud", enabled: true, login_failed_enabled: true)
69
+
70
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::LoginFraud).and_return(
71
+ login_fraud
72
+ )
73
+ expect(TCellAgent).to receive(:send_event).with(
74
+ {
75
+ "event_type" => "login",
76
+ "header_keys" => ["USER_AGENT", "X_FORWARDED_FOR"],
77
+ "user_agent" => "user_agent",
78
+ "referrer" => "referrer",
79
+ "remote_addr" => "1.1.1.1",
80
+ "user_id" => "user_id",
81
+ "document_uri" => "http://tcell.tcell.io/login?param_name=",
82
+ "session" => "48c0ce7961d8d5d4bd57bd77976b3d38",
83
+ "event_name" => "login-success"
84
+ }
85
+ )
86
+
87
+ status = Hooks::V1::Login::LOGIN_SUCCESS
88
+ header_keys = ["HTTP_USER_AGENT", "HTTP_X_FORWARDED_FOR"]
89
+ document_uri = "http://tcell.tcell.io/login?param_name=param_value"
90
+
91
+ Hooks::V1::Login.register_login_event(
92
+ status, "session_id", "user_agent", "referrer", "1.1.1.1", header_keys, "user_id", document_uri
93
+ )
94
+ end
95
+ end
96
+
97
+ context "with an unknown status" do
98
+ it "should log the error" do
99
+ login_fraud = double("login_fraud", enabled: true, login_failed_enabled: true)
100
+ logger = double("logger")
101
+
102
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::LoginFraud).and_return(
103
+ login_fraud
104
+ )
105
+ expect(TCellAgent).to_not receive(:send_event)
106
+ expect(TCellAgent).to receive(:logger).and_return(logger)
107
+ expect(logger).to receive(:error).with("Unkown login status: mumbo-jumbo")
108
+
109
+ status = "mumbo-jumbo"
110
+ header_keys = ["HTTP_USER_AGENT", "HTTP_X_FORWARDED_FOR"]
111
+ document_uri = "http://tcell.tcell.io/login?param_name=param_value"
112
+
113
+ Hooks::V1::Login.register_login_event(
114
+ status, "session_id", "user_agent", "referrer", "1.1.1.1", header_keys, "user_id", document_uri
115
+ )
116
+ end
117
+ end
118
+ end
119
+
120
+ describe "Using rails interface" do
121
+ context "with a login failure" do
122
+ it "should report the login failure" do
123
+ login_fraud = double("login_fraud", enabled: true, login_failed_enabled: true)
124
+ rails_request = double("rails_request")
125
+ tcell_data = TCellAgent::Instrumentation::TCellData.new
126
+ tcell_data.user_agent = "user_agent"
127
+ tcell_data.referrer = "referrer"
128
+ tcell_data.ip_address = "1.1.1.1"
129
+ tcell_data.path = "http://tcell.tcell.io/login?param_name=param_value"
130
+ tcell_data.hmac_session_id = TCellAgent::SensorEvents::Util.hmac("session_id")
131
+ request_env = {
132
+ TCellAgent::Instrumentation::TCELL_ID => tcell_data,
133
+ "HTTP_USER_AGENT" => true,
134
+ "HTTP_X_FORWARDED_FOR" => true
135
+ }
136
+
137
+
138
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::LoginFraud).and_return(
139
+ login_fraud
140
+ )
141
+ expect(rails_request).to receive(:env).and_return(request_env)
142
+ expect(rails_request).to receive(:env).and_return(request_env)
143
+ expect(TCellAgent).to receive(:send_event).with(
144
+ {
145
+ "event_type" => "login",
146
+ "header_keys" => ["USER_AGENT", "X_FORWARDED_FOR"],
147
+ "user_agent" => "user_agent",
148
+ "referrer" => "referrer",
149
+ "remote_addr" => "1.1.1.1",
150
+ "user_id" => "user_id",
151
+ "document_uri" => "http://tcell.tcell.io/login?param_name=",
152
+ "session" => "48c0ce7961d8d5d4bd57bd77976b3d38",
153
+ "event_name" => "login-failure"
154
+ }
155
+ )
156
+
157
+ status = Hooks::V1::Login::LOGIN_FAILURE
158
+
159
+ Hooks::V1::Frameworks::Rails::Login.register_login_event(
160
+ status, rails_request, "user_id"
161
+ )
162
+ end
163
+ end
164
+
165
+ context "with a login success" do
166
+ it "should report the login success" do
167
+ login_fraud = double("login_fraud", enabled: true, login_failed_enabled: true)
168
+ rails_request = double("rails_request")
169
+ tcell_data = TCellAgent::Instrumentation::TCellData.new
170
+ tcell_data.user_agent = "user_agent"
171
+ tcell_data.referrer = "referrer"
172
+ tcell_data.ip_address = "1.1.1.1"
173
+ tcell_data.path = "http://tcell.tcell.io/login?param_name=param_value"
174
+ tcell_data.hmac_session_id = TCellAgent::SensorEvents::Util.hmac("session_id")
175
+ request_env = {
176
+ TCellAgent::Instrumentation::TCELL_ID => tcell_data,
177
+ "HTTP_USER_AGENT" => true,
178
+ "HTTP_X_FORWARDED_FOR" => true
179
+ }
180
+
181
+
182
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::LoginFraud).and_return(
183
+ login_fraud
184
+ )
185
+ expect(rails_request).to receive(:env).and_return(request_env)
186
+ expect(rails_request).to receive(:env).and_return(request_env)
187
+ expect(TCellAgent).to receive(:send_event).with(
188
+ {
189
+ "event_type" => "login",
190
+ "header_keys" => ["USER_AGENT", "X_FORWARDED_FOR"],
191
+ "user_agent" => "user_agent",
192
+ "referrer" => "referrer",
193
+ "remote_addr" => "1.1.1.1",
194
+ "user_id" => "user_id",
195
+ "document_uri" => "http://tcell.tcell.io/login?param_name=",
196
+ "session" => "48c0ce7961d8d5d4bd57bd77976b3d38",
197
+ "event_name" => "login-success"
198
+ }
199
+ )
200
+
201
+ status = Hooks::V1::Login::LOGIN_SUCCESS
202
+
203
+ Hooks::V1::Frameworks::Rails::Login.register_login_event(
204
+ status, rails_request, "user_id"
205
+ )
206
+ end
207
+ end
208
+
209
+ context "with an unknown status" do
210
+ it "should log the error" do
211
+ login_fraud = double("login_fraud", enabled: true, login_failed_enabled: true)
212
+ logger = double("logger")
213
+ rails_request = double("rails_request")
214
+ tcell_data = TCellAgent::Instrumentation::TCellData.new
215
+ tcell_data.user_agent = "user_agent"
216
+ tcell_data.referrer = "referrer"
217
+ tcell_data.ip_address = "1.1.1.1"
218
+ tcell_data.path = "http://tcell.tcell.io/login?param_name=param_value"
219
+ tcell_data.hmac_session_id = TCellAgent::SensorEvents::Util.hmac("session_id")
220
+ request_env = {
221
+ TCellAgent::Instrumentation::TCELL_ID => tcell_data,
222
+ "HTTP_USER_AGENT" => true,
223
+ "HTTP_X_FORWARDED_FOR" => true
224
+ }
225
+
226
+
227
+ expect(TCellAgent).to receive(:policy).with(TCellAgent::PolicyTypes::LoginFraud).and_return(
228
+ login_fraud
229
+ )
230
+ expect(rails_request).to receive(:env).and_return(request_env)
231
+ expect(TCellAgent).to_not receive(:send_event)
232
+ expect(TCellAgent).to receive(:logger).and_return(logger)
233
+ expect(logger).to receive(:error).with("Unkown login status: mumbo-jumbo")
234
+
235
+ status = "mumbo-jumbo"
236
+
237
+ Hooks::V1::Frameworks::Rails::Login.register_login_event(
238
+ status, rails_request, "user_id"
239
+ )
240
+ end
241
+ end
242
+ end
243
+
244
+ end
245
+
246
+ 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: 0.2.24
4
+ version: 0.2.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garrett
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-10 00:00:00.000000000 Z
11
+ date: 2016-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -185,6 +185,8 @@ files:
185
185
  - lib/tcell_agent/policies/secure_headers_policy.rb
186
186
  - lib/tcell_agent/rails/auth/authlogic.rb
187
187
  - lib/tcell_agent/rails/auth/devise.rb
188
+ - lib/tcell_agent/rails/auth/doorkeeper.rb
189
+ - lib/tcell_agent/rails/auth/hooks.rb
188
190
  - lib/tcell_agent/rails/better_ip.rb
189
191
  - lib/tcell_agent/rails/csrf_exception.rb
190
192
  - lib/tcell_agent/rails/dlp/process_request.rb
@@ -311,6 +313,7 @@ files:
311
313
  - spec/lib/tcell_agent/policies/login_policy_spec.rb
312
314
  - spec/lib/tcell_agent/policies/patches_policy_spec.rb
313
315
  - spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb
316
+ - spec/lib/tcell_agent/rails/auth/hooks_spec.rb
314
317
  - spec/lib/tcell_agent/rails/better_ip_spec.rb
315
318
  - spec/lib/tcell_agent/rails/logger_spec.rb
316
319
  - spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb
@@ -460,6 +463,7 @@ test_files:
460
463
  - spec/lib/tcell_agent/policies/login_policy_spec.rb
461
464
  - spec/lib/tcell_agent/policies/patches_policy_spec.rb
462
465
  - spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb
466
+ - spec/lib/tcell_agent/rails/auth/hooks_spec.rb
463
467
  - spec/lib/tcell_agent/rails/better_ip_spec.rb
464
468
  - spec/lib/tcell_agent/rails/logger_spec.rb
465
469
  - spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb