Skip to content

Commit d6512b2

Browse files
added test
1 parent e011ba0 commit d6512b2

File tree

2 files changed

+269
-14
lines changed

2 files changed

+269
-14
lines changed

hhs_oauth_server/request_logging.py

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,39 @@
2323
)
2424

2525
audit = logging.getLogger("audit.%s" % __name__)
26-
MBI_WITH_HYPHEN_PATTERN = r'\b\d[A-Z]{2}\d-[A-Z]{2}\d-[A-Z]{2}\d{2}\b'
27-
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'
26+
MBI_WITH_HYPHEN_PATTERN = r"""\b
27+
[1-9](?![SLOIBZ])[A-Z](?![SLOIBZ)])[A-Z\d]\d
28+
-(?![SLOIBZ])[A-Z](?![SLOIBZ])[A-Z\d]\d
29+
-((?![SLOIBZ])[A-Z]){2}\d{2}
30+
\b
31+
"""
32+
33+
MBI_WITHOUT_HYPHEN_PATTERN = r"""\b
34+
[1-9](?![SLOIBZ])[A-Z](?![SLOIBZ)])[A-Z\d]\d
35+
(?![SLOIBZ])[A-Z](?![SLOIBZ])[A-Z\d]\d
36+
((?![SLOIBZ])[A-Z]){2}\d{2}
37+
\b"""
38+
2839
MBI_PATTERN = f'({MBI_WITH_HYPHEN_PATTERN}|{MBI_WITHOUT_HYPHEN_PATTERN})'
2940

41+
42+
def has_mbi_match(text):
43+
return bool(re.search(MBI_PATTERN, text, flags=re.VERBOSE))
44+
45+
46+
def mask_if_has_mbi(text):
47+
return re.sub(MBI_PATTERN, '***MBI***', text, flags=re.VERBOSE)
48+
49+
50+
def mask_mbi(dictionary):
51+
for key, value in dictionary.items():
52+
if isinstance(value, dict):
53+
mask_mbi(value) # Recursive call for nested dict
54+
elif isinstance(value, str):
55+
dictionary[key] = mask_if_has_mbi(value)
56+
return dictionary
57+
58+
3059
class RequestResponseLog(object):
3160
"""Audit log message to JSON string
3261
@@ -140,20 +169,13 @@ def __init__(self, req, resp):
140169
self.log_msg["location"] = ""
141170
self.log_msg["size"] = 0
142171

143-
144-
def has_mbi_match(text):
145-
return bool(re.search(MBI_PATTERN, text))
146-
147-
def mask_if_has_mbi(text):
148-
return re.sub(MBI_PATTERN, '***MBI***', text)
149-
150172
def _log_msg_update_from_dict(self, from_dict, key, dict_key):
151173
# Log message update from a passed in dictionary
152174
try:
153175
value = from_dict.get(dict_key, None)
154176
if value is not None:
155177
if len(str(value)) > 0:
156-
self.log_msg[key] = self.mask_if_has_mbi(value)
178+
self.log_msg[key] = value
157179
except ObjectDoesNotExist:
158180
self.log_msg[key] = (
159181
"ObjectDoesNotExist exception for key " + key + ":" + dict_key
@@ -169,7 +191,7 @@ def _log_msg_update_from_object(self, obj, key, obj_key):
169191
value = getattr(obj, obj_key, None)
170192
if value is not None:
171193
if len(str(value)) > 0:
172-
self.log_msg[key] = self.mask_if_has_mbi(value)
194+
self.log_msg[key] = value
173195
except ObjectDoesNotExist:
174196
self.log_msg[key] = (
175197
"ObjectDoesNotExist exception for key " + key + ":" + obj_key
@@ -184,7 +206,6 @@ def _log_msg_update_from_querydict(self, key, qp_key):
184206
try:
185207
value_list = self.request.GET.getlist(qp_key, None)
186208
if value_list is not None:
187-
value_list = [self.mask_if_has_mbi(value) for value in value_list]
188209
if len(value_list) == 1:
189210
self.log_msg[key] = value_list[0]
190211
elif len(value_list) > 1:
@@ -532,8 +553,8 @@ def to_dict(self):
532553
except ObjectDoesNotExist:
533554
pass
534555
self._sync_app_name()
535-
masked_logged_dict = {key: self.mask_if_has_mbi(value) for key, value in self.log_msg.items()}
536-
return masked_logged_dict
556+
557+
return mask_mbi(self.log_msg)
537558

538559
##############################################################################
539560
#

hhs_oauth_server/tests.py

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from django.test import TestCase
1010
from .utils import bool_env, TRUE_LIST, FALSE_LIST, int_env
11+
from .request_logging import mask_if_has_mbi
1112

1213

1314
class Check_BooleanVariable_Test(TestCase):
@@ -45,3 +46,236 @@ def test_int_values(self):
4546
for x, y in int_list:
4647
result = int_env(x)
4748
self.assertEqual(result, y)
49+
50+
51+
class MBI_tests(TestCase):
52+
""" Check that text gets converted to Int """
53+
54+
def test_mbi_match(self):
55+
""" Check we get integers """
56+
57+
mbi_test_list = [
58+
# Valid MBI
59+
("1EG4-TE5-MK74", True),
60+
61+
# Valid MBI Position 3 as 0
62+
# Position 3 – alpha-numeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
63+
("1E04-TE5-MK74", True),
64+
65+
# Valid MBI Position 4 as 0
66+
# Position 4 – numeric values 0 thru 9
67+
("1EG0-TE5-MK74", True),
68+
69+
# Valid MBI Position 6 as 0
70+
# Position 6 – alpha-numeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
71+
("1EG4-T05-MK74", True),
72+
73+
# Valid MBI Position 7 as 0
74+
# Position 7 – numeric values 0 thru 9
75+
("1EG4-TE0-MK74", True),
76+
77+
# Valid MBI Position 10 as 0
78+
# Position 10 – numeric values 0 thru 9
79+
("1EG4-TE5-MK04", True),
80+
81+
# Valid MBI Position 11 as 0
82+
# Position 11 – numeric values 0 thru 9
83+
("1EG4-TE5-MK70", True),
84+
85+
86+
# Position 1 is invalid
87+
# Position 1 – numeric values 1 thru 9
88+
("AEG4-TE5-MK74", False),
89+
90+
# Position 2 is invalid
91+
# P osition 2 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
92+
("1SG4-TE5-MK74", False),
93+
("1LG4-TE5-MK74", False),
94+
("1OG4-TE5-MK74", False),
95+
("1IG4-TE5-MK74", False),
96+
("1BG4-TE5-MK74", False),
97+
("1ZG4-TE5-MK74", False),
98+
("11G4-TE5-MK74", False),
99+
100+
# Position 3 is invalid
101+
# Position 3 – alpha-numeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
102+
("1ES4-TE5-MK74", False),
103+
("1EL4-TE5-MK74", False),
104+
("1EO4-TE5-MK74", False),
105+
("1EI4-TE5-MK74", False),
106+
("1EB4-TE5-MK74", False),
107+
("1EZ4-TE5-MK74", False),
108+
109+
# Position 4 is invalid
110+
# Position 4 – numeric values 0 thru 9
111+
("1EGA-TE5-MK74", False),
112+
113+
# Position 5 is invalid
114+
# Position 5 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
115+
("1EG4-1E5-MK74", False),
116+
("1EG4-SE5-MK74", False),
117+
("1EG4-LE5-MK74", False),
118+
("1EG4-OE5-MK74", False),
119+
("1EG4-IE5-MK74", False),
120+
("1EG4-BE5-MK74", False),
121+
("1EG4-ZE5-MK74", False),
122+
123+
# Position 6 is invalid
124+
# Position 6 – alpha-numeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
125+
("1EG4-TS5-MK74", False),
126+
("1EG4-TL5-MK74", False),
127+
("1EG4-TO5-MK74", False),
128+
("1EG4-TI5-MK74", False),
129+
("1EG4-TB5-MK74", False),
130+
("1EG4-TZ5-MK74", False),
131+
132+
# Position 7 is invalid
133+
# Position 7 – numeric values 0 thru 9
134+
("1EG4-TEA-MK74", False),
135+
136+
# Position 8 is invalid
137+
# Position 8 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
138+
("1EG4-TE5-1K74", False),
139+
("1EG4-TE5-SK74", False),
140+
("1EG4-TE5-LK74", False),
141+
("1EG4-TE5-OK74", False),
142+
("1EG4-TE5-IK74", False),
143+
("1EG4-TE5-BK74", False),
144+
("1EG4-TE5-ZK74", False),
145+
146+
# Position 9 is invalid
147+
# Position 9 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
148+
("1EG4-TE5-M174", False),
149+
("1EG4-TE5-MS74", False),
150+
("1EG4-TE5-ML74", False),
151+
("1EG4-TE5-MO74", False),
152+
("1EG4-TE5-MOI74", False),
153+
("1EG4-TE5-MKB4", False),
154+
("1EG4-TE5-MKZ4", False),
155+
156+
# Position 10 is invalid
157+
# Position 10 – numeric values 0 thru 9
158+
("1EG4-TE5-MKA4", False),
159+
160+
# Position 11 is invalid
161+
# Position 11 – numeric values 0 thru 9
162+
("1EG4-TE5-MK7A", False),
163+
164+
# WITHOUT HYPHEN MBI TEST CASES BELOW
165+
# Valid MBI
166+
("1EG4TE5MK74", True),
167+
168+
# Valid MBI Position 3 as 0
169+
# Position 3 – alphanumeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
170+
("1E04TE5MK74", True),
171+
172+
# Valid MBI Position 4 as 0
173+
# Position 4 – numeric values 0 thru 9
174+
("1EG0TE5MK74", True),
175+
176+
# Valid MBI Position 6 as 0
177+
# Position 6 – alphanumeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
178+
("1EG4T05MK74", True),
179+
180+
# Valid MBI Position 7 as 0
181+
# Position 7 – numeric values 0 thru 9
182+
("1EG4TE0MK74", True),
183+
184+
# Valid MBI Position 10 as 0
185+
# Position 10 – numeric values 0 thru 9
186+
("1EG4TE5MK04", True),
187+
188+
# Valid MBI Position 11 as 0
189+
# Position 11 – numeric values 0 thru 9
190+
("1EG4TE5MK70", True),
191+
192+
193+
# Position 1 is invalid
194+
# Position 1 – numeric values 1 thru 9
195+
("AEG4TE5MK74", False),
196+
197+
# Position 2 is invalid
198+
# P osition 2 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
199+
("1SG4TE5MK74", False),
200+
("1LG4TE5MK74", False),
201+
("1OG4TE5MK74", False),
202+
("1IG4TE5MK74", False),
203+
("1BG4TE5MK74", False),
204+
("1ZG4TE5MK74", False),
205+
("11G4TE5MK74", False),
206+
207+
# Position 3 is invalid
208+
# Position 3 – alphanumeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
209+
("1ES4TE5MK74", False),
210+
("1EL4TE5MK74", False),
211+
("1EO4TE5MK74", False),
212+
("1EI4TE5MK74", False),
213+
("1EB4TE5MK74", False),
214+
("1EZ4TE5MK74", False),
215+
216+
# Position 4 is invalid
217+
# Position 4 – numeric values 0 thru 9
218+
("1EGATE5MK74", False),
219+
220+
# Position 5 is invalid
221+
# Position 5 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
222+
("1EG41E5MK74", False),
223+
("1EG4SE5MK74", False),
224+
("1EG4LE5MK74", False),
225+
("1EG4OE5MK74", False),
226+
("1EG4IE5MK74", False),
227+
("1EG4BE5MK74", False),
228+
("1EG4ZE5MK74", False),
229+
230+
# Position 6 is invalid
231+
# Position 6 – alphanumeric values 0 thru 9and A thru Z (minus S, L, O, I, B, Z)
232+
("1EG4TS5MK74", False),
233+
("1EG4TL5MK74", False),
234+
("1EG4TO5MK74", False),
235+
("1EG4TI5MK74", False),
236+
("1EG4TB5MK74", False),
237+
("1EG4TZ5MK74", False),
238+
239+
# Position 7 is invalid
240+
# Position 7 – numeric values 0 thru 9
241+
("1EG4TEAMK74", False),
242+
243+
# Position 8 is invalid
244+
# Position 8 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
245+
("1EG4TE51K74", False),
246+
("1EG4TE5SK74", False),
247+
("1EG4TE5LK74", False),
248+
("1EG4TE5OK74", False),
249+
("1EG4TE5IK74", False),
250+
("1EG4TE5BK74", False),
251+
("1EG4TE5ZK74", False),
252+
253+
# Position 9 is invalid
254+
# Position 9 – alphabetic values A thru Z (minus S, L, O, I, B, Z)
255+
("1EG4TE5M174", False),
256+
("1EG4TE5MS74", False),
257+
("1EG4TE5ML74", False),
258+
("1EG4TE5MO74", False),
259+
("1EG4TE5MOI74", False),
260+
("1EG4TE5MKB4", False),
261+
("1EG4TE5MKZ4", False),
262+
263+
# Position 10 is invalid
264+
# Position 10 – numeric values 0 thru 9
265+
("1EG4TE5MKA4", False),
266+
267+
# Position 11 is invalid
268+
# Position 11 – numeric values 0 thru 9
269+
("1EG4TE5MK7A", False),
270+
]
271+
272+
for mbi_value, expected in mbi_test_list:
273+
# Create a text that contains the MBI
274+
text = f"This is a test string with MBI: {mbi_value}, expected: {expected}."
275+
masked_text = mask_if_has_mbi(text)
276+
277+
# Check if the MBI was masked
278+
if expected:
279+
self.assertIn('***MBI***', masked_text)
280+
else:
281+
self.assertNotIn('***MBI***', masked_text)

0 commit comments

Comments
 (0)