Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#184781889 [WIP] Add applied_to and applied_to_unidentified in governance rules #74

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
add applied_to_unidentified entity
  • Loading branch information
HzANut committed Apr 18, 2023

Verified

This commit was signed with the committer’s verified signature.
achingbrain Alex Potsides
commit 0b10349faaeefe534f9e6fad1090c98a1c281a65
5 changes: 3 additions & 2 deletions moesifdjango/block_response_buffer.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from .governance_rules import RuleType
from .governance_rule_response import GovernanceRuleBlockResponse


class BlockResponseBufferList:
def __init__(self):
def __init__(self, rule_type=RuleType.REGEX.value):
self.responses = []
self.rule_type = None
self.rule_type = rule_type
self.blocked = False

def update(self, block, updated_gr_status, updated_gr_headers, updated_gr_body):
2 changes: 2 additions & 0 deletions moesifdjango/middleware.py
Original file line number Diff line number Diff line change
@@ -269,7 +269,9 @@ def __call__(self, request):
req_body_transfer_encoding, # could be json or base64
self.entity_rules,
self.identified_user_governance_rules,
self.unidentified_user_governance_rules,
self.identified_company_governance_rules,
self.unidentified_company_governance_rules,
self.regex_governance_rules,
self.DEBUG)

217 changes: 146 additions & 71 deletions moesifdjango/moesif_gov.py
Original file line number Diff line number Diff line change
@@ -11,6 +11,22 @@
REVERSED_PRIORITY_RULES_ORDER = [RuleType.REGEX.value, RuleType.COMPANY.value, RuleType.USER.value]


def merge_block_response(block_response_buffer_list_one: BlockResponseBufferList,
block_response_buffer_list_two: BlockResponseBufferList):
if block_response_buffer_list_one.rule_type != block_response_buffer_list_two.rule_type:
print('[moesif] Error when merging block response buffer list, [] and [] rule_type are not matching'
.format(block_response_buffer_list_one.rule_type, block_response_buffer_list_two.rule_type))
return None
merged_block_response_buffer_list = block_response_buffer_list_one
merged_block_response_buffer_list.blocked = block_response_buffer_list_one.blocked \
or block_response_buffer_list_two.blocked

for response in block_response_buffer_list_two.responses:
merged_block_response_buffer_list.responses.append(response)

return merged_block_response_buffer_list


class MoesifGovRuleHelper:
def __init__(self):
pass
@@ -59,7 +75,16 @@ def get_entity_governance_rule_and_check_block(cls, entity_rules, governance_rul
return block_entity_rules

@classmethod
def fetch_governance_rule_response_details(cls, governance_rule):
def fetch_governance_rule_response_details(cls, governance_rule, DEBUG):
if 'response' not in governance_rule \
or 'status' not in governance_rule['response'] \
or 'headers' not in governance_rule['response']:
if DEBUG:
print(
'[moesif] Skipped blocking request as response is not set for the governance rule {} with regex config'.format(
governance_rule))
return None, None, None

# Response status
status = governance_rule['response']['status']
# Response headers
@@ -235,14 +260,17 @@ def check_if_condition_for_request_body_field(cls, condition):

return True

def get_updated_response_with_matched_rules(self, governance_rule, rule_and_values):
def get_updated_response_with_matched_entity_rules(self, governance_rule, rule_and_values, DEBUG):
"""
get updated response if the governance is blocked checked and matched with request
get updated response if the entity governance rule is blocked checked, and event matched with request
utilized by both identified and unidentified
:param governance_rule:
:param rule_and_values:
:return:
"""
gr_status, gr_header, gr_body = self.fetch_governance_rule_response_details(governance_rule)
gr_status, gr_header, gr_body = self.fetch_governance_rule_response_details(governance_rule, DEBUG)
if not gr_status:
return None, None, None

# Updated governance rule headers
updated_gr_headers = {}
@@ -270,26 +298,28 @@ def get_updated_response_with_matched_rules(self, governance_rule, rule_and_valu

return gr_status, updated_gr_headers, updated_gr_body

def block_request_based_on_entity_governance_rule(self,
request_mapping_for_regex_config,
ready_for_body_request,
governance_rules,
entity_rules,
rule_entity_type,
entity_id,
DEBUG):
def block_request_based_on_entity_governance_rule_identified(self,
request_mapping_for_regex_config,
ready_for_body_request,
governance_rules,
entity_rules,
rule_entity_type,
entity_id,
rule_type,
DEBUG):
"""
Check if need to block request based on the governance rule of the entity associated with the request
:param rule_type: the type of BlockResponseBufferList (user, company or regex)
:param request_mapping_for_regex_config:
:param ready_for_body_request:
:param governance_rules:
:param entity_rules:
:param rule_entity_type:
:param entity_id:
:param rule_entity_type: the type of rules from config (user_rules, company_rules or regex_rules)
:param entity_id: user_id or company_id from event
:param DEBUG:
:return: object of updated response status, headers and body, if criteria is matched and block is true, otherwise return None
"""
response_buffer = BlockResponseBufferList()
response_buffer = BlockResponseBufferList(rule_type)

entity_id_rules_mapping = None

@@ -335,8 +365,8 @@ def block_request_based_on_entity_governance_rule(self,
continue

# update response status, headers and body if one block rule matched
updated_gr_status, updated_gr_headers, updated_gr_body = self.get_updated_response_with_matched_rules(
governance_rule, rule_and_values)
updated_gr_status, updated_gr_headers, updated_gr_body = self.get_updated_response_with_matched_entity_rules(
governance_rule, rule_and_values, DEBUG)

block = governance_rule.get('block', False)
response_buffer.update(block, updated_gr_status, updated_gr_headers, updated_gr_body)
@@ -363,45 +393,47 @@ def check_event_should_blocked_by_rule(self, governance_rule,
return (matched and applied_to == AppliedTo.MATCHING.value) \
or (not matched and applied_to == AppliedTo.NOT_MATCHING.value)

def get_rules_id_if_governance_rule_matched(self, regex_governance_rules, event, ready_for_body_request):
def get_rules_id_if_governance_rule_matched(self, governance_rules, request_mapping_for_regex_config,
ready_for_body_request):
"""
find the regex governance rules what matched with request, and return the governance rules id
:param regex_governance_rules:
:param event:
:param request_mapping_for_regex_config: request config generated from event, for regex config matching in gov rules
:param governance_rules:
:param ready_for_body_request:
:return:
:return: list of gov rule ids that event matched
"""
matched_rules_id = []
request_config_mapping = self.prepare_request_config_based_on_regex_config(event, ready_for_body_request)
for id, rule in regex_governance_rules.items():
for id, rule in governance_rules.items():
if 'regex_config' not in rule or not rule['regex_config']:
continue
regex_configs = rule['regex_config']

matched = self.check_request_with_regex_match(regex_configs, request_config_mapping,
matched = self.check_request_with_regex_match(regex_configs, request_mapping_for_regex_config,
ready_for_body_request)

if matched:
try:
matched_rules_id.append(rule['_id'])
except KeyError as ke:
print('[moesif] Error when fetching matched regex governance rule ', ke)

matched_rules_id.append(id)
return matched_rules_id

def block_request_based_on_governance_rule_regex_config(self, event, ready_for_body_request, regex_governance_rules,
DEBUG):
def block_request_based_on_regex_or_unidentified_entity_governance_rule(self,
request_mapping_for_regex_config,
ready_for_body_request,
regex_governance_rules,
rule_type,
DEBUG):
"""
Check if need to block request based on the governance rule regex config associated with the request
:param event:
:param rule_type:
:param request_mapping_for_regex_config:
:param ready_for_body_request:
:param regex_governance_rules:
:param DEBUG:
:return:
"""

response_buffer = BlockResponseBufferList()
matched_rules_id = self.get_rules_id_if_governance_rule_matched(regex_governance_rules, event,
response_buffer = BlockResponseBufferList(rule_type)
matched_rules_id = self.get_rules_id_if_governance_rule_matched(regex_governance_rules,
request_mapping_for_regex_config,
ready_for_body_request)

if not matched_rules_id:
@@ -414,18 +446,10 @@ def block_request_based_on_governance_rule_regex_config(self, event, ready_for_b
if DEBUG:
print(
'[moesif] Skipped blocking request as rule {} is not found'.format(rule_id))
continue

if 'response' not in governance_rule \
or 'status' not in governance_rule['response'] \
or 'headers' not in governance_rule['response']:
if DEBUG:
print(
'[moesif] Skipped blocking request as response is not set for the governance rule with regex config')
continue

block = governance_rule.get('block', False)
gr_status, gr_header, gr_body = self.fetch_governance_rule_response_details(governance_rule)
gr_status, gr_header, gr_body = self.fetch_governance_rule_response_details(governance_rule, DEBUG)

response_buffer.update(block, gr_status, gr_header, gr_body)
if DEBUG:
@@ -520,65 +544,116 @@ def apply_governance_rules(self,
user_id_entity, company_id_entity,
req_body_transfer_encoding,
entity_rules,
user_governance_rules,
company_governance_rules,
identified_user_governance_rules,
unidentified_user_governance_rules,
identified_company_governance_rules,
unidentified_company_governance_rules,
regex_governance_rules,
DEBUG):

ready_for_body_request = self.ok_request_body_regex_rule(event.request, req_body_transfer_encoding)
request_mapping_for_regex_config = self.prepare_request_config_based_on_regex_config(event,
ready_for_body_request)

response_buffers = {}
response_buffers = {
RuleType.REGEX.value: BlockResponseBufferList(RuleType.REGEX.value),
RuleType.COMPANY.value: BlockResponseBufferList(RuleType.COMPANY.value),
RuleType.USER.value: BlockResponseBufferList(RuleType.USER.value)
}
if regex_governance_rules:
regex_response_buffer = self.block_request_based_on_governance_rule_regex_config(event,
ready_for_body_request,
regex_governance_rules,
DEBUG)
regex_response_buffer = self.block_request_based_on_regex_or_unidentified_entity_governance_rule(
request_mapping_for_regex_config,
ready_for_body_request,
regex_governance_rules,
RuleType.REGEX.value,
DEBUG)
if not regex_response_buffer.blocked:
if DEBUG:
print('[moesif] No matching with the request from regex rules')

response_buffers['regex'] = regex_response_buffer
response_buffers[RuleType.REGEX.value] = regex_response_buffer
else:
if DEBUG:
print('[moesif] No regex rules')

if company_id_entity and company_governance_rules:
company_response_buffer = self.block_request_based_on_entity_governance_rule(
if unidentified_company_governance_rules:
unidentified_company_response_buffer = \
self.block_request_based_on_regex_or_unidentified_entity_governance_rule(
request_mapping_for_regex_config,
ready_for_body_request,
unidentified_company_governance_rules,
RuleType.COMPANY.value,
DEBUG
)
if not unidentified_company_response_buffer.blocked:
if DEBUG:
print('[moesif] No matching with the request from unidentified company rules')
else:
response_buffers[RuleType.COMPANY.value] = unidentified_company_response_buffer
else:
if DEBUG:
print('[moesif] no unidentified company governance rules')

if company_id_entity and identified_company_governance_rules:
company_response_buffer = self.block_request_based_on_entity_governance_rule_identified(
request_mapping_for_regex_config,
ready_for_body_request,
company_governance_rules,
identified_company_governance_rules,
entity_rules,
'company_rules',
company_id_entity,
RuleType.COMPANY.value,
DEBUG)
if not company_response_buffer.blocked:
if DEBUG:
print('[moesif] No blocking from company: ', company_id_entity)

response_buffers['company'] = company_response_buffer
else:
response_buffers[RuleType.COMPANY.value] = merge_block_response(
response_buffers.get(RuleType.COMPANY.value, BlockResponseBufferList()),
company_response_buffer)
else:
if DEBUG:
print('[moesif] company_id is not valid or no governance rules for the company')

if user_id_entity and user_governance_rules:
user_response_buffer = self.block_request_based_on_entity_governance_rule(request_mapping_for_regex_config,
ready_for_body_request,
user_governance_rules,
entity_rules,
'user_rules',
user_id_entity,
DEBUG)

if not user_response_buffer.blocked:
print('[moesif] company_id is not valid or no identified company governance rules')

if unidentified_user_governance_rules:
unidentified_company_response_buffer = \
self.block_request_based_on_regex_or_unidentified_entity_governance_rule(
request_mapping_for_regex_config,
ready_for_body_request,
unidentified_user_governance_rules,
RuleType.USER.value,
DEBUG
)
if not unidentified_company_response_buffer.blocked:
if DEBUG:
print('[moesif] No blocking from user: ', user_id_entity)
print('[moesif] No matching with the request from unidentified user rules')
else:
response_buffers[RuleType.USER.value] = unidentified_company_response_buffer
else:
if DEBUG:
print('[moesif] no unidentified user governance rules')

if user_id_entity and identified_user_governance_rules:
identified_user_response_buffer = self.block_request_based_on_entity_governance_rule_identified(
request_mapping_for_regex_config,
ready_for_body_request,
identified_user_governance_rules,
entity_rules,
'user_rules',
user_id_entity,
RuleType.USER.value,
DEBUG)

response_buffers['user'] = user_response_buffer
if not identified_user_response_buffer.blocked:
if DEBUG:
print('[moesif] No blocking from user: ', user_id_entity)
else:
response_buffers[RuleType.USER.value] = merge_block_response(
response_buffers.get(RuleType.USER.value, BlockResponseBufferList()),
identified_user_response_buffer)
else:
if DEBUG:
print('[moesif] user_id is not valid or no governance rules for the user')
print('[moesif] user_id is not valid or no identified user governance rules')

blocking_response = self.generate_blocking_response(response_buffers)