perimeter_x 1.2.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -0
  4. data/Dockerfile +12 -7
  5. data/Gemfile.lock +36 -30
  6. data/Rakefile +1 -0
  7. data/changelog.md +58 -0
  8. data/examples/app/controllers/home_controller.rb +1 -1
  9. data/lib/perimeter_x.rb +195 -71
  10. data/lib/perimeterx/configuration.rb +74 -22
  11. data/lib/perimeterx/internal/clients/perimeter_x_activity_client.rb +32 -6
  12. data/lib/perimeterx/internal/exceptions/px_config_exception.rb +6 -0
  13. data/lib/perimeterx/internal/first_party/px_first_party.rb +124 -0
  14. data/lib/perimeterx/internal/{perimeter_x_cookie_v1.rb → payload/perimeter_x_cookie_v1.rb} +1 -1
  15. data/lib/perimeterx/internal/{perimeter_x_cookie_v3.rb → payload/perimeter_x_cookie_v3.rb} +1 -1
  16. data/lib/perimeterx/internal/{perimeter_x_cookie.rb → payload/perimeter_x_payload.rb} +12 -4
  17. data/lib/perimeterx/internal/payload/perimeter_x_token_v1.rb +38 -0
  18. data/lib/perimeterx/internal/payload/perimeter_x_token_v3.rb +36 -0
  19. data/lib/perimeterx/internal/perimeter_x_context.rb +74 -32
  20. data/lib/perimeterx/internal/validators/hash_schema_validator.rb +26 -0
  21. data/lib/perimeterx/internal/validators/perimeter_x_cookie_validator.rb +29 -21
  22. data/lib/perimeterx/internal/validators/perimeter_x_s2s_validator.rb +33 -9
  23. data/lib/perimeterx/utils/px_constants.rb +35 -17
  24. data/lib/perimeterx/utils/px_http_client.rb +60 -3
  25. data/lib/perimeterx/utils/px_template_factory.rb +18 -8
  26. data/lib/perimeterx/utils/templates/block_template.mustache +175 -0
  27. data/lib/perimeterx/utils/templates/ratelimit.mustache +9 -0
  28. data/lib/perimeterx/version.rb +1 -1
  29. data/perimeter_x.gemspec +3 -3
  30. data/readme.md +115 -31
  31. metadata +24 -20
  32. data/lib/perimeterx/internal/validators/perimeter_x_captcha_validator.rb +0 -65
  33. data/lib/perimeterx/utils/templates/block.mustache +0 -146
  34. data/lib/perimeterx/utils/templates/captcha.mustache +0 -185
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 52e3418c30763e225706ca5ee7a3a88958c4a210
4
- data.tar.gz: 4671a1eb52edc4cfdb9ba4e85932c2dcb7e33dbb
2
+ SHA256:
3
+ metadata.gz: 475e2577bfe9b12bb7edbe3286fb4f1861a9c508791f38b0196dea0f493f355e
4
+ data.tar.gz: b0c61698741743a62ad0a7c9fb67dc6d5ed9f9b78c01d08b764cb1297ee37c98
5
5
  SHA512:
6
- metadata.gz: 13ca73c6ac3c22ff0d9d93d42cab42049a06e458f9596538cd2225a07dd1ea9e20db8bf4c6921519ed29c349e717eb929643051ef1510337b1414bf6ea8f6c01
7
- data.tar.gz: 2bc1a8fe0845f3899537bb34151c545ea7c6a5343b271c7bceb4d221a9551d74dec174042e30b02e7e29d533d7e0453235163ee0635d2275576c75ed4758efd5
6
+ metadata.gz: 3bae8b3e45c8ee8aba86a56ed977158adec12bccfa2542e1a4e54344b6b6fb0503182585816c1b55640bd49ea4d6323831e93ad6c8d3335703e33d695df362ba
7
+ data.tar.gz: d7a64faa2f03fd4bc467cdea545a2f530001431f37281c2a9561dd83c28c00006fe827e8cd510560fbbbd1a69d382993ae513edd214a18a277bcca57dd561fdc
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  *.rbc
2
+ *.iml
2
3
  capybara-*.html
3
4
  .rspec
4
5
  /log
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.7.1
data/Dockerfile CHANGED
@@ -1,21 +1,26 @@
1
1
  # Based on manual compile instructions at http://wiki.nginx.org/HttpLuaModule#Installation
2
- FROM ruby:2.3.0
2
+ FROM ruby:2.7.1
3
3
 
4
- RUN apt-get update && apt-get --force-yes -qq -y install \
5
- nodejs
6
- ENV RAILS_VERSION 4.2.0
4
+ RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg -o /root/yarn-pubkey.gpg && apt-key add /root/yarn-pubkey.gpg
5
+ RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list
6
+ RUN apt-get update && apt-get install -y --no-install-recommends nodejs yarn vim
7
+
8
+ ENV RAILS_VERSION 6.0.3.2
7
9
  RUN gem install rails --version "$RAILS_VERSION"
8
10
  RUN gem install bundler
9
11
  RUN mkdir -p /tmp/ruby_sandbox
10
12
  WORKDIR /tmp/ruby_sandbox
11
- RUN git clone https://github.com/PerimeterX/perimeterx-ruby-sdk.git
13
+ COPY lib /tmp/ruby_sandbox/lib
14
+ COPY Gemfile /tmp/ruby_sandbox/
15
+ COPY perimeter_x.gemspec /tmp/ruby_sandbox/
16
+ COPY Rakefile /tmp/ruby_sandbox/
12
17
  RUN rails new webapp
13
18
  WORKDIR /tmp/ruby_sandbox/webapp
14
19
 
15
20
  RUN rails generate controller home index
16
21
  WORKDIR /tmp/ruby_sandbox/webapp
17
22
  EXPOSE 3000
18
- RUN sed -i '2i gem "perimeter_x", :path => "/tmp/ruby_sandbox/perimeterx-ruby-sdk"' /tmp/ruby_sandbox/webapp/Gemfile
23
+ RUN sed -i '2i gem "perimeter_x", :path => "/tmp/ruby_sandbox"' /tmp/ruby_sandbox/webapp/Gemfile
19
24
  RUN bundler update
20
- COPY ./examples/ /tmp/ruby_sandbox/webapp
25
+ COPY ./dev/site/ /tmp/ruby_sandbox/webapp
21
26
  CMD ["rails","server","-b","0.0.0.0"]
@@ -1,55 +1,61 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- perimeter_x (1.0.5)
5
- activesupport (>= 4.2.0)
6
- httpclient (= 2.8.2.4)
4
+ perimeter_x (2.0.0)
5
+ activesupport (>= 5.2.4.3)
6
+ concurrent-ruby (~> 1.0, >= 1.0.5)
7
7
  mustache (~> 1.0, >= 1.0.3)
8
+ typhoeus (~> 1.1, >= 1.1.2)
8
9
 
9
10
  GEM
10
11
  remote: https://rubygems.org/
11
12
  specs:
12
- activesupport (5.0.2)
13
+ activesupport (6.0.3.2)
13
14
  concurrent-ruby (~> 1.0, >= 1.0.2)
14
- i18n (~> 0.7)
15
+ i18n (>= 0.7, < 2)
15
16
  minitest (~> 5.1)
16
17
  tzinfo (~> 1.1)
17
- concurrent-ruby (1.0.5)
18
- diff-lcs (1.3)
19
- httpclient (2.8.2.4)
20
- i18n (0.8.1)
21
- metaclass (0.0.4)
22
- minitest (5.10.1)
23
- mocha (1.2.1)
24
- metaclass (~> 0.0.1)
25
- mustache (1.0.4)
26
- rake (10.4.2)
27
- rspec (3.5.0)
28
- rspec-core (~> 3.5.0)
29
- rspec-expectations (~> 3.5.0)
30
- rspec-mocks (~> 3.5.0)
31
- rspec-core (3.5.4)
32
- rspec-support (~> 3.5.0)
33
- rspec-expectations (3.5.0)
18
+ zeitwerk (~> 2.2, >= 2.2.2)
19
+ concurrent-ruby (1.1.6)
20
+ diff-lcs (1.4.4)
21
+ ethon (0.12.0)
22
+ ffi (>= 1.3.0)
23
+ ffi (1.13.1)
24
+ i18n (1.8.3)
25
+ concurrent-ruby (~> 1.0)
26
+ minitest (5.14.1)
27
+ mocha (1.11.2)
28
+ mustache (1.1.1)
29
+ rake (13.0.1)
30
+ rspec (3.9.0)
31
+ rspec-core (~> 3.9.0)
32
+ rspec-expectations (~> 3.9.0)
33
+ rspec-mocks (~> 3.9.0)
34
+ rspec-core (3.9.2)
35
+ rspec-support (~> 3.9.3)
36
+ rspec-expectations (3.9.2)
34
37
  diff-lcs (>= 1.2.0, < 2.0)
35
- rspec-support (~> 3.5.0)
36
- rspec-mocks (3.5.0)
38
+ rspec-support (~> 3.9.0)
39
+ rspec-mocks (3.9.1)
37
40
  diff-lcs (>= 1.2.0, < 2.0)
38
- rspec-support (~> 3.5.0)
39
- rspec-support (3.5.0)
41
+ rspec-support (~> 3.9.0)
42
+ rspec-support (3.9.3)
40
43
  thread_safe (0.3.6)
41
- tzinfo (1.2.3)
44
+ typhoeus (1.4.0)
45
+ ethon (>= 0.9.0)
46
+ tzinfo (1.2.7)
42
47
  thread_safe (~> 0.1)
48
+ zeitwerk (2.3.1)
43
49
 
44
50
  PLATFORMS
45
51
  ruby
46
52
 
47
53
  DEPENDENCIES
48
- bundler (~> 1.14)
54
+ bundler (>= 2.1)
49
55
  mocha (~> 1.2, >= 1.2.1)
50
56
  perimeter_x!
51
- rake (~> 10.0)
57
+ rake (>= 12.3)
52
58
  rspec (~> 3.0)
53
59
 
54
60
  BUNDLED WITH
55
- 1.14.6
61
+ 2.1.4
data/Rakefile CHANGED
@@ -3,6 +3,7 @@ begin
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
+ task :default => :spec
6
7
  task :test => :spec
7
8
  rescue LoadError
8
9
  # no rspec available
@@ -5,6 +5,63 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
+ ## [2.2.0] - 2020-09-15
9
+ ### Added
10
+ - First Party
11
+
12
+ ## [2.1.0] - 2020-09-01
13
+ ### Added
14
+ - Added option to set a different px configuration on each request
15
+ - Added types validation on configuration fields
16
+
17
+ ### Fixed
18
+ - New cookie logic for mobile requests
19
+ - Renamed api_connect_timeout to api_timeout_conncection on default configuration
20
+ - Removed unsapported configuration fields: max_buffer_len and local_proxy
21
+ - Send cookie_origin only if there is a cookie
22
+
23
+ ## [2.0.0] - 2020-07-24
24
+ ### Added
25
+ - Added fields to Block Activity: simulated_block, http_version, http_method, risk_rtt, px_orig_cookie
26
+ - Added fields to page_requested activity: pass_reason, risk_rtt, px_orig_cookie
27
+ - Added px_orig_cookie field to risk_api in case of cookie_decryption_failed
28
+ - Added support for captcha v2
29
+ - Added support for Advanced Blocking Response
30
+ - Added support for whitelise routes
31
+ - Added support for bypass monitor header
32
+ - Added support for extracting vid from _pxvid cookie
33
+ - Added support for rate limit
34
+ - Added risk_cookie_max_iterations configuration
35
+
36
+ ### Fixed
37
+ - Updated dependencies
38
+ - Updated sample site dockerfile
39
+ - Fixed monitor mode
40
+ - Fixed send_page_activities and send_block_activities configurations
41
+ - Updated risk to v3
42
+ - Refactored ip header extraction
43
+ - Renamed block_uuid field to client_uuid
44
+ - Renamed perimeterx_server_host configuration to backend_url
45
+ - Updated risk_response handling: pass the request if risk_response.status is -1
46
+ - Forcing http header values to be utf8
47
+
48
+ ## [1.4.0] - 2018-03-18
49
+ ### Fixed
50
+ - Incorrect assigment for s2s_call_reason
51
+ - Fixed empty token result correct s2s reason
52
+
53
+ ### Added
54
+ - Added support to captcha api v2
55
+ - Mobile sdk support for special tokens 1/2/3
56
+
57
+
58
+ ## [1.3.0] - 2017-07-27
59
+ ### Added
60
+ - Sending client_uuid on page_requested activities
61
+ - Supporting mobile sdk
62
+ ### Fixed
63
+ - Using `request.env` instead of `env`
64
+
8
65
  ## [1.2.0] - 2017-06-04
9
66
  ### Fixed
10
67
  - Default timeouts for post api requests
@@ -27,3 +84,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
27
84
  - Constants on px_constants
28
85
  - Cookie Validation flow when cookie score was over the configured threshold
29
86
  - Using symbols instead of strings for requests body
87
+
@@ -1,7 +1,7 @@
1
1
  class HomeController < ApplicationController
2
2
  include PxModule
3
3
 
4
- before_filter :px_verify_request
4
+ before_action :px_verify_request
5
5
 
6
6
  def index
7
7
  end
@@ -1,3 +1,7 @@
1
+ require 'concurrent'
2
+ require 'json'
3
+ require 'base64'
4
+ require 'uri'
1
5
  require 'perimeterx/configuration'
2
6
  require 'perimeterx/utils/px_logger'
3
7
  require 'perimeterx/utils/px_constants'
@@ -7,139 +11,259 @@ require 'perimeterx/internal/perimeter_x_context'
7
11
  require 'perimeterx/internal/clients/perimeter_x_activity_client'
8
12
  require 'perimeterx/internal/validators/perimeter_x_s2s_validator'
9
13
  require 'perimeterx/internal/validators/perimeter_x_cookie_validator'
10
- require 'perimeterx/internal/validators/perimeter_x_captcha_validator'
14
+ require 'perimeterx/internal/exceptions/px_config_exception'
15
+ require 'perimeterx/internal/first_party/px_first_party'
11
16
 
12
17
  module PxModule
13
-
14
18
  # Module expose API
15
- def px_verify_request
16
- verified, px_ctx = PerimeterX.instance.verify(env)
17
-
18
- # Invalidate _pxCaptcha, can be done only on the controller level
19
- cookies[:_pxCaptcha] = { value: "", expires: -1.minutes.from_now }
20
-
21
- if (!verified)
22
- # In case custon block handler exists
23
- if (PerimeterX.instance.px_config.key?(:custom_block_handler))
24
- PerimeterX.instance.px_config[:logger].debug("PxModule[px_verify_request]: custom_block_handler triggered")
25
- return instance_exec(px_ctx, &PerimeterX.instance.px_config[:custom_block_handler])
26
- else
27
- # Generate template
28
- PerimeterX.instance.px_config[:logger].debug("PxModule[px_verify_request]: sending default block page")
29
- html = PxTemplateFactory.get_template(px_ctx, PerimeterX.instance.px_config)
30
- response.headers["Content-Type"] = "text/html"
31
- response.status = 403
32
- render :html => html
19
+ def px_verify_request(request_config={})
20
+ begin
21
+ px_instance = PerimeterX.new(request_config)
22
+ req = ActionDispatch::Request.new(request.env)
23
+
24
+ # handle first party requests
25
+ if px_instance.first_party.is_first_party_request(req)
26
+ render_first_party_response(req, px_instance)
27
+ return true
28
+ end
29
+
30
+ # verify request
31
+ px_ctx = px_instance.verify(req)
32
+ px_config = px_instance.px_config
33
+
34
+ msg_title = 'PxModule[px_verify_request]'
35
+
36
+ # In case custom verification handler is in use
37
+ if px_config.key?(:custom_verification_handler)
38
+ px_config[:logger].debug("#{msg_title}: custom_verification_handler triggered")
39
+ return instance_exec(px_ctx, &px_config[:custom_verification_handler])
33
40
  end
41
+
42
+ unless px_ctx.nil? || px_ctx.context[:verified] || (px_config[:module_mode] == PxModule::MONITOR_MODE && !px_ctx.context[:should_bypass_monitor])
43
+ # In case custom block handler exists (soon to be deprecated)
44
+ if px_config.key?(:custom_block_handler)
45
+ px_config[:logger].debug("#{msg_title}: custom_block_handler triggered")
46
+ px_config[:logger].debug(
47
+ "#{msg_title}: Please note that custom_block_handler is deprecated. Use custom_verification_handler instead.")
48
+ return instance_exec(px_ctx, &px_config[:custom_block_handler])
49
+ else
50
+ if px_ctx.context[:block_action]== 'rate_limit'
51
+ px_config[:logger].debug("#{msg_title}: sending rate limit page")
52
+ response.status = 429
53
+ else
54
+ px_config[:logger].debug("#{msg_title}: sending default block page")
55
+ response.status = 403
56
+ end
57
+
58
+ is_mobile = px_ctx.context[:cookie_origin] == 'header' ? '1' : '0'
59
+ action = px_ctx.context[:block_action][0,1]
60
+
61
+ if px_config[:first_party_enabled]
62
+ px_template_object = {
63
+ js_client_src: "/#{px_config[:app_id][2..-1]}/init.js",
64
+ block_script: "/#{px_config[:app_id][2..-1]}/captcha/#{px_config[:app_id]}/captcha.js?a=#{action}&u=#{px_ctx.context[:uuid]}&v=#{px_ctx.context[:vid]}&m=#{is_mobile}",
65
+ host_url: "/#{px_config[:app_id][2..-1]}/xhr"
66
+ }
67
+ else
68
+ px_template_object = {
69
+ js_client_src: "//#{PxModule::CLIENT_HOST}/#{px_config[:app_id]}/main.min.js",
70
+ block_script: "//#{PxModule::CAPTCHA_HOST}/#{px_config[:app_id]}/captcha.js?a=#{action}&u=#{px_ctx.context[:uuid]}&v=#{px_ctx.context[:vid]}&m=#{is_mobile}",
71
+ host_url: "https://collector-#{px_config[:app_id]}.perimeterx.net"
72
+ }
73
+ end
74
+
75
+ html = PxTemplateFactory.get_template(px_ctx, px_config, px_template_object)
76
+
77
+ # Web handler
78
+ if px_ctx.context[:cookie_origin] == 'cookie'
79
+
80
+ accept_header_value = request.headers['accept'] || request.headers['content-type'];
81
+ is_json_response = px_ctx.context[:block_action] != 'rate_limit' && accept_header_value && accept_header_value.split(',').select {|e| e.downcase.include? 'application/json'}.length > 0;
82
+
83
+ if (is_json_response)
84
+ px_config[:logger].debug("#{msg_title}: advanced blocking response response")
85
+ response.headers['Content-Type'] = 'application/json'
86
+
87
+ hash_json = {
88
+ :appId => px_config[:app_id],
89
+ :jsClientSrc => px_template_object[:js_client_src],
90
+ :firstPartyEnabled => px_ctx.context[:first_party_enabled],
91
+ :uuid => px_ctx.context[:uuid],
92
+ :vid => px_ctx.context[:vid],
93
+ :hostUrl => "https://collector-#{px_config[:app_id]}.perimeterx.net",
94
+ :blockScript => px_template_object[:block_script],
95
+ }
96
+
97
+ render :json => hash_json
98
+ else
99
+ px_config[:logger].debug('#{msg_title}: web block')
100
+ response.headers['Content-Type'] = 'text/html'
101
+ render :html => html
102
+ end
103
+ else # Mobile SDK
104
+ px_config[:logger].debug("#{msg_title}: mobile sdk block")
105
+ response.headers['Content-Type'] = 'application/json'
106
+ hash_json = {
107
+ :action => px_ctx.context[:block_action],
108
+ :uuid => px_ctx.context[:uuid],
109
+ :vid => px_ctx.context[:vid],
110
+ :appId => px_config[:app_id],
111
+ :page => Base64.strict_encode64(html),
112
+ :collectorUrl => "https://collector-#{px_config[:app_id]}.perimeterx.net"
113
+ }
114
+ render :json => hash_json
115
+ end
116
+ end
117
+ end
118
+
119
+ # Request was verified
120
+ return px_ctx.nil? ? true : px_ctx.context[:verified]
121
+
122
+ rescue PxConfigurationException
123
+ raise
124
+ rescue Exception => e
125
+ error_logger = PxLogger.new(true)
126
+ error_logger.error("#{e.backtrace.first}: #{e.message} (#{e.class})")
127
+ e.backtrace.drop(1).map {|s| error_logger.error("\t#{s}")}
128
+ return nil
34
129
  end
130
+ end
35
131
 
36
- return verified
132
+ def render_first_party_response(req, px_instance)
133
+ fp = px_instance.first_party
134
+ px_config = px_instance.px_config
135
+
136
+ if px_config[:first_party_enabled]
137
+ # first party enabled - proxy response
138
+ fp_response = fp.send_first_party_request(req)
139
+ response.status = fp_response.code
140
+ fp_response.to_hash.each do |header_name, header_value_arr|
141
+ if header_name!="content-length"
142
+ response.headers[header_name] = header_value_arr[0]
143
+ end
144
+ end
145
+ res_type = fp.get_response_content_type(req)
146
+ render res_type => fp_response.body
147
+ else
148
+ # first party disabled - return empty response
149
+ response.status = 200
150
+ res_type = fp.get_response_content_type(req)
151
+ render res_type => ""
152
+ end
37
153
  end
38
154
 
39
- def self.configure(params)
40
- @px_instance = PerimeterX.configure(params)
155
+ def self.configure(basic_config)
156
+ PerimeterX.set_basic_config(basic_config)
41
157
  end
42
158
 
43
159
 
44
- # PerimtereX Module
160
+ # PerimeterX Module
45
161
  class PerimeterX
46
- @@__instance = nil
47
- @@mutex = Mutex.new
48
162
 
49
163
  attr_reader :px_config
164
+ attr_reader :first_party
50
165
  attr_accessor :px_http_client
51
166
  attr_accessor :px_activity_client
52
167
 
53
168
  #Static methods
54
- def self.configure(params)
55
- return true if @@__instance
56
- @@mutex.synchronize {
57
- return @@__instance if @@__instance
58
- @@__instance = new(params)
59
- }
60
- return true
61
- end
62
-
63
- def self.instance
64
- return @@__instance if !@@__instance.nil?
65
- raise Exception.new("Please initialize perimeter x first")
169
+ def self.set_basic_config(basic_config)
170
+ Configuration.set_basic_config(basic_config)
66
171
  end
67
172
 
68
-
69
173
  #Instance Methods
70
- def verify(env)
174
+ def verify(req)
71
175
  begin
72
- @logger.debug("PerimeterX[pxVerify]")
73
- req = ActionDispatch::Request.new(env)
74
- if (!@px_config[:module_enabled])
75
- @logger.warn("Module is disabled")
76
- return true
77
- end
78
- px_ctx = PerimeterXContext.new(@px_config, req)
79
176
 
80
- # Captcha phase
81
- captcha_verified, px_ctx = @px_captcha_validator.verify(px_ctx)
82
- if (captcha_verified)
83
- return handle_verification(px_ctx)
177
+ # check module_enabled
178
+ @logger.debug('PerimeterX[pxVerify]')
179
+ if !@px_config[:module_enabled]
180
+ @logger.warn('Module is disabled')
181
+ return nil
182
+ end
183
+
184
+ # filter whitelist routes
185
+ url_path = URI.parse(req.original_url).path
186
+ if url_path && !url_path.empty?
187
+ if check_whitelist_routes(px_config[:whitelist_routes], url_path)
188
+ @logger.debug("PerimeterX[pxVerify]: whitelist route: #{url_path}")
189
+ return nil
190
+ end
84
191
  end
192
+
193
+ # create context
194
+ px_ctx = PerimeterXContext.new(@px_config, req)
85
195
 
86
196
  # Cookie phase
87
197
  cookie_verified, px_ctx = @px_cookie_validator.verify(px_ctx)
88
- if (!cookie_verified)
198
+ if !cookie_verified
199
+ if !px_ctx.context[:mobile_error].nil?
200
+ px_ctx.context[:s2s_call_reason] = "mobile_error_#{px_ctx.context[:mobile_error]}"
201
+ end
89
202
  @px_s2s_validator.verify(px_ctx)
90
203
  end
91
204
 
92
- if (@px_config.key?(:custom_verification_handler))
93
- return @px_config[:custom_verification_handler].call(px_ctx.context)
94
- else
95
- return handle_verification(px_ctx)
96
- end
205
+ return handle_verification(px_ctx)
97
206
  rescue Exception => e
98
207
  @logger.error("#{e.backtrace.first}: #{e.message} (#{e.class})")
99
- e.backtrace.drop(1).map { |s| @logger.error("\t#{s}") }
100
- return true
208
+ e.backtrace.drop(1).map {|s| @logger.error("\t#{s}")}
209
+ return nil
101
210
  end
102
211
  end
103
212
 
104
- private def initialize(params)
105
- @px_config = Configuration.new(params).configuration
213
+ def initialize(request_config)
214
+
215
+ @px_config = Configuration.new(request_config).configuration
106
216
  @logger = @px_config[:logger]
107
217
  @px_http_client = PxHttpClient.new(@px_config)
108
218
 
109
219
  @px_activity_client = PerimeterxActivitiesClient.new(@px_config, @px_http_client)
220
+ @first_party = FirstPartyManager.new(@px_config, @px_http_client, @logger)
110
221
 
111
222
  @px_cookie_validator = PerimeterxCookieValidator.new(@px_config)
112
223
  @px_s2s_validator = PerimeterxS2SValidator.new(@px_config, @px_http_client)
113
- @px_captcha_validator = PerimeterxCaptchaValidator.new(@px_config, @px_http_client)
114
- @logger.debug("PerimeterX[initialize]")
224
+ @logger.debug('PerimeterX[initialize]')
115
225
  end
116
226
 
117
227
  private def handle_verification(px_ctx)
118
- @logger.debug("PerimeterX[handle_verification]")
228
+ @logger.debug('PerimeterX[handle_verification]')
119
229
  @logger.debug("PerimeterX[handle_verification]: processing ended - score:#{px_ctx.context[:score]}, uuid:#{px_ctx.context[:uuid]}")
120
230
 
121
231
  score = px_ctx.context[:score]
232
+ px_ctx.context[:should_bypass_monitor] = @px_config[:bypass_monitor_header] && px_ctx.context[:headers][@px_config[:bypass_monitor_header].to_sym] == '1';
233
+
234
+ px_ctx.context[:verified] = score < @px_config[:blocking_score]
122
235
  # Case PASS request
123
- if (score < @px_config[:blocking_score])
236
+ if px_ctx.context[:verified]
124
237
  @logger.debug("PerimeterX[handle_verification]: score:#{score} < blocking score, passing request")
125
238
  @px_activity_client.send_page_requested_activity(px_ctx)
126
- return true
239
+ return px_ctx
127
240
  end
128
241
 
129
242
  # Case blocking activity
130
243
  @px_activity_client.send_block_activity(px_ctx)
131
244
 
132
245
  # In case were in monitor mode, end here
133
- if(@px_config[:module_mode] == PxModule::MONITOR_MODE)
246
+ if @px_config[:module_mode] == PxModule::MONITOR_MODE && !px_ctx.context[:should_bypass_monitor]
134
247
  @logger.debug("PerimeterX[handle_verification]: monitor mode is on, passing request")
135
- return true
248
+ return px_ctx
136
249
  end
137
250
 
138
- @logger.debug("PerimeterX[handle_verification]: verification ended, the request should be blocked")
251
+ @logger.debug('PerimeterX[handle_verification]: verification ended, the request should be blocked')
252
+
253
+ return px_ctx
254
+ end
139
255
 
140
- return false, px_ctx
256
+ private def check_whitelist_routes(whitelist_routes, path)
257
+ whitelist_routes.each do |whitelist_route|
258
+ if whitelist_route.is_a?(Regexp) && path.match(whitelist_route)
259
+ return true
260
+ end
261
+ if whitelist_route.is_a?(String) && path.start_with?(whitelist_route)
262
+ return true
263
+ end
264
+ end
265
+ false
141
266
  end
142
267
 
143
- private_class_method :new
144
268
  end
145
269
  end