WIP commit of adding a --source-address flag.

This commit is contained in:
signop 2018-05-15 14:53:42 -07:00
parent 722dac86d5
commit 7aee94e221
8 changed files with 30 additions and 6 deletions

View file

@ -878,6 +878,7 @@ class ClientNetwork(object): # pylint: disable=too-many-instance-attributes
if source_address is not None:
adapter = SourceAddressAdapter(source_address)
logger.debug("Set source address for client to %s", source_address)
self.session.mount("http://", adapter)
self.session.mount("https://", adapter)

View file

@ -1134,13 +1134,15 @@ class ClientNetworkSourceAddressBindingTest(unittest.TestCase):
used the provided source address."""
def setUp(self):
self.source_address = "8.8.8.8"
self.source_addresses = ["8.8.8.8", "2001:db8:8:4::2",
"2001:0000:4136:e378:8000:63bf:3fff:fdd2"]
def test_source_address_set(self):
from acme.client import ClientNetwork
net = ClientNetwork(key=None, alg=None, source_address=self.source_address)
for adapter in net.session.adapters.values():
self.assertTrue(self.source_address in adapter.source_address)
for source_address in self.source_addresses:
net = ClientNetwork(key=None, alg=None, source_address=source_address)
for adapter in net.session.adapters.values():
self.assertTrue(source_address in adapter.source_address)
def test_behavior_assumption(self):
"""This is a test that guardrails the HTTPAdapter behavior so that if the default for

View file

@ -1237,6 +1237,9 @@ def _create_subparsers(helpful):
help="Add a comment to the default user agent string. May be used when repackaging Certbot "
"or calling it from another tool to allow additional statistical data to be collected."
" Ignored if --user-agent is set. (Example: Foo-Wrapper/1.0)")
helpful.add(
None, "--source-address", default=None, type=str,
help="Specify a source IP address for the client.")
helpful.add("certonly",
"--csr", default=flag_default("csr"), type=read_file,
help="Path to a Certificate Signing Request (CSR) in DER or PEM format."

View file

@ -42,7 +42,8 @@ def acme_from_config_key(config, key, regr=None):
"Wrangle ACME client construction"
# TODO: Allow for other alg types besides RS256
net = acme_client.ClientNetwork(key, account=regr, verify_ssl=(not config.no_verify_ssl),
user_agent=determine_user_agent(config))
user_agent=determine_user_agent(config),
source_address=config.source_address)
return acme_client.BackwardsCompatibleClientV2(net, key, config.server)

View file

@ -231,6 +231,8 @@ class IConfig(zope.interface.Interface):
"A conforming ACME server will still attempt to connect on port 443.")
tls_sni_01_address = zope.interface.Attribute(
"The address the server listens to during tls-sni-01 challenge.")
source_address = zope.interface.Attribute(
"The address the client binds to when connecting to the ACME server.")
http01_port = zope.interface.Attribute(
"Port used in the http-01 challenge. "

View file

@ -430,6 +430,20 @@ class ParseTest(unittest.TestCase): # pylint: disable=too-many-public-methods
self.assertRaises(errors.Error, self.parse,
"--allow-subset-of-names -d *.example.org".split())
def test_source_address_flag_v4(self):
namespace = self.parse(["--source-address=8.8.8.8"])
self.assertEqual(namespace.source_address, "8.8.8.8")
def test_source_address_flag_v6(self):
ipv6_addrs = ["2001:db8:8:4::2", "2001:0000:4136:e378:8000:63bf:3fff:fdd2"]
for addr in ipv6_addrs:
namespace = self.parse(["--source-address={}".format(addr)])
self.assertEqual(namespace.source_address, addr)
def test_source_address_flag_not_set(self):
namespace = self.parse([])
self.assertIsNone(namespace.source_address)
class DefaultTest(unittest.TestCase):
"""Tests for certbot.cli._Default."""

View file

@ -692,7 +692,7 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met
args += ["--user-agent", ua]
self._call_no_clientmock(args)
acme_net.assert_called_once_with(mock.ANY, account=mock.ANY, verify_ssl=True,
user_agent=ua)
user_agent=ua, source_address=mock.ANY)
@mock.patch('certbot.main.plug_sel.record_chosen_plugins')
@mock.patch('certbot.main.plug_sel.pick_installer')

View file

@ -336,6 +336,7 @@ class ConfigTestCase(TempDirTestCase):
self.config.fullchain_path = constants.CLI_DEFAULTS['auth_chain_path']
self.config.chain_path = constants.CLI_DEFAULTS['auth_chain_path']
self.config.server = "https://example.com"
self.config.source_address = None
def lock_and_call(func, lock_path):
"""Grab a lock for lock_path and call func.