Skip to content

Commit 44cc2dc

Browse files
authored
Merge pull request #474 from rollbar/fixed/sdk-426-scrubbing-for-namedtuples
Fixed SDK-426 scrubbing for namedtuples
2 parents b07720a + 036f4f2 commit 44cc2dc

File tree

5 files changed

+56
-15
lines changed

5 files changed

+56
-15
lines changed

rollbar/__init__.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ def _get_fastapi_request():
333333
# Set in init()
334334
_transforms = []
335335
_serialize_transform = None
336+
_scrub_redact_transform = None
336337

337338
_initialized = False
338339

@@ -362,7 +363,7 @@ def init(access_token, environment='production', scrub_fields=None, url_fields=N
362363
'staging', 'yourname'
363364
**kw: provided keyword arguments will override keys in SETTINGS.
364365
"""
365-
global SETTINGS, agent_log, _initialized, _transforms, _serialize_transform, _threads
366+
global SETTINGS, agent_log, _initialized, _transforms, _serialize_transform, _scrub_redact_transform, _threads
366367

367368
if scrub_fields is not None:
368369
SETTINGS['scrub_fields'] = list(scrub_fields)
@@ -405,6 +406,8 @@ def init(access_token, environment='production', scrub_fields=None, url_fields=N
405406
_serialize_transform = SerializableTransform(safe_repr=SETTINGS['locals']['safe_repr'],
406407
safelist_types=SETTINGS['locals']['safelisted_types'])
407408

409+
_scrub_redact_transform = ScrubRedactTransform(suffixes=[(field,) for field in SETTINGS['scrub_fields']], redact_char='*')
410+
408411
# A list of key prefixes to apply our shortener transform to. The request
409412
# being included in the body key is old behavior and is being retained for
410413
# backwards compatibility.
@@ -429,13 +432,10 @@ def init(access_token, environment='production', scrub_fields=None, url_fields=N
429432
**SETTINGS['locals']['sizes'])
430433
_transforms = [
431434
shortener, # priority: 10
432-
ScrubRedactTransform(), # priority: 20
435+
_scrub_redact_transform, # priority: 20
433436
_serialize_transform, # priority: 30
434-
ScrubTransform(suffixes=[(field,) for field in SETTINGS['scrub_fields']], redact_char='*'), # priority: 40
435-
ScrubUrlTransform(
436-
suffixes=[(field,) for field in SETTINGS['url_fields']],
437-
params_to_scrub=SETTINGS['scrub_fields'],
438-
) # priority: 50
437+
ScrubUrlTransform(suffixes=[(field,) for field in SETTINGS['url_fields']],
438+
params_to_scrub=SETTINGS['scrub_fields']) # priority: 50
439439
]
440440

441441
# Add custom transforms
@@ -1079,7 +1079,7 @@ def _add_locals_data(trace_data, exc_info):
10791079
def _serialize_frame_data(data):
10801080
return transforms.transform(
10811081
data,
1082-
[ScrubRedactTransform(), _serialize_transform],
1082+
[_scrub_redact_transform, _serialize_transform],
10831083
batch_transforms=SETTINGS['batch_transforms']
10841084
)
10851085

rollbar/test/test_rollbar.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import uuid
77

88
import sys
9+
from collections import namedtuple
910

1011
try:
1112
from StringIO import StringIO
@@ -1464,6 +1465,29 @@ def _raise():
14641465
undecodable_message = '<Undecodable type:(%s) base64:(%s)>' % ('bytes', base64.b64encode(invalid).decode('ascii'))
14651466
self.assertEqual(undecodable_message, payload['data']['body']['trace']['frames'][-1]['locals']['_invalid'])
14661467

1468+
@mock.patch('rollbar.send_payload')
1469+
def test_scrub_namedtuple(self, send_payload):
1470+
1471+
SomeTuple = namedtuple('SomeTuple', ['password', 'some_field'])
1472+
1473+
def _raise():
1474+
Data = SomeTuple(password='clear_text', some_field='some_field')
1475+
1476+
password = 'sensitive'
1477+
raise Exception((Data, password))
1478+
1479+
try:
1480+
_raise()
1481+
except:
1482+
rollbar.report_exc_info()
1483+
1484+
self.assertEqual(send_payload.called, True)
1485+
1486+
payload = send_payload.call_args[0][0]
1487+
1488+
self.assertRegex(payload['data']['body']['trace']['frames'][-1]['locals']['password'], r'\*+')
1489+
self.assertRegex(payload['data']['body']['trace']['frames'][-1]['locals']['Data'], 'password=\'\*+\'')
1490+
14671491
@mock.patch('rollbar.send_payload')
14681492
def test_scrub_nans(self, send_payload):
14691493
def _raise():

rollbar/test/test_scrub_redact_transform.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,19 @@ def test_scrub_set(self):
5858
expected = set([SCRUBBED, NOT_REDACT_REF])
5959
self._assertScrubbed(obj, expected)
6060

61-
def scrub_tuple(self):
61+
def test_scrub_tuple(self):
6262
obj = (REDACT_REF, REDACT_REF, REDACT_REF)
6363
expected = (SCRUBBED, SCRUBBED, SCRUBBED)
6464
self._assertScrubbed(obj, expected)
6565

66+
def test_scrub_namedtuple(self):
67+
from collections import namedtuple
68+
TestNamedTuple = namedtuple('TestNamedTuple', ['scrub_me', 'dont_scrub_me'])
69+
obj = TestNamedTuple(scrub_me=REDACT_REF, dont_scrub_me=NOT_REDACT_REF)
70+
expected = TestNamedTuple(scrub_me=SCRUBBED, dont_scrub_me=NOT_REDACT_REF)
71+
self._assertScrubbed(obj, expected)
72+
6673
def test_scrub_dict(self):
67-
obj = {'scrub_me': REDACT_REF}
68-
expected = {'scrub_me': SCRUBBED}
74+
obj = {'scrub_me': REDACT_REF, 'dont_scrub_me': NOT_REDACT_REF}
75+
expected = {'scrub_me': SCRUBBED, 'dont_scrub_me': NOT_REDACT_REF}
6976
self._assertScrubbed(obj, expected)

rollbar/test/test_scrub_transform.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ def test_no_suffixes(self):
6161
expected = dict(obj)
6262
self._assertScrubbed([], obj, expected)
6363

64+
def test_scrub_named_tuple(self):
65+
from collections import namedtuple
66+
Obj = namedtuple('obj', ['hello', 'password'])
67+
obj = Obj('world', 'cleartext')
68+
expected = Obj('world', '*********')
69+
self._assertScrubbed([['password']], obj, expected)
70+
71+
def test_scrub_named_tuple_in_list(self):
72+
from collections import namedtuple
73+
Obj = namedtuple('obj', ['hello', 'password'])
74+
obj = [Obj('world', 'cleartext'), 'another element']
75+
expected = [Obj('world', '*********'), 'another element']
76+
self._assertScrubbed([['password']], obj, expected)
77+
6478
def test_scrub_simple_dict(self):
6579
obj = {'hello': 'world', 'password': 'cleartext'}
6680
expected = copy.deepcopy(obj)

rollbar/test/test_transform.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ def test_default_transforms(self):
2626
ShortenerTransform,
2727
ScrubRedactTransform,
2828
SerializableTransform,
29-
ScrubTransform,
3029
ScrubUrlTransform,
3130
}, transforms)
3231

@@ -49,7 +48,6 @@ class CustomTransform(Transform):
4948
ShortenerTransform,
5049
ScrubRedactTransform,
5150
SerializableTransform,
52-
ScrubTransform,
5351
ScrubUrlTransform,
5452
CustomTransform,
5553
}, transforms)
@@ -59,7 +57,6 @@ class CustomTransform(Transform):
5957
ShortenerTransform,
6058
ScrubRedactTransform,
6159
SerializableTransform,
62-
ScrubTransform,
6360
ScrubUrlTransform,
6461
CustomTransform,
6562
], transforms_ordered)
@@ -88,6 +85,5 @@ class CustomTransformTwo(Transform):
8885
ScrubRedactTransform, # priority 20
8986
SerializableTransform, # priority 30
9087
CustomTransformTwo, # priority 35
91-
ScrubTransform, # priority 40
9288
ScrubUrlTransform, # priority 50
9389
], transforms)

0 commit comments

Comments
 (0)