perimeter_x 1.2.0 → 2.2.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.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +3 -0
- data/Dockerfile +12 -7
- data/Gemfile.lock +36 -30
- data/Rakefile +1 -0
- data/changelog.md +58 -0
- data/examples/app/controllers/home_controller.rb +1 -1
- data/lib/perimeter_x.rb +195 -71
- data/lib/perimeterx/configuration.rb +74 -22
- data/lib/perimeterx/internal/clients/perimeter_x_activity_client.rb +32 -6
- data/lib/perimeterx/internal/exceptions/px_config_exception.rb +6 -0
- data/lib/perimeterx/internal/first_party/px_first_party.rb +124 -0
- data/lib/perimeterx/internal/{perimeter_x_cookie_v1.rb → payload/perimeter_x_cookie_v1.rb} +1 -1
- data/lib/perimeterx/internal/{perimeter_x_cookie_v3.rb → payload/perimeter_x_cookie_v3.rb} +1 -1
- data/lib/perimeterx/internal/{perimeter_x_cookie.rb → payload/perimeter_x_payload.rb} +12 -4
- data/lib/perimeterx/internal/payload/perimeter_x_token_v1.rb +38 -0
- data/lib/perimeterx/internal/payload/perimeter_x_token_v3.rb +36 -0
- data/lib/perimeterx/internal/perimeter_x_context.rb +74 -32
- data/lib/perimeterx/internal/validators/hash_schema_validator.rb +26 -0
- data/lib/perimeterx/internal/validators/perimeter_x_cookie_validator.rb +29 -21
- data/lib/perimeterx/internal/validators/perimeter_x_s2s_validator.rb +33 -9
- data/lib/perimeterx/utils/px_constants.rb +35 -17
- data/lib/perimeterx/utils/px_http_client.rb +60 -3
- data/lib/perimeterx/utils/px_template_factory.rb +18 -8
- data/lib/perimeterx/utils/templates/block_template.mustache +175 -0
- data/lib/perimeterx/utils/templates/ratelimit.mustache +9 -0
- data/lib/perimeterx/version.rb +1 -1
- data/perimeter_x.gemspec +3 -3
- data/readme.md +115 -31
- metadata +24 -20
- data/lib/perimeterx/internal/validators/perimeter_x_captcha_validator.rb +0 -65
- data/lib/perimeterx/utils/templates/block.mustache +0 -146
- data/lib/perimeterx/utils/templates/captcha.mustache +0 -185
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 475e2577bfe9b12bb7edbe3286fb4f1861a9c508791f38b0196dea0f493f355e
|
4
|
+
data.tar.gz: b0c61698741743a62ad0a7c9fb67dc6d5ed9f9b78c01d08b764cb1297ee37c98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bae8b3e45c8ee8aba86a56ed977158adec12bccfa2542e1a4e54344b6b6fb0503182585816c1b55640bd49ea4d6323831e93ad6c8d3335703e33d695df362ba
|
7
|
+
data.tar.gz: d7a64faa2f03fd4bc467cdea545a2f530001431f37281c2a9561dd83c28c00006fe827e8cd510560fbbbd1a69d382993ae513edd214a18a277bcca57dd561fdc
|
data/.travis.yml
ADDED
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.
|
2
|
+
FROM ruby:2.7.1
|
3
3
|
|
4
|
-
RUN
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
23
|
+
RUN sed -i '2i gem "perimeter_x", :path => "/tmp/ruby_sandbox"' /tmp/ruby_sandbox/webapp/Gemfile
|
19
24
|
RUN bundler update
|
20
|
-
COPY ./
|
25
|
+
COPY ./dev/site/ /tmp/ruby_sandbox/webapp
|
21
26
|
CMD ["rails","server","-b","0.0.0.0"]
|
data/Gemfile.lock
CHANGED
@@ -1,55 +1,61 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
perimeter_x (
|
5
|
-
activesupport (>=
|
6
|
-
|
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 (
|
13
|
+
activesupport (6.0.3.2)
|
13
14
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
14
|
-
i18n (
|
15
|
+
i18n (>= 0.7, < 2)
|
15
16
|
minitest (~> 5.1)
|
16
17
|
tzinfo (~> 1.1)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
rspec-
|
31
|
-
|
32
|
-
rspec-
|
33
|
-
rspec-
|
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.
|
36
|
-
rspec-mocks (3.
|
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.
|
39
|
-
rspec-support (3.
|
41
|
+
rspec-support (~> 3.9.0)
|
42
|
+
rspec-support (3.9.3)
|
40
43
|
thread_safe (0.3.6)
|
41
|
-
|
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 (
|
54
|
+
bundler (>= 2.1)
|
49
55
|
mocha (~> 1.2, >= 1.2.1)
|
50
56
|
perimeter_x!
|
51
|
-
rake (
|
57
|
+
rake (>= 12.3)
|
52
58
|
rspec (~> 3.0)
|
53
59
|
|
54
60
|
BUNDLED WITH
|
55
|
-
1.
|
61
|
+
2.1.4
|
data/Rakefile
CHANGED
data/changelog.md
CHANGED
@@ -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
|
+
|
data/lib/perimeter_x.rb
CHANGED
@@ -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/
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
|
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(
|
40
|
-
|
155
|
+
def self.configure(basic_config)
|
156
|
+
PerimeterX.set_basic_config(basic_config)
|
41
157
|
end
|
42
158
|
|
43
159
|
|
44
|
-
#
|
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.
|
55
|
-
|
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(
|
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
|
-
#
|
81
|
-
|
82
|
-
if
|
83
|
-
|
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
|
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
|
-
|
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 {
|
100
|
-
return
|
208
|
+
e.backtrace.drop(1).map {|s| @logger.error("\t#{s}")}
|
209
|
+
return nil
|
101
210
|
end
|
102
211
|
end
|
103
212
|
|
104
|
-
|
105
|
-
|
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
|
-
@
|
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(
|
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
|
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
|
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
|
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
|
248
|
+
return px_ctx
|
136
249
|
end
|
137
250
|
|
138
|
-
@logger.debug(
|
251
|
+
@logger.debug('PerimeterX[handle_verification]: verification ended, the request should be blocked')
|
252
|
+
|
253
|
+
return px_ctx
|
254
|
+
end
|
139
255
|
|
140
|
-
|
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
|