Compare commits
23 Commits
test-updat
...
update-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8079a815a | ||
|
|
d7b26c1bb2 | ||
|
|
78261dbae2 | ||
|
|
2ed4e0a17e | ||
|
|
c372dd8aee | ||
|
|
01772280c0 | ||
|
|
814d8d1aba | ||
|
|
a190480517 | ||
|
|
7e8f22e136 | ||
|
|
965a403699 | ||
|
|
968cc5801b | ||
|
|
492b578662 | ||
|
|
e946479b9f | ||
|
|
f88105a952 | ||
|
|
3380694fa8 | ||
|
|
18631b99ef | ||
|
|
55d461392a | ||
|
|
a7a9a8480b | ||
|
|
3640b8546e | ||
|
|
1f94c7db20 | ||
|
|
a02223a97f | ||
|
|
2e31b1ca41 | ||
|
|
7ce86f588b |
@@ -2,14 +2,12 @@ steps:
|
||||
- bash: |
|
||||
FINAL_STATUS=0
|
||||
declare -a FAILED_BUILDS
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python tools/pipstrap.py
|
||||
tools/venv.py
|
||||
source venv/bin/activate
|
||||
for doc_path in */docs
|
||||
do
|
||||
echo ""
|
||||
echo "##[group]Building $doc_path"
|
||||
tools/pip_install_editable.py $doc_path/..[docs]
|
||||
if ! sphinx-build -W --keep-going -b html $doc_path $doc_path/_build/html; then
|
||||
FINAL_STATUS=1
|
||||
FAILED_BUILDS[${#FAILED_BUILDS[@]}]="${doc_path%/docs}"
|
||||
|
||||
@@ -3,9 +3,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Please update tox.ini when modifying dependency version requirements
|
||||
install_requires = [
|
||||
'cryptography>=2.1.4',
|
||||
# formerly known as acme.jose:
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==1.8.0
|
||||
certbot[dev]==1.10.1
|
||||
@@ -1,13 +1,14 @@
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'acme>=1.8.0',
|
||||
'certbot>=1.10.1',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
'python-augeas',
|
||||
'setuptools>=39.0.1',
|
||||
'zope.component',
|
||||
|
||||
@@ -61,7 +61,7 @@ class IntegrationTestsContext:
|
||||
Execute certbot with given args, not renewing certificates by default.
|
||||
:param args: args to pass to certbot
|
||||
:param force_renew: set to False to not renew by default
|
||||
:return: output of certbot execution
|
||||
:return: stdout and stderr from certbot execution
|
||||
"""
|
||||
command = ['--authenticator', 'standalone', '--installer', 'null']
|
||||
command.extend(args)
|
||||
|
||||
@@ -78,9 +78,9 @@ def test_registration_override(context):
|
||||
|
||||
def test_prepare_plugins(context):
|
||||
"""Test that plugins are correctly instantiated and displayed."""
|
||||
output = context.certbot(['plugins', '--init', '--prepare'])
|
||||
stdout, _ = context.certbot(['plugins', '--init', '--prepare'])
|
||||
|
||||
assert 'webroot' in output
|
||||
assert 'webroot' in stdout
|
||||
|
||||
|
||||
def test_http_01(context):
|
||||
@@ -407,9 +407,9 @@ def test_invalid_domain_with_dns_challenge(context):
|
||||
'--manual-cleanup-hook', context.manual_dns_cleanup_hook
|
||||
])
|
||||
|
||||
output = context.certbot(['certificates'])
|
||||
stdout, _ = context.certbot(['certificates'])
|
||||
|
||||
assert context.get_domain('fail-dns1') not in output
|
||||
assert context.get_domain('fail-dns1') not in stdout
|
||||
|
||||
|
||||
def test_reuse_key(context):
|
||||
@@ -614,11 +614,11 @@ def test_revoke_and_unregister(context):
|
||||
|
||||
context.certbot(['unregister'])
|
||||
|
||||
output = context.certbot(['certificates'])
|
||||
stdout, _ = context.certbot(['certificates'])
|
||||
|
||||
assert cert1 not in output
|
||||
assert cert2 not in output
|
||||
assert cert3 in output
|
||||
assert cert1 not in stdout
|
||||
assert cert2 not in stdout
|
||||
assert cert3 in stdout
|
||||
|
||||
|
||||
def test_revoke_mutual_exclusive_flags(context):
|
||||
@@ -630,7 +630,7 @@ def test_revoke_mutual_exclusive_flags(context):
|
||||
'revoke', '--cert-name', cert,
|
||||
'--cert-path', join(context.config_dir, 'live', cert, 'fullchain.pem')
|
||||
])
|
||||
assert 'Exactly one of --cert-path or --cert-name must be specified' in error.out
|
||||
assert 'Exactly one of --cert-path or --cert-name must be specified' in error.value.stderr
|
||||
|
||||
|
||||
def test_revoke_multiple_lineages(context):
|
||||
@@ -685,12 +685,12 @@ def test_wildcard_certificates(context):
|
||||
def test_ocsp_status_stale(context):
|
||||
"""Test retrieval of OCSP statuses for staled config"""
|
||||
sample_data_path = misc.load_sample_data_path(context.workspace)
|
||||
output = context.certbot(['certificates', '--config-dir', sample_data_path])
|
||||
stdout, _ = context.certbot(['certificates', '--config-dir', sample_data_path])
|
||||
|
||||
assert output.count('TEST_CERT') == 2, ('Did not find two test certs as expected ({0})'
|
||||
.format(output.count('TEST_CERT')))
|
||||
assert output.count('EXPIRED') == 2, ('Did not find two expired certs as expected ({0})'
|
||||
.format(output.count('EXPIRED')))
|
||||
assert stdout.count('TEST_CERT') == 2, ('Did not find two test certs as expected ({0})'
|
||||
.format(stdout.count('TEST_CERT')))
|
||||
assert stdout.count('EXPIRED') == 2, ('Did not find two expired certs as expected ({0})'
|
||||
.format(stdout.count('EXPIRED')))
|
||||
|
||||
|
||||
def test_ocsp_status_live(context):
|
||||
@@ -699,20 +699,20 @@ def test_ocsp_status_live(context):
|
||||
|
||||
# OSCP 1: Check live certificate OCSP status (VALID)
|
||||
context.certbot(['--domains', cert])
|
||||
output = context.certbot(['certificates'])
|
||||
stdout, _ = context.certbot(['certificates'])
|
||||
|
||||
assert output.count('VALID') == 1, 'Expected {0} to be VALID'.format(cert)
|
||||
assert output.count('EXPIRED') == 0, 'Did not expect {0} to be EXPIRED'.format(cert)
|
||||
assert stdout.count('VALID') == 1, 'Expected {0} to be VALID'.format(cert)
|
||||
assert stdout.count('EXPIRED') == 0, 'Did not expect {0} to be EXPIRED'.format(cert)
|
||||
|
||||
# OSCP 2: Check live certificate OCSP status (REVOKED)
|
||||
context.certbot(['revoke', '--cert-name', cert, '--no-delete-after-revoke'])
|
||||
# Sometimes in oldest tests (using openssl binary and not cryptography), the OCSP status is
|
||||
# not seen immediately by Certbot as invalid. Waiting few seconds solves this transient issue.
|
||||
time.sleep(5)
|
||||
output = context.certbot(['certificates'])
|
||||
stdout, _ = context.certbot(['certificates'])
|
||||
|
||||
assert output.count('INVALID') == 1, 'Expected {0} to be INVALID'.format(cert)
|
||||
assert output.count('REVOKED') == 1, 'Expected {0} to be REVOKED'.format(cert)
|
||||
assert stdout.count('INVALID') == 1, 'Expected {0} to be INVALID'.format(cert)
|
||||
assert stdout.count('REVOKED') == 1, 'Expected {0} to be REVOKED'.format(cert)
|
||||
|
||||
|
||||
def test_ocsp_renew(context):
|
||||
|
||||
@@ -17,7 +17,7 @@ def certbot_test(certbot_args, directory_url, http_01_port, tls_alpn_01_port,
|
||||
Invoke the certbot executable available in PATH in a test context for the given args.
|
||||
The test context consists in running certbot in debug mode, with various flags suitable
|
||||
for tests (eg. no ssl check, customizable ACME challenge ports and config directory ...).
|
||||
This command captures stdout and returns it to the caller.
|
||||
This command captures both stdout and stderr and returns it to the caller.
|
||||
:param list certbot_args: the arguments to pass to the certbot executable
|
||||
:param str directory_url: URL of the ACME directory server to use
|
||||
:param int http_01_port: port for the HTTP-01 challenges
|
||||
@@ -25,13 +25,19 @@ def certbot_test(certbot_args, directory_url, http_01_port, tls_alpn_01_port,
|
||||
:param str config_dir: certbot configuration directory to use
|
||||
:param str workspace: certbot current directory to use
|
||||
:param bool force_renew: set False to not force renew existing certificates (default: True)
|
||||
:return: stdout as string
|
||||
:rtype: str
|
||||
:return: stdout and stderr as strings
|
||||
:rtype: `tuple` of `str`
|
||||
"""
|
||||
command, env = _prepare_args_env(certbot_args, directory_url, http_01_port, tls_alpn_01_port,
|
||||
config_dir, workspace, force_renew)
|
||||
|
||||
return subprocess.check_output(command, universal_newlines=True, cwd=workspace, env=env)
|
||||
proc = subprocess.run(command, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, check=False, universal_newlines=True,
|
||||
cwd=workspace, env=env)
|
||||
print('--> Certbot log output was:')
|
||||
print(proc.stderr)
|
||||
proc.check_returncode()
|
||||
return proc.stdout, proc.stderr
|
||||
|
||||
|
||||
def _prepare_environ(workspace):
|
||||
|
||||
@@ -48,7 +48,6 @@ class Proxy(configurators_common.Proxy):
|
||||
setattr(self.le_config, "nginx_" + k, constants.os_constant(k))
|
||||
|
||||
conf = configuration.NamespaceConfig(self.le_config)
|
||||
zope.component.provideUtility(conf)
|
||||
self._configurator = configurator.NginxConfigurator(
|
||||
config=conf, name="nginx")
|
||||
self._configurator.prepare()
|
||||
|
||||
@@ -3,7 +3,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'certbot',
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.29.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'cloudflare>=1.5.1',
|
||||
'setuptools>=39.0.1',
|
||||
@@ -16,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.29.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
@@ -16,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.31.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.29.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'python-digitalocean>=1.11', # 1.15.0 or newer is recommended for TTL support
|
||||
'setuptools>=39.0.1',
|
||||
@@ -16,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.29.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'setuptools>=39.0.1',
|
||||
'zope.interface',
|
||||
@@ -15,8 +13,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.31.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
@@ -16,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.31.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,9 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Please update tox.ini when modifying dependency version requirements
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
@@ -15,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.31.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.29.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'google-api-python-client>=1.5.5',
|
||||
'oauth2client>=4.0',
|
||||
@@ -19,8 +17,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.29.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,9 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Please update tox.ini when modifying dependency version requirements
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
@@ -15,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.31.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
@@ -16,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.31.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
@@ -16,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.31.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
@@ -16,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.31.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -27,7 +27,7 @@ DEFAULT_NETWORK_TIMEOUT = 45
|
||||
class Authenticator(dns_common.DNSAuthenticator):
|
||||
"""DNS Authenticator using RFC 2136 Dynamic Updates
|
||||
|
||||
This Authenticator uses RFC 2136 Dynamic Updates to fulfull a dns-01 challenge.
|
||||
This Authenticator uses RFC 2136 Dynamic Updates to fulfill a dns-01 challenge.
|
||||
"""
|
||||
|
||||
ALGORITHMS = {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.29.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'dnspython',
|
||||
'setuptools>=39.0.1',
|
||||
@@ -16,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.29.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
62
certbot-dns-route53/.gitignore
vendored
62
certbot-dns-route53/.gitignore
vendored
@@ -1,62 +0,0 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
#Ipython Notebook
|
||||
.ipynb_checkpoints
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.29.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,10 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'boto3',
|
||||
'setuptools>=39.0.1',
|
||||
@@ -16,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.29.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==0.31.0
|
||||
certbot[dev]==1.1.0
|
||||
@@ -4,9 +4,8 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Please update tox.ini when modifying dependency version requirements
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.1.0', # Changed `rtype` parameter name
|
||||
'setuptools>=39.0.1',
|
||||
@@ -15,8 +14,11 @@ install_requires = [
|
||||
|
||||
if not os.environ.get('SNAP_BUILD'):
|
||||
install_requires.extend([
|
||||
'acme>=0.31.0',
|
||||
'certbot>=1.1.0',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
])
|
||||
elif 'bdist_wheel' in sys.argv[1:]:
|
||||
raise RuntimeError('Unset SNAP_BUILD when building wheels '
|
||||
|
||||
@@ -678,8 +678,9 @@ class NginxConfigurator(common.Installer):
|
||||
"""Generate invalid certs that let us create ssl directives for Nginx"""
|
||||
# TODO: generate only once
|
||||
tmp_dir = os.path.join(self.config.work_dir, "snakeoil")
|
||||
le_key = crypto_util.init_save_key(
|
||||
key_size=1024, key_dir=tmp_dir, keyname="key.pem")
|
||||
le_key = crypto_util.generate_key(
|
||||
key_size=1024, key_dir=tmp_dir, keyname="key.pem",
|
||||
strict_permissions=self.config.strict_permissions)
|
||||
key = OpenSSL.crypto.load_privatekey(
|
||||
OpenSSL.crypto.FILETYPE_PEM, le_key.pem)
|
||||
cert = acme_crypto_util.gen_ss_cert(key, domains=[socket.gethostname()])
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==1.8.0
|
||||
certbot[dev]==1.10.1
|
||||
@@ -1,13 +1,14 @@
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '1.16.0.dev0'
|
||||
version = '1.17.0.dev0'
|
||||
|
||||
# Remember to update local-oldest-requirements.txt when changing the minimum
|
||||
# acme/certbot version.
|
||||
install_requires = [
|
||||
'acme>=1.8.0',
|
||||
'certbot>=1.10.1',
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
# version for simplicity. See
|
||||
# https://github.com/certbot/certbot/issues/8761 for more info.
|
||||
f'acme>={version}',
|
||||
f'certbot>={version}',
|
||||
'PyOpenSSL>=17.3.0',
|
||||
'pyparsing>=2.2.0',
|
||||
'setuptools>=39.0.1',
|
||||
|
||||
@@ -9,7 +9,6 @@ try:
|
||||
except ImportError: # pragma: no cover
|
||||
from unittest import mock # type: ignore
|
||||
import pkg_resources
|
||||
import zope.component
|
||||
|
||||
from certbot import util
|
||||
from certbot.compat import os
|
||||
@@ -79,9 +78,6 @@ class NginxTest(test_util.ConfigTestCase):
|
||||
openssl_version=openssl_version)
|
||||
config.prepare()
|
||||
|
||||
# Provide general config utility.
|
||||
zope.component.provideUtility(self.configuration)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
|
||||
1
certbot/.gitignore
vendored
1
certbot/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
*.crt
|
||||
@@ -2,7 +2,28 @@
|
||||
|
||||
Certbot adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## 1.16.0 - master
|
||||
## 1.17.0 - master
|
||||
|
||||
### Added
|
||||
|
||||
*
|
||||
|
||||
### Changed
|
||||
|
||||
* We changed how dependencies are specified between Certbot packages. For this
|
||||
and future releases, higher level Certbot components will require that lower
|
||||
level components are the same version or newer. More specifically, version X
|
||||
of the Certbot package will now always require acme>=X and version Y of a
|
||||
plugin package will always require acme>=Y and certbot=>Y. Specifying
|
||||
dependencies in this way simplifies testing and development.
|
||||
|
||||
### Fixed
|
||||
|
||||
*
|
||||
|
||||
More details about these changes can be found on our GitHub repo.
|
||||
|
||||
## 1.16.0 - 2021-06-01
|
||||
|
||||
### Added
|
||||
|
||||
@@ -19,11 +40,16 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
|
||||
and clarify output. If you would like to see more verbose output, use
|
||||
the -v or -vv flags. UX improvements are an iterative process and
|
||||
the Certbot team welcomes constructive feedback.
|
||||
* Functions `certbot.crypto_util.init_save_key` and `certbot.crypto_util.init_save_csr`,
|
||||
whose behaviors rely on the global Certbot `config` singleton, are deprecated and will
|
||||
be removed in a future release. Please use `certbot.crypto_util.generate_key` and
|
||||
`certbot.crypto_util.generate_csr` instead.
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix TypeError due to incompatibility with lexicon >= v3.6.0
|
||||
* Installers (e.g. nginx, Apache) were being restarted unnecessarily after dry-run renewals.
|
||||
* Colors and bold text should properly render in all supported versions of Windows.
|
||||
|
||||
More details about these changes can be found on our GitHub repo.
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"""Certbot client."""
|
||||
# version number like 1.2.3a0, must have at least 2 parts, like 1.2
|
||||
__version__ = '1.16.0.dev0'
|
||||
__version__ = '1.17.0.dev0'
|
||||
|
||||
@@ -44,11 +44,12 @@ class AuthHandler:
|
||||
self.account = account
|
||||
self.pref_challs = pref_challs
|
||||
|
||||
def handle_authorizations(self, orderr, best_effort=False, max_retries=30):
|
||||
def handle_authorizations(self, orderr, config, best_effort=False, max_retries=30):
|
||||
"""
|
||||
Retrieve all authorizations, perform all challenges required to validate
|
||||
these authorizations, then poll and wait for the authorization to be checked.
|
||||
:param acme.messages.OrderResource orderr: must have authorizations filled in
|
||||
:param interfaces.IConfig config: current Certbot configuration
|
||||
:param bool best_effort: if True, not all authorizations need to be validated (eg. renew)
|
||||
:param int max_retries: maximum number of retries to poll authorizations
|
||||
:returns: list of all validated authorizations
|
||||
@@ -72,7 +73,6 @@ class AuthHandler:
|
||||
resps = self.auth.perform(achalls)
|
||||
|
||||
# If debug is on, wait for user input before starting the verification process.
|
||||
config = zope.component.getUtility(interfaces.IConfig)
|
||||
if config.debug_challenges:
|
||||
notify = zope.component.getUtility(interfaces.IDisplay).notification
|
||||
notify('Challenges loaded. Press continue to submit to CA. '
|
||||
|
||||
@@ -334,7 +334,7 @@ class Client:
|
||||
key = None
|
||||
|
||||
key_size = self.config.rsa_key_size
|
||||
elliptic_curve = None
|
||||
elliptic_curve = "secp256r1"
|
||||
|
||||
# key-type defaults to a list, but we are only handling 1 currently
|
||||
if isinstance(self.config.key_type, list):
|
||||
@@ -362,13 +362,15 @@ class Client:
|
||||
data=acme_crypto_util.make_csr(
|
||||
key.pem, domains, self.config.must_staple))
|
||||
else:
|
||||
key = key or crypto_util.init_save_key(
|
||||
key = key or crypto_util.generate_key(
|
||||
key_size=key_size,
|
||||
key_dir=self.config.key_dir,
|
||||
key_type=self.config.key_type,
|
||||
elliptic_curve=elliptic_curve,
|
||||
strict_permissions=self.config.strict_permissions,
|
||||
)
|
||||
csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir)
|
||||
csr = crypto_util.generate_csr(key, domains, self.config.csr_dir,
|
||||
self.config.must_staple, self.config.strict_permissions)
|
||||
|
||||
orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names)
|
||||
authzr = orderr.authorizations
|
||||
@@ -420,7 +422,7 @@ class Client:
|
||||
logger.warning("Certbot was unable to obtain fresh authorizations for every domain"
|
||||
". The dry run will continue, but results may not be accurate.")
|
||||
|
||||
authzr = self.auth_handler.handle_authorizations(orderr, best_effort)
|
||||
authzr = self.auth_handler.handle_authorizations(orderr, self.config, best_effort)
|
||||
return orderr.update(authorizations=authzr)
|
||||
|
||||
def obtain_and_enroll_certificate(self, domains, certname):
|
||||
@@ -516,11 +518,9 @@ class Client:
|
||||
|
||||
return abs_cert_path, abs_chain_path, abs_fullchain_path
|
||||
|
||||
def deploy_certificate(self, cert_name, domains, privkey_path,
|
||||
cert_path, chain_path, fullchain_path):
|
||||
def deploy_certificate(self, domains, privkey_path, cert_path, chain_path, fullchain_path):
|
||||
"""Install certificate
|
||||
|
||||
:param str cert_name: name of the certificate lineage (optional)
|
||||
:param list domains: list of domains to install the certificate
|
||||
:param str privkey_path: path to certificate private key
|
||||
:param str cert_path: certificate file path (optional)
|
||||
@@ -536,11 +536,7 @@ class Client:
|
||||
|
||||
display_util.notify("Deploying certificate")
|
||||
|
||||
msg = f"Failed to install the certificate (installer: {self.config.installer})."
|
||||
if cert_name:
|
||||
msg += (" Try again after fixing errors by running:\n\n"
|
||||
f" {cli.cli_constants.cli_command} install --cert-name {cert_name}\n")
|
||||
|
||||
msg = "Could not install certificate"
|
||||
with error_handler.ErrorHandler(self._recovery_routine_with_msg, msg):
|
||||
for dom in domains:
|
||||
self.installer.deploy_cert(
|
||||
@@ -616,9 +612,7 @@ class Client:
|
||||
|
||||
|
||||
"""
|
||||
msg = ("We were unable to set up enhancement %s for your server, "
|
||||
"however, we successfully installed your certificate."
|
||||
% (enhancement))
|
||||
msg = f"Could not set up {enhancement} enhancement"
|
||||
with error_handler.ErrorHandler(self._recovery_routine_with_msg, msg):
|
||||
for dom in domains:
|
||||
try:
|
||||
|
||||
@@ -202,7 +202,7 @@ def _handle_subset_cert_request(config: configuration.NamespaceConfig,
|
||||
"--duplicate option.{br}{br}"
|
||||
"For example:{br}{br}{1} --duplicate {2}".format(
|
||||
existing,
|
||||
sys.argv[0], " ".join(sys.argv[1:]),
|
||||
cli.cli_command, " ".join(sys.argv[1:]),
|
||||
br=os.linesep
|
||||
))
|
||||
raise errors.Error(USER_CANCELLED)
|
||||
@@ -469,6 +469,67 @@ def _find_domains_or_certname(config, installer, question=None):
|
||||
return domains, certname
|
||||
|
||||
|
||||
def _report_next_steps(config: interfaces.IConfig, installer_err: Optional[errors.Error],
|
||||
lineage: Optional[storage.RenewableCert],
|
||||
new_or_renewed_cert: bool = True) -> None:
|
||||
"""Displays post-run/certonly advice to the user about renewal and installation.
|
||||
|
||||
The output varies by runtime configuration and any errors encountered during installation.
|
||||
|
||||
:param config: Configuration object
|
||||
:type config: interfaces.IConfig
|
||||
|
||||
:param installer_err: The installer/enhancement error encountered, if any.
|
||||
:type error: Optional[errors.Error]
|
||||
|
||||
:param lineage: The resulting certificate lineage from the issuance, if any.
|
||||
:type lineage: Optional[storage.RenewableCert]
|
||||
|
||||
:param bool new_or_renewed_cert: Whether the verb execution resulted in a certificate
|
||||
being saved (created or renewed).
|
||||
|
||||
"""
|
||||
steps: List[str] = []
|
||||
|
||||
# If the installation or enhancement raised an error, show advice on trying again
|
||||
if installer_err:
|
||||
steps.append(
|
||||
"The certificate was saved, but could not be installed (installer: "
|
||||
f"{config.installer}). After fixing the error shown below, try installing it again "
|
||||
f"by running:\n {cli.cli_command} install --cert-name "
|
||||
f"{_cert_name_from_config_or_lineage(config, lineage)}"
|
||||
)
|
||||
|
||||
# If a certificate was obtained or renewed, show applicable renewal advice
|
||||
if new_or_renewed_cert:
|
||||
if config.csr:
|
||||
steps.append(
|
||||
"Certificates created using --csr will not be renewed automatically by Certbot. "
|
||||
"You will need to renew the certificate before it expires, by running the same "
|
||||
"Certbot command again.")
|
||||
elif not config.preconfigured_renewal:
|
||||
steps.append(
|
||||
"The certificate will need to be renewed before it expires. Certbot can "
|
||||
"automatically renew the certificate in the background, but you may need "
|
||||
"to take steps to enable that functionality. "
|
||||
"See https://certbot.org/renewal-setup for instructions.")
|
||||
|
||||
if not steps:
|
||||
return
|
||||
|
||||
# TODO: refactor ANSI escapes during https://github.com/certbot/certbot/issues/8848
|
||||
(bold_on, bold_off) = [c if sys.stdout.isatty() and not config.quiet else '' \
|
||||
for c in (util.ANSI_SGR_BOLD, util.ANSI_SGR_RESET)]
|
||||
|
||||
print(bold_on, '\n', 'NEXT STEPS:', bold_off, sep='')
|
||||
for step in steps:
|
||||
display_util.notify(f"- {step}")
|
||||
|
||||
# If there was an installer error, segregate the error output with a trailing newline
|
||||
if installer_err:
|
||||
print()
|
||||
|
||||
|
||||
def _report_new_cert(config, cert_path, fullchain_path, key_path=None):
|
||||
# type: (interfaces.IConfig, Optional[str], Optional[str], Optional[str]) -> None
|
||||
"""Reports the creation of a new certificate to the user.
|
||||
@@ -499,18 +560,13 @@ def _report_new_cert(config, cert_path, fullchain_path, key_path=None):
|
||||
("\nSuccessfully received certificate.\n"
|
||||
"Certificate is saved at: {cert_path}\n{key_msg}"
|
||||
"This certificate expires on {expiry}.\n"
|
||||
"These files will be updated when the certificate renews.\n{renew_msg}{nl}").format(
|
||||
"These files will be updated when the certificate renews.{renewal_msg}{nl}").format(
|
||||
cert_path=fullchain_path,
|
||||
expiry=crypto_util.notAfter(cert_path).date(),
|
||||
key_msg="Key is saved at: {}\n".format(key_path) if key_path else "",
|
||||
renew_msg="Certbot will automatically renew this certificate in the background."
|
||||
if config.preconfigured_renewal else
|
||||
(f'Run "{cli.cli_constants.cli_command} renew" to renew '
|
||||
"expiring certificates. "
|
||||
"We recommend setting up a scheduled task for renewal; see "
|
||||
"https://certbot.eff.org/docs/using.html#automated-renewals "
|
||||
"for instructions."),
|
||||
nl="\n" if config.verb == "run" else "" # visually split output if also deploying
|
||||
renewal_msg="\nCertbot has set up a scheduled task to automatically renew this "
|
||||
"certificate in the background." if config.preconfigured_renewal else "",
|
||||
nl="\n" if config.verb == "run" else "" # Normalize spacing across verbs
|
||||
)
|
||||
)
|
||||
|
||||
@@ -813,6 +869,21 @@ def update_account(config, unused_plugins):
|
||||
return None
|
||||
|
||||
|
||||
def _cert_name_from_config_or_lineage(config: interfaces.IConfig,
|
||||
lineage: Optional[storage.RenewableCert]) -> Optional[str]:
|
||||
if lineage:
|
||||
return lineage.lineagename
|
||||
elif config.certname:
|
||||
return config.certname
|
||||
try:
|
||||
cert_name = cert_manager.cert_path_to_lineage(config)
|
||||
return cert_name
|
||||
except errors.Error:
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def _install_cert(config, le_client, domains, lineage=None):
|
||||
"""Install a cert
|
||||
|
||||
@@ -835,20 +906,8 @@ def _install_cert(config, le_client, domains, lineage=None):
|
||||
path_provider = lineage if lineage else config
|
||||
assert path_provider.cert_path is not None
|
||||
|
||||
cert_name: Optional[str] = None
|
||||
if isinstance(path_provider, storage.RenewableCert):
|
||||
cert_name = path_provider.lineagename
|
||||
elif path_provider.certname:
|
||||
cert_name = path_provider.certname
|
||||
else:
|
||||
# Check if the cert path happens to be part of an existing lineage
|
||||
try:
|
||||
cert_name = cert_manager.cert_path_to_lineage(config)
|
||||
except errors.Error:
|
||||
pass
|
||||
|
||||
le_client.deploy_certificate(cert_name, domains, path_provider.key_path,
|
||||
path_provider.cert_path, path_provider.chain_path, path_provider.fullchain_path)
|
||||
le_client.deploy_certificate(domains, path_provider.key_path, path_provider.cert_path,
|
||||
path_provider.chain_path, path_provider.fullchain_path)
|
||||
le_client.enhance_config(domains, path_provider.chain_path)
|
||||
|
||||
|
||||
@@ -993,7 +1052,7 @@ def enhance(config, plugins):
|
||||
if not enhancements.are_requested(config) and not oldstyle_enh:
|
||||
msg = ("Please specify one or more enhancement types to configure. To list "
|
||||
"the available enhancement types, run:\n\n%s --help enhance\n")
|
||||
logger.error(msg, sys.argv[0])
|
||||
logger.error(msg, cli.cli_command)
|
||||
raise errors.MisconfigurationError("No enhancements requested, exiting.")
|
||||
|
||||
try:
|
||||
@@ -1216,15 +1275,27 @@ def run(config, plugins):
|
||||
if should_get_cert:
|
||||
_report_new_cert(config, cert_path, fullchain_path, key_path)
|
||||
|
||||
_install_cert(config, le_client, domains, new_lineage)
|
||||
# The installer error, if any, is being stored as a value here, in order to first print
|
||||
# relevant advice in a nice way, before re-raising the error for normal processing.
|
||||
installer_err: Optional[errors.Error] = None
|
||||
try:
|
||||
_install_cert(config, le_client, domains, new_lineage)
|
||||
|
||||
if enhancements.are_requested(config) and new_lineage:
|
||||
enhancements.enable(new_lineage, domains, installer, config)
|
||||
if enhancements.are_requested(config) and new_lineage:
|
||||
enhancements.enable(new_lineage, domains, installer, config)
|
||||
|
||||
if lineage is None or not should_get_cert:
|
||||
display_ops.success_installation(domains)
|
||||
else:
|
||||
display_ops.success_renewal(domains)
|
||||
if lineage is None or not should_get_cert:
|
||||
display_ops.success_installation(domains)
|
||||
else:
|
||||
display_ops.success_renewal(domains)
|
||||
except errors.Error as e:
|
||||
installer_err = e
|
||||
finally:
|
||||
_report_next_steps(config, installer_err, new_lineage,
|
||||
new_or_renewed_cert=should_get_cert)
|
||||
# If the installer did fail, re-raise the error to bail out
|
||||
if installer_err:
|
||||
raise installer_err
|
||||
|
||||
_suggest_donation_if_appropriate(config)
|
||||
eff.handle_subscription(config, le_client.account)
|
||||
@@ -1327,6 +1398,7 @@ def certonly(config, plugins):
|
||||
if config.csr:
|
||||
cert_path, chain_path, fullchain_path = _csr_get_and_save_cert(config, le_client)
|
||||
_csr_report_new_cert(config, cert_path, chain_path, fullchain_path)
|
||||
_report_next_steps(config, None, None)
|
||||
_suggest_donation_if_appropriate(config)
|
||||
eff.handle_subscription(config, le_client.account)
|
||||
return
|
||||
@@ -1345,6 +1417,7 @@ def certonly(config, plugins):
|
||||
fullchain_path = lineage.fullchain_path if lineage else None
|
||||
key_path = lineage.key_path if lineage else None
|
||||
_report_new_cert(config, cert_path, fullchain_path, key_path)
|
||||
_report_next_steps(config, None, lineage, new_or_renewed_cert=should_get_cert)
|
||||
_suggest_donation_if_appropriate(config)
|
||||
eff.handle_subscription(config, le_client.account)
|
||||
|
||||
@@ -1445,9 +1518,15 @@ def main(cli_args=None):
|
||||
logger.debug("Arguments: %r", cli_args)
|
||||
logger.debug("Discovered plugins: %r", plugins)
|
||||
|
||||
# Some releases of Windows require escape sequences to be enable explicitly
|
||||
misc.prepare_virtual_console()
|
||||
|
||||
# note: arg parser internally handles --help (and exits afterwards)
|
||||
args = cli.prepare_and_parse_args(plugins, cli_args)
|
||||
config = configuration.NamespaceConfig(args)
|
||||
|
||||
# This call is done only for retro-compatibility purposes.
|
||||
# TODO: Remove this call once zope dependencies are removed from Certbot.
|
||||
zope.component.provideUtility(config)
|
||||
|
||||
# On windows, shell without administrative right cannot create symlinks required by certbot.
|
||||
|
||||
@@ -450,7 +450,8 @@ def handle_renewal_request(config):
|
||||
if renewal_candidate is None:
|
||||
parse_failures.append(renewal_file)
|
||||
else:
|
||||
# XXX: ensure that each call here replaces the previous one
|
||||
# This call is done only for retro-compatibility purposes.
|
||||
# TODO: Remove this call once zope dependencies are removed from Certbot.
|
||||
zope.component.provideUtility(lineage_config)
|
||||
renewal_candidate.ensure_deployed()
|
||||
from certbot._internal import main
|
||||
|
||||
@@ -17,6 +17,8 @@ from certbot.compat import os
|
||||
|
||||
try:
|
||||
from win32com.shell import shell as shellwin32
|
||||
from win32console import GetStdHandle, STD_OUTPUT_HANDLE
|
||||
from pywintypes import error as pywinerror
|
||||
POSIX_MODE = False
|
||||
except ImportError: # pragma: no cover
|
||||
POSIX_MODE = True
|
||||
@@ -39,6 +41,26 @@ def raise_for_non_administrative_windows_rights() -> None:
|
||||
raise errors.Error('Error, certbot must be run on a shell with administrative rights.')
|
||||
|
||||
|
||||
def prepare_virtual_console() -> None:
|
||||
"""
|
||||
On Windows, ensure that Console Virtual Terminal Sequences are enabled.
|
||||
|
||||
"""
|
||||
if POSIX_MODE:
|
||||
return
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/setconsolemode
|
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
|
||||
|
||||
# stdout/stderr will be the same console screen buffer, but this could return None or raise
|
||||
try:
|
||||
h = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
if h:
|
||||
h.SetConsoleMode(h.GetConsoleMode() | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
except pywinerror:
|
||||
logger.debug("Failed to set console mode", exc_info=True)
|
||||
|
||||
|
||||
def readline_with_timeout(timeout: float, prompt: str) -> str:
|
||||
"""
|
||||
Read user input to return the first line entered, or raise after specified timeout.
|
||||
|
||||
@@ -9,7 +9,7 @@ import logging
|
||||
import re
|
||||
import warnings
|
||||
|
||||
from typing import List
|
||||
from typing import List, Set
|
||||
# See https://github.com/pyca/cryptography/issues/4275
|
||||
from cryptography import x509 # type: ignore
|
||||
from cryptography.exceptions import InvalidSignature
|
||||
@@ -38,9 +38,10 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# High level functions
|
||||
def init_save_key(
|
||||
key_size, key_dir, key_type="rsa", elliptic_curve="secp256r1", keyname="key-certbot.pem"
|
||||
):
|
||||
|
||||
def generate_key(key_size: int, key_dir: str, key_type: str = "rsa",
|
||||
elliptic_curve: str = "secp256r1", keyname: str = "key-certbot.pem",
|
||||
strict_permissions: bool = True) -> util.Key:
|
||||
"""Initializes and saves a privkey.
|
||||
|
||||
Inits key and saves it in PEM format on the filesystem.
|
||||
@@ -53,6 +54,8 @@ def init_save_key(
|
||||
:param str key_type: Key Type [rsa, ecdsa]
|
||||
:param str elliptic_curve: Name of the elliptic curve if key type is ecdsa.
|
||||
:param str keyname: Filename of key
|
||||
:param bool strict_permissions: If true and key_dir exists, an exception is raised if
|
||||
the directory doesn't have 0700 permissions or isn't owned by the current user.
|
||||
|
||||
:returns: Key
|
||||
:rtype: :class:`certbot.util.Key`
|
||||
@@ -69,9 +72,8 @@ def init_save_key(
|
||||
logger.error("Encountered error while making key: %s", str(err))
|
||||
raise err
|
||||
|
||||
config = zope.component.getUtility(interfaces.IConfig)
|
||||
# Save file
|
||||
util.make_or_verify_dir(key_dir, 0o700, config.strict_permissions)
|
||||
util.make_or_verify_dir(key_dir, 0o700, strict_permissions)
|
||||
key_f, key_path = util.unique_file(
|
||||
os.path.join(key_dir, keyname), 0o600, "wb")
|
||||
with key_f:
|
||||
@@ -84,9 +86,77 @@ def init_save_key(
|
||||
return util.Key(key_path, key_pem)
|
||||
|
||||
|
||||
# TODO: Remove this call once zope dependencies are removed from Certbot.
|
||||
def init_save_key(key_size, key_dir, key_type="rsa", elliptic_curve="secp256r1",
|
||||
keyname="key-certbot.pem"):
|
||||
"""Initializes and saves a privkey.
|
||||
|
||||
Inits key and saves it in PEM format on the filesystem.
|
||||
|
||||
.. note:: keyname is the attempted filename, it may be different if a file
|
||||
already exists at the path.
|
||||
|
||||
.. deprecated:: 1.16.0
|
||||
Use :func:`generate_key` instead.
|
||||
|
||||
:param int key_size: key size in bits if key size is rsa.
|
||||
:param str key_dir: Key save directory.
|
||||
:param str key_type: Key Type [rsa, ecdsa]
|
||||
:param str elliptic_curve: Name of the elliptic curve if key type is ecdsa.
|
||||
:param str keyname: Filename of key
|
||||
|
||||
:returns: Key
|
||||
:rtype: :class:`certbot.util.Key`
|
||||
|
||||
:raises ValueError: If unable to generate the key given key_size.
|
||||
|
||||
"""
|
||||
warnings.warn("certbot.crypto_util.init_save_key is deprecated, please use "
|
||||
"certbot.crypto_util.generate_key instead.", DeprecationWarning)
|
||||
|
||||
config = zope.component.getUtility(interfaces.IConfig)
|
||||
|
||||
return generate_key(key_size, key_dir, key_type=key_type, elliptic_curve=elliptic_curve,
|
||||
keyname=keyname, strict_permissions=config.strict_permissions)
|
||||
|
||||
|
||||
def generate_csr(privkey: util.Key, names: Set[str], path: str,
|
||||
must_staple: bool = False, strict_permissions: bool = True) -> util.CSR:
|
||||
"""Initialize a CSR with the given private key.
|
||||
|
||||
:param privkey: Key to include in the CSR
|
||||
:type privkey: :class:`certbot.util.Key`
|
||||
:param set names: `str` names to include in the CSR
|
||||
:param str path: Certificate save directory.
|
||||
:param bool must_staple: If true, include the TLS Feature extension "OCSP Must Staple"
|
||||
:param bool strict_permissions: If true and path exists, an exception is raised if
|
||||
the directory doesn't have 0755 permissions or isn't owned by the current user.
|
||||
|
||||
:returns: CSR
|
||||
:rtype: :class:`certbot.util.CSR`
|
||||
|
||||
"""
|
||||
csr_pem = acme_crypto_util.make_csr(
|
||||
privkey.pem, names, must_staple=must_staple)
|
||||
|
||||
# Save CSR
|
||||
util.make_or_verify_dir(path, 0o755, strict_permissions)
|
||||
csr_f, csr_filename = util.unique_file(
|
||||
os.path.join(path, "csr-certbot.pem"), 0o644, "wb")
|
||||
with csr_f:
|
||||
csr_f.write(csr_pem)
|
||||
logger.debug("Creating CSR: %s", csr_filename)
|
||||
|
||||
return util.CSR(csr_filename, csr_pem, "pem")
|
||||
|
||||
|
||||
# TODO: Remove this call once zope dependencies are removed from Certbot.
|
||||
def init_save_csr(privkey, names, path):
|
||||
"""Initialize a CSR with the given private key.
|
||||
|
||||
.. deprecated:: 1.16.0
|
||||
Use :func:`generate_csr` instead.
|
||||
|
||||
:param privkey: Key to include in the CSR
|
||||
:type privkey: :class:`certbot.util.Key`
|
||||
|
||||
@@ -98,20 +168,13 @@ def init_save_csr(privkey, names, path):
|
||||
:rtype: :class:`certbot.util.CSR`
|
||||
|
||||
"""
|
||||
warnings.warn("certbot.crypto_util.init_save_csr is deprecated, please use "
|
||||
"certbot.crypto_util.generate_csr instead.", DeprecationWarning)
|
||||
|
||||
config = zope.component.getUtility(interfaces.IConfig)
|
||||
|
||||
csr_pem = acme_crypto_util.make_csr(
|
||||
privkey.pem, names, must_staple=config.must_staple)
|
||||
|
||||
# Save CSR
|
||||
util.make_or_verify_dir(path, 0o755, config.strict_permissions)
|
||||
csr_f, csr_filename = util.unique_file(
|
||||
os.path.join(path, "csr-certbot.pem"), 0o644, "wb")
|
||||
with csr_f:
|
||||
csr_f.write(csr_pem)
|
||||
logger.debug("Creating CSR: %s", csr_filename)
|
||||
|
||||
return util.CSR(csr_filename, csr_pem, "pem")
|
||||
return generate_csr(privkey, names, path, must_staple=config.must_staple,
|
||||
strict_permissions=config.strict_permissions)
|
||||
|
||||
|
||||
# WARNING: the csr and private key file are possible attack vectors for TOCTOU
|
||||
|
||||
@@ -123,8 +123,7 @@ def choose_names(installer, question=None):
|
||||
names = get_valid_domains(domains)
|
||||
|
||||
if not names:
|
||||
return _choose_names_manually(
|
||||
"No names were found in your configuration files. ")
|
||||
return _choose_names_manually()
|
||||
|
||||
code, names = _filter_names(names, question)
|
||||
if code == display_util.OK and names:
|
||||
@@ -192,7 +191,8 @@ def _choose_names_manually(prompt_prefix=""):
|
||||
"""
|
||||
code, input_ = z_util(interfaces.IDisplay).input(
|
||||
prompt_prefix +
|
||||
"Please enter in your domain name(s) (comma and/or space separated) ",
|
||||
"Please enter the domain name(s) you would like on your certificate "
|
||||
"(comma and/or space separated)",
|
||||
cli_flag="--domains", force_interactive=True)
|
||||
|
||||
if code == display_util.OK:
|
||||
|
||||
@@ -119,7 +119,7 @@ class Plugin:
|
||||
# This is a fallback hint. Authenticators should implement their own auth_hint that
|
||||
# addresses the specific mechanics of that authenticator.
|
||||
challs = " and ".join(sorted({achall.typ for achall in failed_achalls}))
|
||||
return ("The Certificate Authority couldn't exterally verify that the {name} plugin "
|
||||
return ("The Certificate Authority couldn't externally verify that the {name} plugin "
|
||||
"completed the required {challs} challenges. Ensure the plugin is configured "
|
||||
"correctly and that the changes it makes are accessible from the internet."
|
||||
.format(name=self.name, challs=challs))
|
||||
|
||||
@@ -41,7 +41,7 @@ optional arguments:
|
||||
and ~/.config/letsencrypt/cli.ini)
|
||||
-v, --verbose This flag can be used multiple times to incrementally
|
||||
increase the verbosity of output, e.g. -vvv. (default:
|
||||
-2)
|
||||
-3)
|
||||
--max-log-backups MAX_LOG_BACKUPS
|
||||
Specifies the maximum number of backup logs that
|
||||
should be kept by Certbot's built in log rotation.
|
||||
@@ -118,7 +118,7 @@ optional arguments:
|
||||
case, and to know when to deprecate support for past
|
||||
Python versions and flags. If you wish to hide this
|
||||
information from the Let's Encrypt server, set this to
|
||||
"". (default: CertbotACMEClient/1.15.0 (certbot;
|
||||
"". (default: CertbotACMEClient/1.16.0 (certbot;
|
||||
OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY
|
||||
(SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel).
|
||||
The flags encoded in the user agent are: --duplicate,
|
||||
|
||||
@@ -84,7 +84,7 @@ Apache
|
||||
|
||||
The Apache plugin currently `supports
|
||||
<https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/entrypoint.py>`_
|
||||
modern OSes based on Debian, Fedora, SUSE, Gentoo and Darwin.
|
||||
modern OSes based on Debian, Fedora, SUSE, Gentoo, CentOS and Darwin.
|
||||
This automates both obtaining *and* installing certificates on an Apache
|
||||
webserver. To specify this plugin on the command line, simply include
|
||||
``--apache``.
|
||||
@@ -695,10 +695,50 @@ is done by means of a scheduled task which runs ``certbot renew`` periodically.
|
||||
|
||||
If you are unsure whether you need to configure automated renewal:
|
||||
|
||||
1. Review the instructions for your system at https://certbot.eff.org/instructions.
|
||||
They will describe how to set up a scheduled task, if necessary.
|
||||
2. (Linux/BSD): Check your system's crontab (typically `/etc/crontab` and
|
||||
`/etc/cron.*/*`) and systemd timers (``systemctl list-timers``).
|
||||
1. Review the instructions for your system and installation method at
|
||||
https://certbot.eff.org/instructions. They will describe how to set up a scheduled task,
|
||||
if necessary. If no step is listed, your system comes with automated renewal pre-installed,
|
||||
and you should not need to take any additional actions.
|
||||
2. On Linux and BSD, you can check to see if your installation method has pre-installed a timer
|
||||
for you. To do so, look for the ``certbot renew`` command in either your system's crontab
|
||||
(typically `/etc/crontab` or `/etc/cron.*/*`) or systemd timers (``systemctl list-timers``).
|
||||
3. If you're still not sure, you can configure automated renewal manually by following the steps
|
||||
in the next section. Certbot has been carefully engineered to handle the case where both manual
|
||||
automated renewal and pre-installed automated renewal are set up.
|
||||
|
||||
Setting up automated renewal
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you think you may need to set up automated renewal, follow these instructions to set up a
|
||||
scheduled task to automatically renew your certificates in the background. If you are unsure
|
||||
whether your system has a pre-installed scheduled task for Certbot, it is safe to follow these
|
||||
instructions to create one.
|
||||
|
||||
If you're using Windows, these instructions are not neccessary as Certbot on Windows comes with
|
||||
a scheduled task for automated renewal pre-installed.
|
||||
|
||||
Run the following line, which will add a cron job to `/etc/crontab`:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
SLEEPTIME=$(awk 'BEGIN{srand(); print int(rand()*(3600+1))}'); echo "0 0,12 * * * root sleep $SLEEPTIME && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
|
||||
|
||||
If you needed to stop your webserver to run Certbot, you'll want to
|
||||
add ``pre`` and ``post`` hooks to stop and start your webserver automatically.
|
||||
For example, if your webserver is HAProxy, run the following commands to create the hook files
|
||||
in the appropriate directory:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo sh -c 'printf "#!/bin/sh\nservice haproxy stop\n" > /etc/letsencrypt/renewal-hooks/pre/haproxy.sh'
|
||||
sudo sh -c 'printf "#!/bin/sh\nservice haproxy start\n" > /etc/letsencrypt/renewal-hooks/post/haproxy.sh'
|
||||
sudo chmod 755 /etc/letsencrypt/renewal-hooks/pre/haproxy.sh
|
||||
sudo chmod 755 /etc/letsencrypt/renewal-hooks/post/haproxy.sh
|
||||
|
||||
Congratulations, Certbot will now automatically renew your certificates in the background.
|
||||
|
||||
If you are interested in learning more about how Certbot renews your certificates, see the
|
||||
`Renewing certificates`_ section above.
|
||||
|
||||
.. _where-certs:
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ domains = example.com
|
||||
text = True
|
||||
agree-tos = True
|
||||
debug = True
|
||||
# Unfortunately, it's not possible to specify "verbose" multiple times
|
||||
# (correspondingly to -vvvvvv)
|
||||
verbose = True
|
||||
verbose = 3
|
||||
|
||||
authenticator = standalone
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
# Remember to update setup.py to match the package versions below.
|
||||
acme[dev]==1.8.0
|
||||
@@ -41,7 +41,10 @@ version = meta['version']
|
||||
# here to avoid masking the more specific request requirements in acme. See
|
||||
# https://github.com/pypa/pip/issues/988 for more info.
|
||||
install_requires = [
|
||||
'acme>=1.8.0',
|
||||
# We specify the minimum acme version as the current Certbot version for
|
||||
# simplicity. See https://github.com/certbot/certbot/issues/8761 for more
|
||||
# info.
|
||||
f'acme>={version}',
|
||||
# We technically need ConfigArgParse 0.10.0 for Python 2.6 support, but
|
||||
# saying so here causes a runtime error against our temporary fork of 0.9.3
|
||||
# in which we added 2.6 support (see #2243), so we relax the requirement.
|
||||
|
||||
@@ -69,10 +69,9 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
from certbot._internal.auth_handler import AuthHandler
|
||||
|
||||
self.mock_display = mock.Mock()
|
||||
self.mock_config = mock.Mock(debug_challenges=False)
|
||||
zope.component.provideUtility(
|
||||
self.mock_display, interfaces.IDisplay)
|
||||
zope.component.provideUtility(
|
||||
mock.Mock(debug_challenges=False), interfaces.IConfig)
|
||||
|
||||
self.mock_auth = mock.MagicMock(name="ApacheConfigurator")
|
||||
|
||||
@@ -99,7 +98,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
|
||||
self.mock_net.poll.side_effect = _gen_mock_on_poll(retry=1, wait_value=30)
|
||||
with mock.patch('certbot._internal.auth_handler.time') as mock_time:
|
||||
authzr = self.handler.handle_authorizations(mock_order)
|
||||
authzr = self.handler.handle_authorizations(mock_order, self.mock_config)
|
||||
|
||||
self.assertEqual(self.mock_net.answer_challenge.call_count, 1)
|
||||
|
||||
@@ -131,7 +130,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
|
||||
authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=False)
|
||||
mock_order = mock.MagicMock(authorizations=[authzr])
|
||||
authzr = self.handler.handle_authorizations(mock_order)
|
||||
authzr = self.handler.handle_authorizations(mock_order, self.mock_config)
|
||||
|
||||
self.assertEqual(self.mock_net.answer_challenge.call_count, 2)
|
||||
|
||||
@@ -152,7 +151,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
|
||||
authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=False)
|
||||
mock_order = mock.MagicMock(authorizations=[authzr])
|
||||
authzr = self.handler.handle_authorizations(mock_order)
|
||||
authzr = self.handler.handle_authorizations(mock_order, self.mock_config)
|
||||
|
||||
self.assertEqual(self.mock_net.answer_challenge.call_count, 1)
|
||||
|
||||
@@ -176,7 +175,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
mock_order = mock.MagicMock(authorizations=authzrs)
|
||||
|
||||
self.mock_net.poll.side_effect = _gen_mock_on_poll()
|
||||
authzr = self.handler.handle_authorizations(mock_order)
|
||||
authzr = self.handler.handle_authorizations(mock_order, self.mock_config)
|
||||
|
||||
self.assertEqual(self.mock_net.answer_challenge.call_count, 3)
|
||||
|
||||
@@ -195,14 +194,13 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
self._test_name3_http_01_3_common(combos=False)
|
||||
|
||||
def test_debug_challenges(self):
|
||||
zope.component.provideUtility(
|
||||
mock.Mock(debug_challenges=True), interfaces.IConfig)
|
||||
config = mock.Mock(debug_challenges=True)
|
||||
authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)]
|
||||
mock_order = mock.MagicMock(authorizations=authzrs)
|
||||
|
||||
self.mock_net.poll.side_effect = _gen_mock_on_poll()
|
||||
|
||||
self.handler.handle_authorizations(mock_order)
|
||||
self.handler.handle_authorizations(mock_order, config)
|
||||
|
||||
self.assertEqual(self.mock_net.answer_challenge.call_count, 1)
|
||||
self.assertEqual(self.mock_display.notification.call_count, 1)
|
||||
@@ -214,7 +212,8 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
self.mock_auth.perform.side_effect = errors.AuthorizationError
|
||||
|
||||
self.assertRaises(
|
||||
errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
|
||||
errors.AuthorizationError, self.handler.handle_authorizations,
|
||||
mock_order, self.mock_config)
|
||||
|
||||
def test_max_retries_exceeded(self):
|
||||
authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)]
|
||||
@@ -225,12 +224,13 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
|
||||
with self.assertRaises(errors.AuthorizationError) as error:
|
||||
# We retry only once, so retries will be exhausted before STATUS_VALID is returned.
|
||||
self.handler.handle_authorizations(mock_order, False, 1)
|
||||
self.handler.handle_authorizations(mock_order, self.mock_config, False, 1)
|
||||
self.assertIn('All authorizations were not finalized by the CA.', str(error.exception))
|
||||
|
||||
def test_no_domains(self):
|
||||
mock_order = mock.MagicMock(authorizations=[])
|
||||
self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
|
||||
self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations,
|
||||
mock_order, self.mock_config)
|
||||
|
||||
def _test_preferred_challenge_choice_common(self, combos):
|
||||
authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=combos)]
|
||||
@@ -242,7 +242,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
challenges.DNS01.typ,))
|
||||
|
||||
self.mock_net.poll.side_effect = _gen_mock_on_poll()
|
||||
self.handler.handle_authorizations(mock_order)
|
||||
self.handler.handle_authorizations(mock_order, self.mock_config)
|
||||
|
||||
self.assertEqual(self.mock_auth.cleanup.call_count, 1)
|
||||
self.assertEqual(
|
||||
@@ -260,7 +260,8 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
mock_order = mock.MagicMock(authorizations=authzrs)
|
||||
self.handler.pref_challs.append(challenges.DNS01.typ)
|
||||
self.assertRaises(
|
||||
errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
|
||||
errors.AuthorizationError, self.handler.handle_authorizations,
|
||||
mock_order, self.mock_config)
|
||||
|
||||
def test_preferred_challenges_not_supported_acme_1(self):
|
||||
self._test_preferred_challenges_not_supported_common(combos=True)
|
||||
@@ -273,14 +274,16 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
authzrs = [gen_dom_authzr(domain="0", challs=[acme_util.DNS01])]
|
||||
mock_order = mock.MagicMock(authorizations=authzrs)
|
||||
self.assertRaises(
|
||||
errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
|
||||
errors.AuthorizationError, self.handler.handle_authorizations,
|
||||
mock_order, self.mock_config)
|
||||
|
||||
def test_perform_error(self):
|
||||
self.mock_auth.perform.side_effect = errors.AuthorizationError
|
||||
|
||||
authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=True)
|
||||
mock_order = mock.MagicMock(authorizations=[authzr])
|
||||
self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
|
||||
self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations,
|
||||
mock_order, self.mock_config)
|
||||
|
||||
self.assertEqual(self.mock_auth.cleanup.call_count, 1)
|
||||
self.assertEqual(
|
||||
@@ -293,7 +296,8 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
mock_order = mock.MagicMock(authorizations=authzrs)
|
||||
|
||||
self.assertRaises(
|
||||
errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
|
||||
errors.AuthorizationError, self.handler.handle_authorizations,
|
||||
mock_order, self.mock_config)
|
||||
self.assertEqual(self.mock_auth.cleanup.call_count, 1)
|
||||
self.assertEqual(
|
||||
self.mock_auth.cleanup.call_args[0][0][0].typ, "http-01")
|
||||
@@ -305,7 +309,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
|
||||
with test_util.patch_get_utility():
|
||||
with self.assertRaises(errors.AuthorizationError) as error:
|
||||
self.handler.handle_authorizations(mock_order, False)
|
||||
self.handler.handle_authorizations(mock_order, self.mock_config, False)
|
||||
self.assertIn('Some challenges have failed.', str(error.exception))
|
||||
self.assertEqual(self.mock_auth.cleanup.call_count, 1)
|
||||
self.assertEqual(
|
||||
@@ -330,7 +334,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
|
||||
with mock.patch('certbot._internal.auth_handler.AuthHandler._report_failed_authzrs') \
|
||||
as mock_report:
|
||||
valid_authzr = self.handler.handle_authorizations(mock_order, True)
|
||||
valid_authzr = self.handler.handle_authorizations(mock_order, self.mock_config, True)
|
||||
|
||||
# Because best_effort=True, we did not blow up. Instead ...
|
||||
self.assertEqual(len(valid_authzr), 1) # ... the valid authzr has been processed
|
||||
@@ -340,7 +344,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
|
||||
with test_util.patch_get_utility():
|
||||
with self.assertRaises(errors.AuthorizationError) as error:
|
||||
self.handler.handle_authorizations(mock_order, True)
|
||||
self.handler.handle_authorizations(mock_order, self.mock_config, True)
|
||||
|
||||
# Despite best_effort=True, process will fail because no authzr is valid.
|
||||
self.assertIn('All challenges have failed.', str(error.exception))
|
||||
@@ -354,7 +358,8 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
[messages.STATUS_PENDING], False)
|
||||
mock_order = mock.MagicMock(authorizations=[authzr])
|
||||
self.assertRaises(
|
||||
errors.AuthorizationError, self.handler.handle_authorizations, mock_order)
|
||||
errors.AuthorizationError, self.handler.handle_authorizations,
|
||||
mock_order, self.mock_config)
|
||||
|
||||
# With a validated challenge that is not supported by the plugin, we
|
||||
# expect the challenge to not be solved again and
|
||||
@@ -364,7 +369,7 @@ class HandleAuthorizationsTest(unittest.TestCase):
|
||||
[acme_util.DNS01],
|
||||
[messages.STATUS_VALID], False)
|
||||
mock_order = mock.MagicMock(authorizations=[authzr])
|
||||
self.handler.handle_authorizations(mock_order)
|
||||
self.handler.handle_authorizations(mock_order, self.mock_config)
|
||||
|
||||
def test_valid_authzrs_deactivated(self):
|
||||
"""When we deactivate valid authzrs in an orderr, we expect them to become deactivated
|
||||
|
||||
@@ -242,6 +242,7 @@ class ClientTest(ClientTestCommon):
|
||||
|
||||
self.config.allow_subset_of_names = False
|
||||
self.config.dry_run = False
|
||||
self.config.strict_permissions = True
|
||||
self.eg_domains = ["example.com", "www.example.com"]
|
||||
self.eg_order = mock.MagicMock(
|
||||
authorizations=[None],
|
||||
@@ -263,6 +264,7 @@ class ClientTest(ClientTestCommon):
|
||||
if auth_count == 1:
|
||||
self.client.auth_handler.handle_authorizations.assert_called_once_with(
|
||||
self.eg_order,
|
||||
self.config,
|
||||
self.config.allow_subset_of_names)
|
||||
else:
|
||||
self.assertEqual(self.client.auth_handler.handle_authorizations.call_count, auth_count)
|
||||
@@ -273,16 +275,14 @@ class ClientTest(ClientTestCommon):
|
||||
|
||||
@mock.patch("certbot._internal.client.crypto_util")
|
||||
@mock.patch("certbot._internal.client.logger")
|
||||
@test_util.patch_get_utility()
|
||||
def test_obtain_certificate_from_csr(self, unused_mock_get_utility,
|
||||
mock_logger, mock_crypto_util):
|
||||
def test_obtain_certificate_from_csr(self, mock_logger, mock_crypto_util):
|
||||
self._mock_obtain_certificate()
|
||||
test_csr = util.CSR(form="pem", file=None, data=CSR_SAN)
|
||||
auth_handler = self.client.auth_handler
|
||||
self._set_mock_from_fullchain(mock_crypto_util.cert_and_chain_from_fullchain)
|
||||
|
||||
orderr = self.acme.new_order(test_csr.data)
|
||||
auth_handler.handle_authorizations(orderr, False)
|
||||
auth_handler.handle_authorizations(orderr, self.config, False)
|
||||
self.assertEqual(
|
||||
(mock.sentinel.cert, mock.sentinel.chain),
|
||||
self.client.obtain_certificate_from_csr(
|
||||
@@ -310,7 +310,7 @@ class ClientTest(ClientTestCommon):
|
||||
self.client.obtain_certificate_from_csr(
|
||||
test_csr,
|
||||
orderr=None))
|
||||
auth_handler.handle_authorizations.assert_called_with(self.eg_order, False)
|
||||
auth_handler.handle_authorizations.assert_called_with(self.eg_order, self.config, False)
|
||||
|
||||
# Test for no auth_handler
|
||||
self.client.auth_handler = None
|
||||
@@ -323,20 +323,21 @@ class ClientTest(ClientTestCommon):
|
||||
@mock.patch("certbot._internal.client.crypto_util")
|
||||
def test_obtain_certificate(self, mock_crypto_util):
|
||||
csr = util.CSR(form="pem", file=None, data=CSR_SAN)
|
||||
mock_crypto_util.init_save_csr.return_value = csr
|
||||
mock_crypto_util.init_save_key.return_value = mock.sentinel.key
|
||||
mock_crypto_util.generate_csr.return_value = csr
|
||||
mock_crypto_util.generate_key.return_value = mock.sentinel.key
|
||||
self._set_mock_from_fullchain(mock_crypto_util.cert_and_chain_from_fullchain)
|
||||
|
||||
self._test_obtain_certificate_common(mock.sentinel.key, csr)
|
||||
|
||||
mock_crypto_util.init_save_key.assert_called_once_with(
|
||||
mock_crypto_util.generate_key.assert_called_once_with(
|
||||
key_size=self.config.rsa_key_size,
|
||||
key_dir=self.config.key_dir,
|
||||
key_type=self.config.key_type,
|
||||
elliptic_curve=None, # elliptic curve is not set
|
||||
elliptic_curve="secp256r1",
|
||||
strict_permissions=True,
|
||||
)
|
||||
mock_crypto_util.init_save_csr.assert_called_once_with(
|
||||
mock.sentinel.key, self.eg_domains, self.config.csr_dir)
|
||||
mock_crypto_util.generate_csr.assert_called_once_with(
|
||||
mock.sentinel.key, self.eg_domains, self.config.csr_dir, False, True)
|
||||
mock_crypto_util.cert_and_chain_from_fullchain.assert_called_once_with(
|
||||
self.eg_order.fullchain_pem)
|
||||
|
||||
@@ -345,16 +346,16 @@ class ClientTest(ClientTestCommon):
|
||||
def test_obtain_certificate_partial_success(self, mock_remove, mock_crypto_util):
|
||||
csr = util.CSR(form="pem", file=mock.sentinel.csr_file, data=CSR_SAN)
|
||||
key = util.CSR(form="pem", file=mock.sentinel.key_file, data=CSR_SAN)
|
||||
mock_crypto_util.init_save_csr.return_value = csr
|
||||
mock_crypto_util.init_save_key.return_value = key
|
||||
mock_crypto_util.generate_csr.return_value = csr
|
||||
mock_crypto_util.generate_key.return_value = key
|
||||
self._set_mock_from_fullchain(mock_crypto_util.cert_and_chain_from_fullchain)
|
||||
|
||||
authzr = self._authzr_from_domains(["example.com"])
|
||||
self.config.allow_subset_of_names = True
|
||||
self._test_obtain_certificate_common(key, csr, authzr_ret=authzr, auth_count=2)
|
||||
|
||||
self.assertEqual(mock_crypto_util.init_save_key.call_count, 2)
|
||||
self.assertEqual(mock_crypto_util.init_save_csr.call_count, 2)
|
||||
self.assertEqual(mock_crypto_util.generate_key.call_count, 2)
|
||||
self.assertEqual(mock_crypto_util.generate_csr.call_count, 2)
|
||||
self.assertEqual(mock_remove.call_count, 2)
|
||||
self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 1)
|
||||
|
||||
@@ -372,13 +373,13 @@ class ClientTest(ClientTestCommon):
|
||||
|
||||
mock_crypto.make_key.assert_called_once_with(
|
||||
bits=self.config.rsa_key_size,
|
||||
elliptic_curve=None, # not making an elliptic private key
|
||||
elliptic_curve="secp256r1",
|
||||
key_type=self.config.key_type,
|
||||
)
|
||||
mock_acme_crypto.make_csr.assert_called_once_with(
|
||||
mock.sentinel.key_pem, self.eg_domains, self.config.must_staple)
|
||||
mock_crypto.init_save_key.assert_not_called()
|
||||
mock_crypto.init_save_csr.assert_not_called()
|
||||
mock_crypto.generate_key.assert_not_called()
|
||||
mock_crypto.generate_csr.assert_not_called()
|
||||
self.assertEqual(mock_crypto.cert_and_chain_from_fullchain.call_count, 1)
|
||||
|
||||
@mock.patch("certbot._internal.client.logger")
|
||||
@@ -521,13 +522,12 @@ class ClientTest(ClientTestCommon):
|
||||
@test_util.patch_get_utility()
|
||||
def test_deploy_certificate_success(self, mock_util):
|
||||
self.assertRaises(errors.Error, self.client.deploy_certificate,
|
||||
"foo.bar", ["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
|
||||
installer = mock.MagicMock()
|
||||
self.client.installer = installer
|
||||
|
||||
self.client.deploy_certificate(
|
||||
"foo.bar", ["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
self.client.deploy_certificate(["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
installer.deploy_cert.assert_called_once_with(
|
||||
cert_path=os.path.abspath("cert"),
|
||||
chain_path=os.path.abspath("chain"),
|
||||
@@ -546,31 +546,10 @@ class ClientTest(ClientTestCommon):
|
||||
|
||||
installer.deploy_cert.side_effect = errors.PluginError
|
||||
self.assertRaises(errors.PluginError, self.client.deploy_certificate,
|
||||
"foo.bar", ["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
installer.recovery_routine.assert_called_once_with()
|
||||
|
||||
mock_notify.assert_any_call('Deploying certificate')
|
||||
mock_notify.assert_any_call(
|
||||
'Failed to install the certificate (installer: foobar). '
|
||||
'Try again after fixing errors by running:\n\n certbot install --cert-name foo.bar\n'
|
||||
)
|
||||
|
||||
@mock.patch('certbot._internal.client.display_util.notify')
|
||||
@test_util.patch_get_utility()
|
||||
def test_deploy_certificate_failure_no_certname(self, mock_util, mock_notify):
|
||||
installer = mock.MagicMock()
|
||||
self.client.installer = installer
|
||||
self.config.installer = "foobar"
|
||||
|
||||
installer.deploy_cert.side_effect = errors.PluginError
|
||||
self.assertRaises(errors.PluginError, self.client.deploy_certificate,
|
||||
None, ["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
installer.recovery_routine.assert_called_once_with()
|
||||
|
||||
mock_notify.assert_any_call('Deploying certificate')
|
||||
mock_notify.assert_any_call(
|
||||
'Failed to install the certificate (installer: foobar).'
|
||||
)
|
||||
|
||||
|
||||
@test_util.patch_get_utility()
|
||||
@@ -580,7 +559,7 @@ class ClientTest(ClientTestCommon):
|
||||
|
||||
installer.save.side_effect = errors.PluginError
|
||||
self.assertRaises(errors.PluginError, self.client.deploy_certificate,
|
||||
"foo.bar", ["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
installer.recovery_routine.assert_called_once_with()
|
||||
|
||||
@mock.patch('certbot._internal.client.display_util.notify')
|
||||
@@ -591,7 +570,7 @@ class ClientTest(ClientTestCommon):
|
||||
self.client.installer = installer
|
||||
|
||||
self.assertRaises(errors.PluginError, self.client.deploy_certificate,
|
||||
"foo.bar", ["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
mock_notify.assert_called_with(
|
||||
'We were unable to install your certificate, however, we successfully restored '
|
||||
'your server to its prior configuration.')
|
||||
@@ -607,7 +586,7 @@ class ClientTest(ClientTestCommon):
|
||||
self.client.installer = installer
|
||||
|
||||
self.assertRaises(errors.PluginError, self.client.deploy_certificate,
|
||||
"foo.bar", ["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
["foo.bar"], "key", "cert", "chain", "fullchain")
|
||||
self.assertEqual(mock_logger.error.call_count, 1)
|
||||
self.assertIn(
|
||||
'An error occurred and we failed to restore your config',
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
import logging
|
||||
import unittest
|
||||
|
||||
import certbot.util
|
||||
|
||||
try:
|
||||
import mock
|
||||
except ImportError: # pragma: no cover
|
||||
from unittest import mock
|
||||
import OpenSSL
|
||||
import zope.component
|
||||
|
||||
from certbot import errors
|
||||
from certbot import interfaces
|
||||
from certbot import util
|
||||
from certbot.compat import filesystem
|
||||
from certbot.compat import os
|
||||
@@ -33,8 +33,8 @@ CERT_ISSUER = test_util.load_vector('cert_intermediate_1.pem')
|
||||
CERT_ALT_ISSUER = test_util.load_vector('cert_intermediate_2.pem')
|
||||
|
||||
|
||||
class InitSaveKeyTest(test_util.TempDirTestCase):
|
||||
"""Tests for certbot.crypto_util.init_save_key."""
|
||||
class GenerateKeyTest(test_util.TempDirTestCase):
|
||||
"""Tests for certbot.crypto_util.generate_key."""
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
@@ -42,8 +42,6 @@ class InitSaveKeyTest(test_util.TempDirTestCase):
|
||||
filesystem.mkdir(self.workdir, mode=0o700)
|
||||
|
||||
logging.disable(logging.CRITICAL)
|
||||
zope.component.provideUtility(
|
||||
mock.Mock(strict_permissions=True), interfaces.IConfig)
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
@@ -52,8 +50,8 @@ class InitSaveKeyTest(test_util.TempDirTestCase):
|
||||
|
||||
@classmethod
|
||||
def _call(cls, key_size, key_dir):
|
||||
from certbot.crypto_util import init_save_key
|
||||
return init_save_key(key_size, key_dir, 'key-certbot.pem')
|
||||
from certbot.crypto_util import generate_key
|
||||
return generate_key(key_size, key_dir, 'key-certbot.pem', strict_permissions=True)
|
||||
|
||||
@mock.patch('certbot.crypto_util.make_key')
|
||||
def test_success(self, mock_make):
|
||||
@@ -69,29 +67,57 @@ class InitSaveKeyTest(test_util.TempDirTestCase):
|
||||
self.assertRaises(ValueError, self._call, 431, self.workdir)
|
||||
|
||||
|
||||
class InitSaveCSRTest(test_util.TempDirTestCase):
|
||||
"""Tests for certbot.crypto_util.init_save_csr."""
|
||||
class InitSaveKey(unittest.TestCase):
|
||||
"""Test for certbot.crypto_util.init_save_key."""
|
||||
@mock.patch("certbot.crypto_util.generate_key")
|
||||
@mock.patch("certbot.crypto_util.zope.component")
|
||||
def test_it(self, mock_zope, mock_generate):
|
||||
from certbot.crypto_util import init_save_key
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
mock_zope.getUtility.return_value = mock.MagicMock(strict_permissions=True)
|
||||
|
||||
zope.component.provideUtility(
|
||||
mock.Mock(strict_permissions=True), interfaces.IConfig)
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
init_save_key(4096, "/some/path")
|
||||
|
||||
mock_generate.assert_called_with(4096, "/some/path", elliptic_curve="secp256r1",
|
||||
key_type="rsa", keyname="key-certbot.pem",
|
||||
strict_permissions=True)
|
||||
|
||||
|
||||
class GenerateCSRTest(test_util.TempDirTestCase):
|
||||
"""Tests for certbot.crypto_util.generate_csr."""
|
||||
@mock.patch('acme.crypto_util.make_csr')
|
||||
@mock.patch('certbot.crypto_util.util.make_or_verify_dir')
|
||||
def test_it(self, unused_mock_verify, mock_csr):
|
||||
from certbot.crypto_util import init_save_csr
|
||||
from certbot.crypto_util import generate_csr
|
||||
|
||||
mock_csr.return_value = b'csr_pem'
|
||||
|
||||
csr = init_save_csr(
|
||||
mock.Mock(pem='dummy_key'), 'example.com', self.tempdir)
|
||||
csr = generate_csr(
|
||||
mock.Mock(pem='dummy_key'), 'example.com', self.tempdir, strict_permissions=True)
|
||||
|
||||
self.assertEqual(csr.data, b'csr_pem')
|
||||
self.assertIn('csr-certbot.pem', csr.file)
|
||||
|
||||
|
||||
class InitSaveCsr(unittest.TestCase):
|
||||
"""Tests for certbot.crypto_util.init_save_csr."""
|
||||
@mock.patch("certbot.crypto_util.generate_csr")
|
||||
@mock.patch("certbot.crypto_util.zope.component")
|
||||
def test_it(self, mock_zope, mock_generate):
|
||||
from certbot.crypto_util import init_save_csr
|
||||
|
||||
mock_zope.getUtility.return_value = mock.MagicMock(must_staple=True,
|
||||
strict_permissions=True)
|
||||
key = certbot.util.Key(file=None, pem=None)
|
||||
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
init_save_csr(key, {"dummy"}, "/some/path")
|
||||
|
||||
mock_generate.assert_called_with(key, {"dummy"}, "/some/path",
|
||||
must_staple=True, strict_permissions=True)
|
||||
|
||||
|
||||
class ValidCSRTest(unittest.TestCase):
|
||||
"""Tests for certbot.crypto_util.valid_csr."""
|
||||
|
||||
|
||||
@@ -209,7 +209,6 @@ class ChooseNamesTest(unittest.TestCase):
|
||||
actual_doms = self._call(self.mock_install)
|
||||
self.assertEqual(mock_util().input.call_count, 1)
|
||||
self.assertEqual(actual_doms, [domain])
|
||||
self.assertIn("configuration files", mock_util().input.call_args[0][0])
|
||||
|
||||
def test_sort_names_trivial(self):
|
||||
from certbot.display.ops import _sort_names
|
||||
|
||||
@@ -28,8 +28,13 @@ class PreArgParseSetupTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def _call(cls, *args, **kwargs): # pylint: disable=unused-argument
|
||||
from certbot._internal.log import pre_arg_parse_setup
|
||||
with mock.patch('builtins.open', mock.mock_open()):
|
||||
return pre_arg_parse_setup()
|
||||
return pre_arg_parse_setup()
|
||||
|
||||
def tearDown(self):
|
||||
# We need to call logging.shutdown() at the end of this test to
|
||||
# properly clean up any resources created by pre_arg_parse_setup.
|
||||
logging.shutdown()
|
||||
super().tearDown()
|
||||
|
||||
@mock.patch('certbot._internal.log.sys')
|
||||
@mock.patch('certbot._internal.log.pre_arg_parse_except_hook')
|
||||
|
||||
@@ -112,6 +112,7 @@ class RunTest(test_util.ConfigTestCase):
|
||||
mock.patch('certbot._internal.main._report_new_cert'),
|
||||
mock.patch('certbot._internal.main._find_cert'),
|
||||
mock.patch('certbot._internal.eff.handle_subscription'),
|
||||
mock.patch('certbot._internal.main._report_next_steps')
|
||||
]
|
||||
|
||||
self.mock_auth = patches[0].start()
|
||||
@@ -122,6 +123,7 @@ class RunTest(test_util.ConfigTestCase):
|
||||
self.mock_report_cert = patches[5].start()
|
||||
self.mock_find_cert = patches[6].start()
|
||||
self.mock_subscription = patches[7].start()
|
||||
self.mock_report_next_steps = patches[8].start()
|
||||
for patch in patches:
|
||||
self.addCleanup(patch.stop)
|
||||
|
||||
@@ -139,6 +141,8 @@ class RunTest(test_util.ConfigTestCase):
|
||||
self.mock_find_cert.return_value = True, None
|
||||
self._call()
|
||||
self.mock_success_installation.assert_called_once_with([self.domain])
|
||||
self.mock_report_next_steps.assert_called_once_with(mock.ANY, None, mock.ANY,
|
||||
new_or_renewed_cert=True)
|
||||
|
||||
def test_reinstall_success(self):
|
||||
self.mock_auth.return_value = mock.Mock()
|
||||
@@ -161,6 +165,18 @@ class RunTest(test_util.ConfigTestCase):
|
||||
main.run,
|
||||
self.config, plugins)
|
||||
|
||||
@mock.patch('certbot._internal.main._install_cert')
|
||||
def test_cert_success_install_error(self, mock_install_cert):
|
||||
mock_install_cert.side_effect = errors.PluginError("Fake installation error")
|
||||
self.mock_auth.return_value = mock.Mock()
|
||||
self.mock_find_cert.return_value = True, None
|
||||
self.assertRaises(errors.PluginError, self._call)
|
||||
|
||||
# Next steps should contain both renewal advice and installation error
|
||||
self.mock_report_next_steps.assert_called_once_with(
|
||||
mock.ANY, mock_install_cert.side_effect, mock.ANY, new_or_renewed_cert=True)
|
||||
# The final success message shouldn't be shown
|
||||
self.mock_success_installation.assert_not_called()
|
||||
|
||||
class CertonlyTest(unittest.TestCase):
|
||||
"""Tests for certbot._internal.main.certonly."""
|
||||
@@ -198,13 +214,14 @@ class CertonlyTest(unittest.TestCase):
|
||||
def _assert_no_pause(self, message, pause=True): # pylint: disable=unused-argument
|
||||
self.assertIs(pause, False)
|
||||
|
||||
@mock.patch('certbot._internal.main._report_next_steps')
|
||||
@mock.patch('certbot._internal.cert_manager.lineage_for_certname')
|
||||
@mock.patch('certbot._internal.cert_manager.domains_for_certname')
|
||||
@mock.patch('certbot._internal.renewal.renew_cert')
|
||||
@mock.patch('certbot._internal.main._handle_unexpected_key_type_migration')
|
||||
@mock.patch('certbot._internal.main._report_new_cert')
|
||||
def test_find_lineage_for_domains_and_certname(self, mock_report_cert,
|
||||
mock_handle_type, mock_renew_cert, mock_domains, mock_lineage):
|
||||
mock_handle_type, mock_renew_cert, mock_domains, mock_lineage, mock_report_next_steps):
|
||||
domains = ['example.com', 'test.org']
|
||||
mock_domains.return_value = domains
|
||||
mock_lineage.names.return_value = domains
|
||||
@@ -216,6 +233,8 @@ class CertonlyTest(unittest.TestCase):
|
||||
self.assertEqual(mock_renew_cert.call_count, 1)
|
||||
self.assertEqual(mock_report_cert.call_count, 1)
|
||||
self.assertEqual(mock_handle_type.call_count, 1)
|
||||
mock_report_next_steps.assert_called_once_with(
|
||||
mock.ANY, None, mock.ANY, new_or_renewed_cert=True)
|
||||
|
||||
# user confirms updating lineage with new domains
|
||||
self._call(('certonly --webroot -d example.com -d test.com '
|
||||
@@ -231,12 +250,13 @@ class CertonlyTest(unittest.TestCase):
|
||||
self.assertRaises(errors.ConfigurationError, self._call,
|
||||
'certonly --webroot -d example.com -d test.com --cert-name example.com'.split())
|
||||
|
||||
@mock.patch('certbot._internal.main._report_next_steps')
|
||||
@mock.patch('certbot._internal.cert_manager.domains_for_certname')
|
||||
@mock.patch('certbot.display.ops.choose_names')
|
||||
@mock.patch('certbot._internal.cert_manager.lineage_for_certname')
|
||||
@mock.patch('certbot._internal.main._report_new_cert')
|
||||
def test_find_lineage_for_domains_new_certname(self, mock_report_cert,
|
||||
mock_lineage, mock_choose_names, mock_domains_for_certname):
|
||||
mock_lineage, mock_choose_names, mock_domains_for_certname, unused_mock_report_next_steps):
|
||||
mock_lineage.return_value = None
|
||||
|
||||
# no lineage with this name but we specified domains so create a new cert
|
||||
@@ -1823,7 +1843,8 @@ class ReportNewCertTest(unittest.TestCase):
|
||||
'Key is saved at: /path/to/privkey.pem\n'
|
||||
'This certificate expires on 1970-01-01.\n'
|
||||
'These files will be updated when the certificate renews.\n'
|
||||
'Certbot will automatically renew this certificate in the background.'
|
||||
'Certbot has set up a scheduled task to automatically renew this '
|
||||
'certificate in the background.'
|
||||
)
|
||||
|
||||
def test_report_no_key(self):
|
||||
@@ -1836,7 +1857,8 @@ class ReportNewCertTest(unittest.TestCase):
|
||||
'Certificate is saved at: /path/to/fullchain.pem\n'
|
||||
'This certificate expires on 1970-01-01.\n'
|
||||
'These files will be updated when the certificate renews.\n'
|
||||
'Certbot will automatically renew this certificate in the background.'
|
||||
'Certbot has set up a scheduled task to automatically renew this '
|
||||
'certificate in the background.'
|
||||
)
|
||||
|
||||
def test_report_no_preconfigured_renewal(self):
|
||||
@@ -1849,13 +1871,9 @@ class ReportNewCertTest(unittest.TestCase):
|
||||
'Certificate is saved at: /path/to/fullchain.pem\n'
|
||||
'Key is saved at: /path/to/privkey.pem\n'
|
||||
'This certificate expires on 1970-01-01.\n'
|
||||
'These files will be updated when the certificate renews.\n'
|
||||
'Run "certbot renew" to renew expiring certificates. We recommend setting up a '
|
||||
'scheduled task for renewal; see https://certbot.eff.org/docs/using.html#automated'
|
||||
'-renewals for instructions.'
|
||||
'These files will be updated when the certificate renews.'
|
||||
)
|
||||
|
||||
|
||||
def test_csr_report(self):
|
||||
self._call_csr(mock.Mock(dry_run=False), '/path/to/cert.pem',
|
||||
'/path/to/chain.pem', '/path/to/fullchain.pem')
|
||||
|
||||
@@ -9,5 +9,10 @@
|
||||
# deprecation warnings and gives time for plugins that don't use the deprecated
|
||||
# API to propagate, especially for plugins packaged as an external snap, before
|
||||
# we release breaking changes.
|
||||
#
|
||||
# The current warnings being ignored are:
|
||||
# 1) The warning raised when importing certbot.tests.util and the external mock
|
||||
# library is installed.
|
||||
filterwarnings =
|
||||
error
|
||||
ignore:The external mock module:PendingDeprecationWarning
|
||||
|
||||
@@ -87,14 +87,6 @@ for pkg_dir in $SUBPKGS certbot-compatibility-test
|
||||
do
|
||||
sed -i 's/\.dev0//' "$pkg_dir/setup.py"
|
||||
git add "$pkg_dir/setup.py"
|
||||
|
||||
if [ -f "$pkg_dir/local-oldest-requirements.txt" ]; then
|
||||
sed -i "s/-e acme\[dev\]/acme[dev]==$version/" "$pkg_dir/local-oldest-requirements.txt"
|
||||
sed -i "s/-e acme/acme[dev]==$version/" "$pkg_dir/local-oldest-requirements.txt"
|
||||
sed -i "s/-e certbot\[dev\]/certbot[dev]==$version/" "$pkg_dir/local-oldest-requirements.txt"
|
||||
sed -i "s/-e certbot/certbot[dev]==$version/" "$pkg_dir/local-oldest-requirements.txt"
|
||||
git add "$pkg_dir/local-oldest-requirements.txt"
|
||||
fi
|
||||
done
|
||||
|
||||
SetVersion() {
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
"""
|
||||
Given an ACME account key as input, deactivate the account.
|
||||
|
||||
This can be useful if you created an account with a non-Certbot client and now
|
||||
want to deactivate it.
|
||||
|
||||
Private key should be in PKCS#8 PEM form.
|
||||
|
||||
To provide the URL for the ACME server you want to use, set it in the $DIRECTORY
|
||||
environment variable, e.g.:
|
||||
|
||||
DIRECTORY=https://acme-staging.api.letsencrypt.org/directory python \
|
||||
deactivate.py private_key.pem
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
import josepy as jose
|
||||
|
||||
from acme import client as acme_client
|
||||
from acme import errors as acme_errors
|
||||
from acme import messages
|
||||
|
||||
DIRECTORY = os.getenv('DIRECTORY', 'http://localhost:4000/directory')
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python deactivate.py private_key.pem")
|
||||
sys.exit(1)
|
||||
|
||||
data = open(sys.argv[1], "r").read()
|
||||
key = jose.JWKRSA(key=serialization.load_pem_private_key(
|
||||
data, None, default_backend()))
|
||||
|
||||
net = acme_client.ClientNetwork(key, verify_ssl=False,
|
||||
user_agent="acme account deactivator")
|
||||
|
||||
client = acme_client.Client(DIRECTORY, key=key, net=net)
|
||||
try:
|
||||
# We expect this to fail and give us a Conflict response with a Location
|
||||
# header pointing at the account's URL.
|
||||
client.register()
|
||||
except acme_errors.ConflictError as e:
|
||||
location = e.location
|
||||
if location is None:
|
||||
raise "Key was not previously registered (but now is)."
|
||||
client.deactivate_registration(messages.RegistrationResource(uri=location))
|
||||
@@ -1,123 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
// This program can be used to perform RSA public key signatures given only
|
||||
// the hash of the file to be signed as input.
|
||||
|
||||
// To compile:
|
||||
// gcc half-sign.c -lssl -lcrypto -o half-sign
|
||||
|
||||
// Sign with SHA256
|
||||
#define HASH_SIZE 32
|
||||
|
||||
void usage() {
|
||||
printf("half-sign <private key file> [binary hash file]\n");
|
||||
printf("\n");
|
||||
printf(" Computes and prints a binary RSA signature over data given the SHA256 hash of\n");
|
||||
printf(" the data as input.\n");
|
||||
printf("\n");
|
||||
printf(" <private key file> should be PEM encoded.\n");
|
||||
printf("\n");
|
||||
printf(" The input SHA256 hash should be %d bytes in length. If no binary hash file is\n", HASH_SIZE);
|
||||
printf(" specified, it will be read from stdin.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void sign_hashed_data(EVP_PKEY *signing_key, unsigned char *md, size_t mdlen) {
|
||||
// cribbed from the openssl EVP_PKEY_sign man page
|
||||
EVP_PKEY_CTX *ctx;
|
||||
unsigned char *sig;
|
||||
size_t siglen;
|
||||
|
||||
/* NB: assumes signing_key, md and mdlen are already set up
|
||||
* and that signing_key is an RSA private key
|
||||
*/
|
||||
ctx = EVP_PKEY_CTX_new(signing_key, NULL);
|
||||
if ((!ctx)
|
||||
|| (EVP_PKEY_sign_init(ctx) <= 0)
|
||||
|| (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
|
||||
|| (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0)) {
|
||||
fprintf(stderr, "Failure establishing ctx for signature\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Determine buffer length */
|
||||
if (EVP_PKEY_sign(ctx, NULL, &siglen, md, mdlen) <= 0) {
|
||||
fprintf(stderr, "Unable to determine buffer length for signature\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sig = OPENSSL_malloc(siglen);
|
||||
|
||||
if (!sig) {
|
||||
fprintf(stderr, "Malloc failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (EVP_PKEY_sign(ctx, sig, &siglen, md, mdlen) <= 0) {
|
||||
fprintf(stderr, "Signature error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Signature is siglen bytes written to buffer sig */
|
||||
fwrite(sig, siglen, 1, stdout);
|
||||
}
|
||||
|
||||
EVP_PKEY *read_private_key(char *filename) {
|
||||
FILE *keyfile;
|
||||
EVP_PKEY *privkey;
|
||||
keyfile = fopen(filename, "r");
|
||||
if (!keyfile) {
|
||||
fprintf(stderr, "Failed to open private key.pem file %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
privkey = PEM_read_PrivateKey(keyfile, NULL, NULL, NULL);
|
||||
if (!privkey) {
|
||||
fprintf(stderr, "Failed to read PEM private key from %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
if (EVP_PKEY_type(privkey->type) != EVP_PKEY_RSA) {
|
||||
fprintf(stderr, "%s was a non-RSA key\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
return privkey;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
FILE *input;
|
||||
unsigned char *buffer;
|
||||
int test;
|
||||
EVP_PKEY *privkey;
|
||||
if (argc > 3 || argc < 2)
|
||||
usage();
|
||||
if (argc < 3 || strcmp(argv[2],"-") == 0)
|
||||
input = stdin;
|
||||
else {
|
||||
input = fopen(argv[2], "r");
|
||||
if (!input) usage();
|
||||
}
|
||||
privkey = read_private_key(argv[1]);
|
||||
buffer = malloc(HASH_SIZE);
|
||||
if (!buffer) {
|
||||
fprintf(stderr, "Argh, malloc failed\n");
|
||||
exit(1);
|
||||
}
|
||||
if (fread(buffer, HASH_SIZE, 1, input) != 1) {
|
||||
perror("half-sign: Failed to read SHA256 from input\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
test = fgetc(input);
|
||||
if (test != EOF && test != '\n') {
|
||||
fprintf(stderr,"Error, more than %d bytes fed to half-sign\n", HASH_SIZE);
|
||||
fprintf(stderr,"Last byte was :%d\n" , (int) test);
|
||||
exit(1);
|
||||
}
|
||||
sign_hashed_data(privkey, buffer, HASH_SIZE);
|
||||
return 0;
|
||||
}
|
||||
@@ -74,6 +74,4 @@ parsedatetime==2.4
|
||||
# Tracking at https://github.com/certbot/certbot/issues/6473
|
||||
boto3==1.4.7
|
||||
botocore==1.7.41
|
||||
# Lexicon oldest constraint is overridden appropriately on relevant DNS provider plugins
|
||||
# using their local-oldest-requirements.txt
|
||||
dns-lexicon==3.1.0
|
||||
|
||||
@@ -17,6 +17,12 @@ if ! command -v poetry >/dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Old eggs can cause outdated dependency information to be used by poetry so we
|
||||
# delete them before generating the lock file. See
|
||||
# https://github.com/python-poetry/poetry/issues/4103 for more info.
|
||||
cd "${REPO_ROOT}"
|
||||
rm -rf */*.egg-info
|
||||
|
||||
cd "${WORK_DIR}"
|
||||
|
||||
if [ -f poetry.lock ]; then
|
||||
|
||||
@@ -58,11 +58,6 @@ cython = "*"
|
||||
# needed. This dependency can be removed here once Certbot's support for the
|
||||
# 3rd party mock library has been dropped.
|
||||
mock = "*"
|
||||
# Upgrading coverage, pytest, and some of pytest's plugins causes many test
|
||||
# failures so let's pin these packages back for now.
|
||||
coverage = "4.5.4"
|
||||
pytest = "3.2.5"
|
||||
pytest-forked = "0.2"
|
||||
# We were originally pinning back python-augeas for certbot-auto because we
|
||||
# found the way older versions of the library linked to Augeas were more
|
||||
# reliable. That's no longer a concern, however, we continue to pin back the
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# pip installs packages using pinned package versions. If CERTBOT_OLDEST is set
|
||||
# to 1, a combination of tools/oldest_constraints.txt,
|
||||
# tools/dev_constraints.txt, and local-oldest-requirements.txt contained in the
|
||||
# top level of the package's directory is used, otherwise,
|
||||
# tools/requirements.txt is used. If CERTBOT_OLDEST is set, this script must
|
||||
# be run with `-e <package-name>` and no other arguments.
|
||||
# to 1, a combination of tools/oldest_constraints.txt and
|
||||
# tools/dev_constraints.txt is used, otherwise, tools/requirements.txt is used.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
@@ -37,27 +34,13 @@ def find_tools_path():
|
||||
return os.path.dirname(readlink.main(__file__))
|
||||
|
||||
|
||||
def certbot_oldest_processing(tools_path, args, constraints_path):
|
||||
if args[0] != '-e' or len(args) != 2:
|
||||
raise ValueError('When CERTBOT_OLDEST is set, this script must be run '
|
||||
'with a single -e <path> argument.')
|
||||
# remove any extras such as [dev]
|
||||
pkg_dir = re.sub(r'\[\w+\]', '', args[1])
|
||||
def certbot_oldest_processing(tools_path, constraints_path):
|
||||
# The order of the files in this list matters as files specified later can
|
||||
# override the pinnings found in earlier files.
|
||||
pinning_files = [os.path.join(tools_path, 'dev_constraints.txt'),
|
||||
os.path.join(tools_path, 'oldest_constraints.txt')]
|
||||
requirements = os.path.join(pkg_dir, 'local-oldest-requirements.txt')
|
||||
# packages like acme don't have any local oldest requirements
|
||||
if os.path.isfile(requirements):
|
||||
# We add requirements to the end of the list so it can override
|
||||
# anything that it needs to.
|
||||
pinning_files.append(requirements)
|
||||
else:
|
||||
requirements = None
|
||||
with open(constraints_path, 'w') as fd:
|
||||
fd.write(merge_module.main(*pinning_files))
|
||||
return requirements
|
||||
|
||||
|
||||
def certbot_normal_processing(tools_path, constraints_path):
|
||||
@@ -91,27 +74,14 @@ def main(args):
|
||||
else:
|
||||
# Otherwise, we merge requirements to build the constraints and pin dependencies
|
||||
constraints_path = os.path.join(working_dir, 'constraints.txt')
|
||||
requirements = None
|
||||
if os.environ.get('CERTBOT_OLDEST') == '1':
|
||||
requirements = certbot_oldest_processing(tools_path, args, constraints_path)
|
||||
certbot_oldest_processing(tools_path, constraints_path)
|
||||
else:
|
||||
certbot_normal_processing(tools_path, constraints_path)
|
||||
|
||||
env = os.environ.copy()
|
||||
env["PIP_CONSTRAINT"] = constraints_path
|
||||
|
||||
if requirements: # This branch is executed during the oldest tests
|
||||
# First step, install the transitive dependencies of oldest requirements
|
||||
# in respect with oldest constraints.
|
||||
pip_install_with_print('--requirement "{0}"'.format(requirements),
|
||||
env=env)
|
||||
# Second step, ensure that oldest requirements themselves are effectively
|
||||
# installed using --force-reinstall, and avoid corner cases like the one described
|
||||
# in https://github.com/certbot/certbot/issues/7014.
|
||||
pip_install_with_print('--force-reinstall --no-deps --requirement "{0}"'
|
||||
.format(requirements))
|
||||
|
||||
print(' '.join(args))
|
||||
pip_install_with_print(' '.join(args), env=env)
|
||||
|
||||
|
||||
|
||||
@@ -11,16 +11,17 @@ apipkg==1.5; python_version >= "3.6" and python_full_version < "3.0.0" or python
|
||||
appdirs==1.4.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
appnope==0.1.2
|
||||
astroid==2.5.6; python_version >= "3.6" and python_version < "4.0"
|
||||
atomicwrites==1.4.0; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.6" and python_full_version >= "3.4.0"
|
||||
attrs==21.2.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
awscli==1.19.77; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.6.0")
|
||||
awscli==1.19.83; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.6.0")
|
||||
azure-devops==6.0.0b4; python_version >= "3.6"
|
||||
babel==2.9.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0"
|
||||
backcall==0.2.0
|
||||
bcrypt==3.2.0; python_version >= "3.6"
|
||||
beautifulsoup4==4.9.3; python_version >= "3.6" and python_version < "4.0"
|
||||
bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
boto3==1.17.77; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
botocore==1.20.77; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
boto3==1.17.83; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
botocore==1.20.83; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
cachecontrol==0.12.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
cached-property==1.5.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
|
||||
cachetools==4.2.2; python_version >= "3.5" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6")
|
||||
@@ -34,7 +35,7 @@ cloudflare==2.8.15; python_version >= "3.6"
|
||||
colorama==0.4.3; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0")
|
||||
configargparse==1.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
configobj==5.0.6; python_version >= "3.6"
|
||||
coverage==4.5.4; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0" and python_version < "4")
|
||||
coverage==5.5; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6"
|
||||
crashtest==0.3.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0")
|
||||
cryptography==3.4.7; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux" or python_full_version >= "3.5.0" and python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") and sys_platform == "linux"
|
||||
cython==0.29.23; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0")
|
||||
@@ -49,25 +50,26 @@ docker==4.2.2; python_version >= "3.6" and python_full_version < "3.0.0" or pyth
|
||||
dockerpty==0.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
|
||||
docopt==0.6.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
|
||||
docutils==0.15.2; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0")
|
||||
execnet==1.8.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
execnet==1.8.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
fabric==2.6.0; python_version >= "3.6"
|
||||
filelock==3.0.12; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "4.0"
|
||||
google-api-core==1.28.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
google-api-python-client==2.5.0; python_version >= "3.6"
|
||||
google-api-python-client==2.6.0; python_version >= "3.6"
|
||||
google-auth-httplib2==0.1.0; python_version >= "3.6"
|
||||
google-auth==1.30.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
google-auth==1.30.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
googleapis-common-protos==1.53.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
html5lib==1.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
httplib2==0.19.1; python_version >= "3.6"
|
||||
idna==2.10; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_full_version >= "3.5.0" and python_version >= "3.6" and python_version < "4.0"
|
||||
imagesize==1.2.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0"
|
||||
importlib-metadata==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "3.8" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0")
|
||||
importlib-metadata==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0") or python_version < "3.8" and python_version >= "3.6" and python_full_version >= "3.5.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0")
|
||||
importlib-resources==5.1.4; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "3.7"
|
||||
iniconfig==1.1.1; python_version >= "3.6"
|
||||
invoke==1.5.0; python_version >= "3.6"
|
||||
ipdb==0.13.7; python_version >= "3.6"
|
||||
ipdb==0.13.8; python_version >= "3.6"
|
||||
ipython-genutils==0.2.0; python_version == "3.6"
|
||||
ipython==7.16.1; python_version == "3.6"
|
||||
ipython==7.23.1; python_version >= "3.7"
|
||||
ipython==7.24.0; python_version >= "3.7"
|
||||
isodate==0.6.0; python_version >= "3.6"
|
||||
isort==5.8.0; python_version >= "3.6" and python_version < "4.0"
|
||||
jedi==0.18.0
|
||||
@@ -100,12 +102,12 @@ pathlib2==2.3.5; python_version >= "3.6"
|
||||
pexpect==4.8.0
|
||||
pickleshare==0.7.5
|
||||
pkginfo==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
pluggy==0.13.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
pluggy==0.13.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
ply==3.11; python_version >= "3.6"
|
||||
poetry-core==1.0.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
poetry==1.1.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
prompt-toolkit==3.0.3
|
||||
protobuf==3.17.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
protobuf==3.17.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
ptyprocess==0.7.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
@@ -123,10 +125,10 @@ pyparsing==2.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or p
|
||||
pypiwin32==223; sys_platform == "win32" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6")
|
||||
pyrfc3339==1.1; python_version >= "3.6"
|
||||
pyrsistent==0.17.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
|
||||
pytest-cov==2.6.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
|
||||
pytest-forked==0.2
|
||||
pytest-xdist==1.24.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
|
||||
pytest==3.2.5
|
||||
pytest-cov==2.12.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
pytest-forked==1.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
pytest-xdist==2.2.1; python_version >= "3.6"
|
||||
pytest==6.2.4; python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6")
|
||||
python-augeas==0.5.0
|
||||
python-dateutil==2.8.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6"
|
||||
python-digitalocean==1.16.0; python_version >= "3.6"
|
||||
@@ -154,29 +156,29 @@ sphinx-rtd-theme==0.5.2; python_version >= "3.6"
|
||||
sphinx==3.5.4; python_version >= "3.5"
|
||||
sphinxcontrib-applehelp==1.0.2; python_version >= "3.6"
|
||||
sphinxcontrib-devhelp==1.0.2; python_version >= "3.6"
|
||||
sphinxcontrib-htmlhelp==1.0.3; python_version >= "3.6"
|
||||
sphinxcontrib-htmlhelp==2.0.0; python_version >= "3.6"
|
||||
sphinxcontrib-jsmath==1.0.1; python_version >= "3.6"
|
||||
sphinxcontrib-qthelp==1.0.3; python_version >= "3.6"
|
||||
sphinxcontrib-serializinghtml==1.1.4; python_version >= "3.6"
|
||||
sphinxcontrib-serializinghtml==1.1.5; python_version >= "3.6"
|
||||
texttable==1.6.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
|
||||
tldextract==3.1.0; python_version >= "3.6" and python_version < "4.0"
|
||||
toml==0.10.2; python_version == "3.6" and python_full_version < "3.0.0" or python_version > "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version == "3.6" and python_full_version >= "3.5.0" or python_version > "3.6" and python_full_version >= "3.5.0" and python_version < "4.0"
|
||||
toml==0.10.2; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.5.0"
|
||||
tomlkit==0.7.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
tox==3.23.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
tqdm==4.60.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0"
|
||||
tqdm==4.61.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0"
|
||||
traitlets==4.3.3
|
||||
twine==3.3.0; python_version >= "3.6"
|
||||
typed-ast==1.4.3; implementation_name == "cpython" and python_version < "3.8" and python_version >= "3.6"
|
||||
typing-extensions==3.10.0.0; python_version >= "3.6"
|
||||
uritemplate==3.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6"
|
||||
urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.6"
|
||||
virtualenv==20.4.6; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
urllib3==1.26.5; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version < "4" and python_version >= "3.6"
|
||||
virtualenv==20.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
wcwidth==0.2.5; python_version == "3.6"
|
||||
webencodings==0.5.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
websocket-client==0.59.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
wrapt==1.12.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0")
|
||||
yarg==0.1.9; python_version >= "3.6"
|
||||
zipp==3.4.1; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version >= "3.6" and python_full_version >= "3.5.0" and python_version < "3.7"
|
||||
zipp==3.4.1; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version < "3.7" and python_version >= "3.6" and python_full_version >= "3.5.0"
|
||||
zope.component==5.0.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
zope.event==4.5.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
zope.hookable==5.0.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6"
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""A version of Python's SimpleHTTPServer that flushes its output."""
|
||||
import sys
|
||||
|
||||
try:
|
||||
from http.server import HTTPServer, SimpleHTTPRequestHandler
|
||||
except ImportError:
|
||||
from BaseHTTPServer import HTTPServer
|
||||
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
||||
|
||||
|
||||
def serve_forever(port=0):
|
||||
"""Spins up an HTTP server on all interfaces and the given port.
|
||||
|
||||
A message is printed to stdout specifying the address and port being used
|
||||
by the server.
|
||||
|
||||
:param int port: port number to use.
|
||||
|
||||
"""
|
||||
server = HTTPServer(('', port), SimpleHTTPRequestHandler)
|
||||
print('Serving HTTP on {0} port {1} ...'.format(*server.server_address))
|
||||
sys.stdout.flush()
|
||||
server.serve_forever()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
kwargs = {}
|
||||
if len(sys.argv) > 1:
|
||||
kwargs['port'] = int(sys.argv[1])
|
||||
serve_forever(**kwargs)
|
||||
73
tox.ini
73
tox.ini
@@ -14,51 +14,13 @@ pip_install = python {toxinidir}/tools/pip_install_editable.py
|
||||
# before the script moves on to the next package. All dependencies are pinned
|
||||
# to a specific version for increased stability for developers.
|
||||
install_and_test = python {toxinidir}/tools/install_and_test.py
|
||||
dns_packages =
|
||||
certbot-dns-cloudflare \
|
||||
certbot-dns-cloudxns \
|
||||
certbot-dns-digitalocean \
|
||||
certbot-dns-dnsimple \
|
||||
certbot-dns-dnsmadeeasy \
|
||||
certbot-dns-gehirn \
|
||||
certbot-dns-google \
|
||||
certbot-dns-linode \
|
||||
certbot-dns-luadns \
|
||||
certbot-dns-nsone \
|
||||
certbot-dns-ovh \
|
||||
certbot-dns-rfc2136 \
|
||||
certbot-dns-route53 \
|
||||
certbot-dns-sakuracloud
|
||||
all_packages =
|
||||
acme[dev] \
|
||||
certbot[dev] \
|
||||
certbot-apache \
|
||||
{[base]dns_packages} \
|
||||
certbot-nginx
|
||||
install_packages =
|
||||
python {toxinidir}/tools/pip_install_editable.py {[base]all_packages}
|
||||
source_paths =
|
||||
acme/acme
|
||||
certbot/certbot
|
||||
certbot-ci/certbot_integration_tests
|
||||
certbot-apache/certbot_apache
|
||||
certbot-compatibility-test/certbot_compatibility_test
|
||||
certbot-dns-cloudflare/certbot_dns_cloudflare
|
||||
certbot-dns-cloudxns/certbot_dns_cloudxns
|
||||
certbot-dns-digitalocean/certbot_dns_digitalocean
|
||||
certbot-dns-dnsimple/certbot_dns_dnsimple
|
||||
certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy
|
||||
certbot-dns-gehirn/certbot_dns_gehirn
|
||||
certbot-dns-google/certbot_dns_google
|
||||
certbot-dns-linode/certbot_dns_linode
|
||||
certbot-dns-luadns/certbot_dns_luadns
|
||||
certbot-dns-nsone/certbot_dns_nsone
|
||||
certbot-dns-ovh/certbot_dns_ovh
|
||||
certbot-dns-rfc2136/certbot_dns_rfc2136
|
||||
certbot-dns-route53/certbot_dns_route53
|
||||
certbot-dns-sakuracloud/certbot_dns_sakuracloud
|
||||
certbot-nginx/certbot_nginx
|
||||
tests/lock_test.py
|
||||
install_packages = python {toxinidir}/tools/pip_install_editable.py {[base]all_packages}
|
||||
# Packages are listed on one line because tox seems to have inconsistent
|
||||
# behavior with substitutions that contain line continuations, see
|
||||
# https://github.com/tox-dev/tox/issues/2069 for more info.
|
||||
dns_packages = certbot-dns-cloudflare certbot-dns-cloudxns certbot-dns-digitalocean certbot-dns-dnsimple certbot-dns-dnsmadeeasy certbot-dns-gehirn certbot-dns-google certbot-dns-linode certbot-dns-luadns certbot-dns-nsone certbot-dns-ovh certbot-dns-rfc2136 certbot-dns-route53 certbot-dns-sakuracloud
|
||||
all_packages = acme[dev] certbot[dev] certbot-apache {[base]dns_packages} certbot-nginx
|
||||
source_paths = acme/acme certbot/certbot certbot-ci/certbot_integration_tests certbot-apache/certbot_apache certbot-compatibility-test/certbot_compatibility_test certbot-dns-cloudflare/certbot_dns_cloudflare certbot-dns-cloudxns/certbot_dns_cloudxns certbot-dns-digitalocean/certbot_dns_digitalocean certbot-dns-dnsimple/certbot_dns_dnsimple certbot-dns-dnsmadeeasy/certbot_dns_dnsmadeeasy certbot-dns-gehirn/certbot_dns_gehirn certbot-dns-google/certbot_dns_google certbot-dns-linode/certbot_dns_linode certbot-dns-luadns/certbot_dns_luadns certbot-dns-nsone/certbot_dns_nsone certbot-dns-ovh/certbot_dns_ovh certbot-dns-rfc2136/certbot_dns_rfc2136 certbot-dns-route53/certbot_dns_route53 certbot-dns-sakuracloud/certbot_dns_sakuracloud certbot-nginx/certbot_nginx tests/lock_test.py
|
||||
|
||||
[testenv]
|
||||
passenv =
|
||||
@@ -100,7 +62,8 @@ setenv =
|
||||
basepython =
|
||||
{[testenv:oldest]basepython}
|
||||
commands =
|
||||
{[base]install_and_test} certbot-apache
|
||||
{[base]pip_install} acme[dev] certbot[dev] certbot-apache
|
||||
pytest certbot-apache
|
||||
setenv =
|
||||
{[testenv:oldest]setenv}
|
||||
|
||||
@@ -108,7 +71,8 @@ setenv =
|
||||
basepython =
|
||||
{[testenv:oldest]basepython}
|
||||
commands =
|
||||
{[base]install_and_test} certbot-apache[dev]
|
||||
{[base]pip_install} acme[dev] certbot[dev] certbot-apache[dev]
|
||||
pytest certbot-apache
|
||||
setenv =
|
||||
{[testenv:oldest]setenv}
|
||||
|
||||
@@ -116,7 +80,8 @@ setenv =
|
||||
basepython =
|
||||
{[testenv:oldest]basepython}
|
||||
commands =
|
||||
{[base]install_and_test} certbot[dev]
|
||||
{[base]pip_install} acme[dev] certbot[dev]
|
||||
pytest certbot
|
||||
setenv =
|
||||
{[testenv:oldest]setenv}
|
||||
|
||||
@@ -124,7 +89,8 @@ setenv =
|
||||
basepython =
|
||||
{[testenv:oldest]basepython}
|
||||
commands =
|
||||
{[base]install_and_test} {[base]dns_packages}
|
||||
{[base]pip_install} acme[dev] certbot[dev] {[base]dns_packages}
|
||||
pytest {[base]dns_packages}
|
||||
setenv =
|
||||
{[testenv:oldest]setenv}
|
||||
|
||||
@@ -132,7 +98,8 @@ setenv =
|
||||
basepython =
|
||||
{[testenv:oldest]basepython}
|
||||
commands =
|
||||
{[base]install_and_test} certbot-nginx
|
||||
{[base]pip_install} acme[dev] certbot[dev] certbot-nginx
|
||||
pytest certbot-nginx
|
||||
python tests/lock_test.py
|
||||
setenv =
|
||||
{[testenv:oldest]setenv}
|
||||
@@ -258,8 +225,7 @@ passenv = DOCKER_*
|
||||
basepython =
|
||||
{[testenv:oldest]basepython}
|
||||
commands =
|
||||
{[base]pip_install} certbot
|
||||
{[base]pip_install} certbot-ci
|
||||
{[base]pip_install} acme certbot certbot-ci
|
||||
pytest certbot-ci/certbot_integration_tests/certbot_tests \
|
||||
--acme-server={env:ACME_SERVER:pebble}
|
||||
passenv = DOCKER_*
|
||||
@@ -269,8 +235,7 @@ setenv = {[testenv:oldest]setenv}
|
||||
basepython =
|
||||
{[testenv:oldest]basepython}
|
||||
commands =
|
||||
{[base]pip_install} certbot-nginx
|
||||
{[base]pip_install} certbot-ci
|
||||
{[base]pip_install} acme certbot certbot-nginx certbot-ci
|
||||
pytest certbot-ci/certbot_integration_tests/nginx_tests \
|
||||
--acme-server={env:ACME_SERVER:pebble}
|
||||
passenv = DOCKER_*
|
||||
|
||||
12
windows-installer/assets/preamble.py
Normal file
12
windows-installer/assets/preamble.py
Normal file
@@ -0,0 +1,12 @@
|
||||
"""Pynsist extra_preamble for the Certbot entry point.
|
||||
|
||||
This preamble ensures that Certbot on Windows always runs with the --preconfigured-renewal
|
||||
flag set. Since Pynsist creates a Scheduled Task for renewal, we want this flag to be set
|
||||
so that we can provide the right automated renewal advice to Certbot on Windows users.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
sys.argv += ["--preconfigured-renewal"]
|
||||
@@ -82,6 +82,7 @@ def _copy_assets(build_path, repo_path):
|
||||
shutil.copy(os.path.join(repo_path, 'windows-installer', 'assets', 'template.nsi'), build_path)
|
||||
shutil.copy(os.path.join(repo_path, 'windows-installer', 'assets', 'renew-up.ps1'), build_path)
|
||||
shutil.copy(os.path.join(repo_path, 'windows-installer', 'assets', 'renew-down.ps1'), build_path)
|
||||
shutil.copy(os.path.join(repo_path, 'windows-installer', 'assets', 'preamble.py'), build_path)
|
||||
|
||||
|
||||
def _generate_pynsist_config(repo_path, build_path):
|
||||
@@ -121,6 +122,7 @@ files=run.bat
|
||||
|
||||
[Command certbot]
|
||||
entry_point=certbot.main:main
|
||||
extra_preamble=preamble.py
|
||||
'''.format(certbot_version=certbot_version,
|
||||
installer_suffix='win_amd64' if PYTHON_BITNESS == 64 else 'win32',
|
||||
python_bitness=PYTHON_BITNESS,
|
||||
|
||||
Reference in New Issue
Block a user