def __str__(self): # Print the DATA portion of the request with the OPERATION first, # and other keys afterward in sorted order data = self.get(api.DATA) data_list = [] text = "" if api.TARGET in self: text += "TARGET:%s " % self[api.TARGET] if self.is_job_status_request(): text += "STATUS_REQUEST " if api.ACTION in self: text += "ACTION:%s " % self[api.ACTION] if isinstance(data, dict): sorted_keys = sorted(data, key=operator.itemgetter(1)) if api.OPERATION in sorted_keys: sorted_keys.remove(api.OPERATION) text += "OPERATION:%s " % data[api.OPERATION] for key in sorted_keys: value = data[key] data_list.append("%s:%s" % (key, scrub_passwords(value))) text += scrub_passwords("DATA:{%s} " % ",".join(data_list)) if api.TXN_ID in self: text += "TXN:%s " % self[api.TXN_ID] return text
def post(self, **kwargs): # generate a uniq id solely for the purpose of more # easily matching up request/responses in the log try: bll_request = BllRequest(json.loads(request.body)) # Add to thread local storage for logging context.txn_id = bll_request.txn_id if 'X-Auth-Token' in request.headers: bll_request[api.AUTH_TOKEN] = request.headers['X-Auth-Token'] bll_request[api.LANGUAGE] = self.get_language( request.headers.get('Accept-Language')) LOG.info("Received %s", bll_request) # initial service request? if bll_request.is_service_request(): ret = SvcBase.spawn_service(bll_request) else: # Poll to retrieve async response ret = get_job_status(bll_request.txn_id) response.status = 201 if isinstance(ret, dict): logstr = response_to_string(ret) LOG.info("Response %s", logstr) except ValueError as info: # json.loads was unable to convert the request to json LOG.error("Error converting request body to json: %s. " "Request body: %s", info, request.body) response.status = 400 ret = { api.STATUS: api.STATUS_ERROR, api.DATA: [{api.DATA: str(info)}] } LOG.info("Response ValueError: %s", scrub_passwords(ret)) except Exception as info: response.status = 400 ret = { api.STATUS: api.STATUS_ERROR, api.DATA: [{api.DATA: str(info)}] } LOG.info("Response Exception: %s", scrub_passwords(ret)) # Clear out txn_id as it leaves the system context.txn_id = '' return ret
def test_scrub_json_in_a_string_craziness_1(self): test_data = {u'appliance-settings': u'{"monasca-controller2": \ {"ip": "192.168.0.35", "keystone-password": "******", \ "my_token": "sometoken"}}'} result = scrub_passwords(test_data) self.assertTrue('unset' not in result) self.assertTrue('*****oken' in result)
def test_scrub_none_token_element(self): test_data = {'auth_token': None, 'txn_id': '8582cdc0-c09a-4bd6-a1a8-67c5af78a1cf', 'target': 'deploy', 'data': {'operation': 'some_operation'}} result = loads(scrub_passwords(test_data)) self.assertEquals(result['auth_token'], 'None')
def test_scrub_token_from_bll_request(self): test_data = {'auth_token': '4d038a60-2409-4636-b99f-280e4dc3c6fe', 'txn_id': '8582cdc0-c09a-4bd6-a1a8-67c5af78a1cf', 'target': 'deploy', 'data': {'operation': 'some_operation'}} result = scrub_passwords(BllRequest(test_data)) self.assertNotIn('4d038a60', result)
def test_scrub_passwords_rest_wrap_craziness(self): test_data = [u"action=u'GET'", u"data={u'operation': \ u'get_provider_networks', u'api_version': \ u'v1', u'ops_console_admin_password': u'unset'}", u"txn_id=u'1234'", u"target=u'openstack_network'"] result = scrub_passwords(test_data) self.assertTrue('unset' not in result)
def test_scrub_passwords_dict_in_list_with_unicode(self): test_data = [{u'username': u'root', u'name': u'enc1-bay2', u'ip_address': u'192.168.0.71', u'password': u'unset'}] result = loads(scrub_passwords(test_data)) self.assertEquals(result[0]['password'], blanked_password)
def test_scrub_json_in_a_string_craziness_2(self): test_data = '{"appliance-settings": "{\\"monasca-controller2\\": \ {\\"ip\\": \\"4.3.2.1\\", \ \\"keystone-password\\": \\"unset\\", \ \\"my_token\\": \\"sometoken\\"}}"}' result = scrub_passwords(test_data) self.assertTrue('unset' not in result) self.assertTrue('*****oken' in result)
def test_scrub_passwords_single(self): test_data = { 'blah': 'something', 'password': '******', 'pre_password': '******', 'password_post': 'password' } result = loads(scrub_passwords(test_data)) self.assertEquals(result['password'], blanked_password) self.assertEquals(result['pre_password'], blanked_password) self.assertEquals(result['password_post'], blanked_password) self.assertEquals(result['blah'], 'something')
def test_scrub_passwords_json_in_a_string(self): test_str = '{"ma1": {' \ '"ip": "192.168.0.35", ' \ '"keepalive-priority": "98", ' \ '"keystone-password": "******"}, ' \ '"fakehost": {' \ '"ip": "192.168.0.34", ' \ '"somedict": {' \ '"testpassword": "******"}}}' result = loads(scrub_passwords(test_str)) self.assertEquals(result['ma1']['keystone-password'], blanked_password) self.assertEquals(result['fakehost']['somedict']['testpassword'], blanked_password)
def test_scrub_passwords_where_value_is_string(self): body = {'appliance-settings': '{"monasca-controller2": {' '"ip": "192.168.0.35", ' '"keepalive-priority": "98", ' '"keystone-password": "******"}, ' '"fakehost": {' '"ip": "192.168.0.34", ' '"somedict": {' '"testpassword": "******"}}}'} # Valid JSON doesn't allow embedded JSON as a string inside a JSON. # But we do this crazy stuff in our code, so let's make sure this # case still clears for passwords result = scrub_passwords(body) self.assertTrue('mypassword' not in result)
def test_scrub_passwords_deep(self): test_data = { 'blah': 'something', 'password': '******', 'lvl1': { 'a': 'a', 'password': '******', 'lvl2': { 'b': 'b', 'password': '******', 'lvl3': { 'c': 'c', 'password': '******' } } } } result = loads(scrub_passwords(test_data)) self.assertEquals(result['password'], blanked_password) self.assertEquals(result['lvl1']['password'], blanked_password) self.assertEquals(result['lvl1']['lvl2']['password'], blanked_password) self.assertEquals(result['lvl1']['lvl2']['lvl3']['password'], blanked_password) self.assertEquals(result['lvl1']['lvl2']['lvl3']['c'], 'c')
def test_scrub_passwords_none(self): result = scrub_passwords(None) self.assertIsNone(result)