perimeter_x 1.1.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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