Compare commits

...

15 Commits

Author SHA1 Message Date
Brad Warren
d24b1f7310 document default is ACMEv2 2018-04-03 13:13:49 -07:00
ohemorange
bdaccb645b Support quoted server names in Nginx (#5811)
* Support quoted server names in Nginx

* add unit test to check that we strip quotes

* update configurator test
2018-04-03 12:14:23 -07:00
Joona Hoikkala
f5ad08047b Fix comparison to check values (#5815) 2018-04-03 12:04:57 -07:00
Brad Warren
8fd3f6c64c fixes #5380 (#5812) 2018-04-03 11:44:13 -07:00
Joshua Bowman
4d706ac77e Update default to ACMEv2 server (#5722) 2018-03-30 17:16:48 -07:00
sydneyli
8231b1a19c Pin Lexicon version to 2.2.1 (#5803) 2018-03-29 17:09:21 -07:00
ohemorange
5ff7f2211e Explicitly add six as a dependency in letsencrypt-auto-source dockerfiles (#5808)
* update documentation

* explicitly add six as a dependency in letsencrypt-auto-source dockerfiles

* pin six version
2018-03-29 15:34:38 -07:00
Brad Warren
7630550ac4 Revert "Update oldest tests to test against 0.22.0 versions (#5800)" (#5809)
This reverts commit 336950c0b9.
2018-03-29 14:15:59 -07:00
Brad Warren
336950c0b9 Update oldest tests to test against 0.22.0 versions (#5800) 2018-03-28 08:37:00 -07:00
ohemorange
a779e06d47 Add integration tests for nginx plugin (#5441)
* Add a rewrite directive for the .well-known location so we don't hit existing rewrites

* add comment

* Add (nonexistent) document root so we don't use the default value

* Add integration tests for nginx plugin

* add a sleep 5 to test on travis

* put sleep 5 in the right spot

* test return status of grep respecting -e and note that we're actually not posix compliant

* redelete newline
2018-03-27 17:33:48 -07:00
ohemorange
669312d248 We don't try to add location blocks through a mechanism that checks REPEATABLE_DIRECTIVES, and it wouldn't work as an accurate check even if we did, so just remove it (#5787) 2018-03-27 15:25:34 -07:00
ohemorange
4d082e22e6 Remove ipv6only=on from duplicated vhosts (#5793)
* rename delete_default to remove_singleton_listen_params

* update docstring

* add documentation to obj.py

* add test for remove duplicate ipv6only

* Remove ipv6only=on from duplicated vhosts

* add test to make sure ipv6only=on is not erroneously removed
2018-03-27 15:11:39 -07:00
sydneyli
af2cce4ca8 fix(auth_handler): cleanup is always called (#5779)
* fix(auth_handler): cleanup is always called

* test(auth_handler): tests for various error cases
2018-03-26 17:09:02 -07:00
ohemorange
804fd4b78a factor out location_directive_for_achall (#5794) 2018-03-26 16:28:30 -07:00
Andrew Starr-Bochicchio
8cdb213a61 Google DNS: Mock API discovery to run tests without internet connection. (#5791)
* Google DNS: Mock API discovery to run tests without internet connection.

* Allow test to pass when run from main cerbot package.
2018-03-26 16:12:55 -07:00
30 changed files with 1644 additions and 84 deletions

View File

@@ -11,7 +11,7 @@ version = '0.23.0.dev0'
install_requires = [
'acme>=0.21.1',
'certbot>=0.21.1',
'dns-lexicon',
'dns-lexicon>=2.2.1', # Support for >1 TXT record per name
'mock',
'setuptools',
'zope.interface',

View File

@@ -11,7 +11,7 @@ version = '0.23.0.dev0'
install_requires = [
'acme>=0.21.1',
'certbot>=0.21.1',
'dns-lexicon',
'dns-lexicon>=2.2.1', # Support for >1 TXT record per name
'mock',
'setuptools',
'zope.interface',

View File

@@ -11,7 +11,7 @@ version = '0.23.0.dev0'
install_requires = [
'acme>=0.21.1',
'certbot>=0.21.1',
'dns-lexicon',
'dns-lexicon>=2.2.1', # Support for >1 TXT record per name
'mock',
'setuptools',
'zope.interface',

View File

@@ -81,7 +81,7 @@ class _GoogleClient(object):
Encapsulates all communication with the Google Cloud DNS API.
"""
def __init__(self, account_json=None):
def __init__(self, account_json=None, dns_api=None):
scopes = ['https://www.googleapis.com/auth/ndev.clouddns.readwrite']
if account_json is not None:
@@ -92,7 +92,12 @@ class _GoogleClient(object):
credentials = None
self.project_id = self.get_project_id()
self.dns = discovery.build('dns', 'v1', credentials=credentials, cache_discovery=False)
if not dns_api:
self.dns = discovery.build('dns', 'v1',
credentials=credentials,
cache_discovery=False)
else:
self.dns = dns_api
def add_txt_record(self, domain, record_name, record_content, record_ttl):
"""

View File

@@ -4,7 +4,9 @@ import os
import unittest
import mock
from googleapiclient import discovery
from googleapiclient.errors import Error
from googleapiclient.http import HttpMock
from httplib2 import ServerNotFoundError
from certbot import errors
@@ -68,7 +70,13 @@ class GoogleClientTest(unittest.TestCase):
def _setUp_client_with_mock(self, zone_request_side_effect):
from certbot_dns_google.dns_google import _GoogleClient
client = _GoogleClient(ACCOUNT_JSON_PATH)
pwd = os.path.dirname(__file__)
rel_path = 'testdata/discovery.json'
discovery_file = os.path.join(pwd, rel_path)
http_mock = HttpMock(discovery_file, {'status': '200'})
dns_api = discovery.build('dns', 'v1', http=http_mock)
client = _GoogleClient(ACCOUNT_JSON_PATH, dns_api)
# Setup
mock_mz = mock.MagicMock()

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@ version = '0.23.0.dev0'
install_requires = [
'acme>=0.21.1',
'certbot>=0.21.1',
'dns-lexicon',
'dns-lexicon>=2.2.1', # Support for >1 TXT record per name
'mock',
'setuptools',
'zope.interface',

View File

@@ -11,7 +11,7 @@ version = '0.23.0.dev0'
install_requires = [
'acme>=0.21.1',
'certbot>=0.21.1',
'dns-lexicon',
'dns-lexicon>=2.2.1', # Support for >1 TXT record per name
'mock',
'setuptools',
'zope.interface',

View File

@@ -332,7 +332,8 @@ class NginxConfigurator(common.Installer):
def _vhost_from_duplicated_default(self, domain, port=None):
if self.new_vhost is None:
default_vhost = self._get_default_vhost(port)
self.new_vhost = self.parser.duplicate_vhost(default_vhost, delete_default=True)
self.new_vhost = self.parser.duplicate_vhost(default_vhost,
remove_singleton_listen_params=True)
self.new_vhost.names = set()
self._add_server_name_to_vhost(self.new_vhost, domain)
@@ -913,7 +914,7 @@ class NginxConfigurator(common.Installer):
raise errors.PluginError("Nginx build doesn't support SNI")
product_name, product_version = version_matches[0]
if product_name is not 'nginx':
if product_name != 'nginx':
logger.warning("NGINX derivative %s is not officially supported by"
" certbot", product_name)

View File

@@ -159,16 +159,22 @@ class NginxHttp01(common.ChallengePerformer):
document_root = os.path.join(
self.configurator.config.work_dir, "http_01_nonexistent")
block.extend([['server_name', ' ', achall.domain],
['root', ' ', document_root],
self._location_directive_for_achall(achall)
])
# TODO: do we want to return something else if they otherwise access this block?
return [['server'], block]
def _location_directive_for_achall(self, achall):
validation = achall.validation(achall.account_key)
validation_path = self._get_validation_path(achall)
block.extend([['server_name', ' ', achall.domain],
['root', ' ', document_root],
[['location', ' ', '=', ' ', validation_path],
[['default_type', ' ', 'text/plain'],
['return', ' ', '200', ' ', validation]]]])
# TODO: do we want to return something else if they otherwise access this block?
return [['server'], block]
location_directive = [['location', ' ', '=', ' ', validation_path],
[['default_type', ' ', 'text/plain'],
['return', ' ', '200', ' ', validation]]]
return location_directive
def _make_or_mod_server_block(self, achall):
"""Modifies a server block to respond to a challenge.
@@ -191,12 +197,7 @@ class NginxHttp01(common.ChallengePerformer):
vhost = vhosts[0]
# Modify existing server block
validation = achall.validation(achall.account_key)
validation_path = self._get_validation_path(achall)
location_directive = [[['location', ' ', '=', ' ', validation_path],
[['default_type', ' ', 'text/plain'],
['return', ' ', '200', ' ', validation]]]]
location_directive = [self._location_directive_for_achall(achall)]
self.configurator.parser.add_server_directives(vhost,
location_directive)

View File

@@ -29,6 +29,8 @@ class Addr(common.Addr):
:param str port: port number or "\*" or ""
:param bool ssl: Whether the directive includes 'ssl'
:param bool default: Whether the directive includes 'default_server'
:param bool default: Whether this is an IPv6 address
:param bool ipv6only: Whether the directive includes 'ipv6only=on'
"""
UNSPECIFIED_IPV4_ADDRESSES = ('', '*', '0.0.0.0')

View File

@@ -354,13 +354,14 @@ class NginxParser(object):
except errors.MisconfigurationError as err:
raise errors.MisconfigurationError("Problem in %s: %s" % (filename, str(err)))
def duplicate_vhost(self, vhost_template, delete_default=False, only_directives=None):
def duplicate_vhost(self, vhost_template, remove_singleton_listen_params=False,
only_directives=None):
"""Duplicate the vhost in the configuration files.
:param :class:`~certbot_nginx.obj.VirtualHost` vhost_template: The vhost
whose information we copy
:param bool delete_default: If we should remove default_server
from listen directives in the block.
:param bool remove_singleton_listen_params: If we should remove parameters
from listen directives in the block that can only be used once per address
:param list only_directives: If it exists, only duplicate the named directives. Only
looks at first level of depth; does not expand includes.
@@ -387,15 +388,18 @@ class NginxParser(object):
enclosing_block.append(raw_in_parsed)
new_vhost.path[-1] = len(enclosing_block) - 1
if delete_default:
if remove_singleton_listen_params:
for addr in new_vhost.addrs:
addr.default = False
addr.ipv6only = False
for directive in enclosing_block[new_vhost.path[-1]][1]:
if len(directive) > 0 and directive[0] == 'listen':
if 'default_server' in directive:
del directive[directive.index('default_server')]
if 'default' in directive:
del directive[directive.index('default')]
if 'ipv6only=on' in directive:
del directive[directive.index('ipv6only=on')]
return new_vhost
@@ -561,7 +565,7 @@ def _update_or_add_directives(directives, insert_at_top, block):
INCLUDE = 'include'
REPEATABLE_DIRECTIVES = set(['server_name', 'listen', INCLUDE, 'location', 'rewrite'])
REPEATABLE_DIRECTIVES = set(['server_name', 'listen', INCLUDE, 'rewrite'])
COMMENT = ' managed by Certbot'
COMMENT_BLOCK = [' ', '#', COMMENT]
@@ -739,7 +743,7 @@ def _parse_server_raw(server):
if addr.ssl:
parsed_server['ssl'] = True
elif directive[0] == 'server_name':
parsed_server['names'].update(directive[1:])
parsed_server['names'].update(x.strip('"\'') for x in directive[1:])
elif _is_ssl_on_directive(directive):
parsed_server['ssl'] = True
apply_ssl_to_all_addrs = True

View File

@@ -639,7 +639,7 @@ class NginxConfiguratorTest(util.NginxTest):
self.assertEqual([[['server'],
[['listen', 'myhost', 'default_server'],
['listen', 'otherhost', 'default_server'],
['server_name', 'www.example.org'],
['server_name', '"www.example.org"'],
[['location', '/'],
[['root', 'html'],
['index', 'index.html', 'index.htm']]]]],

View File

@@ -430,7 +430,7 @@ class NginxParserTest(util.NginxTest): #pylint: disable=too-many-public-methods
vhosts = nparser.get_vhosts()
default = [x for x in vhosts if 'default' in x.filep][0]
new_vhost = nparser.duplicate_vhost(default, delete_default=True)
new_vhost = nparser.duplicate_vhost(default, remove_singleton_listen_params=True)
nparser.filedump(ext='')
# check properties of new vhost
@@ -448,6 +448,28 @@ class NginxParserTest(util.NginxTest): #pylint: disable=too-many-public-methods
self.assertEqual(len(default.raw), len(new_vhost_parsed.raw))
self.assertTrue(next(iter(default.addrs)).super_eq(next(iter(new_vhost_parsed.addrs))))
def test_duplicate_vhost_remove_ipv6only(self):
nparser = parser.NginxParser(self.config_path)
vhosts = nparser.get_vhosts()
ipv6ssl = [x for x in vhosts if 'ipv6ssl' in x.filep][0]
new_vhost = nparser.duplicate_vhost(ipv6ssl, remove_singleton_listen_params=True)
nparser.filedump(ext='')
for addr in new_vhost.addrs:
self.assertFalse(addr.ipv6only)
identical_vhost = nparser.duplicate_vhost(ipv6ssl, remove_singleton_listen_params=False)
nparser.filedump(ext='')
called = False
for addr in identical_vhost.addrs:
if addr.ipv6:
self.assertTrue(addr.ipv6only)
called = True
self.assertTrue(called)
if __name__ == "__main__":
unittest.main() # pragma: no cover

View File

@@ -1,7 +1,7 @@
server {
listen myhost default_server;
listen otherhost default_server;
server_name www.example.org;
server_name "www.example.org";
location / {
root html;

View File

@@ -49,9 +49,9 @@ http {
server {
# IPv4.
listen 5002;
listen 5002 $default_server;
# IPv6.
listen [::]:5002 default ipv6only=on;
listen [::]:5002 $default_server;
server_name nginx.wtf nginx2.wtf;
root $root/webroot;
@@ -62,5 +62,36 @@ http {
try_files \$uri \$uri/ /index.html;
}
}
server {
listen 5002;
listen [::]:5002;
server_name nginx3.wtf;
root $root/webroot;
location /.well-known/ {
return 404;
}
return 301 https://\$host\$request_uri;
}
server {
listen 8082;
listen [::]:8082;
server_name nginx4.wtf nginx5.wtf;
}
server {
listen 5002;
listen [::]:5002;
listen 5001 ssl;
listen [::]:5001 ssl;
if (\$scheme != "https") {
return 301 https://\$host\$request_uri;
}
server_name nginx6.wtf nginx7.wtf;
}
}
EOF

View File

@@ -1,4 +1,4 @@
#!/bin/sh -xe
#!/bin/bash -xe
# prerequisite: apt-get install --no-install-recommends nginx-light openssl
. ./tests/integration/_common.sh
@@ -6,13 +6,15 @@
export PATH="/usr/sbin:$PATH" # /usr/sbin/nginx
nginx_root="$root/nginx"
mkdir $nginx_root
original=$(root="$nginx_root" ./certbot-nginx/tests/boulder-integration.conf.sh)
nginx_conf="$nginx_root/nginx.conf"
echo "$original" > $nginx_conf
reload_nginx () {
original=$(root="$nginx_root" ./certbot-nginx/tests/boulder-integration.conf.sh)
nginx_conf="$nginx_root/nginx.conf"
echo "$original" > $nginx_conf
killall nginx || true
nginx -c $nginx_root/nginx.conf
killall nginx || true
nginx -c $nginx_root/nginx.conf
}
certbot_test_nginx () {
certbot_test \
@@ -32,10 +34,30 @@ test_deployment_and_rollback() {
diff -q <(echo "$original") $nginx_conf
}
export default_server="default_server"
reload_nginx
certbot_test_nginx --domains nginx.wtf run
test_deployment_and_rollback nginx.wtf
certbot_test_nginx --domains nginx2.wtf --preferred-challenges http
test_deployment_and_rollback nginx2.wtf
# Overlapping location block and server-block-level return 301
certbot_test_nginx --domains nginx3.wtf --preferred-challenges http
test_deployment_and_rollback nginx3.wtf
# No matching server block; default_server exists
certbot_test_nginx --domains nginx4.wtf --preferred-challenges http
test_deployment_and_rollback nginx4.wtf
# No matching server block; default_server does not exist
export default_server=""
reload_nginx
if nginx -c $nginx_root/nginx.conf -T 2>/dev/null | grep "default_server"; then
echo "Failed to remove default_server"
exit 1
fi
certbot_test_nginx --domains nginx5.wtf --preferred-challenges http
test_deployment_and_rollback nginx5.wtf
# Mutiple domains, mix of matching and not
certbot_test_nginx --domains nginx6.wtf,nginx7.wtf --preferred-challenges http
test_deployment_and_rollback nginx6.wtf
# note: not reached if anything above fails, hence "killall" at the
# top

View File

@@ -69,14 +69,15 @@ class AuthHandler(object):
# While there are still challenges remaining...
while self._has_challenges(aauthzrs):
resp = self._solve_challenges(aauthzrs)
logger.info("Waiting for verification...")
if config.debug_challenges:
notify('Challenges loaded. Press continue to submit to CA. '
'Pass "-v" for more info about challenges.', pause=True)
with error_handler.ExitHandler(self._cleanup_challenges, aauthzrs):
resp = self._solve_challenges(aauthzrs)
logger.info("Waiting for verification...")
if config.debug_challenges:
notify('Challenges loaded. Press continue to submit to CA. '
'Pass "-v" for more info about challenges.', pause=True)
# Send all Responses - this modifies achalls
self._respond(aauthzrs, resp, best_effort)
# Send all Responses - this modifies achalls
self._respond(aauthzrs, resp, best_effort)
# Just make sure all decisions are complete.
self.verify_authzr_complete(aauthzrs)
@@ -118,14 +119,13 @@ class AuthHandler(object):
"""Get Responses for challenges from authenticators."""
resp = []
all_achalls = self._get_all_achalls(aauthzrs)
with error_handler.ErrorHandler(self._cleanup_challenges, aauthzrs, all_achalls):
try:
if all_achalls:
resp = self.auth.perform(all_achalls)
except errors.AuthorizationError:
logger.critical("Failure in setting up challenges.")
logger.info("Attempting to clean up outstanding challenges...")
raise
try:
if all_achalls:
resp = self.auth.perform(all_achalls)
except errors.AuthorizationError:
logger.critical("Failure in setting up challenges.")
logger.info("Attempting to clean up outstanding challenges...")
raise
assert len(resp) == len(all_achalls)
@@ -147,13 +147,10 @@ class AuthHandler(object):
"""
# TODO: chall_update is a dirty hack to get around acme-spec #105
chall_update = dict()
active_achalls = self._send_responses(aauthzrs, resp, chall_update)
self._send_responses(aauthzrs, resp, chall_update)
# Check for updated status...
try:
self._poll_challenges(aauthzrs, chall_update, best_effort)
finally:
self._cleanup_challenges(aauthzrs, active_achalls)
self._poll_challenges(aauthzrs, chall_update, best_effort)
def _send_responses(self, aauthzrs, resps, chall_update):
"""Send responses and make sure errors are handled.
@@ -294,7 +291,7 @@ class AuthHandler(object):
chall_prefs.extend(plugin_pref)
return chall_prefs
def _cleanup_challenges(self, aauthzrs, achalls):
def _cleanup_challenges(self, aauthzrs, achalls=None):
"""Cleanup challenges.
:param aauthzrs: authorizations and their selected annotated
@@ -305,7 +302,8 @@ class AuthHandler(object):
"""
logger.info("Cleaning up challenges")
if achalls is None:
achalls = self._get_all_achalls(aauthzrs)
if achalls:
self.auth.cleanup(achalls)
for achall in achalls:

View File

@@ -84,7 +84,7 @@ CLI_DEFAULTS = dict(
config_dir="/etc/letsencrypt",
work_dir="/var/lib/letsencrypt",
logs_dir="/var/log/letsencrypt",
server="https://acme-v01.api.letsencrypt.org/directory",
server="https://acme-v02.api.letsencrypt.org/directory",
# Plugins parsers
configurator=None,

View File

@@ -24,7 +24,6 @@ if os.name != "nt":
if signal.getsignal(signal_code) != signal.SIG_IGN:
_SIGNALS.append(signal_code)
class ErrorHandler(object):
"""Context manager for running code that must be cleaned up on failure.
@@ -55,6 +54,7 @@ class ErrorHandler(object):
"""
def __init__(self, func=None, *args, **kwargs):
self.call_on_regular_exit = False
self.body_executed = False
self.funcs = []
self.prev_handlers = {}
@@ -70,8 +70,11 @@ class ErrorHandler(object):
self.body_executed = True
retval = False
# SystemExit is ignored to properly handle forks that don't exec
if exec_type in (None, SystemExit):
if exec_type is SystemExit:
return retval
elif exec_type is None:
if not self.call_on_regular_exit:
return retval
elif exec_type is errors.SignalExit:
logger.debug("Encountered signals: %s", self.received_signals)
retval = True
@@ -136,3 +139,15 @@ class ErrorHandler(object):
for signum in self.received_signals:
logger.debug("Calling signal %s", signum)
os.kill(os.getpid(), signum)
class ExitHandler(ErrorHandler):
"""Context manager for running code that must be cleaned up.
Subclass of ErrorHandler, with the same usage and parameters.
In addition to cleaning up on all signals, also cleans up on
regular exit.
"""
def __init__(self, func=None, *args, **kwargs):
ErrorHandler.__init__(self, func, *args, **kwargs)
self.call_on_regular_exit = True

View File

@@ -289,6 +289,32 @@ class HandleAuthorizationsTest(unittest.TestCase):
self.assertEqual(
self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01")
@mock.patch("certbot.auth_handler.AuthHandler._respond")
def test_respond_error(self, mock_respond):
authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)]
mock_order = mock.MagicMock(authorizations=authzrs)
mock_respond.side_effect = errors.AuthorizationError
self.assertRaises(
errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
self.assertEqual(self.mock_auth.cleanup.call_count, 1)
self.assertEqual(
self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01")
@mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
@mock.patch("certbot.auth_handler.AuthHandler.verify_authzr_complete")
def test_incomplete_authzr_error(self, mock_verify, mock_poll):
authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)]
mock_order = mock.MagicMock(authorizations=authzrs)
mock_verify.side_effect = errors.AuthorizationError
mock_poll.side_effect = self._validate_all
self.assertRaises(
errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
self.assertEqual(self.mock_auth.cleanup.call_count, 1)
self.assertEqual(
self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01")
def _validate_all(self, aauthzrs, unused_1, unused_2):
for i, aauthzr in enumerate(aauthzrs):
azr = aauthzr.authzr

View File

@@ -36,7 +36,7 @@ def send_signal(signum):
class ErrorHandlerTest(unittest.TestCase):
"""Tests for certbot.error_handler."""
"""Tests for certbot.error_handler.ErrorHandler."""
def setUp(self):
from certbot import error_handler
@@ -47,6 +47,7 @@ class ErrorHandlerTest(unittest.TestCase):
self.handler = error_handler.ErrorHandler(self.init_func,
*self.init_args,
**self.init_kwargs)
# pylint: disable=protected-access
self.signals = error_handler._SIGNALS
@@ -113,6 +114,33 @@ class ErrorHandlerTest(unittest.TestCase):
pass
self.assertFalse(self.init_func.called)
def test_regular_exit(self):
func = mock.MagicMock()
self.handler.register(func)
with self.handler:
pass
self.init_func.assert_not_called()
func.assert_not_called()
class ExitHandlerTest(ErrorHandlerTest):
"""Tests for certbot.error_handler.ExitHandler."""
def setUp(self):
from certbot import error_handler
super(ExitHandlerTest, self).setUp()
self.handler = error_handler.ExitHandler(self.init_func,
*self.init_args,
**self.init_kwargs)
def test_regular_exit(self):
func = mock.MagicMock()
self.handler.register(func)
with self.handler:
pass
self.init_func.assert_called_once_with(*self.init_args,
**self.init_kwargs)
func.assert_called_once_with()
if __name__ == "__main__":
unittest.main() # pragma: no cover

View File

@@ -3,3 +3,7 @@
.. automodule:: certbot.constants
:members:
:exclude-members: SSL_DHPARAMS_SRC
.. autodata:: SSL_DHPARAMS_SRC
:annotation: = '/path/to/certbot/ssl-dhparams.pem'

View File

@@ -871,24 +871,16 @@ Example usage for DNS-01 (Cloudflare API v4) (for example purposes only, do not
Changing the ACME Server
========================
By default, Certbot uses Let's Encrypt's initial production server at
https://acme-v01.api.letsencrypt.org/. You can tell Certbot to use a
By default, Certbot uses Let's Encrypt's ACMEv2 production server at
https://acme-v02.api.letsencrypt.org/. You can tell Certbot to use a
different CA by providing ``--server`` on the command line or in a
:ref:`configuration file <config-file>` with the URL of the server's
ACME directory. For example, if you would like to use Let's Encrypt's
new ACMEv2 server, you would add ``--server
https://acme-v02.api.letsencrypt.org/directory`` to the command line.
initial ACMEv1 server, you would add ``--server
https://acme-v01.api.letsencrypt.org/directory`` to the command line.
Certbot will automatically select which version of the ACME protocol to
use based on the contents served at the provided URL.
If you use ``--server`` to specify an ACME CA that implements a newer
version of the spec, you may be able to obtain a certificate for a
wildcard domain. Some CAs (such as Let's Encrypt) require that domain
validation for wildcard domains must be done through modifications to
DNS records which means that the dns-01_ challenge type must be used. To
see a list of Certbot plugins that support this challenge type and how
to use them, see plugins_.
Lock Files
==========

View File

@@ -11,7 +11,7 @@ RUN yum install -y python-pip sudo
COPY ./pieces/pipstrap.py /opt
RUN /opt/pipstrap.py
# Pin pytest version for increased stability
RUN pip install pytest==3.2.5
RUN pip install pytest==3.2.5 six==1.10.0
# Add an unprivileged user:
RUN useradd --create-home --home-dir /home/lea --shell /bin/bash --groups wheel --uid 1000 lea

View File

@@ -15,7 +15,7 @@ RUN apt-get update && \
COPY ./pieces/pipstrap.py /opt
RUN /opt/pipstrap.py
# Pin pytest version for increased stability
RUN pip install pytest==3.2.5
RUN pip install pytest==3.2.5 six==1.10.0
# Let that user sudo:
RUN sed -i.bkp -e \

View File

@@ -19,7 +19,7 @@ RUN apt-get update && \
COPY ./pieces/pipstrap.py /opt
RUN /opt/pipstrap.py
# Pin pytest version for increased stability
RUN pip install pytest==3.2.5
RUN pip install pytest==3.2.5 six==1.10.0
RUN mkdir -p /home/lea/certbot

View File

@@ -14,7 +14,7 @@ RUN apt-get update && \
COPY ./pieces/pipstrap.py /opt
RUN /opt/pipstrap.py
# Pin pytest version for increased stability
RUN pip install pytest==3.2.5
RUN pip install pytest==3.2.5 six==1.10.0
# Let that user sudo:
RUN sed -i.bkp -e \

View File

@@ -2,6 +2,6 @@
Run these locally by saying... ::
./build.py && docker build -t lea . && docker run --rm -t -i lea
./build.py && docker build -t lea . -f Dockerfile.<distro> && docker run --rm -t -i lea
"""

View File

@@ -12,7 +12,7 @@ botocore==1.7.41
cloudflare==1.5.1
coverage==4.4.2
decorator==4.1.2
dns-lexicon==2.1.14
dns-lexicon==2.2.1
dnspython==1.15.0
docutils==0.14
execnet==1.5.0