diff --git a/tests/test_main.py b/tests/test_main.py --- a/tests/test_main.py +++ b/tests/test_main.py @@ -16,8 +16,10 @@ # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import mock +import pytest from vcsserver import main +from vcsserver.base import obfuscate_qs @mock.patch('vcsserver.main.VcsServerCommand', mock.Mock()) @@ -34,3 +36,13 @@ def test_applies_largefiles_patch(patch_ mock.Mock(side_effect=Exception("Must not be called"))) def test_applies_largefiles_patch_only_if_mercurial_is_available(): main.main([]) + + +@pytest.mark.parametrize('given, expected', [ + ('foo=bar', 'foo=bar'), + ('auth_token=secret', 'auth_token=*****'), + ('auth_token=secret&api_key=secret2', 'auth_token=*****&api_key=*****'), + ('auth_token=secret&api_key=secret2¶m=value', 'auth_token=*****&api_key=*****¶m=value'), +]) +def test_obfuscate_qs(given, expected): + assert expected == obfuscate_qs(given) diff --git a/vcsserver/base.py b/vcsserver/base.py --- a/vcsserver/base.py +++ b/vcsserver/base.py @@ -16,7 +16,7 @@ # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import logging - +import urlparse log = logging.getLogger(__name__) @@ -69,3 +69,13 @@ class RepoFactory(object): 'INIT %s@%s repo object based on wire %s. Context: %s', self.__class__.__name__, wire['path'], wire, context) return createfunc() + + +def obfuscate_qs(query_string): + parsed = [] + for k, v in urlparse.parse_qsl(query_string): + if k in ['auth_token', 'api_key']: + v = "*****" + parsed.append((k, v)) + + return '&'.join('{}={}'.format(k,v) for k,v in parsed) diff --git a/vcsserver/git.py b/vcsserver/git.py --- a/vcsserver/git.py +++ b/vcsserver/git.py @@ -35,7 +35,7 @@ from dulwich.server import update_server from vcsserver import exceptions, settings, subprocessio from vcsserver.utils import safe_str -from vcsserver.base import RepoFactory +from vcsserver.base import RepoFactory, obfuscate_qs from vcsserver.hgcompat import ( hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler) @@ -170,6 +170,7 @@ class GitRemote(object): url_obj = url_parser(url) test_uri, _ = url_obj.authinfo() url_obj.passwd = '*****' + url_obj.query = obfuscate_qs(url_obj.query) cleaned_uri = str(url_obj) log.info("Checking URL for remote cloning/import: %s", cleaned_uri) diff --git a/vcsserver/hg.py b/vcsserver/hg.py --- a/vcsserver/hg.py +++ b/vcsserver/hg.py @@ -28,7 +28,7 @@ from mercurial import commands from mercurial import unionrepo from vcsserver import exceptions -from vcsserver.base import RepoFactory +from vcsserver.base import RepoFactory, obfuscate_qs from vcsserver.hgcompat import ( archival, bin, clone, config as hgconfig, diffopts, hex, hg_url as url_parser, httpbasicauthhandler, httpdigestauthhandler, @@ -329,6 +329,8 @@ class HgRemote(object): url_obj = url_parser(url) test_uri, authinfo = url_obj.authinfo() url_obj.passwd = '*****' + url_obj.query = obfuscate_qs(url_obj.query) + cleaned_uri = str(url_obj) log.info("Checking URL for remote cloning/import: %s", cleaned_uri)