From 605577192d7158ecf40bd9a94b7cf3acc2ce1c95 Mon Sep 17 00:00:00 2001 From: Brant Knudson Date: Mon, 28 Jul 2014 14:34:53 -0500 Subject: [PATCH] Redact tokens in request headers Tokens shouldn't be logged since a token could be gathered from a log file and used. The client was logging the X-Auth-Token and X-Subject-Token request headers. With this change, the X-Auth-Token and X-Subject-Token are shown as "TOKEN_REDACTED". Also, the "Authentication" header is also redacted. This is for security hardening. SecurityImpact Closes-Bug: #1004114 Closes-Bug: #1327019 Change-Id: I1edc3821ed028471102cc9b95eb9f3b54c9e2778 --- keystoneclient/session.py | 9 ++++++++- keystoneclient/tests/test_session.py | 11 ++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/keystoneclient/session.py b/keystoneclient/session.py index c74f752a6..26b95e1ee 100644 --- a/keystoneclient/session.py +++ b/keystoneclient/session.py @@ -139,6 +139,13 @@ class Session(object): # debug log. return + def process_header(header): + secure_headers = ('authorization', 'x-auth-token', + 'x-subject-token',) + if header[0].lower() in secure_headers: + return (header[0], 'TOKEN_REDACTED') + return header + string_parts = ['REQ: curl -i'] # NOTE(jamielennox): None means let requests do its default validation @@ -153,7 +160,7 @@ class Session(object): if headers: for header in six.iteritems(headers): - string_parts.append('-H "%s: %s"' % header) + string_parts.append('-H "%s: %s"' % process_header(header)) if json: data = jsonutils.dumps(json) if data: diff --git a/keystoneclient/tests/test_session.py b/keystoneclient/tests/test_session.py index 20596e6d0..3893e0ce7 100644 --- a/keystoneclient/tests/test_session.py +++ b/keystoneclient/tests/test_session.py @@ -11,6 +11,7 @@ # under the License. import argparse +import itertools import uuid import mock @@ -139,10 +140,15 @@ class SessionTests(utils.TestCase): def test_session_debug_output(self): session = client_session.Session(verify=False) headers = {'HEADERA': 'HEADERVALB'} + security_headers = {'Authorization': uuid.uuid4().hex, + 'X-Auth-Token': uuid.uuid4().hex, + 'X-Subject-Token': uuid.uuid4().hex, } body = 'BODYRESPONSE' data = 'BODYDATA' self.stub_url('POST', text=body) - session.post(self.TEST_URL, headers=headers, data=data) + all_headers = dict( + itertools.chain(headers.items(), security_headers.items())) + session.post(self.TEST_URL, headers=all_headers, data=data) self.assertIn('curl', self.logger.output) self.assertIn('POST', self.logger.output) @@ -153,6 +159,9 @@ class SessionTests(utils.TestCase): for k, v in six.iteritems(headers): self.assertIn(k, self.logger.output) self.assertIn(v, self.logger.output) + for k, v in six.iteritems(security_headers): + self.assertIn(k, self.logger.output) + self.assertNotIn(v, self.logger.output) class RedirectTests(utils.TestCase):