Skip to content

Commit

Permalink
#188414493 Update README, bump versions (#69)
Browse files Browse the repository at this point in the history
* Update README, bump versions

Update readme for EVENT_BATCH_TIMEOUT changes in moesifapi-python.
Bump moesifwsgi version.
Bump moesifapi-python version requirement.

* Update requirements.txt

- Update requests to 2.32.0 to allign with moesifapi
- Bumop moesifpythonrequest and moesifapi versions
- Update all example projects requirements.txt
- update .gitignore

* Fix headers not being included in requests

* Refactor: Update moesifapi-python and moesifpythonrequest dependency

Refactor: Update moesifapi-python and moesifpythonrequest dependency
Refactor: Ensure gov rules regex match on insensitive headers

---------

Co-authored-by: Keyur <[email protected]>
Co-authored-by: Praveen Kumar <[email protected]>
  • Loading branch information
3 people authored Oct 29, 2024
1 parent b96e9a1 commit b4938a9
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,5 @@ fabric.properties
# modules.xml
# .idea/misc.xml
# *.ipr
**/Pipfile
**/Pipfile.lock
2 changes: 1 addition & 1 deletion examples/bottle/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
moesifwsgi==1.9.4
moesifwsgi>=1.9.6
bottle
4 changes: 2 additions & 2 deletions examples/falcon/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
moesifwsgi==1.9.4
moesifwsgi>=1.9.6
falcon==3.1.0
gunicorn
falcon-multipart
falcon-multipart
2 changes: 1 addition & 1 deletion examples/flask/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
moesifwsgi>=1.9.4
moesifwsgi>=1.9.6
Flask
4 changes: 2 additions & 2 deletions moesifwsgi/config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,5 @@ def have_governance_rules(self):
with self._lock.gen_rlock():
return self.govern_manager.has_rules()

def govern_request(self, requestData, userId, companyId, request_body):
return self.govern_manager.govern_request(self.config, requestData, userId, companyId, request_body)
def govern_request(self, requestData, userId, companyId, request_body, request_headers):
return self.govern_manager.govern_request(self.config, requestData, userId, companyId, request_body, request_headers)
55 changes: 25 additions & 30 deletions moesifwsgi/governance_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@
logger = logging.getLogger(__name__)


def get_field_value_for_path(path, request_fields={}, request_body={}):
def get_field_value_for_path(path, request_fields={}, request_body={}, request_headers={}):
# Transforming the headers to be case insensitive to ensure regex matches on headers across all frameworks
request_headers = {k.lower(): v for k, v in request_headers.items()}
if path and path.startswith('request.body.') and request_body and isinstance(request_body, dict):
return request_body.get(path.replace('request.body.', ''), None)
elif path and path.startswith('request.headers.') and request_headers and isinstance(request_headers, dict):
return request_headers.get(path.replace('request.headers.', '').lower(), None)
return request_fields.get(path, None)

def does_regex_config_match(regex_config, request_fields, request_body):
def does_regex_config_match(regex_config, request_fields, request_body, request_headers):
if not regex_config:
return True

def does_one_condition_match(condition):
path = condition['path']
field_value = get_field_value_for_path(path, request_fields, request_body)
field_value = get_field_value_for_path(path, request_fields, request_body, request_headers)
regex_pattern = condition['value']
if field_value:
return re.search(regex_pattern, field_value)
Expand Down Expand Up @@ -171,25 +175,25 @@ def cache_rules(self, rules):
def has_rules(self):
return self.rules and len(self.rules) > 0

def get_applicable_regex_rules(self, request_fields, request_body):
def get_applicable_regex_rules(self, request_fields, request_body, request_headers):
if self.regex_rules:
return filter(lambda rule: does_regex_config_match(rule['regex_config'], request_fields, request_body), self.regex_rules)
return filter(lambda rule: does_regex_config_match(rule['regex_config'], request_fields, request_body, request_headers), self.regex_rules)
else:
return []

def get_applicable_unidentified_user_rules(self, request_fields, request_body):
def get_applicable_unidentified_user_rules(self, request_fields, request_body, request_headers):
if self.unidentified_user_rules:
return filter(lambda rule: does_regex_config_match(rule['regex_config'], request_fields, request_body), self.unidentified_user_rules)
return filter(lambda rule: does_regex_config_match(rule['regex_config'], request_fields, request_body, request_headers), self.unidentified_user_rules)
else:
return []

def get_applicable_unidentified_company_rules(self, request_fields, request_body):
def get_applicable_unidentified_company_rules(self, request_fields, request_body, request_headers):
if self.unidentified_company_rules:
return filter(lambda rule: does_regex_config_match(rule['regex_config'], request_fields, request_body), self.unidentified_company_rules)
return filter(lambda rule: does_regex_config_match(rule['regex_config'], request_fields, request_body, request_headers), self.unidentified_company_rules)
else:
return []

def get_user_rules(self, config_rules_values, request_fields, request_body):
def get_user_rules(self, config_rules_values, request_fields, request_body, request_headers):
applicable_rules = []
in_cohort_of_rule_hash = {}

Expand All @@ -205,7 +209,7 @@ def get_user_rules(self, config_rules_values, request_fields, request_body):
# print an debug log here.
break

regex_matched = does_regex_config_match(found_rule['regex_config'], request_fields, request_body)
regex_matched = does_regex_config_match(found_rule['regex_config'], request_fields, request_body, request_headers)

if not regex_matched:
break
Expand All @@ -221,14 +225,14 @@ def get_user_rules(self, config_rules_values, request_fields, request_body):
for rule in self.user_rules.items():
rule_info = rule[1]
if rule_info['applied_to'] == 'not_matching' and not in_cohort_of_rule_hash.get(rule_info['_id'], None):
regex_matched = does_regex_config_match(rule_info['regex_config'], request_fields, request_body)
regex_matched = does_regex_config_match(rule_info['regex_config'], request_fields, request_body, request_headers)
if regex_matched:
applicable_rules.append(rule_info)

return applicable_rules


def get_company_rules(self, config_rules_values, request_fields, request_body):
def get_company_rules(self, config_rules_values, request_fields, request_body, request_headers):
applicable_rules = []
in_cohort_of_rule_hash = {}

Expand All @@ -243,7 +247,7 @@ def get_company_rules(self, config_rules_values, request_fields, request_body):
# print an debug log here.
break

regex_matched = does_regex_config_match(found_rule['regex_config'], request_fields, request_body)
regex_matched = does_regex_config_match(found_rule['regex_config'], request_fields, request_body, request_headers)

if not regex_matched:
break
Expand All @@ -259,13 +263,13 @@ def get_company_rules(self, config_rules_values, request_fields, request_body):
for rule in self.company_rules.items():
rule_info = rule[1]
if rule_info['applied_to'] == 'not_matching' and not in_cohort_of_rule_hash.get(rule_info['_id'], None):
regex_matched = does_regex_config_match(rule_info['regex_config'], request_fields, request_body)
regex_matched = does_regex_config_match(rule_info['regex_config'], request_fields, request_body, request_headers)
if regex_matched:
applicable_rules.append(rule_info)

return applicable_rules

def govern_request(self, config, event_info, user_id, company_id, request_body):
def govern_request(self, config, event_info, user_id, company_id, request_body, request_headers):

request_fields = prepare_request_fields(event_info, request_body)

Expand All @@ -277,36 +281,27 @@ def govern_request(self, config, event_info, user_id, company_id, request_body):
'body': None
}

applicable_regex_rules = self.get_applicable_regex_rules(request_fields, request_body)
applicable_regex_rules = self.get_applicable_regex_rules(request_fields, request_body, request_headers)

response_holder = apply_rules(applicable_regex_rules, response_holder, None)

if company_id is None:
unidentified_company_rules = self.get_applicable_unidentified_company_rules(request_fields, request_body)
unidentified_company_rules = self.get_applicable_unidentified_company_rules(request_fields, request_body, request_headers)
response_holder = apply_rules(unidentified_company_rules, response_holder, None)
else:
config_rules_values = config_json.get('company_rules', {}).get(company_id)
company_rules = self.get_company_rules(config_rules_values, request_fields, request_body)
company_rules = self.get_company_rules(config_rules_values, request_fields, request_body, request_headers)
response_holder = apply_rules(company_rules, response_holder, config_rules_values)

if user_id is None:
unidentified_user_rules = self.get_applicable_unidentified_user_rules(request_fields, request_body)
unidentified_user_rules = self.get_applicable_unidentified_user_rules(request_fields, request_body, request_headers)
response_holder = apply_rules(unidentified_user_rules, response_holder, None)
else:
config_rules_values = config_json.get('user_rules', {}).get(user_id)
user_rules = self.get_user_rules(config_rules_values, request_fields, request_body)
user_rules = self.get_user_rules(config_rules_values, request_fields, request_body, request_headers)
response_holder = apply_rules(user_rules, response_holder, config_rules_values)

if 'blocked_by' in response_holder:
response_holder['body'] = format_body_for_middleware(response_holder['body'])

return response_holder









5 changes: 3 additions & 2 deletions moesifwsgi/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def initialize_config(self):
response_catcher = HttpResponseCatcher(self.DEBUG)
self.api_client.http_call_back = response_catcher
Configuration.BASE_URI = self.settings.get("BASE_URI") or self.settings.get("LOCAL_MOESIF_BASEURL", "https://api.moesif.net")
Configuration.version = "moesifwsgi-python/1.9.5"
Configuration.version = "moesifwsgi-python/1.9.6"
if self.settings.get("CAPTURE_OUTGOING_REQUESTS", False):
StartCapture().start_capture_outgoing(self.settings)

Expand Down Expand Up @@ -138,7 +138,8 @@ def __call__(self, environ, start_response):
# we must fire these hooks early.
request_user_id = self.logger_helper.get_user_id(environ, self.settings, self.app, self.DEBUG)
request_company_id = self.logger_helper.get_company_id(environ, self.settings, self.app, self.DEBUG)
governed_response = self.config.govern_request(event_info, request_user_id, request_company_id, event_info.request_body)
request_headers = dict(self.logger_helper.parse_request_headers(environ))
governed_response = self.config.govern_request(event_info, request_user_id, request_company_id, event_info.request_body, request_headers)

# monkey patch the default start_response to capture data and add headers
def _start_response(status, response_headers, *args):
Expand Down
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
requests==2.30.0
requests==2.32.0
nose==1.3.7
isodatetimehandler==1.0.2
moesifapi>=1.4.9
moesifpythonrequest==0.3.3
moesifapi>=1.5.3
moesifpythonrequest>=0.3.4
readerwriterlock==1.0.9
apscheduler==3.10.4
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version='1.9.5',
version='1.9.6',

description='Moesif Middleware for Python WSGI based platforms (Flask, Bottle & Others)',
long_description=long_description,
Expand Down Expand Up @@ -90,8 +90,8 @@
install_requires=[
'requests>=2.30.0',
'isodatetimehandler>=1.0.2',
'moesifapi>=1.4.9',
'moesifpythonrequest>=0.3.1',
'moesifapi>=1.5.3',
'moesifpythonrequest>=0.3.4',
'readerwriterlock>=1.0.9',
'apscheduler>=3.10.4'
],
Expand Down

0 comments on commit b4938a9

Please sign in to comment.