Fix the logging of request body credentials

Recently we moved the logging of request from rest_client's
request() to raw_request which end up logging the credentials
also from Token client request.

This is to add a kwargs in raw_request() method which tell whether
request body needs to log or not. Also update Token clients to
pass '<omitted>' to stop logging the credential.

Change-Id: I7cbd3656463a51d18b4d72f45a324145283fc7eb
This commit is contained in:
Ghanshyam Mann 2019-10-02 16:56:26 +00:00
parent 420155c234
commit 47a4199326
7 changed files with 29 additions and 13 deletions

View File

@ -0,0 +1,6 @@
---
security:
- |
Recently we moved the logging of API request in rest_client's
raw_request which end up logging the credentials also from
Token client request. This issue has been fixed now.

View File

@ -556,7 +556,8 @@ class RestClient(object):
return resp, resp_body
def raw_request(self, url, method, headers=None, body=None, chunked=False):
def raw_request(self, url, method, headers=None, body=None, chunked=False,
log_req_body=None):
"""Send a raw HTTP request without the keystone catalog or auth
This method sends a HTTP request in the same manner as the request()
@ -572,6 +573,11 @@ class RestClient(object):
explicitly requires no headers use an empty dict.
:param str body: Body to send with the request
:param bool chunked: sends the body with chunked encoding
:param str log_req_body: Whether to log the request body or not.
It is default to None which means request
body is safe to log otherwise pass any string
you want to log in place of request body.
For example: '<omitted>'
:rtype: tuple
:return: a tuple with the first entry containing the response headers
and the second the response body
@ -585,8 +591,9 @@ class RestClient(object):
url, method, headers=headers,
body=body, chunked=chunked)
end = time.time()
req_body = body if log_req_body is None else log_req_body
self._log_request(method, url, resp, secs=(end - start),
req_headers=headers, req_body=body,
req_headers=headers, req_body=req_body,
resp_body=resp_body)
return resp, resp_body

View File

@ -105,9 +105,8 @@ class TokenClient(rest_client.RestClient):
headers = self.get_headers(accept_type="json")
resp, resp_body = self.raw_request(url, method,
headers=headers, body=body)
self._log_request(method, url, resp, req_headers=headers,
req_body='<omitted>', resp_body=resp_body)
headers=headers, body=body,
log_req_body='<omitted>')
if resp.status in [401, 403]:
resp_body = json.loads(resp_body)

View File

@ -160,10 +160,8 @@ class V3TokenClient(rest_client.RestClient):
headers = self.get_headers(accept_type="json")
resp, resp_body = self.raw_request(url, method,
headers=headers, body=body)
self._log_request(method, url, resp, req_headers=headers,
req_body='<omitted>', resp_body=resp_body)
headers=headers, body=body,
log_req_body='<omitted>')
if resp.status in [401, 403]:
resp_body = json.loads(resp_body)
raise exceptions.Unauthorized(resp_body['error']['message'])

View File

@ -192,7 +192,7 @@ ALT_IDENTITY_V3 = IDENTITY_V3_RESPONSE
def _fake_v3_response(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
redirections=5, connection_type=None, log_req_body=None):
fake_headers = {
"x-subject-token": TOKEN
}
@ -202,7 +202,7 @@ def _fake_v3_response(self, uri, method="GET", body=None, headers=None,
def _fake_v3_response_domain_scope(self, uri, method="GET", body=None,
headers=None, redirections=5,
connection_type=None):
connection_type=None, log_req_body=None):
fake_headers = {
"status": "201",
"x-subject-token": TOKEN
@ -213,7 +213,7 @@ def _fake_v3_response_domain_scope(self, uri, method="GET", body=None,
def _fake_v3_response_no_scope(self, uri, method="GET", body=None,
headers=None, redirections=5,
connection_type=None):
connection_type=None, log_req_body=None):
fake_headers = {
"status": "201",
"x-subject-token": TOKEN
@ -223,7 +223,7 @@ def _fake_v3_response_no_scope(self, uri, method="GET", body=None,
def _fake_v2_response(self, uri, method="GET", body=None, headers=None,
redirections=5, connection_type=None):
redirections=5, connection_type=None, log_req_body=None):
return (fake_http.fake_http_response({}, status=200),
json.dumps(IDENTITY_V2_RESPONSE))

View File

@ -86,6 +86,9 @@ class TestTokenClientV2(base.TestCase):
with mock.patch.object(token_client_v2, 'raw_request') as mock_raw_r:
mock_raw_r.return_value = response, body
resp, body = token_client_v2.request('GET', 'fake_uri')
mock_raw_r.assert_called_once_with('fake_uri', 'GET',
headers=mock.ANY, body=None,
log_req_body='<omitted>')
self.assertIsInstance(body, dict)
def test_request_with_bytes_body(self):

View File

@ -136,6 +136,9 @@ class TestTokenClientV3(base.TestCase):
mock_raw_r.return_value = (
fake_identity._fake_v3_response(None, None))
resp, body = token_client_v3.request('GET', 'fake_uri')
mock_raw_r.assert_called_once_with('fake_uri', 'GET',
headers=mock.ANY, body=None,
log_req_body='<omitted>')
self.assertIsInstance(body, dict)