diff --git a/CHANGELOG.md b/CHANGELOG.md index c606a16a..81b5229b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ [PyPI History][1] [1]: https://pypi.org/project/demisto-py/#history +## 3.2.10 +* Added URL decoding of proxy url credentials. + ## 3.2.9 * Added the ability to add custom request headers. diff --git a/demisto_client/demisto_api/rest.py b/demisto_client/demisto_api/rest.py index 5cbb1a78..d026eaf3 100644 --- a/demisto_client/demisto_api/rest.py +++ b/demisto_client/demisto_api/rest.py @@ -27,6 +27,7 @@ try: import urllib3 + import urllib except ImportError: raise ImportError('Swagger python client requires urllib3.') @@ -88,7 +89,8 @@ def __init__(self, configuration, pools_size=4, maxsize=None): proxy_headers = None parsed_proxy_url = urllib3.util.parse_url(configuration.proxy) if parsed_proxy_url.auth is not None: - proxy_headers = urllib3.util.make_headers(proxy_basic_auth=parsed_proxy_url.auth) + configuration.proxy_auth = urllib.parse.unquote(parsed_proxy_url.auth) + proxy_headers = urllib3.util.make_headers(proxy_basic_auth=configuration.proxy_auth) self.pool_manager = urllib3.ProxyManager( num_pools=pools_size, diff --git a/gen-code.sh b/gen-code.sh index 14acedad..58d3c237 100755 --- a/gen-code.sh +++ b/gen-code.sh @@ -32,6 +32,7 @@ mv README.md.org README.md sed -i "${INPLACE[@]}" -e 's/^from demisto_client.demisto_api.models.advance_arg import AdvanceArg/# &/' demisto_client/demisto_api/models/operator_argument.py sed -i "${INPLACE[@]}" -e 's/^from demisto_client.demisto_api.models.group import Group/# &/' demisto_client/demisto_api/models/groups.py sed -i "${INPLACE[@]}" -e 's/^from demisto_client.demisto_api.models.investigation_playbook import InvestigationPlaybook/# &/' demisto_client/demisto_api/models/investigation_playbook_task.py + # __api_call needs to work with dict objects and not Classes when updating data such as POST requests sed -i "${INPLACE[@]}" -e 's/config = self.configuration/&; body = demisto_client.to_extended_dict(body) # noqa: E702/' demisto_client/demisto_api/api_client.py # Update the docs @@ -73,11 +74,14 @@ sed -i "${INPLACE[@]}" -e 's/"""Custom error messages for exception"""/"""Custom else:\ sensitive_logging = False/' demisto_client/demisto_api/rest.py +sed -i "${INPLACE[@]}" -e 's/import urllib3/import urllib3\ + import urllib/' demisto_client/demisto_api/rest.py sed -i "${INPLACE[@]}" -e 's/if configuration.proxy:/if configuration.proxy:\ proxy_headers = None\ parsed_proxy_url = urllib3.util.parse_url(configuration.proxy)\ if parsed_proxy_url.auth is not None:\ - proxy_headers = urllib3.util.make_headers(proxy_basic_auth=parsed_proxy_url.auth)\ + configuration.proxy_auth = urllib.parse.unquote(parsed_proxy_url.auth)\ + proxy_headers = urllib3.util.make_headers(proxy_basic_auth=configuration.proxy_auth)\ /' demisto_client/demisto_api/rest.py sed -i "${INPLACE[@]}" -e 's/proxy_url=configuration.proxy,/proxy_headers=proxy_headers,\ diff --git a/tests/mocks_test.py b/tests/mocks_test.py index da621c57..983caef4 100644 --- a/tests/mocks_test.py +++ b/tests/mocks_test.py @@ -405,6 +405,51 @@ def run(): assert_reset() +class TestWithProxyBasicAuthentication(unittest.TestCase): + + def test_generic_request(self): + """ + Given: + - Request which use proxy authentication + When: + - Environment variable HTTP_PROXY and HTTPS_PROXY which contains a username and password with special characters + Then: + - Ensure the request made to the correct url via correct proxy username and password. Special character should be decoded. + """ + import sys + # Error should be the same in both Py2 and Py3, but Py2 does not support unittest mock in + # the same way + if sys.version_info[0] > 2: + from unittest import mock + + @mock.patch.dict(os.environ, {"HTTP_PROXY": "http://user1:pass%21%23%24%25%5E@localhost:8080"}) + @mock.patch.dict(os.environ, {"HTTPS_PROXY": "http://user1:pass%21%23%24%25%5E@localhost:8080"}) + @responses.activate + def run(): + responses.add('POST', 'http://localhost:8080/test', + body="Good", + status=200, + content_type='text/plain') + api_instance = demisto_client.configure(base_url=host, api_key=api_key, debug=False) + + api_instance.generic_request('/test', 'POST', + body="this is a test", + content_type='text/plain', + accept='text/plain') + + assert len(responses.calls) == 1 + assert responses.calls[0].request.url == 'http://localhost:8080/test' + assert responses.calls[0].request.host == 'localhost' + assert responses.calls[0].request.scheme == 'http' + assert api_instance.api_client.configuration.proxy_auth == 'user1:pass!#$%^' + + else: + def run(): + assert 1 == 1 + run() + assert_reset() + + def test_import_incidentfields(mocker): """ Given: