Skip to content

Commit

Permalink
added test
Browse files Browse the repository at this point in the history
  • Loading branch information
stiwarisemanticbits committed Oct 15, 2024
1 parent 941658a commit a54a97b
Show file tree
Hide file tree
Showing 2 changed files with 272 additions and 14 deletions.
49 changes: 35 additions & 14 deletions hhs_oauth_server/request_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,39 @@
)

audit = logging.getLogger("audit.%s" % __name__)
MBI_WITH_HYPHEN_PATTERN = r'\b\d[A-Z]{2}\d-[A-Z]{2}\d-[A-Z]{2}\d{2}\b'
MBI_WITHOUT_HYPHEN_PATTERN = r'\b[1-9](?![SLOIBZ])[A-Z](?![SLOIBZ)])[A-Z\d]\d(?![SLOIBZ])[A-Z](?![SLOIBZ])[A-Z\d]\d(?![SLOIBZ])[A-Z]{2}\d{2}\b'
MBI_WITH_HYPHEN_PATTERN = r"""\b
[1-9](?![SLOIBZsloibz])[A-Za-z](?![SLOIBZsloibz)])[A-Za-z\d]\d
-(?![SLOIBZsloibz])[A-Za-z](?![SLOIBZsloibz])[A-Za-z\d]\d
-((?![SLOIBZsloibz])[A-Za-z]){2}\d{2}
\b
"""

MBI_WITHOUT_HYPHEN_PATTERN = r"""\b
[1-9](?![SLOIBZsloibz])[A-Za-z](?![SLOIBZsloibz)])[A-Za-z\d]\d
(?![SLOIBZsloibz])[A-Za-z](?![SLOIBZsloibz])[A-Za-z\d]\d
((?![SLOIBZsloibzd])[A-Za-z]){2}\d{2}
\b"""

MBI_PATTERN = f'({MBI_WITH_HYPHEN_PATTERN}|{MBI_WITHOUT_HYPHEN_PATTERN})'


def has_mbi_match(text):
return bool(re.search(MBI_PATTERN, text, flags=re.VERBOSE))


def mask_if_has_mbi(text):
return re.sub(MBI_PATTERN, '***MBI***', text, flags=re.VERBOSE)


def mask_mbi(dictionary):
for key, value in dictionary.items():
if isinstance(value, dict):
mask_mbi(value)
elif isinstance(value, str):
dictionary[key] = mask_if_has_mbi(value)
return dictionary


class RequestResponseLog(object):
"""Audit log message to JSON string
Expand Down Expand Up @@ -140,20 +169,13 @@ def __init__(self, req, resp):
self.log_msg["location"] = ""
self.log_msg["size"] = 0


def has_mbi_match(text):
return bool(re.search(MBI_PATTERN, text))

def mask_if_has_mbi(text):
return re.sub(MBI_PATTERN, '***MBI***', text)

def _log_msg_update_from_dict(self, from_dict, key, dict_key):
# Log message update from a passed in dictionary
try:
value = from_dict.get(dict_key, None)
if value is not None:
if len(str(value)) > 0:
self.log_msg[key] = self.mask_if_has_mbi(value)
self.log_msg[key] = value
except ObjectDoesNotExist:
self.log_msg[key] = (
"ObjectDoesNotExist exception for key " + key + ":" + dict_key
Expand All @@ -169,7 +191,7 @@ def _log_msg_update_from_object(self, obj, key, obj_key):
value = getattr(obj, obj_key, None)
if value is not None:
if len(str(value)) > 0:
self.log_msg[key] = self.mask_if_has_mbi(value)
self.log_msg[key] = value
except ObjectDoesNotExist:
self.log_msg[key] = (
"ObjectDoesNotExist exception for key " + key + ":" + obj_key
Expand All @@ -184,7 +206,6 @@ def _log_msg_update_from_querydict(self, key, qp_key):
try:
value_list = self.request.GET.getlist(qp_key, None)
if value_list is not None:
value_list = [self.mask_if_has_mbi(value) for value in value_list]
if len(value_list) == 1:
self.log_msg[key] = value_list[0]
elif len(value_list) > 1:
Expand Down Expand Up @@ -532,8 +553,8 @@ def to_dict(self):
except ObjectDoesNotExist:
pass
self._sync_app_name()
masked_logged_dict = {key: self.mask_if_has_mbi(value) for key, value in self.log_msg.items()}
return masked_logged_dict

return mask_mbi(self.log_msg)

##############################################################################
#
Expand Down
237 changes: 237 additions & 0 deletions hhs_oauth_server/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from django.test import TestCase
from .utils import bool_env, TRUE_LIST, FALSE_LIST, int_env
from .request_logging import mask_if_has_mbi


class Check_BooleanVariable_Test(TestCase):
Expand Down Expand Up @@ -45,3 +46,239 @@ def test_int_values(self):
for x, y in int_list:
result = int_env(x)
self.assertEqual(result, y)


class MBI_tests(TestCase):
""" Check that text gets converted to Int """

def test_mbi_match(self):
""" Check we get integers """

mbi_test_list = [
# Valid MBI
("1EG4-TE5-MK74", True),

# Valid MBI Position 3 as 0
# Position 3 – alpha-numeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
("1E04-TE5-MK74", True),

# Valid MBI Position 4 as 0
# Position 4 – numeric values 0 thru 9
("1EG0-TE5-MK74", True),

# Valid MBI Position 6 as 0
# Position 6 – alpha-numeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
("1EG4-T05-MK74", True),

# Valid MBI Position 7 as 0
# Position 7 – numeric values 0 thru 9
("1EG4-TE0-MK74", True),

# Valid MBI Position 10 as 0
# Position 10 – numeric values 0 thru 9
("1EG4-TE5-MK04", True),

# Valid MBI Position 11 as 0
# Position 11 – numeric values 0 thru 9
("1EG4-TE5-MK70", True),


# Position 1 is invalid
# Position 1 – numeric values 1 thru 9
("AEG4-TE5-MK74", False),

# Position 2 is invalid
# P osition 2 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
("1SG4-TE5-MK74", False),
("1LG4-TE5-MK74", False),
("1OG4-TE5-MK74", False),
("1IG4-TE5-MK74", False),
("1BG4-TE5-MK74", False),
("1ZG4-TE5-MK74", False),
("11G4-TE5-MK74", False),

# Position 3 is invalid
# Position 3 – alpha-numeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
("1ES4-TE5-MK74", False),
("1EL4-TE5-MK74", False),
("1EO4-TE5-MK74", False),
("1EI4-TE5-MK74", False),
("1EB4-TE5-MK74", False),
("1EZ4-TE5-MK74", False),

# Position 4 is invalid
# Position 4 – numeric values 0 thru 9
("1EGA-TE5-MK74", False),

# Position 5 is invalid
# Position 5 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
("1EG4-1E5-MK74", False),
("1EG4-SE5-MK74", False),
("1EG4-LE5-MK74", False),
("1EG4-OE5-MK74", False),
("1EG4-IE5-MK74", False),
("1EG4-BE5-MK74", False),
("1EG4-ZE5-MK74", False),

# Position 6 is invalid
# Position 6 – alpha-numeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
("1EG4-TS5-MK74", False),
("1EG4-TL5-MK74", False),
("1EG4-TO5-MK74", False),
("1EG4-TI5-MK74", False),
("1EG4-TB5-MK74", False),
("1EG4-TZ5-MK74", False),

# Position 7 is invalid
# Position 7 – numeric values 0 thru 9
("1EG4-TEA-MK74", False),

# Position 8 is invalid
# Position 8 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
("1EG4-TE5-1K74", False),
("1EG4-TE5-SK74", False),
("1EG4-TE5-LK74", False),
("1EG4-TE5-OK74", False),
("1EG4-TE5-IK74", False),
("1EG4-TE5-BK74", False),
("1EG4-TE5-ZK74", False),

# Position 9 is invalid
# Position 9 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
("1EG4-TE5-M174", False),
("1EG4-TE5-MS74", False),
("1EG4-TE5-ML74", False),
("1EG4-TE5-MO74", False),
("1EG4-TE5-MOI74", False),
("1EG4-TE5-MKB4", False),
("1EG4-TE5-MKZ4", False),

# Position 10 is invalid
# Position 10 – numeric values 0 thru 9
("1EG4-TE5-MKA4", False),

# Position 11 is invalid
# Position 11 – numeric values 0 thru 9
("1EG4-TE5-MK7A", False),

# WITHOUT HYPHEN MBI TEST CASES BELOW
# Valid MBI
("1EG4TE5MK74", True),

# Valid MBI Position 3 as 0
# Position 3 – alphanumeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
("1E04TE5MK74", True),

# Valid MBI Position 4 as 0
# Position 4 – numeric values 0 thru 9
("1EG0TE5MK74", True),

# Valid MBI Position 6 as 0
# Position 6 – alphanumeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
("1EG4T05MK74", True),

# Valid MBI Position 7 as 0
# Position 7 – numeric values 0 thru 9
("1EG4TE0MK74", True),

# Valid MBI Position 10 as 0
# Position 10 – numeric values 0 thru 9
("1EG4TE5MK04", True),

# Valid MBI Position 11 as 0
# Position 11 – numeric values 0 thru 9
("1EG4TE5MK70", True),


# Position 1 is invalid
# Position 1 – numeric values 1 thru 9
("AEG4TE5MK74", False),

# Position 2 is invalid
# P osition 2 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
("1SG4TE5MK74", False),
("1LG4TE5MK74", False),
("1OG4TE5MK74", False),
("1IG4TE5MK74", False),
("1BG4TE5MK74", False),
("1ZG4TE5MK74", False),
("11G4TE5MK74", False),

# Position 3 is invalid
# Position 3 – alphanumeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
("1ES4TE5MK74", False),
("1EL4TE5MK74", False),
("1EO4TE5MK74", False),
("1EI4TE5MK74", False),
("1EB4TE5MK74", False),
("1EZ4TE5MK74", False),

# Position 4 is invalid
# Position 4 – numeric values 0 thru 9
("1EGATE5MK74", False),

# Position 5 is invalid
# Position 5 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
("1EG41E5MK74", False),
("1EG4SE5MK74", False),
("1EG4LE5MK74", False),
("1EG4OE5MK74", False),
("1EG4IE5MK74", False),
("1EG4BE5MK74", False),
("1EG4ZE5MK74", False),

# Position 6 is invalid
# Position 6 – alphanumeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
("1EG4TS5MK74", False),
("1EG4TL5MK74", False),
("1EG4TO5MK74", False),
("1EG4TI5MK74", False),
("1EG4TB5MK74", False),
("1EG4TZ5MK74", False),

# Position 7 is invalid
# Position 7 – numeric values 0 thru 9
("1EG4TEAMK74", False),

# Position 8 is invalid
# Position 8 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
("1EG4TE51K74", False),
("1EG4TE5SK74", False),
("1EG4TE5LK74", False),
("1EG4TE5OK74", False),
("1EG4TE5IK74", False),
("1EG4TE5BK74", False),
("1EG4TE5ZK74", False),

# Position 9 is invalid
# Position 9 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
("1EG4TE5M174", False),
("1EG4TE5MS74", False),
("1EG4TE5ML74", False),
("1EG4TE5MO74", False),
("1EG4TE5MOI74", False),
("1EG4TE5MKB4", False),
("1EG4TE5MKZ4", False),

# Position 10 is invalid
# Position 10 – numeric values 0 thru 9
("1EG4TE5MKA4", False),

# Position 11 is invalid
# Position 11 – numeric values 0 thru 9
("1EG4TE5MK7A", False),
]

for mbi_value, expected in mbi_test_list:
# Create a text that contains the MBI
uppercase_mbi_text = f"This is a test string with MBI: {mbi_value}, expected: {expected}."
masked_uppercase_text = mask_if_has_mbi(uppercase_mbi_text)
lowercase_mbi_text = uppercase_mbi_text.lower()
masked_mbi_lowercase_text = mask_if_has_mbi(lowercase_mbi_text)
# Check if the MBI was masked
if expected:
self.assertIn('***MBI***', masked_uppercase_text)
self.assertIn('***MBI***', masked_mbi_lowercase_text)
else:
self.assertNotIn('***MBI***', masked_uppercase_text)
self.assertNotIn('***MBI***', masked_mbi_lowercase_text)

0 comments on commit a54a97b

Please sign in to comment.