mirror of
https://github.com/theupdateframework/python-tuf
synced 2026-05-24 10:08:28 +00:00
Add support for leading dots in no_proxy and "*" as a no_proxy value. Both are supported in requests and based on https://about.gitlab.com/blog/2021/01/27/we-need-to-talk-no-proxy/ both are somewhat common. Signed-off-by: Jussi Kukkonen <jkukkonen@google.com>
217 lines
8.1 KiB
Python
217 lines
8.1 KiB
Python
# Copyright 2025, the TUF contributors
|
|
# SPDX-License-Identifier: MIT OR Apache-2.0
|
|
|
|
"""Test ngclient ProxyEnvironment"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
import unittest
|
|
from unittest.mock import Mock, patch
|
|
|
|
from urllib3 import PoolManager, ProxyManager
|
|
|
|
from tests import utils
|
|
from tuf.ngclient._internal.proxy import ProxyEnvironment
|
|
|
|
|
|
class TestProxyEnvironment(unittest.TestCase):
|
|
"""Test ngclient ProxyEnvironment implementation
|
|
|
|
These tests use the ProxyEnvironment.get_pool_manager() endpoint and then
|
|
look at the ProxyEnvironment._poolmanagers dict keys to decide if the result
|
|
is correct.
|
|
|
|
The test environment is changed via mocking getproxies(): this is a urllib
|
|
method that returns a dict with the proxy environment variable contents.
|
|
|
|
Testing ProxyEnvironment.request() would possibly be better but far more
|
|
difficult: the current test implementation does not require actually setting up
|
|
all of the different proxies.
|
|
"""
|
|
|
|
def assert_pool_managers(
|
|
self, env: ProxyEnvironment, expected: list[str | None]
|
|
) -> None:
|
|
# Pool managers have the expected proxy urls
|
|
self.assertEqual(list(env._pool_managers.keys()), expected)
|
|
|
|
# Pool manager types are as expected
|
|
for proxy_url, pool_manager in env._pool_managers.items():
|
|
self.assertIsInstance(pool_manager, PoolManager)
|
|
if proxy_url is not None:
|
|
self.assertIsInstance(pool_manager, ProxyManager)
|
|
|
|
@patch("tuf.ngclient._internal.proxy.getproxies")
|
|
def test_no_variables(self, mock_getproxies: Mock) -> None:
|
|
mock_getproxies.return_value = {}
|
|
|
|
env = ProxyEnvironment()
|
|
env.get_pool_manager("http", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "subdomain.example.com")
|
|
env.get_pool_manager("https", "differentsite.com")
|
|
|
|
# There is a single pool manager (no proxies)
|
|
self.assert_pool_managers(env, [None])
|
|
|
|
@patch("tuf.ngclient._internal.proxy.getproxies")
|
|
def test_proxy_set(self, mock_getproxies: Mock) -> None:
|
|
mock_getproxies.return_value = {
|
|
"https": "http://localhost:8888",
|
|
}
|
|
|
|
env = ProxyEnvironment()
|
|
env.get_pool_manager("http", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "differentsite.com")
|
|
|
|
# There are two pool managers: A plain poolmanager and https proxymanager
|
|
self.assert_pool_managers(env, [None, "http://localhost:8888"])
|
|
|
|
@patch("tuf.ngclient._internal.proxy.getproxies")
|
|
def test_proxies_set(self, mock_getproxies: Mock) -> None:
|
|
mock_getproxies.return_value = {
|
|
"http": "http://localhost:8888",
|
|
"https": "http://localhost:9999",
|
|
}
|
|
|
|
env = ProxyEnvironment()
|
|
env.get_pool_manager("http", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "subdomain.example.com")
|
|
env.get_pool_manager("https", "differentsite.com")
|
|
|
|
# There are two pool managers: A http proxymanager and https proxymanager
|
|
self.assert_pool_managers(
|
|
env, ["http://localhost:8888", "http://localhost:9999"]
|
|
)
|
|
|
|
@patch("tuf.ngclient._internal.proxy.getproxies")
|
|
def test_no_proxy_set(self, mock_getproxies: Mock) -> None:
|
|
mock_getproxies.return_value = {
|
|
"http": "http://localhost:8888",
|
|
"https": "http://localhost:9999",
|
|
"no": "somesite.com, example.com, another.site.com",
|
|
}
|
|
|
|
env = ProxyEnvironment()
|
|
env.get_pool_manager("http", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
|
|
# There is a single pool manager (no proxies)
|
|
self.assert_pool_managers(env, [None])
|
|
|
|
env.get_pool_manager("http", "differentsite.com")
|
|
env.get_pool_manager("https", "differentsite.com")
|
|
|
|
# There are three pool managers: plain poolmanager for no_proxy domains,
|
|
# http proxymanager and https proxymanager
|
|
self.assert_pool_managers(
|
|
env, [None, "http://localhost:8888", "http://localhost:9999"]
|
|
)
|
|
|
|
@patch("tuf.ngclient._internal.proxy.getproxies")
|
|
def test_no_proxy_subdomain_match(self, mock_getproxies: Mock) -> None:
|
|
mock_getproxies.return_value = {
|
|
"https": "http://localhost:9999",
|
|
"no": "somesite.com, example.com, another.site.com",
|
|
}
|
|
|
|
env = ProxyEnvironment()
|
|
|
|
# this should match example.com in no_proxy
|
|
env.get_pool_manager("https", "subdomain.example.com")
|
|
|
|
# There is a single pool manager (no proxies)
|
|
self.assert_pool_managers(env, [None])
|
|
|
|
# this should not match example.com in no_proxy
|
|
env.get_pool_manager("https", "xexample.com")
|
|
|
|
# There are two pool managers: plain poolmanager for no_proxy domains,
|
|
# and a https proxymanager
|
|
self.assert_pool_managers(env, [None, "http://localhost:9999"])
|
|
|
|
@patch("tuf.ngclient._internal.proxy.getproxies")
|
|
def test_no_proxy_wildcard(self, mock_getproxies: Mock) -> None:
|
|
mock_getproxies.return_value = {
|
|
"https": "http://localhost:8888",
|
|
"no": "*",
|
|
}
|
|
|
|
env = ProxyEnvironment()
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "differentsite.com")
|
|
env.get_pool_manager("https", "subdomain.example.com")
|
|
|
|
# There is a single pool manager, no proxies
|
|
self.assert_pool_managers(env, [None])
|
|
|
|
@patch("tuf.ngclient._internal.proxy.getproxies")
|
|
def test_no_proxy_leading_dot(self, mock_getproxies: Mock) -> None:
|
|
mock_getproxies.return_value = {
|
|
"https": "http://localhost:8888",
|
|
"no": ".example.com",
|
|
}
|
|
|
|
env = ProxyEnvironment()
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "subdomain.example.com")
|
|
|
|
# There is a single pool manager, no proxies
|
|
self.assert_pool_managers(env, [None])
|
|
|
|
@patch("tuf.ngclient._internal.proxy.getproxies")
|
|
def test_all_proxy_set(self, mock_getproxies: Mock) -> None:
|
|
mock_getproxies.return_value = {
|
|
"all": "http://localhost:8888",
|
|
}
|
|
|
|
env = ProxyEnvironment()
|
|
env.get_pool_manager("http", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "subdomain.example.com")
|
|
env.get_pool_manager("https", "differentsite.com")
|
|
|
|
# There is a single proxy manager
|
|
self.assert_pool_managers(env, ["http://localhost:8888"])
|
|
|
|
# This urllib3 currently only handles http and https but let's test anyway
|
|
env.get_pool_manager("file", None)
|
|
|
|
# proxy manager and a plain pool manager
|
|
self.assert_pool_managers(env, ["http://localhost:8888", None])
|
|
|
|
@patch("tuf.ngclient._internal.proxy.getproxies")
|
|
def test_all_proxy_and_no_proxy_set(self, mock_getproxies: Mock) -> None:
|
|
mock_getproxies.return_value = {
|
|
"all": "http://localhost:8888",
|
|
"no": "somesite.com, example.com, another.site.com",
|
|
}
|
|
|
|
env = ProxyEnvironment()
|
|
env.get_pool_manager("http", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "example.com")
|
|
env.get_pool_manager("https", "subdomain.example.com")
|
|
|
|
# There is a single pool manager (no proxies)
|
|
self.assert_pool_managers(env, [None])
|
|
|
|
env.get_pool_manager("http", "differentsite.com")
|
|
env.get_pool_manager("https", "differentsite.com")
|
|
|
|
# There are two pool managers: plain poolmanager for no_proxy domains and
|
|
# one proxymanager
|
|
self.assert_pool_managers(env, [None, "http://localhost:8888"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
utils.configure_test_logging(sys.argv)
|
|
unittest.main()
|