perimeter_x 1.1.0 → 2.1.0

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 (33) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -0
  4. data/Dockerfile +19 -43
  5. data/Gemfile.lock +36 -30
  6. data/Rakefile +1 -0
  7. data/changelog.md +63 -0
  8. data/examples/app/controllers/home_controller.rb +1 -1
  9. data/lib/perimeter_x.rb +152 -70
  10. data/lib/perimeterx/configuration.rb +71 -22
  11. data/lib/perimeterx/internal/clients/perimeter_x_activity_client.rb +36 -15
  12. data/lib/perimeterx/internal/exceptions/px_config_exception.rb +6 -0
  13. data/lib/perimeterx/internal/{perimeter_x_cookie_v1.rb → payload/perimeter_x_cookie_v1.rb} +1 -1
  14. data/lib/perimeterx/internal/{perimeter_x_cookie_v3.rb → payload/perimeter_x_cookie_v3.rb} +1 -1
  15. data/lib/perimeterx/internal/{perimeter_x_cookie.rb → payload/perimeter_x_payload.rb} +12 -4
  16. data/lib/perimeterx/internal/payload/perimeter_x_token_v1.rb +38 -0
  17. data/lib/perimeterx/internal/payload/perimeter_x_token_v3.rb +36 -0
  18. data/lib/perimeterx/internal/perimeter_x_context.rb +66 -31
  19. data/lib/perimeterx/internal/validators/hash_schema_validator.rb +26 -0
  20. data/lib/perimeterx/internal/validators/perimeter_x_cookie_validator.rb +29 -21
  21. data/lib/perimeterx/internal/validators/perimeter_x_s2s_validator.rb +34 -10
  22. data/lib/perimeterx/utils/px_constants.rb +35 -17
  23. data/lib/perimeterx/utils/px_http_client.rb +29 -35
  24. data/lib/perimeterx/utils/px_template_factory.rb +18 -8
  25. data/lib/perimeterx/utils/templates/block_template.mustache +175 -0
  26. data/lib/perimeterx/utils/templates/ratelimit.mustache +9 -0
  27. data/lib/perimeterx/version.rb +1 -1
  28. data/perimeter_x.gemspec +5 -4
  29. data/readme.md +95 -32
  30. metadata +53 -24
  31. data/lib/perimeterx/internal/validators/perimeter_x_captcha_validator.rb +0 -65
  32. data/lib/perimeterx/utils/templates/block.mustache +0 -146
  33. data/lib/perimeterx/utils/templates/captcha.mustache +0 -185
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8821c69fed2516694f5cfc66c4fd86cb8350e1c6
4
- data.tar.gz: cb26bfa40459f6e0745c9d1d1bdb94a07ade258b
2
+ SHA256:
3
+ metadata.gz: d65b91dbf3bdf1829dbfe7b1d44677d86ecde223bc0bd614618d1a9b1a188e84
4
+ data.tar.gz: 473dc3f4a54232d59c2f89dcc6a1bddbb6a95de0268fddf53cfa28b47e8653d6
5
5
  SHA512:
6
- metadata.gz: 79d0af263099a0b1cc363546e26a2c7c3c42b80e71a7eb1b39c9f07a784ad5ad925598aa42be2036cc79620528762398c4ac58d1ee448ca792b55aa422bf2784
7
- data.tar.gz: a13e5dab8ce2a5a9380996921799a5e90bb3b141f10b08b13821b07ff36efaa6cb12c1b853f7071e7ebcc3d2ffa84e21233d8442f07a01aa3607a80f287edf77
6
+ metadata.gz: a89194401d9a60cd41fdb524724329bee547285742c218ffd157337203090ab66f4992fed517389868c639fea175a9c3561663b81b2463a9b1f3fb0011391e7b
7
+ data.tar.gz: 428757d1a7dafc96543a125db63a8a2c7639ba27673f96bd5222b1628bafcd117f26d1fefb8041179f30e89f5ea286454ebbfb897b0d81d54e5be2be24d6fb8e
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,50 +1,26 @@
1
1
  # Based on manual compile instructions at http://wiki.nginx.org/HttpLuaModule#Installation
2
- FROM ubuntu:14.04
3
- RUN apt-get update && apt-get --force-yes -qq -y install \
4
- build-essential \
5
- ca-certificates \
6
- curl \
7
- git \
8
- libpcre3 \
9
- libpcre3-dev \
10
- libssl-dev \
11
- libreadline-dev \
12
- libyaml-dev \
13
- libgdbm-dev \
14
- libtool \
15
- automake \
16
- bison \
17
- lua-cjson \
18
- libncurses5-dev \
19
- m4 \
20
- libsqlite3-dev \
21
- rsyslog \
22
- sqlite3 \
23
- libxml2-dev \
24
- libxslt1-dev \
25
- libcurl4-openssl-dev \
26
- python-software-properties \
27
- libffi-dev \
28
- nodejs \
29
- wget \
30
- zlib1g-dev
2
+ FROM ruby:2.7.1
31
3
 
32
- RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
33
- RUN /bin/bash -l -c "curl -L get.rvm.io | bash -s stable --rails"
34
- RUN /bin/bash -l -c "rvm install 2.3.0"
35
- RUN /bin/bash -l -c "rvm use 2.3.0"
36
- RUN /bin/bash -l -c "gem install bundler"
37
- RUN /bin/bash -l -c "gem install rails -v 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
9
+ RUN gem install rails --version "$RAILS_VERSION"
10
+ RUN gem install bundler
38
11
  RUN mkdir -p /tmp/ruby_sandbox
39
12
  WORKDIR /tmp/ruby_sandbox
40
- RUN git clone https://github.com/PerimeterX/perimeterx-ruby-sdk.git
41
- RUN /bin/bash -l -c "rails new webapp"
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/
17
+ RUN rails new webapp
42
18
  WORKDIR /tmp/ruby_sandbox/webapp
43
- RUN /bin/bash -l -c "rails generate controller home index"
19
+
20
+ RUN rails generate controller home index
44
21
  WORKDIR /tmp/ruby_sandbox/webapp
45
22
  EXPOSE 3000
46
- # TODO: make it take the files from git
47
- RUN sed -i '2i gem "perimeter_x", :path => "/tmp/ruby_sandbox/perimeterx-ruby-sdk"' /tmp/ruby_sandbox/webapp/Gemfile
48
- RUN /bin/bash -l -c "bundler update"
49
- COPY ./examples/ /tmp/ruby_sandbox/webapp
50
- CMD ["/bin/bash", "-l", "-c", "rails server -b 0.0.0.0;"]
23
+ RUN sed -i '2i gem "perimeter_x", :path => "/tmp/ruby_sandbox"' /tmp/ruby_sandbox/webapp/Gemfile
24
+ RUN bundler update
25
+ COPY ./dev/site/ /tmp/ruby_sandbox/webapp
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,68 @@ 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.1.0] - 2020-09-01
9
+ ### Added
10
+ - Added option to set a different px configuration on each request
11
+ - Added types validation on configuration fields
12
+
13
+ ### Fixed
14
+ - New cookie logic for mobile requests
15
+ - Renamed api_connect_timeout to api_timeout_conncection on default configuration
16
+ - Removed unsapported configuration fields: max_buffer_len and local_proxy
17
+ - Send cookie_origin only if there is a cookie
18
+
19
+ ## [2.0.0] - 2020-07-24
20
+ ### Added
21
+ - Added fields to Block Activity: simulated_block, http_version, http_method, risk_rtt, px_orig_cookie
22
+ - Added fields to page_requested activity: pass_reason, risk_rtt, px_orig_cookie
23
+ - Added px_orig_cookie field to risk_api in case of cookie_decryption_failed
24
+ - Added support for captcha v2
25
+ - Added support for Advanced Blocking Response
26
+ - Added support for whitelise routes
27
+ - Added support for bypass monitor header
28
+ - Added support for extracting vid from _pxvid cookie
29
+ - Added support for rate limit
30
+ - Added risk_cookie_max_iterations configuration
31
+
32
+ ### Fixed
33
+ - Updated dependencies
34
+ - Updated sample site dockerfile
35
+ - Fixed monitor mode
36
+ - Fixed send_page_activities and send_block_activities configurations
37
+ - Updated risk to v3
38
+ - Refactored ip header extraction
39
+ - Renamed block_uuid field to client_uuid
40
+ - Renamed perimeterx_server_host configuration to backend_url
41
+ - Updated risk_response handling: pass the request if risk_response.status is -1
42
+ - Forcing http header values to be utf8
43
+
44
+ ## [1.4.0] - 2018-03-18
45
+ ### Fixed
46
+ - Incorrect assigment for s2s_call_reason
47
+ - Fixed empty token result correct s2s reason
48
+
49
+ ### Added
50
+ - Added support to captcha api v2
51
+ - Mobile sdk support for special tokens 1/2/3
52
+
53
+
54
+ ## [1.3.0] - 2017-07-27
55
+ ### Added
56
+ - Sending client_uuid on page_requested activities
57
+ - Supporting mobile sdk
58
+ ### Fixed
59
+ - Using `request.env` instead of `env`
60
+
61
+ ## [1.2.0] - 2017-06-04
62
+ ### Fixed
63
+ - Default timeouts for post api requests
64
+ - Fixed Dockerfile
65
+ ### Changed
66
+ - Removed httpclient and instead using typheous
67
+ ### Added
68
+ - Using concurrent-ruby for async post requests
69
+
8
70
  ## [1.1.0] - 2017-06-04
9
71
  ### Added
10
72
  - Added support for sensitive routes
@@ -18,3 +80,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
18
80
  - Constants on px_constants
19
81
  - Cookie Validation flow when cookie score was over the configured threshold
20
82
  - Using symbols instead of strings for requests body
83
+
@@ -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,102 +11,167 @@ 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'
11
15
 
12
16
  module PxModule
13
-
14
17
  # 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
18
+ def px_verify_request(request_config={})
19
+ begin
20
+ px_instance = PerimeterX.new(request_config)
21
+ px_ctx = px_instance.verify(request.env)
22
+ px_config = px_instance.px_config
23
+
24
+ msg_title = 'PxModule[px_verify_request]'
25
+
26
+ # In case custom verification handler is in use
27
+ if px_config.key?(:custom_verification_handler)
28
+ px_config[:logger].debug("#{msg_title}: custom_verification_handler triggered")
29
+ return instance_exec(px_ctx, &px_config[:custom_verification_handler])
33
30
  end
34
- end
35
31
 
36
- return verified
32
+ unless px_ctx.nil? || px_ctx.context[:verified] || (px_config[:module_mode] == PxModule::MONITOR_MODE && !px_ctx.context[:should_bypass_monitor])
33
+ # In case custom block handler exists (soon to be deprecated)
34
+ if px_config.key?(:custom_block_handler)
35
+ px_config[:logger].debug("#{msg_title}: custom_block_handler triggered")
36
+ px_config[:logger].debug(
37
+ "#{msg_title}: Please note that custom_block_handler is deprecated. Use custom_verification_handler instead.")
38
+ return instance_exec(px_ctx, &px_config[:custom_block_handler])
39
+ else
40
+ if px_ctx.context[:block_action]== 'rate_limit'
41
+ px_config[:logger].debug("#{msg_title}: sending rate limit page")
42
+ response.status = 429
43
+ else
44
+ px_config[:logger].debug("#{msg_title}: sending default block page")
45
+ response.status = 403
46
+ end
47
+
48
+ is_mobile = px_ctx.context[:cookie_origin] == 'header' ? '1' : '0'
49
+ action = px_ctx.context[:block_action][0,1]
50
+
51
+ px_template_object = {
52
+ 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}",
53
+ js_client_src: "//#{PxModule::CLIENT_HOST}/#{px_config[:app_id]}/main.min.js"
54
+ }
55
+
56
+ html = PxTemplateFactory.get_template(px_ctx, px_config, px_template_object)
57
+
58
+ # Web handler
59
+ if px_ctx.context[:cookie_origin] == 'cookie'
60
+
61
+ accept_header_value = request.headers['accept'] || request.headers['content-type'];
62
+ 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;
63
+
64
+ if (is_json_response)
65
+ px_config[:logger].debug("#{msg_title}: advanced blocking response response")
66
+ response.headers['Content-Type'] = 'application/json'
67
+
68
+ hash_json = {
69
+ :appId => px_config[:app_id],
70
+ :jsClientSrc => px_template_object[:js_client_src],
71
+ :firstPartyEnabled => false,
72
+ :uuid => px_ctx.context[:uuid],
73
+ :vid => px_ctx.context[:vid],
74
+ :hostUrl => "https://collector-#{px_config[:app_id]}.perimeterx.net",
75
+ :blockScript => px_template_object[:block_script],
76
+ }
77
+
78
+ render :json => hash_json
79
+ else
80
+ px_config[:logger].debug('#{msg_title}: web block')
81
+ response.headers['Content-Type'] = 'text/html'
82
+ render :html => html
83
+ end
84
+ else # Mobile SDK
85
+ px_config[:logger].debug("#{msg_title}: mobile sdk block")
86
+ response.headers['Content-Type'] = 'application/json'
87
+ hash_json = {
88
+ :action => px_ctx.context[:block_action],
89
+ :uuid => px_ctx.context[:uuid],
90
+ :vid => px_ctx.context[:vid],
91
+ :appId => px_config[:app_id],
92
+ :page => Base64.strict_encode64(html),
93
+ :collectorUrl => "https://collector-#{px_config[:app_id]}.perimeterx.net"
94
+ }
95
+ render :json => hash_json
96
+ end
97
+ end
98
+ end
99
+
100
+ # Request was verified
101
+ return px_ctx.nil? ? true : px_ctx.context[:verified]
102
+
103
+ rescue PxConfigurationException
104
+ raise
105
+ rescue Exception => e
106
+ error_logger = PxLogger.new(true)
107
+ error_logger.error("#{e.backtrace.first}: #{e.message} (#{e.class})")
108
+ e.backtrace.drop(1).map {|s| error_logger.error("\t#{s}")}
109
+ return nil
110
+ end
37
111
  end
38
112
 
39
- def self.configure(params)
40
- @px_instance = PerimeterX.configure(params)
113
+ def self.configure(basic_config)
114
+ PerimeterX.set_basic_config(basic_config)
41
115
  end
42
116
 
43
117
 
44
- # PerimtereX Module
118
+ # PerimeterX Module
45
119
  class PerimeterX
46
- @@__instance = nil
47
- @@mutex = Mutex.new
48
120
 
49
121
  attr_reader :px_config
50
122
  attr_accessor :px_http_client
51
123
  attr_accessor :px_activity_client
52
124
 
53
125
  #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
126
+ def self.set_basic_config(basic_config)
127
+ Configuration.set_basic_config(basic_config)
61
128
  end
62
129
 
63
- def self.instance
64
- return @@__instance if !@@__instance.nil?
65
- raise Exception.new("Please initialize perimeter x first")
66
- end
67
-
68
-
69
130
  #Instance Methods
70
131
  def verify(env)
71
132
  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
133
+
134
+ # check module_enabled
135
+ @logger.debug('PerimeterX[pxVerify]')
136
+ if !@px_config[:module_enabled]
137
+ @logger.warn('Module is disabled')
138
+ return nil
77
139
  end
78
- px_ctx = PerimeterXContext.new(@px_config, req)
79
140
 
80
- # Captcha phase
81
- captcha_verified, px_ctx = @px_captcha_validator.verify(px_ctx)
82
- if (captcha_verified)
83
- return handle_verification(px_ctx)
141
+ req = ActionDispatch::Request.new(env)
142
+
143
+ # filter whitelist routes
144
+ url_path = URI.parse(req.original_url).path
145
+ if url_path && !url_path.empty?
146
+ if check_whitelist_routes(px_config[:whitelist_routes], url_path)
147
+ @logger.debug("PerimeterX[pxVerify]: whitelist route: #{url_path}")
148
+ return nil
149
+ end
84
150
  end
151
+
152
+ # create context
153
+ px_ctx = PerimeterXContext.new(@px_config, req)
85
154
 
86
155
  # Cookie phase
87
156
  cookie_verified, px_ctx = @px_cookie_validator.verify(px_ctx)
88
- if (!cookie_verified)
157
+ if !cookie_verified
158
+ if !px_ctx.context[:mobile_error].nil?
159
+ px_ctx.context[:s2s_call_reason] = "mobile_error_#{px_ctx.context[:mobile_error]}"
160
+ end
89
161
  @px_s2s_validator.verify(px_ctx)
90
162
  end
91
163
 
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
164
+ return handle_verification(px_ctx)
97
165
  rescue Exception => e
98
166
  @logger.error("#{e.backtrace.first}: #{e.message} (#{e.class})")
99
- e.backtrace.drop(1).map { |s| @logger.error("\t#{s}") }
100
- return true
167
+ e.backtrace.drop(1).map {|s| @logger.error("\t#{s}")}
168
+ return nil
101
169
  end
102
170
  end
103
171
 
104
- private def initialize(params)
105
- @px_config = Configuration.new(params).configuration
172
+ def initialize(request_config)
173
+
174
+ @px_config = Configuration.new(request_config).configuration
106
175
  @logger = @px_config[:logger]
107
176
  @px_http_client = PxHttpClient.new(@px_config)
108
177
 
@@ -110,36 +179,49 @@ module PxModule
110
179
 
111
180
  @px_cookie_validator = PerimeterxCookieValidator.new(@px_config)
112
181
  @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]")
182
+ @logger.debug('PerimeterX[initialize]')
115
183
  end
116
184
 
117
185
  private def handle_verification(px_ctx)
118
- @logger.debug("PerimeterX[handle_verification]")
186
+ @logger.debug('PerimeterX[handle_verification]')
119
187
  @logger.debug("PerimeterX[handle_verification]: processing ended - score:#{px_ctx.context[:score]}, uuid:#{px_ctx.context[:uuid]}")
120
188
 
121
189
  score = px_ctx.context[:score]
190
+ px_ctx.context[:should_bypass_monitor] = @px_config[:bypass_monitor_header] && px_ctx.context[:headers][@px_config[:bypass_monitor_header].to_sym] == '1';
191
+
192
+ px_ctx.context[:verified] = score < @px_config[:blocking_score]
122
193
  # Case PASS request
123
- if (score < @px_config[:blocking_score])
194
+ if px_ctx.context[:verified]
124
195
  @logger.debug("PerimeterX[handle_verification]: score:#{score} < blocking score, passing request")
125
196
  @px_activity_client.send_page_requested_activity(px_ctx)
126
- return true
197
+ return px_ctx
127
198
  end
128
199
 
129
200
  # Case blocking activity
130
201
  @px_activity_client.send_block_activity(px_ctx)
131
202
 
132
203
  # In case were in monitor mode, end here
133
- if(@px_config[:module_mode] == PxModule::MONITOR_MODE)
204
+ if @px_config[:module_mode] == PxModule::MONITOR_MODE && !px_ctx.context[:should_bypass_monitor]
134
205
  @logger.debug("PerimeterX[handle_verification]: monitor mode is on, passing request")
135
- return true
206
+ return px_ctx
136
207
  end
137
208
 
138
- @logger.debug("PerimeterX[handle_verification]: verification ended, the request should be blocked")
209
+ @logger.debug('PerimeterX[handle_verification]: verification ended, the request should be blocked')
139
210
 
140
- return false, px_ctx
211
+ return px_ctx
212
+ end
213
+
214
+ private def check_whitelist_routes(whitelist_routes, path)
215
+ whitelist_routes.each do |whitelist_route|
216
+ if whitelist_route.is_a?(Regexp) && path.match(whitelist_route)
217
+ return true
218
+ end
219
+ if whitelist_route.is_a?(String) && path.start_with?(whitelist_route)
220
+ return true
221
+ end
222
+ end
223
+ false
141
224
  end
142
225
 
143
- private_class_method :new
144
226
  end
145
227
  end