perimeter_x 2.1.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 +4 -4
- data/changelog.md +4 -0
- data/lib/perimeter_x.rb +52 -10
- data/lib/perimeterx/configuration.rb +5 -2
- data/lib/perimeterx/internal/first_party/px_first_party.rb +124 -0
- data/lib/perimeterx/internal/perimeter_x_context.rb +32 -25
- data/lib/perimeterx/utils/px_constants.rb +2 -2
- data/lib/perimeterx/utils/px_http_client.rb +57 -0
- data/lib/perimeterx/utils/px_template_factory.rb +2 -2
- data/lib/perimeterx/version.rb +1 -1
- data/readme.md +22 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
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/changelog.md
CHANGED
@@ -5,6 +5,10 @@ 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
|
+
|
8
12
|
## [2.1.0] - 2020-09-01
|
9
13
|
### Added
|
10
14
|
- Added option to set a different px configuration on each request
|
data/lib/perimeter_x.rb
CHANGED
@@ -12,13 +12,23 @@ require 'perimeterx/internal/clients/perimeter_x_activity_client'
|
|
12
12
|
require 'perimeterx/internal/validators/perimeter_x_s2s_validator'
|
13
13
|
require 'perimeterx/internal/validators/perimeter_x_cookie_validator'
|
14
14
|
require 'perimeterx/internal/exceptions/px_config_exception'
|
15
|
+
require 'perimeterx/internal/first_party/px_first_party'
|
15
16
|
|
16
17
|
module PxModule
|
17
18
|
# Module expose API
|
18
19
|
def px_verify_request(request_config={})
|
19
20
|
begin
|
20
21
|
px_instance = PerimeterX.new(request_config)
|
21
|
-
|
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)
|
22
32
|
px_config = px_instance.px_config
|
23
33
|
|
24
34
|
msg_title = 'PxModule[px_verify_request]'
|
@@ -46,12 +56,21 @@ module PxModule
|
|
46
56
|
end
|
47
57
|
|
48
58
|
is_mobile = px_ctx.context[:cookie_origin] == 'header' ? '1' : '0'
|
49
|
-
action = px_ctx.context[:block_action][0,1]
|
59
|
+
action = px_ctx.context[:block_action][0,1]
|
50
60
|
|
51
|
-
|
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",
|
52
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}",
|
53
|
-
|
54
|
-
|
71
|
+
host_url: "https://collector-#{px_config[:app_id]}.perimeterx.net"
|
72
|
+
}
|
73
|
+
end
|
55
74
|
|
56
75
|
html = PxTemplateFactory.get_template(px_ctx, px_config, px_template_object)
|
57
76
|
|
@@ -68,7 +87,7 @@ module PxModule
|
|
68
87
|
hash_json = {
|
69
88
|
:appId => px_config[:app_id],
|
70
89
|
:jsClientSrc => px_template_object[:js_client_src],
|
71
|
-
:firstPartyEnabled =>
|
90
|
+
:firstPartyEnabled => px_ctx.context[:first_party_enabled],
|
72
91
|
:uuid => px_ctx.context[:uuid],
|
73
92
|
:vid => px_ctx.context[:vid],
|
74
93
|
:hostUrl => "https://collector-#{px_config[:app_id]}.perimeterx.net",
|
@@ -110,6 +129,29 @@ module PxModule
|
|
110
129
|
end
|
111
130
|
end
|
112
131
|
|
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
|
153
|
+
end
|
154
|
+
|
113
155
|
def self.configure(basic_config)
|
114
156
|
PerimeterX.set_basic_config(basic_config)
|
115
157
|
end
|
@@ -119,6 +161,7 @@ module PxModule
|
|
119
161
|
class PerimeterX
|
120
162
|
|
121
163
|
attr_reader :px_config
|
164
|
+
attr_reader :first_party
|
122
165
|
attr_accessor :px_http_client
|
123
166
|
attr_accessor :px_activity_client
|
124
167
|
|
@@ -128,7 +171,7 @@ module PxModule
|
|
128
171
|
end
|
129
172
|
|
130
173
|
#Instance Methods
|
131
|
-
def verify(
|
174
|
+
def verify(req)
|
132
175
|
begin
|
133
176
|
|
134
177
|
# check module_enabled
|
@@ -137,13 +180,11 @@ module PxModule
|
|
137
180
|
@logger.warn('Module is disabled')
|
138
181
|
return nil
|
139
182
|
end
|
140
|
-
|
141
|
-
req = ActionDispatch::Request.new(env)
|
142
183
|
|
143
184
|
# filter whitelist routes
|
144
185
|
url_path = URI.parse(req.original_url).path
|
145
186
|
if url_path && !url_path.empty?
|
146
|
-
if check_whitelist_routes(px_config[:whitelist_routes], url_path)
|
187
|
+
if check_whitelist_routes(px_config[:whitelist_routes], url_path)
|
147
188
|
@logger.debug("PerimeterX[pxVerify]: whitelist route: #{url_path}")
|
148
189
|
return nil
|
149
190
|
end
|
@@ -176,6 +217,7 @@ module PxModule
|
|
176
217
|
@px_http_client = PxHttpClient.new(@px_config)
|
177
218
|
|
178
219
|
@px_activity_client = PerimeterxActivitiesClient.new(@px_config, @px_http_client)
|
220
|
+
@first_party = FirstPartyManager.new(@px_config, @px_http_client, @logger)
|
179
221
|
|
180
222
|
@px_cookie_validator = PerimeterxCookieValidator.new(@px_config)
|
181
223
|
@px_s2s_validator = PerimeterxS2SValidator.new(@px_config, @px_http_client)
|
@@ -30,7 +30,8 @@ module PxModule
|
|
30
30
|
:ip_headers => [],
|
31
31
|
:ip_header_function => nil,
|
32
32
|
:bypass_monitor_header => nil,
|
33
|
-
:risk_cookie_max_iterations => 5000
|
33
|
+
:risk_cookie_max_iterations => 5000,
|
34
|
+
:first_party_enabled => true
|
34
35
|
}
|
35
36
|
|
36
37
|
CONFIG_SCHEMA = {
|
@@ -60,7 +61,9 @@ module PxModule
|
|
60
61
|
:custom_logo => {types: [String], required: false},
|
61
62
|
:css_ref => {types: [String], required: false},
|
62
63
|
:js_ref => {types: [String], required: false},
|
63
|
-
:custom_uri => {types: [Proc], required: false}
|
64
|
+
:custom_uri => {types: [Proc], required: false},
|
65
|
+
:first_party_enabled => {types: [FalseClass, TrueClass], required: false}
|
66
|
+
|
64
67
|
}
|
65
68
|
|
66
69
|
def self.set_basic_config(basic_config)
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'perimeterx/internal/perimeter_x_context'
|
2
|
+
module PxModule
|
3
|
+
class FirstPartyManager
|
4
|
+
def initialize(px_config, px_http_client, logger)
|
5
|
+
@px_config = px_config
|
6
|
+
@app_id = px_config[:app_id]
|
7
|
+
@px_http_client = px_http_client
|
8
|
+
@logger = logger
|
9
|
+
@from = [
|
10
|
+
"/#{@app_id[2..-1]}/init.js",
|
11
|
+
"/#{@app_id[2..-1]}/captcha",
|
12
|
+
"/#{@app_id[2..-1]}/xhr"
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
def send_first_party_request(req)
|
17
|
+
uri = URI.parse(req.original_url)
|
18
|
+
url_path = uri.path
|
19
|
+
|
20
|
+
headers = extract_headers(req)
|
21
|
+
headers["x-px-first-party"] = "1"
|
22
|
+
headers["x-px-enforcer-true-ip"] = PerimeterXContext.extract_ip(req, @px_config)
|
23
|
+
|
24
|
+
if url_path.start_with?(@from[0])
|
25
|
+
return get_client(req, uri, headers)
|
26
|
+
elsif url_path.start_with?(@from[1])
|
27
|
+
return get_captcha(req, uri, headers)
|
28
|
+
elsif url_path.start_with?(@from[2])
|
29
|
+
return send_xhr(req, uri, headers)
|
30
|
+
else
|
31
|
+
return nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_client(req, uri, headers)
|
36
|
+
@logger.debug("FirstPartyManager[get_client]")
|
37
|
+
|
38
|
+
# define host
|
39
|
+
headers["host"] = PxModule::CLIENT_HOST
|
40
|
+
|
41
|
+
# define request url
|
42
|
+
url = "#{uri.scheme}://#{PxModule::CLIENT_HOST}/#{@app_id}/main.min.js"
|
43
|
+
|
44
|
+
# send request
|
45
|
+
return @px_http_client.get(url, headers)
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_captcha(req, uri, headers)
|
49
|
+
@logger.debug("FirstPartyManager[get_captcha]")
|
50
|
+
|
51
|
+
# define host
|
52
|
+
headers["host"] = PxModule::CAPTCHA_HOST
|
53
|
+
|
54
|
+
# define request url
|
55
|
+
path_and_query = uri.request_uri
|
56
|
+
uri_suffix = path_and_query.sub "/#{@app_id[2..-1]}/captcha", ""
|
57
|
+
url = "#{uri.scheme}://#{PxModule::CAPTCHA_HOST}#{uri_suffix}"
|
58
|
+
|
59
|
+
# send request
|
60
|
+
return @px_http_client.get(url, headers)
|
61
|
+
end
|
62
|
+
|
63
|
+
def send_xhr(req, uri, headers)
|
64
|
+
@logger.debug("FirstPartyManager[send_xhr]")
|
65
|
+
|
66
|
+
# handle vid cookies
|
67
|
+
if !req.cookies.nil?
|
68
|
+
if req.cookies.key?("_pxvid")
|
69
|
+
vid = PerimeterXContext.force_utf8(req.cookies["_pxvid"])
|
70
|
+
if headers.key?('cookie')
|
71
|
+
headers['cookie'] += "; pxvid=#{vid}";
|
72
|
+
else
|
73
|
+
headers['cookie'] = "pxvid=#{vid}";
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# define host
|
79
|
+
headers["host"] = "collector-#{@app_id.downcase}.perimeterx.net"
|
80
|
+
|
81
|
+
# define request url
|
82
|
+
path_and_query = uri.request_uri
|
83
|
+
path_suffix = path_and_query.sub "/#{@app_id[2..-1]}/xhr", ""
|
84
|
+
url = "#{uri.scheme}://collector-#{@app_id.downcase}.perimeterx.net#{path_suffix}"
|
85
|
+
|
86
|
+
# send request
|
87
|
+
return @px_http_client.post_xhr(url, req.body.string, headers)
|
88
|
+
end
|
89
|
+
|
90
|
+
def extract_headers(req)
|
91
|
+
headers = Hash.new
|
92
|
+
req.headers.each do |k, v|
|
93
|
+
if (k.start_with? 'HTTP_') && (!@px_config[:sensitive_headers].include? k)
|
94
|
+
header = k.to_s.gsub('HTTP_', '')
|
95
|
+
header = header.gsub('_', '-').downcase
|
96
|
+
headers[header] = PerimeterXContext.force_utf8(v)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
return headers
|
100
|
+
end
|
101
|
+
|
102
|
+
# -1 - not first party request
|
103
|
+
# 0 - /init.js
|
104
|
+
# 1 - /captcha
|
105
|
+
# 2 - /xhr
|
106
|
+
def get_first_party_request_type(req)
|
107
|
+
url_path = URI.parse(req.original_url).path
|
108
|
+
@from.each_with_index do |val,index|
|
109
|
+
if url_path.start_with?(val)
|
110
|
+
return index
|
111
|
+
end
|
112
|
+
end
|
113
|
+
return -1
|
114
|
+
end
|
115
|
+
|
116
|
+
def is_first_party_request(req)
|
117
|
+
return get_first_party_request_type(req) != -1
|
118
|
+
end
|
119
|
+
|
120
|
+
def get_response_content_type(req)
|
121
|
+
return get_first_party_request_type(req) == 2 ? :json : :js
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -6,6 +6,28 @@ module PxModule
|
|
6
6
|
|
7
7
|
attr_accessor :context
|
8
8
|
attr_accessor :px_config
|
9
|
+
|
10
|
+
# class methods
|
11
|
+
|
12
|
+
def self.extract_ip(req, px_config)
|
13
|
+
# Get IP from header/custom function
|
14
|
+
if px_config[:ip_headers].length() > 0
|
15
|
+
px_config[:ip_headers].each do |ip_header|
|
16
|
+
if req.headers[ip_header]
|
17
|
+
return PerimeterXContext.force_utf8(req.headers[ip_header])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
elsif px_config[:ip_header_function] != nil
|
21
|
+
return px_config[:ip_header_function].call(req)
|
22
|
+
end
|
23
|
+
return req.ip
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.force_utf8(str)
|
27
|
+
return str.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
|
28
|
+
end
|
29
|
+
|
30
|
+
# instance methods
|
9
31
|
|
10
32
|
def initialize(px_config, req)
|
11
33
|
@logger = px_config[:logger]
|
@@ -16,33 +38,22 @@ module PxModule
|
|
16
38
|
@context[:headers] = Hash.new
|
17
39
|
@context[:cookie_origin] = 'cookie'
|
18
40
|
@context[:made_s2s_risk_api_call] = false
|
41
|
+
@context[:first_party_enabled] = px_config[:first_party_enabled]
|
42
|
+
|
19
43
|
cookies = req.cookies
|
20
44
|
|
21
|
-
|
22
|
-
if px_config[:ip_headers].length() > 0
|
23
|
-
px_config[:ip_headers].each do |ip_header|
|
24
|
-
if req.headers[ip_header]
|
25
|
-
@context[:ip] = force_utf8(req.headers[ip_header])
|
26
|
-
end
|
27
|
-
end
|
28
|
-
elsif px_config[:ip_header_function] != nil
|
29
|
-
@context[:ip] = px_config[:ip_header_function].call(req)
|
30
|
-
end
|
31
|
-
|
32
|
-
if @context[:ip] == nil
|
33
|
-
@context[:ip] = req.ip
|
34
|
-
end
|
45
|
+
@context[:ip] = PerimeterXContext.extract_ip(req, px_config)
|
35
46
|
|
36
47
|
# Get token from header
|
37
48
|
if req.headers[PxModule::TOKEN_HEADER]
|
38
49
|
@context[:cookie_origin] = 'header'
|
39
|
-
token = force_utf8(req.headers[PxModule::TOKEN_HEADER])
|
50
|
+
token = PerimeterXContext.force_utf8(req.headers[PxModule::TOKEN_HEADER])
|
40
51
|
if token.match(PxModule::MOBILE_TOKEN_V3_REGEX)
|
41
52
|
@context[:px_cookie][:v3] = token[2..-1]
|
42
53
|
elsif token.match(PxModule::MOBILE_ERROR_REGEX)
|
43
54
|
@context[:mobile_error] = token
|
44
55
|
if req.headers[PxModule::ORIGINAL_TOKEN_HEADER]
|
45
|
-
token = force_utf8(req.headers[PxModule::ORIGINAL_TOKEN_HEADER])
|
56
|
+
token = PerimeterXContext.force_utf8(req.headers[PxModule::ORIGINAL_TOKEN_HEADER])
|
46
57
|
if token.match(PxModule::MOBILE_TOKEN_V3_REGEX)
|
47
58
|
@context[:px_cookie][:v3] = token[2..-1]
|
48
59
|
end
|
@@ -53,13 +64,13 @@ module PxModule
|
|
53
64
|
cookies.each do |k, v|
|
54
65
|
case k.to_s
|
55
66
|
when '_px3'
|
56
|
-
@context[:px_cookie][:v3] = force_utf8(v)
|
67
|
+
@context[:px_cookie][:v3] = PerimeterXContext.force_utf8(v)
|
57
68
|
when '_px'
|
58
|
-
@context[:px_cookie][:v1] = force_utf8(v)
|
69
|
+
@context[:px_cookie][:v1] = PerimeterXContext.force_utf8(v)
|
59
70
|
when '_pxvid'
|
60
71
|
if v.is_a?(String) && v.match(PxModule::VID_REGEX)
|
61
72
|
@context[:vid_source] = "vid_cookie"
|
62
|
-
@context[:vid] = force_utf8(v)
|
73
|
+
@context[:vid] = PerimeterXContext.force_utf8(v)
|
63
74
|
end
|
64
75
|
end
|
65
76
|
end #end case
|
@@ -69,10 +80,10 @@ module PxModule
|
|
69
80
|
if (k.start_with? 'HTTP_')
|
70
81
|
header = k.to_s.gsub('HTTP_', '')
|
71
82
|
header = header.gsub('_', '-').downcase
|
72
|
-
@context[:headers][header.to_sym] = force_utf8(v)
|
83
|
+
@context[:headers][header.to_sym] = PerimeterXContext.force_utf8(v)
|
73
84
|
end
|
74
85
|
end #end headers foreach
|
75
|
-
|
86
|
+
|
76
87
|
@context[:hostname]= req.server_name
|
77
88
|
@context[:user_agent] = req.user_agent ? req.user_agent : ''
|
78
89
|
@context[:uri] = px_config[:custom_uri] ? px_config[:custom_uri].call(req) : req.fullpath
|
@@ -97,10 +108,6 @@ module PxModule
|
|
97
108
|
false
|
98
109
|
end
|
99
110
|
|
100
|
-
def force_utf8(str)
|
101
|
-
return str.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
|
102
|
-
end
|
103
|
-
|
104
111
|
def set_block_action_type(action)
|
105
112
|
@context[:block_action] = case action
|
106
113
|
when 'c'
|
@@ -46,8 +46,8 @@ module PxModule
|
|
46
46
|
PROP_FIRST_PARTY_ENABLED = :firstPartyEnabled
|
47
47
|
|
48
48
|
# Hosts
|
49
|
-
CLIENT_HOST = 'client.
|
50
|
-
CAPTCHA_HOST = 'captcha.px-
|
49
|
+
CLIENT_HOST = 'client.perimeterx.net'
|
50
|
+
CAPTCHA_HOST = 'captcha.px-cdn.net'
|
51
51
|
|
52
52
|
VISIBLE = 'visible'
|
53
53
|
HIDDEN = 'hidden'
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'perimeterx/utils/px_logger'
|
2
2
|
require 'typhoeus'
|
3
3
|
require 'concurrent'
|
4
|
+
require 'net/http'
|
4
5
|
|
5
6
|
module PxModule
|
6
7
|
class PxHttpClient
|
@@ -45,5 +46,61 @@ module PxModule
|
|
45
46
|
return response
|
46
47
|
end
|
47
48
|
|
49
|
+
|
50
|
+
def post_xhr(url, body, headers)
|
51
|
+
s = Time.now
|
52
|
+
begin
|
53
|
+
@logger.debug("PxHttpClient[post]: sending xhr post request to #{url} with headers {#{headers.to_json()}}")
|
54
|
+
|
55
|
+
#set url
|
56
|
+
uri = URI(url)
|
57
|
+
req = Net::HTTP::Post.new(uri)
|
58
|
+
|
59
|
+
# set body
|
60
|
+
req.body=body
|
61
|
+
|
62
|
+
# set headers
|
63
|
+
headers.each do |key, value|
|
64
|
+
req[key] = value
|
65
|
+
end
|
66
|
+
|
67
|
+
# send request
|
68
|
+
response = Net::HTTP.start(uri.hostname, uri.port) {|http|
|
69
|
+
http.request(req)
|
70
|
+
}
|
71
|
+
|
72
|
+
ensure
|
73
|
+
e = Time.now
|
74
|
+
@logger.debug("PxHttpClient[get]: runtime: #{(e-s) * 1000.0}")
|
75
|
+
end
|
76
|
+
return response
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def get(url, headers)
|
81
|
+
s = Time.now
|
82
|
+
begin
|
83
|
+
@logger.debug("PxHttpClient[get]: sending get request to #{url} with headers {#{headers.to_json()}}")
|
84
|
+
|
85
|
+
#set url
|
86
|
+
uri = URI(url)
|
87
|
+
req = Net::HTTP::Get.new(uri)
|
88
|
+
|
89
|
+
# set headers
|
90
|
+
headers.each do |key, value|
|
91
|
+
req[key] = value
|
92
|
+
end
|
93
|
+
|
94
|
+
# send request
|
95
|
+
response = Net::HTTP.start(uri.hostname, uri.port) {|http|
|
96
|
+
http.request(req)
|
97
|
+
}
|
98
|
+
|
99
|
+
ensure
|
100
|
+
e = Time.now
|
101
|
+
@logger.debug("PxHttpClient[get]: runtime: #{(e-s) * 1000.0}")
|
102
|
+
end
|
103
|
+
return response
|
104
|
+
end
|
48
105
|
end
|
49
106
|
end
|
@@ -29,11 +29,11 @@ module PxModule
|
|
29
29
|
view[PxModule::PROP_CUSTOM_LOGO] = px_config[:custom_logo]
|
30
30
|
view[PxModule::PROP_CSS_REF] = px_config[:css_ref]
|
31
31
|
view[PxModule::PROP_JS_REF] = px_config[:js_ref]
|
32
|
-
view[PxModule::PROP_HOST_URL] =
|
32
|
+
view[PxModule::PROP_HOST_URL] = px_template_object[:host_url]
|
33
33
|
view[PxModule::PROP_LOGO_VISIBILITY] = px_config[:custom_logo] ? PxModule::VISIBLE : PxModule::HIDDEN
|
34
34
|
view[PxModule::PROP_BLOCK_SCRIPT] = px_template_object[:block_script]
|
35
35
|
view[PxModule::PROP_JS_CLIENT_SRC] = px_template_object[:js_client_src]
|
36
|
-
view[PxModule::PROP_FIRST_PARTY_ENABLED] =
|
36
|
+
view[PxModule::PROP_FIRST_PARTY_ENABLED] = px_ctx.context[:first_party_enabled]
|
37
37
|
|
38
38
|
return view.render.html_safe
|
39
39
|
end
|
data/lib/perimeterx/version.rb
CHANGED
data/readme.md
CHANGED
@@ -31,6 +31,7 @@ Table of Contents
|
|
31
31
|
* [Debug Mode](#debug-mode)
|
32
32
|
* [Whitelist Routes](#whitelist-routes)
|
33
33
|
* [Update Configuration on Runtime](#update-config)
|
34
|
+
* [First Party](#first-party)
|
34
35
|
|
35
36
|
**[Contributing](#contributing)**
|
36
37
|
|
@@ -347,6 +348,27 @@ class HomeController < ApplicationController
|
|
347
348
|
end
|
348
349
|
```
|
349
350
|
|
351
|
+
<a name="first-party"></a>**First Party**
|
352
|
+
To enable first party on your enforcer, add the following routes to your `config/routes.rb` file:
|
353
|
+
|
354
|
+
```ruby
|
355
|
+
get '/:appid_postfix/init.js', to: 'home#index', constraints: { appid_postfix: /XXXXXXXX/ }
|
356
|
+
get '/:appid_postfix/captcha/:all', to: 'home#index', constraints: { appid_postfix: /XXXXXXXX/, all:/.*/ }
|
357
|
+
post '/:appid_postfix/xhr/:all', to: 'home#index', constraints: { appid_postfix: /XXXXXXXX/, all:/.*/ }
|
358
|
+
```
|
359
|
+
|
360
|
+
Notice that all occurences of `XXXXXXXX` should be replaced with your px_app_id without the "PX" prefix. For example, if your px_app_id is `PX2H4seK9L`, reeplace `XXXXXXXX` with `2H4seK9L`.
|
361
|
+
In case you are using more than one px_app_id, provide all of them with a `|` sign between them. For example: 2H4seK9L|9bMs6K94|Lc5kPMNx
|
362
|
+
|
363
|
+
|
364
|
+
First Party configuration:
|
365
|
+
Default: true
|
366
|
+
|
367
|
+
```ruby
|
368
|
+
params[:first_party_enabled] = false
|
369
|
+
```
|
370
|
+
|
371
|
+
|
350
372
|
<a name="contributing"></a># Contributing #
|
351
373
|
------------------------------
|
352
374
|
The following steps are welcome when contributing to our project.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perimeter_x
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nitzan Goldfeder
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -173,6 +173,7 @@ files:
|
|
173
173
|
- lib/perimeterx/internal/clients/perimeter_x_risk_client.rb
|
174
174
|
- lib/perimeterx/internal/exceptions/px_config_exception.rb
|
175
175
|
- lib/perimeterx/internal/exceptions/px_cookie_decryption_exception.rb
|
176
|
+
- lib/perimeterx/internal/first_party/px_first_party.rb
|
176
177
|
- lib/perimeterx/internal/payload/perimeter_x_cookie_v1.rb
|
177
178
|
- lib/perimeterx/internal/payload/perimeter_x_cookie_v3.rb
|
178
179
|
- lib/perimeterx/internal/payload/perimeter_x_payload.rb
|