mirror of
https://github.com/certbot/certbot.git
synced 2026-01-21 19:01:07 +03:00
Split --test-mode into --no-verify-ssl and --dvsni-port (fixes #462).
This commit is contained in:
@@ -249,8 +249,19 @@ def create_parser(plugins):
|
||||
help="Skip the end user license agreement screen.")
|
||||
add("-t", "--text", dest="text_mode", action="store_true",
|
||||
help="Use the text output instead of the curses UI.")
|
||||
add("--test-mode", action="store_true", help=config_help("test_mode"),
|
||||
default=flag_default("test_mode"))
|
||||
|
||||
testing_group = parser.add_argument_group(
|
||||
"testing", description="The following flags are meant for "
|
||||
"testing purposes only! Do NOT change them, unless you "
|
||||
"really know what you're doing!")
|
||||
testing_group.add_argument(
|
||||
"--no-verify-ssl", action="store_true",
|
||||
help=config_help("no_verify_ssl"),
|
||||
default=flag_default("no_verify_ssl"))
|
||||
# TODO: apache and nginx plugins do NOT respect it
|
||||
testing_group.add_argument(
|
||||
"--dvsni-port", type=int, help=config_help("dvsni_port"),
|
||||
default=flag_default("dvsni_port"))
|
||||
|
||||
subparsers = parser.add_subparsers(metavar="SUBCOMMAND")
|
||||
def add_subparser(name, func): # pylint: disable=missing-docstring
|
||||
|
||||
@@ -64,7 +64,7 @@ class Client(object):
|
||||
# TODO: Allow for other alg types besides RS256
|
||||
self.network = network2.Network(
|
||||
config.server, jwk.JWKRSA.load(self.account.key.pem),
|
||||
verify_ssl=(not config.test_mode))
|
||||
verify_ssl=config.no_verify_ssl)
|
||||
|
||||
self.config = config
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ CLI_DEFAULTS = dict(
|
||||
cert_path="/etc/letsencrypt/certs/cert-letsencrypt.pem",
|
||||
chain_path="/etc/letsencrypt/certs/chain-letsencrypt.pem",
|
||||
renewer_config_file="/etc/letsencrypt/renewer.conf",
|
||||
test_mode=False,
|
||||
no_verify_ssl=False,
|
||||
dvsni_port=challenges.DVSNI.PORT,
|
||||
)
|
||||
"""Defaults for CLI flags and `.IConfig` attributes."""
|
||||
|
||||
@@ -84,7 +85,3 @@ IConfig.work_dir)."""
|
||||
NETSTAT = "/bin/netstat"
|
||||
"""Location of netstat binary for checking whether a listener is already
|
||||
running on the specified port (Linux-specific)."""
|
||||
|
||||
BOULDER_TEST_MODE_CHALLENGE_PORT = 5001
|
||||
"""Port that Boulder will connect on for validations in test mode."""
|
||||
|
||||
|
||||
@@ -182,8 +182,11 @@ class IConfig(zope.interface.Interface):
|
||||
cert_path = zope.interface.Attribute("Let's Encrypt certificate file path.")
|
||||
chain_path = zope.interface.Attribute("Let's Encrypt chain file path.")
|
||||
|
||||
test_mode = zope.interface.Attribute(
|
||||
"Test mode. Disables certificate verification.")
|
||||
no_verify_ssl = zope.interface.Attribute(
|
||||
"Disable SSL certificate verification.")
|
||||
dvsni_port = zope.interface.Attribute(
|
||||
"Port number to perform DVSNI challenge. "
|
||||
"Boulder in testing mode defaults to 5001.")
|
||||
|
||||
|
||||
class IInstaller(IPlugin):
|
||||
|
||||
@@ -15,7 +15,6 @@ import zope.interface
|
||||
from acme import challenges
|
||||
|
||||
from letsencrypt import achallenges
|
||||
from letsencrypt import constants
|
||||
from letsencrypt import interfaces
|
||||
|
||||
from letsencrypt.plugins import common
|
||||
@@ -379,10 +378,8 @@ class StandaloneAuthenticator(common.Plugin):
|
||||
results_if_failure.append(False)
|
||||
if not self.tasks:
|
||||
raise ValueError("nothing for .perform() to do")
|
||||
port = challenges.DVSNI.PORT
|
||||
if self.config and self.config.test_mode:
|
||||
port = constants.BOULDER_TEST_MODE_CHALLENGE_PORT
|
||||
if self.already_listening(port):
|
||||
|
||||
if self.already_listening(self.config.port):
|
||||
# If we know a process is already listening on this port,
|
||||
# tell the user, and don't even attempt to bind it. (This
|
||||
# test is Linux-specific and won't indicate that the port
|
||||
@@ -390,7 +387,7 @@ class StandaloneAuthenticator(common.Plugin):
|
||||
return results_if_failure
|
||||
# Try to do the authentication; note that this creates
|
||||
# the listener subprocess via os.fork()
|
||||
if self.start_listener(port, key):
|
||||
if self.start_listener(self.config.port, key):
|
||||
return results_if_success
|
||||
else:
|
||||
# TODO: This should probably raise a DVAuthError exception
|
||||
@@ -427,8 +424,9 @@ class StandaloneAuthenticator(common.Plugin):
|
||||
def more_info(self): # pylint: disable=no-self-use
|
||||
"""Human-readable string that describes the Authenticator."""
|
||||
return ("The Standalone Authenticator uses PyOpenSSL to listen "
|
||||
"on port 443 and perform DVSNI challenges. Once a certificate "
|
||||
"on port {port} and perform DVSNI challenges. Once a certificate "
|
||||
"is attained, it will be saved in the "
|
||||
"(TODO) current working directory.{0}{0}"
|
||||
"TCP port 443 must be available in order to use the "
|
||||
"Standalone Authenticator.".format(os.linesep))
|
||||
"(TODO) current working directory.{linesep}{linesep}"
|
||||
"TCP port {port} must be available in order to use the "
|
||||
"Standalone Authenticator.".format(
|
||||
linesep=os.linesep, port=self.config.port))
|
||||
|
||||
@@ -22,6 +22,7 @@ KEY = le_util.Key("foo", pkg_resources.resource_string(
|
||||
"acme.jose", os.path.join("testdata", "rsa512_key.pem")))
|
||||
PRIVATE_KEY = OpenSSL.crypto.load_privatekey(
|
||||
OpenSSL.crypto.FILETYPE_PEM, KEY.pem)
|
||||
CONFIG = mock.Mock(port=5001)
|
||||
|
||||
|
||||
# Classes based on to allow interrupting infinite loop under test
|
||||
@@ -59,7 +60,7 @@ class ChallPrefTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
|
||||
def test_chall_pref(self):
|
||||
self.assertEqual(self.authenticator.get_chall_pref("example.com"),
|
||||
@@ -71,7 +72,7 @@ class SNICallbackTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
self.cert = achallenges.DVSNI(
|
||||
challb=acme_util.DVSNI_P,
|
||||
domain="example.com", key=KEY).gen_cert_and_response()[0]
|
||||
@@ -109,7 +110,7 @@ class ClientSignalHandlerTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
self.authenticator.tasks = {"foononce.acme.invalid": "stuff"}
|
||||
self.authenticator.child_pid = 12345
|
||||
|
||||
@@ -138,7 +139,7 @@ class SubprocSignalHandlerTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
self.authenticator.tasks = {"foononce.acme.invalid": "stuff"}
|
||||
self.authenticator.child_pid = 12345
|
||||
self.authenticator.parent_pid = 23456
|
||||
@@ -190,7 +191,7 @@ class AlreadyListeningTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
|
||||
@mock.patch("letsencrypt.plugins.standalone.authenticator.psutil."
|
||||
"net_connections")
|
||||
@@ -293,7 +294,7 @@ class PerformTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
|
||||
self.achall1 = achallenges.DVSNI(
|
||||
challb=acme_util.chall_to_challb(
|
||||
@@ -327,7 +328,8 @@ class PerformTest(unittest.TestCase):
|
||||
self.assertTrue(isinstance(result[0], challenges.ChallengeResponse))
|
||||
self.assertTrue(isinstance(result[1], challenges.ChallengeResponse))
|
||||
self.assertFalse(result[2])
|
||||
self.authenticator.start_listener.assert_called_once_with(443, KEY)
|
||||
self.authenticator.start_listener.assert_called_once_with(
|
||||
CONFIG.port, KEY)
|
||||
|
||||
def test_cannot_perform(self):
|
||||
"""What happens if start_listener() returns False."""
|
||||
@@ -342,7 +344,8 @@ class PerformTest(unittest.TestCase):
|
||||
self.assertTrue(isinstance(result, list))
|
||||
self.assertEqual(len(result), 3)
|
||||
self.assertEqual(result, [None, None, False])
|
||||
self.authenticator.start_listener.assert_called_once_with(443, KEY)
|
||||
self.authenticator.start_listener.assert_called_once_with(
|
||||
CONFIG.port, KEY)
|
||||
|
||||
def test_perform_with_pending_tasks(self):
|
||||
self.authenticator.tasks = {"foononce.acme.invalid": "cert_data"}
|
||||
@@ -367,7 +370,7 @@ class StartListenerTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
|
||||
@mock.patch("letsencrypt.plugins.standalone.authenticator."
|
||||
"Crypto.Random.atfork")
|
||||
@@ -402,7 +405,7 @@ class DoParentProcessTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
|
||||
@mock.patch("letsencrypt.plugins.standalone.authenticator."
|
||||
"zope.component.getUtility")
|
||||
@@ -444,7 +447,7 @@ class DoChildProcessTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
self.cert = achallenges.DVSNI(
|
||||
challb=acme_util.chall_to_challb(
|
||||
challenges.DVSNI(r=("x" * 32), nonce="abcdef"), "pending"),
|
||||
@@ -530,7 +533,7 @@ class CleanupTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import \
|
||||
StandaloneAuthenticator
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
self.achall = achallenges.DVSNI(
|
||||
challb=acme_util.chall_to_challb(
|
||||
challenges.DVSNI(r="whee", nonce="foononce"), "pending"),
|
||||
@@ -562,7 +565,7 @@ class MoreInfoTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import (
|
||||
StandaloneAuthenticator)
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
|
||||
def test_more_info(self):
|
||||
"""Make sure exceptions aren't raised."""
|
||||
@@ -574,7 +577,7 @@ class InitTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
from letsencrypt.plugins.standalone.authenticator import (
|
||||
StandaloneAuthenticator)
|
||||
self.authenticator = StandaloneAuthenticator(config=None, name=None)
|
||||
self.authenticator = StandaloneAuthenticator(config=CONFIG, name=None)
|
||||
|
||||
def test_prepare(self):
|
||||
"""Make sure exceptions aren't raised.
|
||||
|
||||
Reference in New Issue
Block a user