1- from px_logger import Logger
21import px_context
32import px_activities_client
43import px_cookie_validator
54import px_httpc
65import px_blocker
76import px_api
8- import px_template
9- from px_proxy import PXProxy
10- import Cookie
117import px_constants
8+ import px_utils
9+ from px_proxy import PXProxy
10+ from px_config import PXConfig
11+
1212
1313class PerimeterX (object ):
1414 def __init__ (self , app , config = None ):
1515 self .app = app
1616 # merging user's defined configurations with the default one
17- self .config = {
18- 'blocking_score' : 60 ,
19- 'debug_mode' : False ,
20- 'perimeterx_server_host' : 'sapi.perimeterx.net' ,
21- 'captcha_enabled' : True ,
22- 'server_calls_enabled' : True ,
23- 'encryption_enabled' : True ,
24- 'sensitive_headers' : ['cookie' , 'cookies' ],
25- 'send_page_activities' : True ,
26- 'api_timeout' : 1 ,
27- 'custom_logo' : None ,
28- 'css_ref' : None ,
29- 'js_ref' : None ,
30- 'is_mobile' : False ,
31- 'first_party' : True ,
32- 'first_party_xhr_enabled' : True ,
33- 'monitor_mode' : px_constants .MODULE_MODE_MONITORING ,
34- }
35-
36- self .config = dict (self .config .items () + config .items ())
37- self .config ['logger' ] = logger = Logger (self .config ['debug_mode' ])
38- if not config ['app_id' ]:
17+ px_config = PXConfig (config )
18+ logger = px_config .logger
19+ if not px_config .app_id :
3920 logger .error ('PX App ID is missing' )
4021 raise ValueError ('PX App ID is missing' )
41- url = px_constants .COLLECTOR_URL
4222
43- self .config ['collector_url' ] = url .format (config .get ('app_id' ).lower ())
4423 # if APP_ID is not set, use the deafult perimeterx server - else, use the appid specific sapi.
45- self .config ['perimeterx_server_host' ] = 'sapi.perimeterx.net' if self .config ['app_id' ] == 'PX_APP_ID' else 'sapi-' + self .config ['app_id' ].lower () + '.perimeterx.net'
46- if not config ['auth_token' ]:
24+ if not px_config .auth_token :
4725 logger .error ('PX Auth Token is missing' )
4826 raise ValueError ('PX Auth Token is missing' )
4927
50- if not config [ ' cookie_key' ] :
28+ if not px_config . cookie_key :
5129 logger .error ('PX Cookie Key is missing' )
5230 raise ValueError ('PX Cookie Key is missing' )
53- self .reverse_proxy_prefix = self .config ['app_id' ][2 :].lower ()
54-
55- self .PXBlocker = px_blocker .PXBlocker ()
56- px_httpc .init (self .config )
31+ self .reverse_proxy_prefix = px_config .app_id [2 :].lower ()
32+ if px_config .custom_request_handler :
33+ self .handle_verification = px_config .custom_request_handler .__get__ (self , PerimeterX )
34+ self ._PXBlocker = px_blocker .PXBlocker ()
35+ self ._config = px_config
36+ px_httpc .init (px_config )
5737
5838 def __call__ (self , environ , start_response ):
5939 return self ._verify (environ , start_response )
6040
6141 def _verify (self , environ , start_response ):
62- logger = self .config ['logger' ]
42+ config = self .config
43+ logger = config .logger
6344 try :
64- ctx = px_context .build_context (environ , self . config )
45+ ctx = px_context .build_context (environ , config )
6546 uri = ctx .get ('uri' )
66- px_proxy = PXProxy (self . config , ctx )
67- if px_proxy .should_reverse_request (uri ):
47+ px_proxy = PXProxy (config )
48+ if px_proxy .should_reverse_request (uri ):
6849 return px_proxy .handle_reverse_request (self .config , ctx , start_response )
69- if ctx . get ( 'module_mode' ) == 'inactive' or is_static_file (ctx ):
50+ if px_utils . is_static_file (ctx ):
7051 logger .debug ('Filter static file request. uri: ' + uri )
7152 return self .app (environ , start_response )
53+ if not self ._config ._module_enabled :
54+ logger .debug ('Module is disabled, request will not be verified' )
55+ return self .app (environ , start_response )
7256
73- cookies = Cookie .SimpleCookie (environ .get ('HTTP_COOKIE' ))
57+ if ctx .get ('whitelist' ):
58+ logger .debug ('The requested uri is whitelisted, passing request' )
59+ return self .app (environ , start_response )
7460
7561 # PX Cookie verification
76- if not px_cookie_validator .verify (ctx , self . config ) and self . config . get ( 'server_calls_enabled' , True ):
62+ if not px_cookie_validator .verify (ctx , config ):
7763 # Server-to-Server verification fallback
7864 if not px_api .verify (ctx , self .config ):
7965 return self .app (environ , start_response )
80-
66+ if config .custom_request_handler :
67+ return config .custom_request_handler (ctx , self .config , environ , start_response )
8168 return self .handle_verification (ctx , self .config , environ , start_response )
8269 except :
8370 logger .error ("Cought exception, passing request" )
@@ -86,33 +73,31 @@ def _verify(self, environ, start_response):
8673 def handle_verification (self , ctx , config , environ , start_response ):
8774 score = ctx .get ('risk_score' , - 1 )
8875
89- if score < config [ ' blocking_score' ] :
76+ if score < config . blocking_score :
9077 return self .pass_traffic (environ , start_response , ctx )
9178
92- if config .get ( ' custom_block_handler' , False ) :
79+ if config .custom_block_handler :
9380 px_activities_client .send_block_activity (ctx , config )
94- return config [ ' custom_block_handler' ] (ctx , start_response )
95- elif config .get ( ' module_mode' ) == px_constants .MODULE_MODE_BLOCKING :
96- return self .PXBlocker .handle_blocking (ctx = ctx , config = config , start_response = start_response )
81+ return config . custom_block_handler (ctx , start_response )
82+ elif config .module_mode == px_constants .MODULE_MODE_BLOCKING :
83+ return self .px_blocker .handle_blocking (ctx = ctx , config = config , start_response = start_response )
9784 else :
9885 return self .pass_traffic (environ , start_response , ctx )
9986
10087 def pass_traffic (self , environ , start_response , ctx ):
10188 details = {}
10289 if ctx .get ('decoded_cookie' , '' ):
10390 details = {"px_cookie" : ctx ['decoded_cookie' ]}
104- px_activities_client .send_to_perimeterx ('page_requested' , ctx , self .config , details )
91+ px_activities_client .send_to_perimeterx (px_constants . PAGE_REQUESTED_ACTIVITY , ctx , self .config , details )
10592 return self .app (environ , start_response )
10693
94+ @property
95+ def config (self ):
96+ return self ._config
97+
98+ @property
99+ def px_blocker (self ):
100+ return self ._PXBlocker
101+
107102
108- def is_static_file (ctx ):
109- uri = ctx .get ('uri' , '' )
110- static_extensions = ['.css' , '.bmp' , '.tif' , '.ttf' , '.docx' , '.woff2' , '.js' , '.pict' , '.tiff' , '.eot' ,
111- '.xlsx' , '.jpg' , '.csv' , '.eps' , '.woff' , '.xls' , '.jpeg' , '.doc' , '.ejs' , '.otf' , '.pptx' ,
112- '.gif' , '.pdf' , '.swf' , '.svg' , '.ps' , '.ico' , '.pls' , '.midi' , '.svgz' , '.class' , '.png' ,
113- '.ppt' , '.mid' , 'webp' , '.jar' ]
114103
115- for ext in static_extensions :
116- if uri .endswith (ext ):
117- return True
118- return False
0 commit comments