tcell_agent 0.2.24 → 0.2.25

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
  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