summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose Porrua <jose.porrua@netapp.com>2016-01-15 15:07:53 -0500
committerJose Porrua <jose.porrua@netapp.com>2016-02-16 15:36:32 +0000
commit5efb5964f7eedf002e9535bf202b5da9ac5e200f (patch)
treefd80aed57509d6a7f8de7ab058273337e84b9335
parentaa06b2dd5442704548a2372cffc56a24de98882d (diff)
downloadpython-cinderclient-5efb5964f7eedf002e9535bf202b5da9ac5e200f.tar.gz
Avoid logging sensitive info in http requests.
This patch follows the same approach as other OpenStack python clients, by adding a safe header method to hash sensitive information. Change-Id: I980ea7411b1e7f6d47d0a75d58de87b0f944d0d9 Closes-bug: #1516689
-rw-r--r--cinderclient/client.py16
-rw-r--r--cinderclient/openstack/common/apiclient/client.py16
-rw-r--r--cinderclient/tests/unit/test_client.py27
3 files changed, 57 insertions, 2 deletions
diff --git a/cinderclient/client.py b/cinderclient/client.py
index 2717152..e456cfe 100644
--- a/cinderclient/client.py
+++ b/cinderclient/client.py
@@ -21,6 +21,7 @@ OpenStack Client interface. Handles the REST calls and responses.
from __future__ import print_function
import glob
+import hashlib
import imp
import itertools
import logging
@@ -39,6 +40,7 @@ from cinderclient import exceptions
import cinderclient.extension
from cinderclient.openstack.common import importutils
from cinderclient.openstack.common.gettextutils import _
+from oslo_utils import encodeutils
from oslo_utils import strutils
osprofiler_web = importutils.try_import("osprofiler.web")
@@ -145,6 +147,7 @@ class SessionClient(adapter.LegacyJsonAdapter):
class HTTPClient(object):
+ SENSITIVE_HEADERS = ('X-Auth-Token', 'X-Subject-Token',)
USER_AGENT = 'python-cinderclient'
def __init__(self, user, password, projectid, auth_url=None,
@@ -198,6 +201,16 @@ class HTTPClient(object):
self._logger = logging.getLogger(__name__)
+ def _safe_header(self, name, value):
+ if name in HTTPClient.SENSITIVE_HEADERS:
+ encoded = value.encode('utf-8')
+ hashed = hashlib.sha1(encoded)
+ digested = hashed.hexdigest()
+ return encodeutils.safe_decode(name), "{SHA1}%s" % digested
+ else:
+ return (encodeutils.safe_decode(name),
+ encodeutils.safe_decode(value))
+
def http_log_req(self, args, kwargs):
if not self.http_log_debug:
return
@@ -210,7 +223,8 @@ class HTTPClient(object):
string_parts.append(' %s' % element)
for element in kwargs['headers']:
- header = ' -H "%s: %s"' % (element, kwargs['headers'][element])
+ header = ("-H '%s: %s'" %
+ self._safe_header(element, kwargs['headers'][element]))
string_parts.append(header)
if 'data' in kwargs:
diff --git a/cinderclient/openstack/common/apiclient/client.py b/cinderclient/openstack/common/apiclient/client.py
index da2e177..69b551b 100644
--- a/cinderclient/openstack/common/apiclient/client.py
+++ b/cinderclient/openstack/common/apiclient/client.py
@@ -33,13 +33,16 @@ try:
except ImportError:
import json
+import hashlib
import requests
from cinderclient.openstack.common.apiclient import exceptions
from cinderclient.openstack.common import importutils
+from oslo_utils import encodeutils
_logger = logging.getLogger(__name__)
+SENSITIVE_HEADERS = ('X-Auth-Token', 'X-Subject-Token',)
class HTTPClient(object):
@@ -97,6 +100,16 @@ class HTTPClient(object):
self.cached_token = None
+ def _safe_header(self, name, value):
+ if name in SENSITIVE_HEADERS:
+ encoded = value.encode('utf-8')
+ hashed = hashlib.sha1(encoded)
+ digested = hashed.hexdigest()
+ return encodeutils.safe_decode(name), "{SHA1}%s" % digested
+ else:
+ return (encodeutils.safe_decode(name),
+ encodeutils.safe_decode(value))
+
def _http_log_req(self, method, url, kwargs):
if not self.debug:
return
@@ -108,7 +121,8 @@ class HTTPClient(object):
]
for element in kwargs['headers']:
- header = "-H '%s: %s'" % (element, kwargs['headers'][element])
+ header = ("-H '%s: %s'" %
+ self._safe_header(element, kwargs['headers'][element]))
string_parts.append(header)
_logger.debug("REQ: %s" % " ".join(string_parts))
diff --git a/cinderclient/tests/unit/test_client.py b/cinderclient/tests/unit/test_client.py
index ff5e6d9..3e35af4 100644
--- a/cinderclient/tests/unit/test_client.py
+++ b/cinderclient/tests/unit/test_client.py
@@ -188,3 +188,30 @@ class ClientTest(utils.TestCase):
# AuthorizationFailure exception, check exceptions.from_response
# is not getting called.
self.assertFalse(mock_from_resp.called)
+
+
+class ClientTestSensitiveInfo(utils.TestCase):
+ def test_req_does_not_log_sensitive_info(self):
+ self.logger = self.useFixture(
+ fixtures.FakeLogger(
+ format="%(message)s",
+ level=logging.DEBUG,
+ nuke_handlers=True
+ )
+ )
+
+ secret_auth_token = "MY_SECRET_AUTH_TOKEN"
+ kwargs = {
+ 'headers': {"X-Auth-Token": secret_auth_token},
+ 'data': ('{"auth": {"tenantName": "fakeService",'
+ ' "passwordCredentials": {"username": "fakeUser",'
+ ' "password": "fakePassword"}}}')
+ }
+
+ cs = cinderclient.client.HTTPClient("user", None, None,
+ "http://127.0.0.1:5000")
+ cs.http_log_debug = True
+ cs.http_log_req('PUT', kwargs)
+
+ output = self.logger.output.split('\n')
+ self.assertNotIn(secret_auth_token, output[1])