diff --git a/shotgun_api3/shotgun.py b/shotgun_api3/shotgun.py index 9f62074af..34d570847 100755 --- a/shotgun_api3/shotgun.py +++ b/shotgun_api3/shotgun.py @@ -1379,7 +1379,7 @@ def share_thumbnail(self, entities, thumbnail_path=None, source_entity=None, except urllib2.HTTPError, e: if e.code == 500: raise ShotgunError("Server encountered an internal error. " - "\n%s\n(%s)\n%s\n\n" % (url, params, e)) + "\n%s\n(%s)\n%s\n\n" % (url, self._sanitize_auth_params(params), e)) else: raise ShotgunError("Unanticipated error occurred %s" % (e)) else: @@ -1491,7 +1491,7 @@ def upload(self, entity_type, entity_id, path, field_name=None, except urllib2.HTTPError, e: if e.code == 500: raise ShotgunError("Server encountered an internal error. " - "\n%s\n(%s)\n%s\n\n" % (url, params, e)) + "\n%s\n(%s)\n%s\n\n" % (url, self._sanitize_auth_params(params), e)) else: raise ShotgunError("Unanticipated error occurred uploading " "%s: %s" % (path, e)) @@ -2097,6 +2097,17 @@ def _auth_params(self): return auth_params + def _sanitize_auth_params(self, params): + """ + Given an authentication parameter dictionary, sanitize any sensitive + information and return the sanitized dict copy. + """ + sanitized_params = copy.copy(params) + for k in ['user_password', 'script_key', 'session_token']: + if k in sanitized_params: + sanitized_params[k] = '********' + return sanitized_params + def _build_payload(self, method, params, include_auth_params=True): """Builds the payload to be send to the rpc endpoint. diff --git a/tests/test_api.py b/tests/test_api.py index 1b7984dd5..e5d69b424 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -12,6 +12,7 @@ import uuid import unittest import urlparse +import urllib2 import shotgun_api3 from shotgun_api3.lib.httplib2 import Http @@ -1469,6 +1470,25 @@ def test_status_not_200(self, mock_request): mock_request.return_value = (response, {}) self.assertRaises(shotgun_api3.ProtocolError, self.sg.find_one, 'Shot', []) + @patch.object(urllib2.OpenerDirector, 'open') + def test_sanitized_auth_params(self, mock_open): + # Simulate the server blowing up and giving us a 500 error + mock_open.side_effect = urllib2.HTTPError('url', 500, 'message', {}, None) + + this_dir, _ = os.path.split(__file__) + thumbnail_path = os.path.abspath(os.path.join(this_dir, "sg_logo.jpg")) + + try: + # Try to upload a bogus file + self.sg.upload('Note', 1234, thumbnail_path) + except shotgun_api3.ShotgunError, e: + self.assertFalse(self.api_key in str(e)) + return + + # You should never get here... Otherwise some mocking failed and the + # except above wasn't properly run + self.assertTrue(False) + # def test_malformed_response(self): # #TODO ResponseError # pass