sqreen 1.18.2-java → 1.19.0-java

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.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/LICENSE +3 -0
  4. data/lib/sqreen.rb +2 -0
  5. data/lib/sqreen/actions.rb +13 -337
  6. data/lib/sqreen/actions/actions_index.rb +16 -0
  7. data/lib/sqreen/actions/base.rb +104 -0
  8. data/lib/sqreen/actions/block_ip.rb +34 -0
  9. data/lib/sqreen/actions/block_user.rb +46 -0
  10. data/lib/sqreen/actions/ip_range_indexed_action_class.rb +16 -0
  11. data/lib/sqreen/actions/ip_ranges_index.rb +57 -0
  12. data/lib/sqreen/actions/redirect_ip.rb +42 -0
  13. data/lib/sqreen/actions/redirect_user.rb +47 -0
  14. data/lib/sqreen/actions/repository.rb +43 -0
  15. data/lib/sqreen/actions/unknown_action_type.rb +20 -0
  16. data/lib/sqreen/actions/user_action_class.rb +16 -0
  17. data/lib/sqreen/actions/users_index.rb +35 -0
  18. data/lib/sqreen/agent.rb +6 -2
  19. data/lib/sqreen/attack_blocked.rb +19 -0
  20. data/lib/sqreen/backport.rb +2 -0
  21. data/lib/sqreen/backport/clock_gettime.rb +74 -0
  22. data/lib/sqreen/backport/original_name.rb +2 -0
  23. data/lib/sqreen/binding_accessor.rb +11 -102
  24. data/lib/sqreen/binding_accessor/path_elem.rb +10 -0
  25. data/lib/sqreen/binding_accessor/transforms.rb +114 -0
  26. data/lib/sqreen/call_countable.rb +2 -0
  27. data/lib/sqreen/capped_queue.rb +4 -0
  28. data/lib/sqreen/{callbacks.rb → cb.rb} +3 -53
  29. data/lib/sqreen/{callback_tree.rb → cb_tree.rb} +4 -2
  30. data/lib/sqreen/condition_evaluator.rb +24 -5
  31. data/lib/sqreen/conditionable.rb +2 -0
  32. data/lib/sqreen/configuration.rb +19 -0
  33. data/lib/sqreen/context.rb +2 -0
  34. data/lib/sqreen/default_cb.rb +22 -0
  35. data/lib/sqreen/deferred_logger.rb +65 -0
  36. data/lib/sqreen/deliveries.rb +12 -0
  37. data/lib/sqreen/deliveries/batch.rb +9 -1
  38. data/lib/sqreen/deliveries/simple.rb +7 -0
  39. data/lib/sqreen/dependency.rb +3 -1
  40. data/lib/sqreen/dependency/detector.rb +22 -14
  41. data/lib/sqreen/dependency/libsqreen.rb +32 -0
  42. data/lib/sqreen/dependency/new_relic.rb +2 -0
  43. data/lib/sqreen/dependency/rack.rb +10 -5
  44. data/lib/sqreen/dependency/rails.rb +8 -0
  45. data/lib/sqreen/dependency/sentry.rb +2 -0
  46. data/lib/sqreen/dependency/sinatra.rb +58 -14
  47. data/lib/sqreen/encoding_sanitizer.rb +2 -0
  48. data/lib/sqreen/error_handling_middleware.rb +32 -0
  49. data/lib/sqreen/event.rb +4 -0
  50. data/lib/sqreen/events/attack.rb +4 -0
  51. data/lib/sqreen/events/remote_exception.rb +2 -0
  52. data/lib/sqreen/events/request_record.rb +13 -56
  53. data/lib/sqreen/exception.rb +11 -40
  54. data/lib/sqreen/formatter_with_tid.rb +47 -0
  55. data/lib/sqreen/framework_cb.rb +30 -0
  56. data/lib/sqreen/frameworks.rb +9 -0
  57. data/lib/sqreen/frameworks/generic.rb +22 -2
  58. data/lib/sqreen/frameworks/rails.rb +3 -0
  59. data/lib/sqreen/frameworks/rails3.rb +2 -0
  60. data/lib/sqreen/frameworks/request_recorder.rb +5 -0
  61. data/lib/sqreen/frameworks/sinatra.rb +4 -0
  62. data/lib/sqreen/frameworks/sqreen_test.rb +4 -0
  63. data/lib/sqreen/graft.rb +12 -0
  64. data/lib/sqreen/graft/call.rb +150 -0
  65. data/lib/sqreen/{dependency → graft}/callback.rb +12 -4
  66. data/lib/sqreen/graft/hook.rb +316 -0
  67. data/lib/sqreen/{dependency → graft}/hook_point.rb +152 -33
  68. data/lib/sqreen/graft/hook_point_error.rb +10 -0
  69. data/lib/sqreen/invalid_signature_exception.rb +10 -0
  70. data/lib/sqreen/js.rb +11 -0
  71. data/lib/sqreen/js/call_context.rb +12 -0
  72. data/lib/sqreen/js/context_pool.rb +62 -0
  73. data/lib/sqreen/js/exec_js_runnable.rb +22 -0
  74. data/lib/sqreen/js/execjs_adapter.rb +8 -47
  75. data/lib/sqreen/js/executable_js.rb +14 -0
  76. data/lib/sqreen/js/js_service.rb +4 -22
  77. data/lib/sqreen/js/js_service_adapter.rb +20 -0
  78. data/lib/sqreen/js/mini_racer_adapter.rb +8 -180
  79. data/lib/sqreen/js/mini_racer_executable_js.rb +144 -0
  80. data/lib/sqreen/js/thread_local_exec_js_runnable.rb +49 -0
  81. data/lib/{sqreen-alt.rb → sqreen/legacy.rb} +5 -1
  82. data/lib/sqreen/{instrumentation.rb → legacy/instrumentation.rb} +44 -15
  83. data/lib/sqreen/log.rb +10 -188
  84. data/lib/sqreen/log/loggable.rb +28 -0
  85. data/lib/sqreen/logger.rb +85 -0
  86. data/lib/sqreen/metrics.rb +2 -0
  87. data/lib/sqreen/metrics/average.rb +2 -0
  88. data/lib/sqreen/metrics/base.rb +2 -0
  89. data/lib/sqreen/metrics/binning.rb +2 -0
  90. data/lib/sqreen/metrics/collect.rb +2 -0
  91. data/lib/sqreen/metrics/sum.rb +2 -0
  92. data/lib/sqreen/metrics_store.rb +5 -11
  93. data/lib/sqreen/metrics_store/already_registered_metric.rb +13 -0
  94. data/lib/sqreen/metrics_store/unknown_metric.rb +13 -0
  95. data/lib/sqreen/metrics_store/unregistered_metric.rb +13 -0
  96. data/lib/sqreen/middleware.rb +2 -34
  97. data/lib/sqreen/mono_time.rb +4 -0
  98. data/lib/sqreen/node.rb +46 -0
  99. data/lib/sqreen/not_implemented_yet.rb +10 -0
  100. data/lib/sqreen/null_logger.rb +26 -0
  101. data/lib/sqreen/payload_creator.rb +4 -19
  102. data/lib/sqreen/payload_creator/header_section.rb +30 -0
  103. data/lib/sqreen/performance_notifications.rb +2 -0
  104. data/lib/sqreen/performance_notifications/binned_metrics.rb +2 -0
  105. data/lib/sqreen/performance_notifications/log.rb +2 -0
  106. data/lib/sqreen/performance_notifications/log_performance.rb +2 -0
  107. data/lib/sqreen/performance_notifications/metrics.rb +2 -0
  108. data/lib/sqreen/performance_notifications/newrelic.rb +2 -0
  109. data/lib/sqreen/prefix.rb +35 -0
  110. data/lib/sqreen/rails_middleware.rb +16 -0
  111. data/lib/sqreen/remote_command.rb +3 -8
  112. data/lib/sqreen/remote_command/failure_output.rb +16 -0
  113. data/lib/sqreen/rules.rb +34 -2
  114. data/lib/sqreen/{rule_attributes.rb → rules/attrs.rb} +2 -0
  115. data/lib/sqreen/{rules_callbacks/sdk_auth_track.rb → rules/auth_track_cb.rb} +4 -2
  116. data/lib/sqreen/{rules_callbacks/binding_accessor_matcher.rb → rules/binding_accessor_matcher_cb.rb} +6 -8
  117. data/lib/sqreen/{rules_callbacks → rules}/binding_accessor_metrics.rb +3 -1
  118. data/lib/sqreen/{rules_callbacks/blacklist_ips.rb → rules/blacklist_ips_cb.rb} +5 -2
  119. data/lib/sqreen/{rules_callbacks → rules}/count_http_codes.rb +4 -2
  120. data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches.rb → rules/crawler_user_agent_matches_cb.rb} +3 -1
  121. data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches_metrics.rb → rules/crawler_user_agent_matches_metrics_cb.rb} +3 -1
  122. data/lib/sqreen/{rules_callbacks/custom_error.rb → rules/custom_error_cb.rb} +3 -1
  123. data/lib/sqreen/{rules_callbacks/devise_auth_track.rb → rules/devise_auth_track_cb.rb} +4 -2
  124. data/lib/sqreen/{rules_callbacks/devise_signup_track.rb → rules/devise_signup_track_cb.rb} +4 -2
  125. data/lib/sqreen/{rules_callbacks/execjs.rb → rules/execjs_cb.rb} +51 -50
  126. data/lib/sqreen/{rules_callbacks/headers_insert.rb → rules/headers_insert_cb.rb} +8 -1
  127. data/lib/sqreen/{rules_callbacks → rules}/matcher_rule.rb +4 -2
  128. data/lib/sqreen/{rules_callbacks/not_found.rb → rules/not_found_cb.rb} +7 -2
  129. data/lib/sqreen/{rules_callbacks/rails_parameters.rb → rules/rails_parameters_cb.rb} +3 -1
  130. data/lib/sqreen/{rules_callbacks → rules}/record_request_context.rb +3 -1
  131. data/lib/sqreen/{rules_callbacks/regexp_rule.rb → rules/regexp_rule_cb.rb} +3 -1
  132. data/lib/sqreen/{rule_callback.rb → rules/rule_cb.rb} +4 -2
  133. data/lib/sqreen/{rules_callbacks → rules}/run_req_start_actions.rb +7 -3
  134. data/lib/sqreen/{rules_callbacks → rules}/run_user_actions.rb +4 -2
  135. data/lib/sqreen/{rules_callbacks/shell_env.rb → rules/shell_env_cb.rb} +3 -1
  136. data/lib/sqreen/{rules_callbacks/sdk_signup_track.rb → rules/signup_track_cb.rb} +4 -2
  137. data/lib/sqreen/rules/update_request_context.rb +22 -0
  138. data/lib/sqreen/{rules_callbacks/url_matches.rb → rules/url_matches_cb.rb} +3 -1
  139. data/lib/sqreen/{rules_callbacks/user_agent_matches.rb → rules/user_agent_matches_cb.rb} +3 -1
  140. data/lib/sqreen/{rules_callbacks/waf.rb → rules/waf_cb.rb} +41 -21
  141. data/lib/sqreen/{rules_callbacks/reflected_xss.rb → rules/xss_cb.rb} +12 -7
  142. data/lib/sqreen/run_when_called_cb.rb +23 -0
  143. data/lib/sqreen/runner.rb +25 -7
  144. data/lib/sqreen/runtime_infos.rb +4 -9
  145. data/lib/sqreen/safe_json.rb +2 -0
  146. data/lib/sqreen/sdk.rb +4 -0
  147. data/lib/sqreen/sensitive_data_redactor.rb +113 -0
  148. data/lib/sqreen/serializer.rb +2 -0
  149. data/lib/sqreen/session.rb +2 -0
  150. data/lib/sqreen/shared_storage.rb +2 -0
  151. data/lib/sqreen/shared_storage23.rb +2 -0
  152. data/lib/sqreen/shrink_wrap.rb +16 -0
  153. data/lib/sqreen/signature_verifier.rb +22 -0
  154. data/lib/sqreen/sinatra_middleware.rb +16 -0
  155. data/lib/sqreen/{rules_signature.rb → sqreen_signed_verifier.rb} +7 -17
  156. data/lib/sqreen/token_invalid_exception.rb +10 -0
  157. data/lib/sqreen/token_not_found_exception.rb +11 -0
  158. data/lib/sqreen/trie.rb +5 -64
  159. data/lib/sqreen/unauthorized.rb +10 -0
  160. data/lib/sqreen/util.rb +7 -0
  161. data/lib/sqreen/util/capped_array.rb +35 -0
  162. data/lib/sqreen/util/capped_hash.rb +41 -0
  163. data/lib/sqreen/util/capped_string.rb +26 -0
  164. data/lib/sqreen/util/capper.rb +67 -0
  165. data/lib/sqreen/version.rb +3 -1
  166. data/lib/sqreen/waf_error.rb +20 -0
  167. data/lib/sqreen/weave.rb +12 -0
  168. data/lib/sqreen/weave/hardcoded.rb +19 -0
  169. data/lib/sqreen/weave/instrumentor.rb +48 -0
  170. data/lib/sqreen/weave/legacy.rb +12 -0
  171. data/lib/sqreen/weave/legacy/instrumentation.rb +406 -0
  172. data/lib/sqreen/web_server.rb +2 -0
  173. data/lib/sqreen/web_server/generic.rb +2 -0
  174. data/lib/sqreen/web_server/passenger.rb +2 -0
  175. data/lib/sqreen/web_server/puma.rb +2 -0
  176. data/lib/sqreen/web_server/rainbows.rb +2 -0
  177. data/lib/sqreen/web_server/thin.rb +2 -0
  178. data/lib/sqreen/web_server/unicorn.rb +2 -0
  179. data/lib/sqreen/web_server/webrick.rb +2 -0
  180. data/lib/sqreen/worker.rb +2 -0
  181. metadata +105 -39
  182. data/lib/sqreen/dependency/hook.rb +0 -102
  183. data/lib/sqreen/rules_callbacks.rb +0 -35
  184. data/lib/sqreen/rules_callbacks/inspect_rule.rb +0 -25
@@ -0,0 +1,104 @@
1
+ # typed: false
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ # TODO: remove class vars
7
+
8
+ require 'sqreen/sdk'
9
+ require 'sqreen/exception'
10
+
11
+ module Sqreen
12
+ # Implements actions (behavior taken in response to agent signals)
13
+ module Actions
14
+ # Base class for actions
15
+ # subclasses must also implement some methods in their singleton classes
16
+ # (actions_matching, index and clear)
17
+ class Base
18
+ attr_reader :id, :expiry, :send_response
19
+
20
+ def initialize(id, opts)
21
+ @id = id
22
+ duration = opts[:duration]
23
+ @expiry = Time.new + duration unless duration.nil?
24
+ @send_response = if opts[:send_response].nil?
25
+ true
26
+ else
27
+ opts[:send_response] ? true : false
28
+ end
29
+ end
30
+
31
+ # See Sqreen::CB for return values
32
+ def run(*args)
33
+ return if expiry && Time.new > expiry
34
+ ret = do_run(*args)
35
+ unless ret.nil? || !@send_response
36
+ Sqreen.internal_track(event_name,
37
+ 'properties' => {
38
+ 'output' => event_properties(*args),
39
+ 'action_id' => id,
40
+ })
41
+ end
42
+ ret
43
+ end
44
+
45
+ protected
46
+
47
+ def do_run(*_args)
48
+ raise ::Sqreen::NotImplementedYet, "do_run not implemented in #{self.class}"
49
+ # implement in subclasses
50
+ end
51
+
52
+ def event_properties(*_run_args)
53
+ raise ::Sqreen::NotImplementedYet, "event_properties not implemented in #{self.class}"
54
+ # implement in subclasses
55
+ end
56
+
57
+ private
58
+
59
+ def event_name
60
+ "sq.action.#{self.class.type_name}"
61
+ end
62
+
63
+ @@subclasses = {} # rubocop:disable Style/ClassVars
64
+ class << self
65
+ private :new
66
+
67
+ attr_reader :type_name
68
+
69
+ def get_type_class(name)
70
+ subclasses[name]
71
+ end
72
+
73
+ def known_subclasses
74
+ subclasses.values
75
+ end
76
+
77
+ def known_types
78
+ subclasses.keys
79
+ end
80
+
81
+ def new_index
82
+ raise 'implement in singletons of subclasses'
83
+ end
84
+
85
+ def inherited(subclass)
86
+ class << subclass
87
+ public :new
88
+ end
89
+ end
90
+
91
+ protected
92
+
93
+ def subclasses
94
+ @@subclasses
95
+ end
96
+
97
+ def type_name=(name)
98
+ @type_name = name
99
+ subclasses[name] = self
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,34 @@
1
+ # typed: true
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/exception'
7
+ require 'sqreen/actions/base'
8
+ require 'sqreen/actions/ip_range_indexed_action_class'
9
+
10
+ module Sqreen
11
+ module Actions
12
+ # Block a list of IP address ranges. Standard "raise" behavior.
13
+ class BlockIp < Base
14
+ extend IpRangeIndexedActionClass
15
+
16
+ self.type_name = 'block_ip'
17
+
18
+ def initialize(id, opts, _params = {})
19
+ # no need to store the ranges for this action, the index filter the class
20
+ super(id, opts)
21
+ end
22
+
23
+ def do_run(client_ip)
24
+ e = Sqreen::AttackBlocked.new("Blocked client's IP #{client_ip} " \
25
+ "(action: #{id}). No action is required")
26
+ { :status => :raise, :exception => e, :skip_rem_cbs => true }
27
+ end
28
+
29
+ def event_properties(client_ip)
30
+ { 'ip_address' => client_ip }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,46 @@
1
+ # typed: true
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/log'
7
+ require 'sqreen/exception'
8
+ require 'sqreen/actions/base'
9
+ require 'sqreen/actions/user_action_class'
10
+
11
+ module Sqreen
12
+ module Actions
13
+ # Blocks a user at the point Sqreen::identify()
14
+ # or Sqreen::auth_track() are called
15
+ class BlockUser < Base
16
+ extend UserActionClass
17
+
18
+ self.type_name = 'block_user'
19
+
20
+ def initialize(id, opts, _params = {})
21
+ super(id, opts)
22
+ end
23
+
24
+ def do_run(identity_params)
25
+ Sqreen.log.info(
26
+ "Will raise due to user being blocked by action #{id}. " \
27
+ "Blocked user identity: #{identity_params}"
28
+ )
29
+
30
+ e = Sqreen::AttackBlocked.new(
31
+ "Blocked user with identity #{identity_params} " \
32
+ 'due to automatic security response. No action is required'
33
+ )
34
+
35
+ {
36
+ :status => :raise,
37
+ :exception => e,
38
+ }
39
+ end
40
+
41
+ def event_properties(identity_params)
42
+ { 'user' => identity_params }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,16 @@
1
+ # typed: true
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/actions/ip_ranges_index'
7
+
8
+ module Sqreen
9
+ module Actions
10
+ module IpRangeIndexedActionClass
11
+ def new_index
12
+ IpRangesIndex.new
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,57 @@
1
+ # typed: true
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'ipaddr'
7
+ require 'sqreen/actions/actions_index'
8
+ require 'sqreen/trie'
9
+ require 'sqreen/prefix'
10
+
11
+ module Sqreen
12
+ module Actions
13
+ class IpRangesIndex < ActionsIndex
14
+ def initialize
15
+ @trie_v4 = Sqreen::Trie.new
16
+ @trie_v6 = Sqreen::Trie.new(nil, nil, Socket::AF_INET6)
17
+ end
18
+
19
+ def index(params, action)
20
+ ranges = parse_ip_ranges params
21
+
22
+ ranges.each do |r|
23
+ add_prefix r, action
24
+ end
25
+ end
26
+
27
+ def actions_matching(client_ip)
28
+ parsed_ip = IPAddr.new(client_ip.gsub(/%[^%\/]+/, ''))
29
+ trie = parsed_ip.family == Socket::AF_INET6 ? @trie_v6 : @trie_v4
30
+ return [] unless trie
31
+ found = trie.search_matching(parsed_ip.to_i, parsed_ip.family)
32
+ return [] unless found.size > 0
33
+
34
+ Sqreen.log.debug("Client ip #{client_ip} matches #{found.inspect}")
35
+ found.map(&:data)
36
+ end
37
+
38
+ private
39
+
40
+ # returns array of prefixes in string form
41
+ def parse_ip_ranges(params)
42
+ ranges = params['ip_cidr']
43
+ unless ranges && ranges.is_a?(Array) && !ranges.empty?
44
+ raise 'no non-empty ip_cidr array present'
45
+ end
46
+
47
+ ranges
48
+ end
49
+
50
+ def add_prefix(prefix_str, data)
51
+ prefix = Sqreen::Prefix.from_str(prefix_str, data)
52
+ trie = prefix.family == Socket::AF_INET6 ? @trie_v6 : @trie_v4
53
+ trie.insert prefix
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,42 @@
1
+ # typed: true
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/log'
7
+ require 'sqreen/exception'
8
+ require 'sqreen/actions/base'
9
+
10
+ module Sqreen
11
+ module Actions
12
+ # Block a list of IP address ranges by forcefully redirecting the user
13
+ # to a specific URL.
14
+ class RedirectIp < Base
15
+ extend IpRangeIndexedActionClass
16
+
17
+ self.type_name = 'redirect_ip'
18
+
19
+ attr_reader :redirect_url
20
+
21
+ def initialize(id, opts, params = {})
22
+ super(id, opts)
23
+ @redirect_url = params['url']
24
+ raise "no url provided for action #{id}" unless @redirect_url
25
+ end
26
+
27
+ def do_run(client_ip)
28
+ Sqreen.log.info "Will request redirect for client with IP #{client_ip} " \
29
+ "(action: #{id})."
30
+ {
31
+ :status => :skip,
32
+ :new_return_value => [303, { 'Location' => @redirect_url }, ['']],
33
+ :skip_rem_cbs => true,
34
+ }
35
+ end
36
+
37
+ def event_properties(client_ip)
38
+ { 'ip_address' => client_ip, 'url' => @redirect_url }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ # typed: true
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/log'
7
+ require 'sqreen/exception'
8
+ require 'sqreen/actions/base'
9
+ require 'sqreen/actions/user_action_class'
10
+
11
+ module Sqreen
12
+ module Actions
13
+ # Redirects a user at the point Sqreen::identify()
14
+ # or Sqreen::auth_track() are called
15
+ class RedirectUser < Base
16
+ extend UserActionClass
17
+
18
+ self.type_name = 'redirect_user'
19
+
20
+ def initialize(id, opts, params = {})
21
+ super(id, opts)
22
+ @redirect_url = params['url']
23
+ raise "no url provided for action #{id}" unless @redirect_url
24
+ end
25
+
26
+ def do_run(identity_params)
27
+ Sqreen.log.info 'Will request redirect for user with identity ' \
28
+ "#{identity_params} (action: #{id})."
29
+
30
+ e = Sqreen::AttackBlocked.new(
31
+ "Redirected user with identity #{identity_params} " \
32
+ 'due to automatic security response. No action is required'
33
+ )
34
+ e.redirect_url = @redirect_url
35
+
36
+ {
37
+ :status => :raise,
38
+ :exception => e,
39
+ }
40
+ end
41
+
42
+ def event_properties(identity_params)
43
+ { 'user' => identity_params }
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,43 @@
1
+ # typed: true
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ module Sqreen
7
+ module Actions
8
+ # Where the actions are stored
9
+ # The current ones are stored in Repository.current
10
+ class Repository
11
+ def initialize
12
+ @indexes = Hash[Base.known_subclasses.map do |clazz|
13
+ [clazz.type_name, clazz.new_index]
14
+ end]
15
+ end
16
+
17
+ def add(params, action)
18
+ @indexes[action.class.type_name].index(params || {}, action)
19
+ end
20
+
21
+ # type is either a class or a type name
22
+ def get(type, key)
23
+ type = type.type_name if type.class == Class
24
+ @indexes[type].actions_matching key
25
+ end
26
+
27
+ singleton_class.class_eval do
28
+ attr_reader :current
29
+ def current=(new_inst)
30
+ raise 'nil is unacceptable' if new_inst.nil?
31
+ @current = new_inst
32
+ end
33
+
34
+ def clear
35
+ self.current = Repository.new
36
+ end
37
+ end
38
+
39
+ # initialize current to empty repository
40
+ clear
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ # typed: true
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/exception'
7
+
8
+ module Sqreen
9
+ # Implements actions (behavior taken in response to agent signals)
10
+ module Actions
11
+ # Exception for when an unknown action type is gotten from the server
12
+ class UnknownActionType < ::Sqreen::Exception
13
+ attr_reader :action_type
14
+ def initialize(action_type)
15
+ super("no such action type: #{action_type}. Must be one of #{Base.known_types}")
16
+ @action_type = action_type
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # typed: true
2
+
3
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
4
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
5
+
6
+ require 'sqreen/actions/users_index'
7
+
8
+ module Sqreen
9
+ module Actions
10
+ module UserActionClass
11
+ def new_index
12
+ UsersIndex.new
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,35 @@
1
+ # typed: true
2
+ require 'sqreen/actions/actions_index'
3
+
4
+ module Sqreen
5
+ module Actions
6
+ class UsersIndex < ActionsIndex
7
+ def actions_matching(identity_params)
8
+ return [] unless @idx
9
+ key = stringify_keys(identity_params)
10
+ actions = @idx[key]
11
+ actions || []
12
+ end
13
+
14
+ def index(params, action)
15
+ @idx ||= {}
16
+ users = params['users']
17
+ raise ::Sqreen::Exception, 'nil "users" param for block_user action' if users.nil?
18
+ raise ::Sqreen::Exception, '"users" param must be an array' unless users.is_a? Array
19
+
20
+ users.each do |u|
21
+ @idx[u] ||= []
22
+ @idx[u] << action
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def stringify_keys(hash)
29
+ Hash[
30
+ hash.map { |k, v| [k.to_s, v] }
31
+ ]
32
+ end
33
+ end
34
+ end
35
+ end