forked from MirrorHub/synapse
Allow providing credentials to http_proxy
(#10360)
This commit is contained in:
parent
7695ca0618
commit
c7603af1d0
3 changed files with 64 additions and 14 deletions
1
changelog.d/10360.feature
Normal file
1
changelog.d/10360.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Allow providing credentials to `http_proxy`.
|
|
@ -117,7 +117,8 @@ class ProxyAgent(_AgentBase):
|
||||||
https_proxy = proxies["https"].encode() if "https" in proxies else None
|
https_proxy = proxies["https"].encode() if "https" in proxies else None
|
||||||
no_proxy = proxies["no"] if "no" in proxies else None
|
no_proxy = proxies["no"] if "no" in proxies else None
|
||||||
|
|
||||||
# Parse credentials from https proxy connection string if present
|
# Parse credentials from http and https proxy connection string if present
|
||||||
|
self.http_proxy_creds, http_proxy = parse_username_password(http_proxy)
|
||||||
self.https_proxy_creds, https_proxy = parse_username_password(https_proxy)
|
self.https_proxy_creds, https_proxy = parse_username_password(https_proxy)
|
||||||
|
|
||||||
self.http_proxy_endpoint = _http_proxy_endpoint(
|
self.http_proxy_endpoint = _http_proxy_endpoint(
|
||||||
|
@ -189,6 +190,15 @@ class ProxyAgent(_AgentBase):
|
||||||
and self.http_proxy_endpoint
|
and self.http_proxy_endpoint
|
||||||
and not should_skip_proxy
|
and not should_skip_proxy
|
||||||
):
|
):
|
||||||
|
# Determine whether we need to set Proxy-Authorization headers
|
||||||
|
if self.http_proxy_creds:
|
||||||
|
# Set a Proxy-Authorization header
|
||||||
|
if headers is None:
|
||||||
|
headers = Headers()
|
||||||
|
headers.addRawHeader(
|
||||||
|
b"Proxy-Authorization",
|
||||||
|
self.http_proxy_creds.as_proxy_authorization_value(),
|
||||||
|
)
|
||||||
# Cache *all* connections under the same key, since we are only
|
# Cache *all* connections under the same key, since we are only
|
||||||
# connecting to a single destination, the proxy:
|
# connecting to a single destination, the proxy:
|
||||||
pool_key = ("http-proxy", self.http_proxy_endpoint)
|
pool_key = ("http-proxy", self.http_proxy_endpoint)
|
||||||
|
|
|
@ -205,6 +205,41 @@ class MatrixFederationAgentTests(TestCase):
|
||||||
|
|
||||||
@patch.dict(os.environ, {"http_proxy": "proxy.com:8888", "no_proxy": "unused.com"})
|
@patch.dict(os.environ, {"http_proxy": "proxy.com:8888", "no_proxy": "unused.com"})
|
||||||
def test_http_request_via_proxy(self):
|
def test_http_request_via_proxy(self):
|
||||||
|
"""
|
||||||
|
Tests that requests can be made through a proxy.
|
||||||
|
"""
|
||||||
|
self._do_http_request_via_proxy(auth_credentials=None)
|
||||||
|
|
||||||
|
@patch.dict(
|
||||||
|
os.environ,
|
||||||
|
{"http_proxy": "bob:pinkponies@proxy.com:8888", "no_proxy": "unused.com"},
|
||||||
|
)
|
||||||
|
def test_http_request_via_proxy_with_auth(self):
|
||||||
|
"""
|
||||||
|
Tests that authenticated requests can be made through a proxy.
|
||||||
|
"""
|
||||||
|
self._do_http_request_via_proxy(auth_credentials="bob:pinkponies")
|
||||||
|
|
||||||
|
@patch.dict(os.environ, {"https_proxy": "proxy.com", "no_proxy": "unused.com"})
|
||||||
|
def test_https_request_via_proxy(self):
|
||||||
|
"""Tests that TLS-encrypted requests can be made through a proxy"""
|
||||||
|
self._do_https_request_via_proxy(auth_credentials=None)
|
||||||
|
|
||||||
|
@patch.dict(
|
||||||
|
os.environ,
|
||||||
|
{"https_proxy": "bob:pinkponies@proxy.com", "no_proxy": "unused.com"},
|
||||||
|
)
|
||||||
|
def test_https_request_via_proxy_with_auth(self):
|
||||||
|
"""Tests that authenticated, TLS-encrypted requests can be made through a proxy"""
|
||||||
|
self._do_https_request_via_proxy(auth_credentials="bob:pinkponies")
|
||||||
|
|
||||||
|
def _do_http_request_via_proxy(
|
||||||
|
self,
|
||||||
|
auth_credentials: Optional[str] = None,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Tests that requests can be made through a proxy.
|
||||||
|
"""
|
||||||
agent = ProxyAgent(self.reactor, use_proxy=True)
|
agent = ProxyAgent(self.reactor, use_proxy=True)
|
||||||
|
|
||||||
self.reactor.lookups["proxy.com"] = "1.2.3.5"
|
self.reactor.lookups["proxy.com"] = "1.2.3.5"
|
||||||
|
@ -229,6 +264,23 @@ class MatrixFederationAgentTests(TestCase):
|
||||||
self.assertEqual(len(http_server.requests), 1)
|
self.assertEqual(len(http_server.requests), 1)
|
||||||
|
|
||||||
request = http_server.requests[0]
|
request = http_server.requests[0]
|
||||||
|
|
||||||
|
# Check whether auth credentials have been supplied to the proxy
|
||||||
|
proxy_auth_header_values = request.requestHeaders.getRawHeaders(
|
||||||
|
b"Proxy-Authorization"
|
||||||
|
)
|
||||||
|
|
||||||
|
if auth_credentials is not None:
|
||||||
|
# Compute the correct header value for Proxy-Authorization
|
||||||
|
encoded_credentials = base64.b64encode(b"bob:pinkponies")
|
||||||
|
expected_header_value = b"Basic " + encoded_credentials
|
||||||
|
|
||||||
|
# Validate the header's value
|
||||||
|
self.assertIn(expected_header_value, proxy_auth_header_values)
|
||||||
|
else:
|
||||||
|
# Check that the Proxy-Authorization header has not been supplied to the proxy
|
||||||
|
self.assertIsNone(proxy_auth_header_values)
|
||||||
|
|
||||||
self.assertEqual(request.method, b"GET")
|
self.assertEqual(request.method, b"GET")
|
||||||
self.assertEqual(request.path, b"http://test.com")
|
self.assertEqual(request.path, b"http://test.com")
|
||||||
self.assertEqual(request.requestHeaders.getRawHeaders(b"host"), [b"test.com"])
|
self.assertEqual(request.requestHeaders.getRawHeaders(b"host"), [b"test.com"])
|
||||||
|
@ -241,19 +293,6 @@ class MatrixFederationAgentTests(TestCase):
|
||||||
body = self.successResultOf(treq.content(resp))
|
body = self.successResultOf(treq.content(resp))
|
||||||
self.assertEqual(body, b"result")
|
self.assertEqual(body, b"result")
|
||||||
|
|
||||||
@patch.dict(os.environ, {"https_proxy": "proxy.com", "no_proxy": "unused.com"})
|
|
||||||
def test_https_request_via_proxy(self):
|
|
||||||
"""Tests that TLS-encrypted requests can be made through a proxy"""
|
|
||||||
self._do_https_request_via_proxy(auth_credentials=None)
|
|
||||||
|
|
||||||
@patch.dict(
|
|
||||||
os.environ,
|
|
||||||
{"https_proxy": "bob:pinkponies@proxy.com", "no_proxy": "unused.com"},
|
|
||||||
)
|
|
||||||
def test_https_request_via_proxy_with_auth(self):
|
|
||||||
"""Tests that authenticated, TLS-encrypted requests can be made through a proxy"""
|
|
||||||
self._do_https_request_via_proxy(auth_credentials="bob:pinkponies")
|
|
||||||
|
|
||||||
def _do_https_request_via_proxy(
|
def _do_https_request_via_proxy(
|
||||||
self,
|
self,
|
||||||
auth_credentials: Optional[str] = None,
|
auth_credentials: Optional[str] = None,
|
||||||
|
|
Loading…
Reference in a new issue