perimeter_x 1.0.6.pre.alpha → 2.0.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 +6 -3
- data/.travis.yml +3 -0
- data/Dockerfile +19 -41
- data/Gemfile +1 -1
- data/Gemfile.lock +51 -3
- data/LICENSE.txt +9 -12
- data/Rakefile +10 -2
- data/changelog.md +72 -0
- data/examples/app/controllers/home_controller.rb +9 -0
- data/examples/app/views/home/index.html.erb.dist +20 -0
- data/examples/config/initializers/perimeterx.rb.dist +8 -0
- data/examples/{routes.rb → config/routes.rb} +0 -0
- data/lib/perimeter_x.rb +192 -37
- data/lib/perimeterx/configuration.rb +30 -18
- data/lib/perimeterx/internal/clients/perimeter_x_activity_client.rb +110 -0
- data/lib/perimeterx/internal/clients/perimeter_x_risk_client.rb +28 -0
- data/lib/perimeterx/internal/exceptions/px_cookie_decryption_exception.rb +5 -0
- data/lib/perimeterx/internal/payload/perimeter_x_cookie_v1.rb +42 -0
- data/lib/perimeterx/internal/payload/perimeter_x_cookie_v3.rb +37 -0
- data/lib/perimeterx/internal/payload/perimeter_x_payload.rb +148 -0
- 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 +112 -53
- data/lib/perimeterx/internal/validators/perimeter_x_cookie_validator.rb +103 -0
- data/lib/perimeterx/internal/validators/perimeter_x_s2s_validator.rb +128 -0
- data/lib/perimeterx/utils/px_constants.rb +62 -0
- data/lib/perimeterx/utils/px_http_client.rb +43 -28
- data/lib/perimeterx/utils/px_logger.rb +12 -6
- data/lib/perimeterx/utils/px_template_factory.rb +41 -0
- data/lib/perimeterx/utils/templates/block_template.mustache +175 -0
- data/lib/perimeterx/utils/templates/ratelimit.mustache +9 -0
- data/lib/perimeterx/version.rb +2 -2
- data/perimeter_x.gemspec +10 -4
- data/readme.md +258 -42
- metadata +130 -24
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/examples/home_controller.rb.dist +0 -23
- data/lib/perimeterx/internal/perimeter_x_risk_client.rb +0 -29
- data/lib/perimeterx/internal/perimeter_x_s2s_validator.rb +0 -67
@@ -0,0 +1,36 @@
|
|
1
|
+
module PxModule
|
2
|
+
class PerimeterxTokenV3 < PerimeterxPayload
|
3
|
+
|
4
|
+
attr_accessor :px_config, :px_ctx, :cookie_hash
|
5
|
+
|
6
|
+
def initialize(px_config, px_ctx)
|
7
|
+
super(px_config)
|
8
|
+
hash, cookie = px_ctx.get_px_cookie().split(':', 2)
|
9
|
+
@px_cookie = cookie
|
10
|
+
@cookie_hash = hash
|
11
|
+
@px_ctx = px_ctx
|
12
|
+
@cookie_secret = px_config[:cookie_key]
|
13
|
+
@logger.debug('PerimeterxTokenV3[initialize]')
|
14
|
+
end
|
15
|
+
|
16
|
+
def cookie_score
|
17
|
+
return @decoded_cookie[:s]
|
18
|
+
end
|
19
|
+
|
20
|
+
def cookie_hmac
|
21
|
+
return @cookie_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid_format?(cookie)
|
25
|
+
return cookie.key?(:t) && cookie.key?(:s) && cookie.key?(:u) && cookie.key?(:u) && cookie.key?(:a)
|
26
|
+
end
|
27
|
+
|
28
|
+
def cookie_block_action
|
29
|
+
@decoded_cookie[:a]
|
30
|
+
end
|
31
|
+
|
32
|
+
def secured?
|
33
|
+
return hmac_valid?(@px_cookie, cookie_hmac)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,62 +1,121 @@
|
|
1
1
|
require 'perimeterx/utils/px_logger'
|
2
|
+
require 'perimeterx/utils/px_constants'
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
cookies
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
4
|
+
module PxModule
|
5
|
+
class PerimeterXContext
|
6
|
+
|
7
|
+
attr_accessor :context
|
8
|
+
attr_accessor :px_config
|
9
|
+
|
10
|
+
def initialize(px_config, req)
|
11
|
+
@logger = px_config[:logger]
|
12
|
+
@logger.debug('PerimeterXContext[initialize]')
|
13
|
+
@context = Hash.new
|
14
|
+
|
15
|
+
@context[:px_cookie] = Hash.new
|
16
|
+
@context[:headers] = Hash.new
|
17
|
+
@context[:cookie_origin] = 'cookie'
|
18
|
+
@context[:made_s2s_risk_api_call] = false
|
19
|
+
cookies = req.cookies
|
20
|
+
|
21
|
+
# Get IP from header/custom function
|
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
|
26
27
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
req.headers.each do |k, v|
|
31
|
-
if (k.start_with? "HTTP_")
|
32
|
-
header = k.to_s.gsub("HTTP_", "")
|
33
|
-
header = header.gsub("_", "-").downcase
|
34
|
-
@context[:headers][header.to_sym] = v
|
28
|
+
elsif px_config[:ip_header_function] != nil
|
29
|
+
@context[:ip] = px_config[:ip_header_function].call(req)
|
35
30
|
end
|
36
|
-
end #end headers foreach
|
37
|
-
|
38
|
-
@context[:hostname]= req.headers['HTTP_HOST']
|
39
|
-
@context[:user_agent] = req.headers['HTTP_USER_AGENT'] ? req.headers['HTTP_USER_AGENT'] : ''
|
40
|
-
@context[:full_url] = req.original_url
|
41
|
-
@context[:score] = 0
|
42
|
-
|
43
|
-
if px_config.key?('custom_user_ip')
|
44
|
-
@context[:ip] = px_config['custom_user_ip']
|
45
|
-
elsif px_config.key?('px_custom_user_ip_method')
|
46
|
-
puts "px_custom_user_ip_method triggered"
|
47
|
-
@context[:ip] = px_config['px_custom_user_ip_method'].call(req)
|
48
|
-
else
|
49
|
-
@context[:ip] = req.headers['REMOTE_ADDR'];
|
50
|
-
end
|
51
31
|
|
52
|
-
|
53
|
-
|
54
|
-
if httpVer.size > 0
|
55
|
-
@context[:http_version] = httpVer[1];
|
32
|
+
if @context[:ip] == nil
|
33
|
+
@context[:ip] = req.ip
|
56
34
|
end
|
35
|
+
|
36
|
+
# Get token from header
|
37
|
+
if req.headers[PxModule::TOKEN_HEADER]
|
38
|
+
@context[:cookie_origin] = 'header'
|
39
|
+
token = force_utf8(req.headers[PxModule::TOKEN_HEADER])
|
40
|
+
if token.include? ':'
|
41
|
+
exploded_token = token.split(':', 2)
|
42
|
+
cookie_sym = "v#{exploded_token[0]}".to_sym
|
43
|
+
@context[:px_cookie][cookie_sym] = exploded_token[1]
|
44
|
+
else # TOKEN_HEADER exists yet there's no ':' delimiter - may indicate an error (storing original value)
|
45
|
+
@context[:px_cookie] = force_utf8(req.headers[PxModule::TOKEN_HEADER])
|
46
|
+
end
|
47
|
+
elsif !cookies.empty? # Get cookie from jar
|
48
|
+
# Prepare hashed cookies
|
49
|
+
cookies.each do |k, v|
|
50
|
+
case k.to_s
|
51
|
+
when '_px3'
|
52
|
+
@context[:px_cookie][:v3] = force_utf8(v)
|
53
|
+
when '_px'
|
54
|
+
@context[:px_cookie][:v1] = force_utf8(v)
|
55
|
+
when '_pxvid'
|
56
|
+
if v.is_a?(String) && v.match(PxModule::VID_REGEX)
|
57
|
+
@context[:vid_source] = "vid_cookie"
|
58
|
+
@context[:vid] = force_utf8(v)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end #end case
|
62
|
+
end #end empty cookies
|
63
|
+
|
64
|
+
req.headers.each do |k, v|
|
65
|
+
if (k.start_with? 'HTTP_')
|
66
|
+
header = k.to_s.gsub('HTTP_', '')
|
67
|
+
header = header.gsub('_', '-').downcase
|
68
|
+
@context[:headers][header.to_sym] = force_utf8(v)
|
69
|
+
end
|
70
|
+
end #end headers foreach
|
71
|
+
|
72
|
+
@context[:hostname]= req.server_name
|
73
|
+
@context[:user_agent] = req.user_agent ? req.user_agent : ''
|
74
|
+
@context[:uri] = px_config[:custom_uri] ? px_config[:custom_uri].call(req) : req.fullpath
|
75
|
+
@context[:full_url] = req.original_url
|
76
|
+
@context[:format] = req.format.symbol
|
77
|
+
@context[:score] = 0
|
78
|
+
|
79
|
+
if req.server_protocol
|
80
|
+
httpVer = req.server_protocol.split('/')
|
81
|
+
if httpVer.size > 0
|
82
|
+
@context[:http_version] = httpVer[1]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
@context[:http_method] = req.method
|
86
|
+
@context[:sensitive_route] = check_sensitive_route(px_config[:sensitive_routes], @context[:uri])
|
87
|
+
end #end init
|
88
|
+
|
89
|
+
def check_sensitive_route(sensitive_routes, uri)
|
90
|
+
sensitive_routes.each do |sensitive_route|
|
91
|
+
return true if uri.start_with? sensitive_route
|
92
|
+
end
|
93
|
+
false
|
94
|
+
end
|
95
|
+
|
96
|
+
def force_utf8(str)
|
97
|
+
return str.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
|
98
|
+
end
|
99
|
+
|
100
|
+
def set_block_action_type(action)
|
101
|
+
@context[:block_action] = case action
|
102
|
+
when 'c'
|
103
|
+
'captcha'
|
104
|
+
when 'b'
|
105
|
+
return 'block'
|
106
|
+
when 'j'
|
107
|
+
return 'challenge'
|
108
|
+
when 'r'
|
109
|
+
return 'rate_limit'
|
110
|
+
else
|
111
|
+
return captcha
|
112
|
+
end
|
57
113
|
end
|
58
|
-
@context[:http_method] = req.headers['REQUEST_METHOD'];
|
59
114
|
|
60
|
-
|
115
|
+
def get_px_cookie
|
116
|
+
cookie = @context[:px_cookie].key?(:v3) ? @context[:px_cookie][:v3] : @context[:px_cookie][:v1]
|
117
|
+
return cookie.tr(' ','+') if !cookie.nil?
|
118
|
+
end
|
61
119
|
|
62
|
-
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'perimeterx/utils/px_constants'
|
2
|
+
require 'perimeterx/internal/payload/perimeter_x_payload'
|
3
|
+
require 'perimeterx/internal/payload/perimeter_x_token_v1'
|
4
|
+
require 'perimeterx/internal/payload/perimeter_x_token_v3'
|
5
|
+
require 'perimeterx/internal/payload/perimeter_x_cookie_v1'
|
6
|
+
require 'perimeterx/internal/payload/perimeter_x_cookie_v3'
|
7
|
+
|
8
|
+
module PxModule
|
9
|
+
class PerimeterxCookieValidator
|
10
|
+
|
11
|
+
attr_accessor :px_config
|
12
|
+
|
13
|
+
def initialize(px_config)
|
14
|
+
@px_config = px_config
|
15
|
+
@logger = px_config[:logger]
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def verify(px_ctx)
|
20
|
+
begin
|
21
|
+
# Mobile Error cases
|
22
|
+
if px_ctx.context[:cookie_origin] == 'header'
|
23
|
+
if px_ctx.context[:px_cookie].to_s.empty?
|
24
|
+
@logger.warn("PerimeterxCookieValidator:[verify]: Empty token value - decryption failed")
|
25
|
+
px_ctx.context[:s2s_call_reason] = PxModule::COOKIE_DECRYPTION_FAILED
|
26
|
+
return false, px_ctx
|
27
|
+
elsif px_ctx.context[:px_cookie] == "1"
|
28
|
+
@logger.warn("PerimeterxCookieValidator:[verify]: no cookie")
|
29
|
+
px_ctx.context[:s2s_call_reason] = PxModule::NO_COOKIE
|
30
|
+
return false, px_ctx
|
31
|
+
elsif px_ctx.context[:px_cookie] == "2" # Mobile SDK connection error
|
32
|
+
@logger.warn("PerimeterxCookieValidator:[verify]: mobile sdk connection error")
|
33
|
+
px_ctx.context[:s2s_call_reason] = PxModule::MOBILE_SDK_CONNECTION_ERROR
|
34
|
+
return false, px_ctx
|
35
|
+
elsif px_ctx.context[:px_cookie] == "3" # Mobile SDK pinning error
|
36
|
+
@logger.warn("PerimeterxCookieValidator:[verify]: mobile sdk pinning error")
|
37
|
+
px_ctx.context[:s2s_call_reason] = PxModule::MOBILE_SDK_PINNING_ERROR
|
38
|
+
return false, px_ctx
|
39
|
+
end
|
40
|
+
elsif px_ctx.context[:px_cookie].empty?
|
41
|
+
@logger.warn("PerimeterxCookieValidator:[verify]: no cookie")
|
42
|
+
px_ctx.context[:s2s_call_reason] = PxModule::NO_COOKIE
|
43
|
+
return false, px_ctx
|
44
|
+
end
|
45
|
+
|
46
|
+
# Deserialize cookie start
|
47
|
+
cookie = PerimeterxPayload.px_cookie_factory(px_ctx, @px_config)
|
48
|
+
if !cookie.deserialize()
|
49
|
+
@logger.warn("PerimeterxCookieValidator:[verify]: invalid cookie")
|
50
|
+
px_ctx.context[:px_orig_cookie] = px_ctx.get_px_cookie
|
51
|
+
px_ctx.context[:s2s_call_reason] = PxModule::COOKIE_DECRYPTION_FAILED
|
52
|
+
return false, px_ctx
|
53
|
+
end
|
54
|
+
px_ctx.context[:decoded_cookie] = cookie.decoded_cookie
|
55
|
+
px_ctx.context[:score] = cookie.cookie_score()
|
56
|
+
px_ctx.context[:uuid] = cookie.decoded_cookie[:u]
|
57
|
+
px_ctx.context[:block_action] = px_ctx.set_block_action_type(cookie.cookie_block_action())
|
58
|
+
px_ctx.context[:cookie_hmac] = cookie.cookie_hmac()
|
59
|
+
|
60
|
+
vid = cookie.decoded_cookie[:v]
|
61
|
+
if vid.is_a?(String) && vid.match(PxModule::VID_REGEX)
|
62
|
+
px_ctx.context[:vid_source] = "risk_cookie"
|
63
|
+
px_ctx.context[:vid] = vid
|
64
|
+
end
|
65
|
+
|
66
|
+
if cookie.expired?
|
67
|
+
@logger.warn("PerimeterxCookieValidator:[verify]: cookie expired")
|
68
|
+
px_ctx.context[:s2s_call_reason] = PxModule::EXPIRED_COOKIE
|
69
|
+
return false, px_ctx
|
70
|
+
end
|
71
|
+
|
72
|
+
if cookie.high_score?
|
73
|
+
@logger.warn("PerimeterxCookieValidator:[verify]: cookie high score")
|
74
|
+
px_ctx.context[:blocking_reason] = 'cookie_high_score'
|
75
|
+
return true, px_ctx
|
76
|
+
end
|
77
|
+
|
78
|
+
if !cookie.secured?
|
79
|
+
@logger.warn("PerimeterxCookieValidator:[verify]: cookie invalid hmac")
|
80
|
+
px_ctx.context[:s2s_call_reason] = PxModule:: COOKIE_VALIDATION_FAILED
|
81
|
+
return false, px_ctx
|
82
|
+
end
|
83
|
+
|
84
|
+
if px_ctx.context[:sensitive_route]
|
85
|
+
@logger.info("PerimeterxCookieValidator:[verify]: cookie was verified but route is sensitive")
|
86
|
+
px_ctx.context[:s2s_call_reason] = PxModule::SENSITIVE_ROUTE
|
87
|
+
return false, px_ctx
|
88
|
+
end
|
89
|
+
|
90
|
+
@logger.debug("PerimeterxCookieValidator:[verify]: cookie validation passed succesfully")
|
91
|
+
|
92
|
+
px_ctx.context[:pass_reason] = 'cookie'
|
93
|
+
return true, px_ctx
|
94
|
+
rescue Exception => e
|
95
|
+
@logger.error("PerimeterxCookieValidator:[verify]: exception while verifying cookie => #{e.message}")
|
96
|
+
px_ctx.context[:px_orig_cookie] = px_ctx.context[:px_cookie]
|
97
|
+
px_ctx.context[:s2s_call_reason] = PxModule::COOKIE_DECRYPTION_FAILED
|
98
|
+
return false, px_ctx
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'perimeterx/internal/clients/perimeter_x_risk_client'
|
2
|
+
|
3
|
+
module PxModule
|
4
|
+
class PerimeterxS2SValidator < PerimeterxRiskClient
|
5
|
+
|
6
|
+
def initialize(px_config, http_client)
|
7
|
+
super(px_config, http_client)
|
8
|
+
@logger.debug('PerimeterxS2SValidator[initialize]')
|
9
|
+
end
|
10
|
+
|
11
|
+
def send_risk_request(px_ctx)
|
12
|
+
@logger.debug('PerimeterxS2SValidator[send_risk_request]: send_risk_request')
|
13
|
+
|
14
|
+
risk_mode = PxModule::RISK_MODE_ACTIVE
|
15
|
+
if @px_config[:module_mode] == PxModule::MONITOR_MODE
|
16
|
+
risk_mode = PxModule::RISK_MODE_MONITOR
|
17
|
+
end
|
18
|
+
|
19
|
+
request_body = {
|
20
|
+
:request => {
|
21
|
+
:ip => px_ctx.context[:ip],
|
22
|
+
:headers => format_headers(px_ctx),
|
23
|
+
:uri => px_ctx.context[:uri],
|
24
|
+
:url => px_ctx.context[:full_url]
|
25
|
+
},
|
26
|
+
:additional => {
|
27
|
+
:s2s_call_reason => px_ctx.context[:s2s_call_reason],
|
28
|
+
:module_version => @px_config[:sdk_name],
|
29
|
+
:cookie_origin => px_ctx.context[:cookie_origin],
|
30
|
+
:http_method => px_ctx.context[:http_method],
|
31
|
+
:http_version => px_ctx.context[:http_version],
|
32
|
+
:risk_mode => risk_mode
|
33
|
+
}
|
34
|
+
}
|
35
|
+
#Check for hmac
|
36
|
+
@logger.debug("px_ctx cookie_hmac key = #{px_ctx.context.key?(:cookie_hmac)}, value is: #{px_ctx.context[:cookie_hmac]}")
|
37
|
+
if px_ctx.context.key?(:cookie_hmac)
|
38
|
+
request_body[:additional][:px_cookie_hmac] = px_ctx.context[:cookie_hmac]
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
#Check for VID
|
43
|
+
if px_ctx.context.key?(:vid)
|
44
|
+
request_body[:vid] = px_ctx.context[:vid]
|
45
|
+
end
|
46
|
+
|
47
|
+
#Check for uuid
|
48
|
+
if px_ctx.context.key?(:uuid)
|
49
|
+
request_body[:uuid] = px_ctx.context[:uuid]
|
50
|
+
end
|
51
|
+
|
52
|
+
#S2S Call reason
|
53
|
+
decode_cookie_reasons = [PxModule::EXPIRED_COOKIE, PxModule::COOKIE_VALIDATION_FAILED]
|
54
|
+
if ( px_ctx.context[:s2s_call_reason] == PxModule::COOKIE_DECRYPTION_FAILED )
|
55
|
+
@logger.debug("PerimeterxS2SValidator[send_risk_request]: attaching px_orig_cookie to request")
|
56
|
+
request_body[:additional][:px_orig_cookie] = px_ctx.context[:px_orig_cookie]
|
57
|
+
elsif decode_cookie_reasons.include? (px_ctx.context[:s2s_call_reason])
|
58
|
+
if (px_ctx.context.key?(:decoded_cookie))
|
59
|
+
request_body[:additional][:px_cookie] = px_ctx.context[:decoded_cookie]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Prepare request
|
64
|
+
headers = {
|
65
|
+
"Authorization" => "Bearer #{@px_config[:auth_token]}" ,
|
66
|
+
"Content-Type" => "application/json"
|
67
|
+
};
|
68
|
+
|
69
|
+
# Custom risk handler
|
70
|
+
risk_start = Time.now
|
71
|
+
if (risk_mode == PxModule::ACTIVE_MODE && @px_config.key?(:custom_risk_handler))
|
72
|
+
response = @px_config[:custom_risk_handler].call(PxModule::API_V3_RISK, request_body, headers, @px_config[:api_timeout], @px_config[:api_timeout_connection])
|
73
|
+
else
|
74
|
+
response = @http_client.post(PxModule::API_V3_RISK , request_body, headers, @px_config[:api_timeout], @px_config[:api_timeout_connection])
|
75
|
+
end
|
76
|
+
|
77
|
+
# Set risk_rtt
|
78
|
+
if(response)
|
79
|
+
risk_end = Time.now
|
80
|
+
px_ctx.context[:risk_rtt] = ((risk_end-risk_start)*1000).round
|
81
|
+
end
|
82
|
+
|
83
|
+
return response
|
84
|
+
end
|
85
|
+
|
86
|
+
def verify(px_ctx)
|
87
|
+
@logger.debug("PerimeterxS2SValidator[verify]")
|
88
|
+
response = send_risk_request(px_ctx)
|
89
|
+
if (!response)
|
90
|
+
px_ctx.context[:pass_reason] = "s2s_timeout"
|
91
|
+
return px_ctx
|
92
|
+
end
|
93
|
+
px_ctx.context[:made_s2s_risk_api_call] = true
|
94
|
+
|
95
|
+
# From here response should be valid, if success or error
|
96
|
+
response_body = eval(response.body);
|
97
|
+
# When success
|
98
|
+
if (response.code == 200 && response_body.key?(:score) && response_body.key?(:action) && response_body.key?(:status) && response_body[:status] == 0 )
|
99
|
+
@logger.debug("PerimeterxS2SValidator[verify]: response ok")
|
100
|
+
score = response_body[:score]
|
101
|
+
px_ctx.context[:score] = score
|
102
|
+
px_ctx.context[:uuid] = response_body[:uuid]
|
103
|
+
px_ctx.context[:block_action] = px_ctx.set_block_action_type(response_body[:action])
|
104
|
+
if (response_body[:action] == 'j' && response_body.key?(:action_data) && response_body[:action_data].key?(:body))
|
105
|
+
px_ctx.context[:block_action_data] = response_body[:action_data][:body]
|
106
|
+
px_ctx.context[:blocking_reason] = 'challenge'
|
107
|
+
elsif (score >= @px_config[:blocking_score])
|
108
|
+
px_ctx.context[:blocking_reason] = 's2s_high_score'
|
109
|
+
else
|
110
|
+
px_ctx.context[:pass_reason] = 's2s'
|
111
|
+
end #end challange or blocking score
|
112
|
+
end #end success response
|
113
|
+
|
114
|
+
# When error
|
115
|
+
risk_error_status = response_body && response_body.key?(:status) && response_body[:status] == -1
|
116
|
+
if(response.code != 200 || risk_error_status)
|
117
|
+
@logger.warn("PerimeterxS2SValidator[verify]: bad response, returned code #{response.code} #{risk_error_status ? "risk status: -1" : ""}")
|
118
|
+
px_ctx.context[:pass_reason] = 'request_failed'
|
119
|
+
px_ctx.context[:uuid] = (!response_body || response_body[:uuid].nil?)? "" : response_body[:uuid]
|
120
|
+
px_ctx.context[:s2s_error_msg] = !response_body || response_body[:message].nil? ? 'unknown' : response_body[:message]
|
121
|
+
end
|
122
|
+
|
123
|
+
@logger.debug("PerimeterxS2SValidator[verify]: done")
|
124
|
+
return px_ctx
|
125
|
+
end #end method
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'perimeterx/version'
|
2
|
+
|
3
|
+
module PxModule
|
4
|
+
# Misc
|
5
|
+
MONITOR_MODE = 1
|
6
|
+
ACTIVE_MODE = 2
|
7
|
+
RISK_MODE_ACTIVE = 'active_blocking'
|
8
|
+
RISK_MODE_MONITOR = 'monitor'
|
9
|
+
SDK_NAME = "RUBY SDK v#{PxModule::VERSION}"
|
10
|
+
|
11
|
+
# Routes
|
12
|
+
API_V1_S2S = '/api/v1/collector/s2s'
|
13
|
+
API_V3_RISK = '/api/v3/risk'
|
14
|
+
|
15
|
+
# Activity Types
|
16
|
+
BLOCK_ACTIVITY = 'block'
|
17
|
+
PAGE_REQUESTED_ACTIVITY = 'page_requested'
|
18
|
+
|
19
|
+
# PxContext
|
20
|
+
NO_COOKIE = 'no_cookie'
|
21
|
+
INVALID_COOKIE = 'invalid_cookie'
|
22
|
+
EXPIRED_COOKIE = 'cookie_expired'
|
23
|
+
COOKIE_HIGH_SCORE = 'cookie_high_score'
|
24
|
+
COOKIE_VALIDATION_FAILED = 'cookie_validation_failed'
|
25
|
+
COOKIE_DECRYPTION_FAILED = 'cookie_decryption_failed'
|
26
|
+
SENSITIVE_ROUTE = 'sensitive_route'
|
27
|
+
|
28
|
+
# Templates
|
29
|
+
CHALLENGE_TEMPLATE = 'block_template'
|
30
|
+
TEMPLATE_EXT = '.mustache'
|
31
|
+
RATELIMIT_TEMPLATE = 'ratelimit'
|
32
|
+
|
33
|
+
|
34
|
+
# Template Props
|
35
|
+
PROP_REF_ID = :refId
|
36
|
+
PROP_APP_ID = :appId
|
37
|
+
PROP_VID = :vid
|
38
|
+
PROP_UUID = :uuid
|
39
|
+
PROP_LOGO_VISIBILITY = :logoVisibility
|
40
|
+
PROP_CUSTOM_LOGO = :customLogo
|
41
|
+
PROP_CSS_REF = :cssRef
|
42
|
+
PROP_JS_REF = :jsRef
|
43
|
+
PROP_BLOCK_SCRIPT = :blockScript
|
44
|
+
PROP_JS_CLIENT_SRC = :jsClientSrc
|
45
|
+
PROP_HOST_URL = :hostUrl
|
46
|
+
PROP_FIRST_PARTY_ENABLED = :firstPartyEnabled
|
47
|
+
|
48
|
+
# Hosts
|
49
|
+
CLIENT_HOST = 'client.px-cloud.net'
|
50
|
+
CAPTCHA_HOST = 'captcha.px-cloud.net'
|
51
|
+
|
52
|
+
VISIBLE = 'visible'
|
53
|
+
HIDDEN = 'hidden'
|
54
|
+
|
55
|
+
# Mobile SDK
|
56
|
+
TOKEN_HEADER = 'X-PX-AUTHORIZATION'
|
57
|
+
MOBILE_SDK_CONNECTION_ERROR = 'mobile_sdk_connection_error'
|
58
|
+
MOBILE_SDK_PINNING_ERROR = 'mobile_sdk_pinning_error'
|
59
|
+
|
60
|
+
# Regular Expressions
|
61
|
+
VID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/
|
62
|
+
end
|