mirror of
https://github.com/certbot/certbot.git
synced 2026-06-08 16:22:18 -04:00
Merge remote-tracking branch 'upstream/master' into fix_cert_path
This commit is contained in:
commit
4e41e65bfc
29 changed files with 798 additions and 166 deletions
|
|
@ -21,6 +21,7 @@ WORKDIR /opt/certbot
|
|||
# If <dest> doesn't exist, it is created along with all missing
|
||||
# directories in its path.
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
COPY letsencrypt-auto-source/letsencrypt-auto /opt/certbot/src/letsencrypt-auto-source/letsencrypt-auto
|
||||
RUN /opt/certbot/src/letsencrypt-auto-source/letsencrypt-auto --os-packages-only && \
|
||||
|
|
|
|||
14
README.rst
14
README.rst
|
|
@ -31,14 +31,17 @@ Contributing
|
|||
If you'd like to contribute to this project please read `Developer Guide
|
||||
<https://certbot.eff.org/docs/contributing.html>`_.
|
||||
|
||||
.. _installation:
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
If ``certbot`` (or ``letsencrypt``) is packaged for your Unix OS, you can install
|
||||
it from there, and run it by typing ``certbot`` (or ``letsencrypt``).
|
||||
Because not all operating systems have packages yet, we provide a temporary
|
||||
solution via the ``certbot-auto`` wrapper script, which obtains some
|
||||
dependencies from your OS and puts others in a python virtual environment::
|
||||
If ``certbot`` (or ``letsencrypt``) is packaged for your Unix OS (visit
|
||||
certbot.eff.org_ to find out), you can install it
|
||||
from there, and run it by typing ``certbot`` (or ``letsencrypt``). Because
|
||||
not all operating systems have packages yet, we provide a temporary solution
|
||||
via the ``certbot-auto`` wrapper script, which obtains some dependencies from
|
||||
your OS and puts others in a python virtual environment::
|
||||
|
||||
user@webserver:~$ wget https://dl.eff.org/certbot-auto
|
||||
user@webserver:~$ chmod a+x ./certbot-auto
|
||||
|
|
@ -188,3 +191,4 @@ Current Features
|
|||
.. _Freenode: https://webchat.freenode.net?channels=%23letsencrypt
|
||||
.. _OFTC: https://webchat.oftc.net?channels=%23certbot
|
||||
.. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev
|
||||
.. _certbot.eff.org: https://certbot.eff.org/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
"""Crypto utilities."""
|
||||
import binascii
|
||||
import contextlib
|
||||
import logging
|
||||
import re
|
||||
|
|
@ -203,7 +204,7 @@ def gen_ss_cert(key, domains, not_before=None,
|
|||
"""
|
||||
assert domains, "Must provide one or more hostnames for the cert."
|
||||
cert = OpenSSL.crypto.X509()
|
||||
cert.set_serial_number(1337)
|
||||
cert.set_serial_number(int(binascii.hexlify(OpenSSL.rand.bytes(16)), 16))
|
||||
cert.set_version(2)
|
||||
|
||||
extensions = [
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import unittest
|
|||
import six
|
||||
from six.moves import socketserver # pylint: disable=import-error
|
||||
|
||||
import OpenSSL
|
||||
|
||||
from acme import errors
|
||||
from acme import jose
|
||||
from acme import test_util
|
||||
|
|
@ -126,5 +128,23 @@ class PyOpenSSLCertOrReqSANTest(unittest.TestCase):
|
|||
self._get_idn_names())
|
||||
|
||||
|
||||
class RandomSnTest(unittest.TestCase):
|
||||
"""Test for random certificate serial numbers."""
|
||||
|
||||
def setUp(self):
|
||||
self.cert_count = 5
|
||||
self.serial_num = []
|
||||
self.key = OpenSSL.crypto.PKey()
|
||||
self.key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
|
||||
|
||||
def test_sn_collisions(self):
|
||||
from acme.crypto_util import gen_ss_cert
|
||||
|
||||
for _ in range(self.cert_count):
|
||||
cert = gen_ss_cert(self.key, ['dummy'], force_san=True)
|
||||
self.serial_num.append(cert.get_serial_number())
|
||||
self.assertTrue(len(set(self.serial_num)) > 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main() # pragma: no cover
|
||||
|
|
|
|||
|
|
@ -124,13 +124,16 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
self.assoc = dict()
|
||||
# Outstanding challenges
|
||||
self._chall_out = set()
|
||||
# Maps enhancements to vhosts we've enabled the enhancement for
|
||||
self._enhanced_vhosts = defaultdict(set)
|
||||
|
||||
# These will be set in the prepare function
|
||||
self.parser = None
|
||||
self.version = version
|
||||
self.vhosts = None
|
||||
self._enhance_func = {"redirect": self._enable_redirect,
|
||||
"ensure-http-header": self._set_http_header}
|
||||
"ensure-http-header": self._set_http_header,
|
||||
"staple-ocsp": self._enable_ocsp_stapling}
|
||||
|
||||
@property
|
||||
def mod_ssl_conf(self):
|
||||
|
|
@ -593,8 +596,8 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
:type addr: :class:`~certbot_apache.obj.Addr`
|
||||
|
||||
"""
|
||||
loc = parser.get_aug_path(self.parser.loc["name"])
|
||||
|
||||
loc = parser.get_aug_path(self.parser.loc["name"])
|
||||
if addr.get_port() == "443":
|
||||
path = self.parser.add_dir_to_ifmodssl(
|
||||
loc, "NameVirtualHost", [str(addr)])
|
||||
|
|
@ -944,7 +947,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
######################################################################
|
||||
def supported_enhancements(self): # pylint: disable=no-self-use
|
||||
"""Returns currently supported enhancements."""
|
||||
return ["redirect", "ensure-http-header"]
|
||||
return ["redirect", "ensure-http-header", "staple-ocsp"]
|
||||
|
||||
def enhance(self, domain, enhancement, options=None):
|
||||
"""Enhance configuration.
|
||||
|
|
@ -971,6 +974,68 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
logger.warn("Failed %s for %s", enhancement, domain)
|
||||
raise
|
||||
|
||||
def _enable_ocsp_stapling(self, ssl_vhost, unused_options):
|
||||
"""Enables OCSP Stapling
|
||||
|
||||
In OCSP, each client (e.g. browser) would have to query the
|
||||
OCSP Responder to validate that the site certificate was not revoked.
|
||||
|
||||
Enabling OCSP Stapling, would allow the web-server to query the OCSP
|
||||
Responder, and staple its response to the offered certificate during
|
||||
TLS. i.e. clients would not have to query the OCSP responder.
|
||||
|
||||
OCSP Stapling enablement on Apache implicitly depends on
|
||||
SSLCertificateChainFile being set by other code.
|
||||
|
||||
.. note:: This function saves the configuration
|
||||
|
||||
:param ssl_vhost: Destination of traffic, an ssl enabled vhost
|
||||
:type ssl_vhost: :class:`~letsencrypt_apache.obj.VirtualHost`
|
||||
|
||||
:param unused_options: Not currently used
|
||||
:type unused_options: Not Available
|
||||
|
||||
:returns: Success, general_vhost (HTTP vhost)
|
||||
:rtype: (bool, :class:`~letsencrypt_apache.obj.VirtualHost`)
|
||||
|
||||
"""
|
||||
min_apache_ver = (2, 3, 3)
|
||||
if self.get_version() < min_apache_ver:
|
||||
raise errors.PluginError(
|
||||
"Unable to set OCSP directives.\n"
|
||||
"Apache version is below 2.3.3.")
|
||||
|
||||
if "socache_shmcb_module" not in self.parser.modules:
|
||||
self.enable_mod("socache_shmcb")
|
||||
|
||||
# Check if there's an existing SSLUseStapling directive on.
|
||||
use_stapling_aug_path = self.parser.find_dir("SSLUseStapling",
|
||||
"on", start=ssl_vhost.path)
|
||||
if not use_stapling_aug_path:
|
||||
self.parser.add_dir(ssl_vhost.path, "SSLUseStapling", "on")
|
||||
|
||||
ssl_vhost_aug_path = parser.get_aug_path(ssl_vhost.filep)
|
||||
|
||||
# Check if there's an existing SSLStaplingCache directive.
|
||||
stapling_cache_aug_path = self.parser.find_dir('SSLStaplingCache',
|
||||
None, ssl_vhost_aug_path)
|
||||
|
||||
# We'll simply delete the directive, so that we'll have a
|
||||
# consistent OCSP cache path.
|
||||
if stapling_cache_aug_path:
|
||||
self.aug.remove(
|
||||
re.sub(r"/\w*$", "", stapling_cache_aug_path[0]))
|
||||
|
||||
self.parser.add_dir_to_ifmodssl(ssl_vhost_aug_path,
|
||||
"SSLStaplingCache",
|
||||
["shmcb:/var/run/apache2/stapling_cache(128000)"])
|
||||
|
||||
msg = "OCSP Stapling was enabled on SSL Vhost: %s.\n"%(
|
||||
ssl_vhost.filep)
|
||||
self.save_notes += msg
|
||||
self.save()
|
||||
logger.info(msg)
|
||||
|
||||
def _set_http_header(self, ssl_vhost, header_substring):
|
||||
"""Enables header that is identified by header_substring on ssl_vhost.
|
||||
|
||||
|
|
@ -1058,9 +1123,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
:param unused_options: Not currently used
|
||||
:type unused_options: Not Available
|
||||
|
||||
:returns: Success, general_vhost (HTTP vhost)
|
||||
:rtype: (bool, :class:`~certbot_apache.obj.VirtualHost`)
|
||||
|
||||
:raises .errors.PluginError: If no viable HTTP host can be created or
|
||||
used for the redirect.
|
||||
|
||||
|
|
@ -1083,6 +1145,10 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
"redirection")
|
||||
self._create_redirect_vhost(ssl_vhost)
|
||||
else:
|
||||
if general_vh in self._enhanced_vhosts["redirect"]:
|
||||
logger.debug("Already enabled redirect for this vhost")
|
||||
return
|
||||
|
||||
# Check if Certbot redirection already exists
|
||||
self._verify_no_certbot_redirect(general_vh)
|
||||
|
||||
|
|
@ -1118,6 +1184,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
(general_vh.filep, ssl_vhost.filep))
|
||||
self.save()
|
||||
|
||||
self._enhanced_vhosts["redirect"].add(general_vh)
|
||||
logger.info("Redirecting vhost in %s to ssl vhost in %s",
|
||||
general_vh.filep, ssl_vhost.filep)
|
||||
|
||||
|
|
@ -1177,10 +1244,14 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
|
||||
|
||||
"""
|
||||
rewrite_engine_path = self.parser.find_dir("RewriteEngine", "on",
|
||||
rewrite_engine_path_list = self.parser.find_dir("RewriteEngine", "on",
|
||||
start=vhost.path)
|
||||
if rewrite_engine_path:
|
||||
return self.parser.get_arg(rewrite_engine_path[0])
|
||||
if rewrite_engine_path_list:
|
||||
for re_path in rewrite_engine_path_list:
|
||||
# A RewriteEngine directive may also be included in per
|
||||
# directory .htaccess files. We only care about the VirtualHost.
|
||||
if 'VirtualHost' in re_path:
|
||||
return self.parser.get_arg(re_path)
|
||||
return False
|
||||
|
||||
def _create_redirect_vhost(self, ssl_vhost):
|
||||
|
|
@ -1202,6 +1273,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
|
|||
# Make a new vhost data structure and add it to the lists
|
||||
new_vhost = self._create_vhost(parser.get_aug_path(redirect_filepath))
|
||||
self.vhosts.append(new_vhost)
|
||||
self._enhanced_vhosts["redirect"].add(new_vhost)
|
||||
|
||||
# Finally create documentation for the change
|
||||
self.save_notes += ("Created a port 80 vhost, %s, for redirection to "
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from certbot import errors
|
|||
from certbot.tests import acme_util
|
||||
|
||||
from certbot_apache import configurator
|
||||
from certbot_apache import parser
|
||||
from certbot_apache import obj
|
||||
|
||||
from certbot_apache.tests import util
|
||||
|
|
@ -85,7 +86,8 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
mock_getutility.notification = mock.MagicMock(return_value=True)
|
||||
names = self.config.get_all_names()
|
||||
self.assertEqual(names, set(
|
||||
["certbot.demo", "encryption-example.demo", "ip-172-30-0-17", "*.blue.purple.com"]))
|
||||
["certbot.demo", "ocspvhost.com", "encryption-example.demo",
|
||||
"ip-172-30-0-17", "*.blue.purple.com"]))
|
||||
|
||||
@mock.patch("zope.component.getUtility")
|
||||
@mock.patch("certbot_apache.configurator.socket.gethostbyaddr")
|
||||
|
|
@ -100,14 +102,24 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
obj.Addr(("zombo.com",)),
|
||||
obj.Addr(("192.168.1.2"))]),
|
||||
True, False)
|
||||
|
||||
self.config.vhosts.append(vhost)
|
||||
|
||||
names = self.config.get_all_names()
|
||||
self.assertEqual(len(names), 6)
|
||||
self.assertEqual(len(names), 7)
|
||||
self.assertTrue("zombo.com" in names)
|
||||
self.assertTrue("google.com" in names)
|
||||
self.assertTrue("certbot.demo" in names)
|
||||
|
||||
def test_bad_servername_alias(self):
|
||||
ssl_vh1 = obj.VirtualHost(
|
||||
"fp1", "ap1", set([obj.Addr(("*", "443"))]),
|
||||
True, False)
|
||||
# pylint: disable=protected-access
|
||||
self.config._add_servernames(ssl_vh1)
|
||||
self.assertTrue(
|
||||
self.config._add_servername_alias("oy_vey", ssl_vh1) is None)
|
||||
|
||||
def test_add_servernames_alias(self):
|
||||
self.config.parser.add_dir(
|
||||
self.vh_truth[2].path, "ServerAlias", ["*.le.co"])
|
||||
|
|
@ -124,7 +136,7 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
|
||||
"""
|
||||
vhs = self.config.get_virtual_hosts()
|
||||
self.assertEqual(len(vhs), 7)
|
||||
self.assertEqual(len(vhs), 8)
|
||||
found = 0
|
||||
|
||||
for vhost in vhs:
|
||||
|
|
@ -135,7 +147,7 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
else:
|
||||
raise Exception("Missed: %s" % vhost) # pragma: no cover
|
||||
|
||||
self.assertEqual(found, 7)
|
||||
self.assertEqual(found, 8)
|
||||
|
||||
# Handle case of non-debian layout get_virtual_hosts
|
||||
with mock.patch(
|
||||
|
|
@ -143,7 +155,7 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
) as mock_conf:
|
||||
mock_conf.return_value = False
|
||||
vhs = self.config.get_virtual_hosts()
|
||||
self.assertEqual(len(vhs), 7)
|
||||
self.assertEqual(len(vhs), 8)
|
||||
|
||||
@mock.patch("certbot_apache.display_ops.select_vhost")
|
||||
def test_choose_vhost_none_avail(self, mock_select):
|
||||
|
|
@ -224,16 +236,18 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
# Assume only the two default vhosts.
|
||||
self.config.vhosts = [
|
||||
vh for vh in self.config.vhosts
|
||||
if vh.name not in ["certbot.demo", "encryption-example.demo"]
|
||||
if vh.name not in ["certbot.demo",
|
||||
"encryption-example.demo",
|
||||
"ocspvhost.com"]
|
||||
and "*.blue.purple.com" not in vh.aliases
|
||||
]
|
||||
|
||||
self.assertEqual(
|
||||
self.config._find_best_vhost("example.demo"), self.vh_truth[2])
|
||||
self.config._find_best_vhost("encryption-example.demo"),
|
||||
self.vh_truth[2])
|
||||
|
||||
def test_non_default_vhosts(self):
|
||||
# pylint: disable=protected-access
|
||||
self.assertEqual(len(self.config._non_default_vhosts()), 5)
|
||||
self.assertEqual(len(self.config._non_default_vhosts()), 6)
|
||||
|
||||
def test_is_site_enabled(self):
|
||||
"""Test if site is enabled.
|
||||
|
|
@ -539,7 +553,7 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
self.assertEqual(self.config.is_name_vhost(self.vh_truth[0]),
|
||||
self.config.is_name_vhost(ssl_vhost))
|
||||
|
||||
self.assertEqual(len(self.config.vhosts), 8)
|
||||
self.assertEqual(len(self.config.vhosts), 9)
|
||||
|
||||
def test_clean_vhost_ssl(self):
|
||||
# pylint: disable=protected-access
|
||||
|
|
@ -726,16 +740,15 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
|
||||
def test_get_all_certs_keys(self):
|
||||
c_k = self.config.get_all_certs_keys()
|
||||
|
||||
self.assertEqual(len(c_k), 2)
|
||||
self.assertEqual(len(c_k), 3)
|
||||
cert, key, path = next(iter(c_k))
|
||||
self.assertTrue("cert" in cert)
|
||||
self.assertTrue("key" in key)
|
||||
self.assertTrue("default-ssl" in path)
|
||||
self.assertTrue("default-ssl" in path or "ocsp-ssl" in path)
|
||||
|
||||
def test_get_all_certs_keys_malformed_conf(self):
|
||||
self.config.parser.find_dir = mock.Mock(
|
||||
side_effect=[["path"], [], ["path"], []])
|
||||
side_effect=[["path"], [], ["path"], [], ["path"], []])
|
||||
c_k = self.config.get_all_certs_keys()
|
||||
|
||||
self.assertFalse(c_k)
|
||||
|
|
@ -756,15 +769,20 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
def test_supported_enhancements(self):
|
||||
self.assertTrue(isinstance(self.config.supported_enhancements(), list))
|
||||
|
||||
@mock.patch("certbot_apache.configurator.ApacheConfigurator._get_http_vhost")
|
||||
@mock.patch("certbot_apache.display_ops.select_vhost")
|
||||
@mock.patch("certbot.le_util.exe_exists")
|
||||
def test_enhance_unknown_vhost(self, mock_exe):
|
||||
def test_enhance_unknown_vhost(self, mock_exe, mock_sel_vhost, mock_get):
|
||||
self.config.parser.modules.add("rewrite_module")
|
||||
mock_exe.return_value = True
|
||||
ssl_vh = obj.VirtualHost(
|
||||
"fp", "ap", set([obj.Addr(("*", "443"))]),
|
||||
ssl_vh1 = obj.VirtualHost(
|
||||
"fp1", "ap1", set([obj.Addr(("*", "443"))]),
|
||||
True, False)
|
||||
ssl_vh.name = "satoshi.com"
|
||||
self.config.vhosts.append(ssl_vh)
|
||||
ssl_vh1.name = "satoshi.com"
|
||||
self.config.vhosts.append(ssl_vh1)
|
||||
mock_sel_vhost.return_value = None
|
||||
mock_get.return_value = None
|
||||
|
||||
self.assertRaises(
|
||||
errors.PluginError,
|
||||
self.config.enhance, "satoshi.com", "redirect")
|
||||
|
|
@ -774,6 +792,85 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
errors.PluginError,
|
||||
self.config.enhance, "certbot.demo", "unknown_enhancement")
|
||||
|
||||
@mock.patch("certbot.le_util.run_script")
|
||||
@mock.patch("certbot.le_util.exe_exists")
|
||||
def test_ocsp_stapling(self, mock_exe, mock_run_script):
|
||||
self.config.parser.update_runtime_variables = mock.Mock()
|
||||
self.config.parser.modules.add("mod_ssl.c")
|
||||
self.config.get_version = mock.Mock(return_value=(2, 4, 7))
|
||||
mock_exe.return_value = True
|
||||
|
||||
# This will create an ssl vhost for certbot.demo
|
||||
self.config.enhance("certbot.demo", "staple-ocsp")
|
||||
|
||||
self.assertTrue("socache_shmcb_module" in self.config.parser.modules)
|
||||
self.assertTrue(mock_run_script.called)
|
||||
|
||||
# Get the ssl vhost for certbot.demo
|
||||
ssl_vhost = self.config.assoc["certbot.demo"]
|
||||
|
||||
ssl_use_stapling_aug_path = self.config.parser.find_dir(
|
||||
"SSLUseStapling", "on", ssl_vhost.path)
|
||||
|
||||
self.assertEqual(len(ssl_use_stapling_aug_path), 1)
|
||||
|
||||
ssl_vhost_aug_path = parser.get_aug_path(ssl_vhost.filep)
|
||||
stapling_cache_aug_path = self.config.parser.find_dir('SSLStaplingCache',
|
||||
"shmcb:/var/run/apache2/stapling_cache(128000)",
|
||||
ssl_vhost_aug_path)
|
||||
|
||||
self.assertEqual(len(stapling_cache_aug_path), 1)
|
||||
|
||||
@mock.patch("certbot.le_util.exe_exists")
|
||||
def test_ocsp_stapling_twice(self, mock_exe):
|
||||
self.config.parser.update_runtime_variables = mock.Mock()
|
||||
self.config.parser.modules.add("mod_ssl.c")
|
||||
self.config.parser.modules.add("socache_shmcb_module")
|
||||
self.config.get_version = mock.Mock(return_value=(2, 4, 7))
|
||||
mock_exe.return_value = True
|
||||
|
||||
# Checking the case with already enabled ocsp stapling configuration
|
||||
self.config.enhance("ocspvhost.com", "staple-ocsp")
|
||||
|
||||
# Get the ssl vhost for letsencrypt.demo
|
||||
ssl_vhost = self.config.assoc["ocspvhost.com"]
|
||||
|
||||
ssl_use_stapling_aug_path = self.config.parser.find_dir(
|
||||
"SSLUseStapling", "on", ssl_vhost.path)
|
||||
|
||||
self.assertEqual(len(ssl_use_stapling_aug_path), 1)
|
||||
|
||||
ssl_vhost_aug_path = parser.get_aug_path(ssl_vhost.filep)
|
||||
stapling_cache_aug_path = self.config.parser.find_dir('SSLStaplingCache',
|
||||
"shmcb:/var/run/apache2/stapling_cache(128000)",
|
||||
ssl_vhost_aug_path)
|
||||
|
||||
self.assertEqual(len(stapling_cache_aug_path), 1)
|
||||
|
||||
|
||||
@mock.patch("certbot.le_util.exe_exists")
|
||||
def test_ocsp_unsupported_apache_version(self, mock_exe):
|
||||
mock_exe.return_value = True
|
||||
self.config.parser.update_runtime_variables = mock.Mock()
|
||||
self.config.parser.modules.add("mod_ssl.c")
|
||||
self.config.parser.modules.add("socache_shmcb_module")
|
||||
self.config.get_version = mock.Mock(return_value=(2, 2, 0))
|
||||
|
||||
self.assertRaises(errors.PluginError,
|
||||
self.config.enhance, "certbot.demo", "staple-ocsp")
|
||||
|
||||
|
||||
def test_get_http_vhost_third_filter(self):
|
||||
ssl_vh = obj.VirtualHost(
|
||||
"fp", "ap", set([obj.Addr(("*", "443"))]),
|
||||
True, False)
|
||||
ssl_vh.name = "satoshi.com"
|
||||
self.config.vhosts.append(ssl_vh)
|
||||
|
||||
# pylint: disable=protected-access
|
||||
http_vh = self.config._get_http_vhost(ssl_vh)
|
||||
self.assertTrue(http_vh.ssl == False)
|
||||
|
||||
@mock.patch("certbot.le_util.run_script")
|
||||
@mock.patch("certbot.le_util.exe_exists")
|
||||
def test_http_header_hsts(self, mock_exe, _):
|
||||
|
|
@ -899,7 +996,7 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
def test_redirect_with_existing_rewrite(self, mock_exe, _):
|
||||
self.config.parser.update_runtime_variables = mock.Mock()
|
||||
mock_exe.return_value = True
|
||||
self.config.get_version = mock.Mock(return_value=(2, 2))
|
||||
self.config.get_version = mock.Mock(return_value=(2, 2, 0))
|
||||
|
||||
# Create a preexisting rewrite rule
|
||||
self.config.parser.add_dir(
|
||||
|
|
@ -938,15 +1035,31 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
self.assertRaises(
|
||||
errors.PluginError, self.config._enable_redirect, ssl_vh, "")
|
||||
|
||||
def test_redirect_twice(self):
|
||||
def test_redirect_two_domains_one_vhost(self):
|
||||
# Skip the enable mod
|
||||
self.config.parser.modules.add("rewrite_module")
|
||||
self.config.get_version = mock.Mock(return_value=(2, 3, 9))
|
||||
|
||||
self.config.enhance("encryption-example.demo", "redirect")
|
||||
self.config.enhance("red.blue.purple.com", "redirect")
|
||||
verify_no_redirect = ("certbot_apache.configurator."
|
||||
"ApacheConfigurator._verify_no_certbot_redirect")
|
||||
with mock.patch(verify_no_redirect) as mock_verify:
|
||||
self.config.enhance("green.blue.purple.com", "redirect")
|
||||
self.assertFalse(mock_verify.called)
|
||||
|
||||
def test_redirect_from_previous_run(self):
|
||||
# Skip the enable mod
|
||||
self.config.parser.modules.add("rewrite_module")
|
||||
self.config.get_version = mock.Mock(return_value=(2, 3, 9))
|
||||
|
||||
self.config.enhance("red.blue.purple.com", "redirect")
|
||||
# Clear state about enabling redirect on this run
|
||||
# pylint: disable=protected-access
|
||||
self.config._enhanced_vhosts["redirect"].clear()
|
||||
|
||||
self.assertRaises(
|
||||
errors.PluginEnhancementAlreadyPresent,
|
||||
self.config.enhance, "encryption-example.demo", "redirect")
|
||||
self.config.enhance, "green.blue.purple.com", "redirect")
|
||||
|
||||
def test_create_own_redirect(self):
|
||||
self.config.parser.modules.add("rewrite_module")
|
||||
|
|
@ -957,7 +1070,7 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
|
||||
# pylint: disable=protected-access
|
||||
self.config._enable_redirect(self.vh_truth[1], "")
|
||||
self.assertEqual(len(self.config.vhosts), 8)
|
||||
self.assertEqual(len(self.config.vhosts), 9)
|
||||
|
||||
def test_create_own_redirect_for_old_apache_version(self):
|
||||
self.config.parser.modules.add("rewrite_module")
|
||||
|
|
@ -968,7 +1081,7 @@ class MultipleVhostsTest(util.ApacheTest):
|
|||
|
||||
# pylint: disable=protected-access
|
||||
self.config._enable_redirect(self.vh_truth[1], "")
|
||||
self.assertEqual(len(self.config.vhosts), 8)
|
||||
self.assertEqual(len(self.config.vhosts), 9)
|
||||
|
||||
def test_sift_line(self):
|
||||
# pylint: disable=protected-access
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<IfModule mod_ssl.c>
|
||||
SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)
|
||||
<VirtualHost 10.2.3.4:443>
|
||||
# The ServerName directive sets the request scheme, hostname and port that
|
||||
# the server uses to identify itself. This is used when creating
|
||||
# redirection URLs. In the context of virtual hosts, the ServerName
|
||||
# specifies what hostname must appear in the request's Host: header to
|
||||
# match this virtual host. For the default virtual host (this file) this
|
||||
# value is not decisive as it is used as a last resort host regardless.
|
||||
# However, you must set it for any further virtual host explicitly.
|
||||
ServerName ocspvhost.com
|
||||
|
||||
ServerAdmin webmaster@dumpbits.com
|
||||
DocumentRoot /var/www/html
|
||||
|
||||
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
|
||||
# error, crit, alert, emerg.
|
||||
# It is also possible to configure the loglevel for particular
|
||||
# modules, e.g.
|
||||
#LogLevel info ssl:warn
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
|
||||
# For most configuration files from conf-available/, which are
|
||||
# enabled or disabled at a global level, it is possible to
|
||||
# include a line for only one particular virtual host. For example the
|
||||
# following line enables the CGI configuration for this host only
|
||||
# after it has been globally disabled with "a2disconf".
|
||||
#Include conf-available/serve-cgi-bin.conf
|
||||
SSLCertificateFile /etc/apache2/certs/certbot-cert_5.pem
|
||||
SSLCertificateKeyFile /etc/apache2/ssl/key-certbot_15.pem
|
||||
SSLUseStapling on
|
||||
</VirtualHost>
|
||||
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
|
||||
</IfModule>
|
||||
|
|
@ -0,0 +1 @@
|
|||
../sites-available/ocsp-ssl.conf
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
sites-available/certbot.conf, certbot.demo
|
||||
sites-available/encryption-example.conf, encryption-example.demo
|
||||
sites-available/ocsp-ssl.conf, ocspvhost.com
|
||||
|
|
|
|||
|
|
@ -156,8 +156,12 @@ def get_vh_truth(temp_dir, config_name):
|
|||
os.path.join(prefix, "wildcard.conf"),
|
||||
os.path.join(aug_pre, "wildcard.conf/VirtualHost"),
|
||||
set([obj.Addr.fromstring("*:80")]), False, False,
|
||||
"ip-172-30-0-17", aliases=["*.blue.purple.com"])
|
||||
]
|
||||
"ip-172-30-0-17", aliases=["*.blue.purple.com"]),
|
||||
obj.VirtualHost(
|
||||
os.path.join(prefix, "ocsp-ssl.conf"),
|
||||
os.path.join(aug_pre, "ocsp-ssl.conf/IfModule/VirtualHost"),
|
||||
set([obj.Addr.fromstring("10.2.3.4:443")]), True, True,
|
||||
"ocspvhost.com")]
|
||||
return vh_truth
|
||||
|
||||
return None # pragma: no cover
|
||||
|
|
|
|||
|
|
@ -731,9 +731,20 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False):
|
|||
" https:// for every http:// resource.", dest="uir", default=None)
|
||||
helpful.add(
|
||||
"security", "--no-uir", action="store_false",
|
||||
help=" Do not automatically set the \"Content-Security-Policy:"
|
||||
help="Do not automatically set the \"Content-Security-Policy:"
|
||||
" upgrade-insecure-requests\" header to every HTTP response.",
|
||||
dest="uir", default=None)
|
||||
helpful.add(
|
||||
"security", "--staple-ocsp", action="store_true",
|
||||
help="Enables OCSP Stapling. A valid OCSP response is stapled to"
|
||||
" the certificate that the server offers during TLS.",
|
||||
dest="staple", default=None)
|
||||
helpful.add(
|
||||
"security", "--no-staple-ocsp", action="store_false",
|
||||
help="Do not automatically enable OCSP Stapling.",
|
||||
dest="staple", default=None)
|
||||
|
||||
|
||||
helpful.add(
|
||||
"security", "--strict-permissions", action="store_true",
|
||||
help="Require that all configuration files are owned by the current "
|
||||
|
|
@ -748,7 +759,8 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False):
|
|||
" certificate lineage. You can try it with `--dry-run` first. For"
|
||||
" more fine-grained control, you can renew individual lineages with"
|
||||
" the `certonly` subcommand. Hooks are available to run commands "
|
||||
" before and after renewal; see XXX for more information on these.")
|
||||
" before and after renewal; see"
|
||||
" https://certbot.eff.org/docs/using.html#renewal for more information on these.")
|
||||
|
||||
helpful.add(
|
||||
"renew", "--pre-hook",
|
||||
|
|
@ -760,7 +772,8 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False):
|
|||
"renew", "--post-hook",
|
||||
help="Command to be run in a shell after attempting to obtain/renew "
|
||||
" certificates. Can be used to deploy renewed certificates, or to restart"
|
||||
" any servers that were stopped by --pre-hook.")
|
||||
" any servers that were stopped by --pre-hook. This is only run if"
|
||||
" an attempt was made to obtain/renew a certificate.")
|
||||
helpful.add(
|
||||
"renew", "--renew-hook",
|
||||
help="Command to be run in a shell once for each successfully renewed certificate."
|
||||
|
|
|
|||
|
|
@ -402,7 +402,8 @@ class Client(object):
|
|||
supported = self.installer.supported_enhancements()
|
||||
redirect = config.redirect if "redirect" in supported else False
|
||||
hsts = config.hsts if "ensure-http-header" in supported else False
|
||||
uir = config.uir if "ensure-http-header" in supported else False
|
||||
uir = config.uir if "ensure-http-header" in supported else False
|
||||
staple = config.staple if "staple-ocsp" in supported else False
|
||||
|
||||
if redirect is None:
|
||||
redirect = enhancements.ask("redirect")
|
||||
|
|
@ -416,9 +417,11 @@ class Client(object):
|
|||
if uir:
|
||||
self.apply_enhancement(domains, "ensure-http-header",
|
||||
"Upgrade-Insecure-Requests")
|
||||
if staple:
|
||||
self.apply_enhancement(domains, "staple-ocsp")
|
||||
|
||||
msg = ("We were unable to restart web server")
|
||||
if redirect or hsts or uir:
|
||||
if redirect or hsts or uir or staple:
|
||||
with error_handler.ErrorHandler(self._rollback_and_restart, msg):
|
||||
self.installer.restart()
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ def _validate_hook(shell_cmd, hook_name):
|
|||
:raises .errors.HookCommandNotFound: if the command is not found
|
||||
"""
|
||||
if shell_cmd:
|
||||
cmd = shell_cmd.partition(" ")[0]
|
||||
cmd = shell_cmd.split(None, 1)[0]
|
||||
if not _prog(cmd):
|
||||
path = os.environ["PATH"]
|
||||
msg = "Unable to find {2}-hook command {0} in the PATH.\n(PATH is {1})".format(
|
||||
|
|
@ -39,7 +39,7 @@ def pre_hook(config):
|
|||
if config.pre_hook and not pre_hook.already:
|
||||
logger.info("Running pre-hook command: %s", config.pre_hook)
|
||||
_run_hook(config.pre_hook)
|
||||
pre_hook.already = True
|
||||
pre_hook.already = True
|
||||
|
||||
pre_hook.already = False
|
||||
|
||||
|
|
@ -50,6 +50,11 @@ def post_hook(config, final=False):
|
|||
we're called with final=True before actually doing anything.
|
||||
"""
|
||||
if config.post_hook:
|
||||
if not pre_hook.already:
|
||||
logger.info("No renewals attempted, so not running post-hook")
|
||||
if config.verb != "renew":
|
||||
logger.warn("Sanity failure in renewal hooks")
|
||||
return
|
||||
if final or config.verb != "renew":
|
||||
logger.info("Running post-hook command: %s", config.post_hook)
|
||||
_run_hook(config.post_hook)
|
||||
|
|
|
|||
|
|
@ -94,10 +94,10 @@ def _auth_from_domains(le_client, config, domains, lineage=None):
|
|||
if lineage is False:
|
||||
raise errors.Error("Certificate could not be obtained")
|
||||
finally:
|
||||
hooks.post_hook(config)
|
||||
hooks.post_hook(config, final=False)
|
||||
|
||||
if not config.dry_run and not config.verb == "renew":
|
||||
_report_new_cert(lineage.cert, lineage.fullchain)
|
||||
_report_new_cert(config, lineage.cert, lineage.fullchain)
|
||||
|
||||
return lineage, action
|
||||
|
||||
|
|
@ -267,7 +267,7 @@ def _find_domains(config, installer):
|
|||
return domains
|
||||
|
||||
|
||||
def _report_new_cert(cert_path, fullchain_path):
|
||||
def _report_new_cert(config, cert_path, fullchain_path):
|
||||
"""Reports the creation of a new certificate to the user.
|
||||
|
||||
:param str cert_path: path to cert
|
||||
|
|
@ -285,12 +285,15 @@ def _report_new_cert(cert_path, fullchain_path):
|
|||
# Unless we're in .csr mode and there really isn't one
|
||||
and_chain = "has "
|
||||
path = cert_path
|
||||
|
||||
verbswitch = ' with the "certonly" option' if config.verb == "run" else ""
|
||||
# XXX Perhaps one day we could detect the presence of known old webservers
|
||||
# and say something more informative here.
|
||||
msg = ("Congratulations! Your certificate {0} been saved at {1}."
|
||||
" Your cert will expire on {2}. To obtain a new version of the "
|
||||
"certificate in the future, simply run Certbot again."
|
||||
.format(and_chain, path, expiry))
|
||||
msg = ('Congratulations! Your certificate {0} been saved at {1}.'
|
||||
' Your cert will expire on {2}. To obtain a new or tweaked version of this '
|
||||
'certificate in the future, simply run {3} again{4}. '
|
||||
'To non-interactively renew *all* of your ceriticates, run "{3} renew"'
|
||||
.format(and_chain, path, expiry, cli.cli_command, verbswitch))
|
||||
reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY)
|
||||
|
||||
|
||||
|
|
@ -485,7 +488,7 @@ def _csr_obtain_cert(config, le_client):
|
|||
else:
|
||||
cert_path, _, cert_fullchain = le_client.save_certificate(
|
||||
certr, chain, config.cert_path, config.chain_path, config.fullchain_path)
|
||||
_report_new_cert(cert_path, cert_fullchain)
|
||||
_report_new_cert(config, cert_path, cert_fullchain)
|
||||
|
||||
|
||||
def obtain_cert(config, plugins, lineage=None):
|
||||
|
|
|
|||
|
|
@ -301,7 +301,10 @@ def _renew_describe_results(config, renew_successes, renew_failures,
|
|||
def renew_all_lineages(config):
|
||||
"""Examine each lineage; renew if due and report results"""
|
||||
|
||||
if config.domains != []:
|
||||
# This is trivially False if config.domains is empty
|
||||
if any(domain not in config.webroot_map for domain in config.domains):
|
||||
# If more plugins start using cli.add_domains,
|
||||
# we may want to only log a warning here
|
||||
raise errors.Error("Currently, the renew verb is only capable of "
|
||||
"renewing all installed certificates that are due "
|
||||
"to be renewed; individual domains cannot be "
|
||||
|
|
|
|||
|
|
@ -712,6 +712,12 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods
|
|||
self._test_renew_common(renewalparams=renewalparams,
|
||||
assert_oc_called=True)
|
||||
|
||||
def test_renew_with_webroot_map(self):
|
||||
renewalparams = {'authenticator': 'webroot'}
|
||||
self._test_renew_common(
|
||||
renewalparams=renewalparams, assert_oc_called=True,
|
||||
args=['renew', '--webroot-map', '{"example.com": "/tmp"}'])
|
||||
|
||||
def test_renew_reconstitute_error(self):
|
||||
# pylint: disable=protected-access
|
||||
with mock.patch('certbot.main.renewal._reconstitute') as mock_reconstitute:
|
||||
|
|
|
|||
|
|
@ -56,14 +56,22 @@ class HookTest(unittest.TestCase):
|
|||
return mock_logger.warning
|
||||
|
||||
def test_pre_hook(self):
|
||||
hooks.pre_hook.already = False
|
||||
config = mock.MagicMock(pre_hook="true")
|
||||
self._test_a_hook(config, hooks.pre_hook, 1)
|
||||
config = mock.MagicMock(pre_hook="")
|
||||
self._test_a_hook(config, hooks.pre_hook, 0)
|
||||
|
||||
def test_post_hook(self):
|
||||
hooks.pre_hook.already = False
|
||||
# if pre-hook isn't called, post-hook shouldn't be
|
||||
config = mock.MagicMock(post_hook="true", verb="splonk")
|
||||
self._test_a_hook(config, hooks.post_hook, 0)
|
||||
|
||||
config = mock.MagicMock(post_hook="true", verb="splonk")
|
||||
self._test_a_hook(config, hooks.pre_hook, 1)
|
||||
self._test_a_hook(config, hooks.post_hook, 2)
|
||||
|
||||
config = mock.MagicMock(post_hook="true", verb="renew")
|
||||
self._test_a_hook(config, hooks.post_hook, 0)
|
||||
|
||||
|
|
|
|||
340
docs/cli-help.txt
Normal file
340
docs/cli-help.txt
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
usage:
|
||||
certbot [SUBCOMMAND] [options] [-d domain] [-d domain] ...
|
||||
|
||||
Certbot can obtain and install HTTPS/TLS/SSL certificates. By default,
|
||||
it will attempt to use a webserver both for obtaining and installing the
|
||||
cert. Major SUBCOMMANDS are:
|
||||
|
||||
(default) run Obtain & install a cert in your current webserver
|
||||
certonly Obtain cert, but do not install it (aka "auth")
|
||||
install Install a previously obtained cert in a server
|
||||
renew Renew previously obtained certs that are near expiry
|
||||
revoke Revoke a previously obtained certificate
|
||||
rollback Rollback server configuration changes made during install
|
||||
config_changes Show changes made to server config during installation
|
||||
plugins Display information about installed plugins
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-c CONFIG_FILE, --config CONFIG_FILE
|
||||
config file path (default: None)
|
||||
-v, --verbose This flag can be used multiple times to incrementally
|
||||
increase the verbosity of output, e.g. -vvv. (default:
|
||||
-3)
|
||||
-t, --text Use the text output instead of the curses UI.
|
||||
(default: False)
|
||||
-n, --non-interactive, --noninteractive
|
||||
Run without ever asking for user input. This may
|
||||
require additional command line flags; the client will
|
||||
try to explain which ones are required if it finds one
|
||||
missing (default: False)
|
||||
--dry-run Perform a test run of the client, obtaining test
|
||||
(invalid) certs but not saving them to disk. This can
|
||||
currently only be used with the 'certonly' and 'renew'
|
||||
subcommands. Note: Although --dry-run tries to avoid
|
||||
making any persistent changes on a system, it is not
|
||||
completely side-effect free: if used with webserver
|
||||
authenticator plugins like apache and nginx, it makes
|
||||
and then reverts temporary config changes in order to
|
||||
obtain test certs, and reloads webservers to deploy
|
||||
and then roll back those changes. It also calls --pre-
|
||||
hook and --post-hook commands if they are defined
|
||||
because they may be necessary to accurately simulate
|
||||
renewal. --renew-hook commands are not called.
|
||||
(default: False)
|
||||
--register-unsafely-without-email
|
||||
Specifying this flag enables registering an account
|
||||
with no email address. This is strongly discouraged,
|
||||
because in the event of key loss or account compromise
|
||||
you will irrevocably lose access to your account. You
|
||||
will also be unable to receive notice about impending
|
||||
expiration or revocation of your certificates. Updates
|
||||
to the Subscriber Agreement will still affect you, and
|
||||
will be effective 14 days after posting an update to
|
||||
the web site. (default: False)
|
||||
-m EMAIL, --email EMAIL
|
||||
Email used for registration and recovery contact.
|
||||
(default: None)
|
||||
-d DOMAIN, --domains DOMAIN, --domain DOMAIN
|
||||
Domain names to apply. For multiple domains you can
|
||||
use multiple -d flags or enter a comma separated list
|
||||
of domains as a parameter. (default: [])
|
||||
--user-agent USER_AGENT
|
||||
Set a custom user agent string for the client. User
|
||||
agent strings allow the CA to collect high level
|
||||
statistics about success rates by OS and plugin. If
|
||||
you wish to hide your server OS version from the Let's
|
||||
Encrypt server, set this to "". (default: None)
|
||||
|
||||
automation:
|
||||
Arguments for automating execution & other tweaks
|
||||
|
||||
--keep-until-expiring, --keep, --reinstall
|
||||
If the requested cert matches an existing cert, always
|
||||
keep the existing one until it is due for renewal (for
|
||||
the 'run' subcommand this means reinstall the existing
|
||||
cert) (default: False)
|
||||
--expand If an existing cert covers some subset of the
|
||||
requested names, always expand and replace it with the
|
||||
additional names. (default: False)
|
||||
--version show program's version number and exit
|
||||
--force-renewal, --renew-by-default
|
||||
If a certificate already exists for the requested
|
||||
domains, renew it now, regardless of whether it is
|
||||
near expiry. (Often --keep-until-expiring is more
|
||||
appropriate). Also implies --expand. (default: False)
|
||||
--allow-subset-of-names
|
||||
When performing domain validation, do not consider it
|
||||
a failure if authorizations can not be obtained for a
|
||||
strict subset of the requested domains. This may be
|
||||
useful for allowing renewals for multiple domains to
|
||||
succeed even if some domains no longer point at this
|
||||
system. This option cannot be used with --csr.
|
||||
(default: False)
|
||||
--agree-tos Agree to the ACME Subscriber Agreement (default:
|
||||
False)
|
||||
--account ACCOUNT_ID Account ID to use (default: None)
|
||||
--duplicate Allow making a certificate lineage that duplicates an
|
||||
existing one (both can be renewed in parallel)
|
||||
(default: False)
|
||||
--os-packages-only (letsencrypt-auto only) install OS package
|
||||
dependencies and then stop (default: False)
|
||||
--no-self-upgrade (letsencrypt-auto only) prevent the letsencrypt-auto
|
||||
script from upgrading itself to newer released
|
||||
versions (default: False)
|
||||
-q, --quiet Silence all output except errors. Useful for
|
||||
automation via cron. Implies --non-interactive.
|
||||
(default: False)
|
||||
|
||||
testing:
|
||||
The following flags are meant for testing purposes only! Do NOT change
|
||||
them, unless you really know what you're doing!
|
||||
|
||||
--debug Show tracebacks in case of errors, and allow
|
||||
letsencrypt-auto execution on experimental platforms
|
||||
(default: False)
|
||||
--no-verify-ssl Disable SSL certificate verification. (default: False)
|
||||
--tls-sni-01-port TLS_SNI_01_PORT
|
||||
Port number to perform tls-sni-01 challenge. Boulder
|
||||
in testing mode defaults to 5001. (default: 443)
|
||||
--http-01-port HTTP01_PORT
|
||||
Port used in the SimpleHttp challenge. (default: 80)
|
||||
--break-my-certs Be willing to replace or renew valid certs with
|
||||
invalid (testing/staging) certs (default: False)
|
||||
--test-cert, --staging
|
||||
Use the staging server to obtain test (invalid) certs;
|
||||
equivalent to --server https://acme-
|
||||
staging.api.letsencrypt.org/directory (default: False)
|
||||
|
||||
security:
|
||||
Security parameters & server settings
|
||||
|
||||
--rsa-key-size N Size of the RSA key. (default: 2048)
|
||||
--redirect Automatically redirect all HTTP traffic to HTTPS for
|
||||
the newly authenticated vhost. (default: None)
|
||||
--no-redirect Do not automatically redirect all HTTP traffic to
|
||||
HTTPS for the newly authenticated vhost. (default:
|
||||
None)
|
||||
--hsts Add the Strict-Transport-Security header to every HTTP
|
||||
response. Forcing browser to use always use SSL for
|
||||
the domain. Defends against SSL Stripping. (default:
|
||||
False)
|
||||
--no-hsts Do not automatically add the Strict-Transport-Security
|
||||
header to every HTTP response. (default: False)
|
||||
--uir Add the "Content-Security-Policy: upgrade-insecure-
|
||||
requests" header to every HTTP response. Forcing the
|
||||
browser to use https:// for every http:// resource.
|
||||
(default: None)
|
||||
--no-uir Do not automatically set the "Content-Security-Policy:
|
||||
upgrade-insecure-requests" header to every HTTP
|
||||
response. (default: None)
|
||||
--strict-permissions Require that all configuration files are owned by the
|
||||
current user; only needed if your config is somewhere
|
||||
unsafe like /tmp/ (default: False)
|
||||
|
||||
renew:
|
||||
The 'renew' subcommand will attempt to renew all certificates (or more
|
||||
precisely, certificate lineages) you have previously obtained if they are
|
||||
close to expiry, and print a summary of the results. By default, 'renew'
|
||||
will reuse the options used to create obtain or most recently successfully
|
||||
renew each certificate lineage. You can try it with `--dry-run` first. For
|
||||
more fine-grained control, you can renew individual lineages with the
|
||||
`certonly` subcommand. Hooks are available to run commands before and
|
||||
after renewal; see https://certbot.eff.org/docs/using.html#renewal for
|
||||
more information on these.
|
||||
|
||||
--pre-hook PRE_HOOK Command to be run in a shell before obtaining any
|
||||
certificates. Intended primarily for renewal, where it
|
||||
can be used to temporarily shut down a webserver that
|
||||
might conflict with the standalone plugin. This will
|
||||
only be called if a certificate is actually to be
|
||||
obtained/renewed. (default: None)
|
||||
--post-hook POST_HOOK
|
||||
Command to be run in a shell after attempting to
|
||||
obtain/renew certificates. Can be used to deploy
|
||||
renewed certificates, or to restart any servers that
|
||||
were stopped by --pre-hook. (default: None)
|
||||
--renew-hook RENEW_HOOK
|
||||
Command to be run in a shell once for each
|
||||
successfully renewed certificate.For this command, the
|
||||
shell variable $RENEWED_LINEAGE will point to
|
||||
theconfig live subdirectory containing the new certs
|
||||
and keys; the shell variable $RENEWED_DOMAINS will
|
||||
contain a space-delimited list of renewed cert domains
|
||||
(default: None)
|
||||
|
||||
certonly:
|
||||
Options for modifying how a cert is obtained
|
||||
|
||||
--csr CSR Path to a Certificate Signing Request (CSR) in DER
|
||||
format; note that the .csr file *must* contain a
|
||||
Subject Alternative Name field for each domain you
|
||||
want certified. Currently --csr only works with the
|
||||
'certonly' subcommand' (default: None)
|
||||
|
||||
install:
|
||||
Options for modifying how a cert is deployed
|
||||
|
||||
revoke:
|
||||
Options for revocation of certs
|
||||
|
||||
rollback:
|
||||
Options for reverting config changes
|
||||
|
||||
--checkpoints N Revert configuration N number of checkpoints.
|
||||
(default: 1)
|
||||
|
||||
plugins:
|
||||
Plugin options
|
||||
|
||||
--init Initialize plugins. (default: False)
|
||||
--prepare Initialize and prepare plugins. (default: False)
|
||||
--authenticators Limit to authenticator plugins only. (default: None)
|
||||
--installers Limit to installer plugins only. (default: None)
|
||||
|
||||
config_changes:
|
||||
Options for showing a history of config changes
|
||||
|
||||
--num NUM How many past revisions you want to be displayed
|
||||
(default: None)
|
||||
|
||||
paths:
|
||||
Arguments changing execution paths & servers
|
||||
|
||||
--cert-path CERT_PATH
|
||||
Path to where cert is saved (with auth --csr),
|
||||
installed from or revoked. (default: None)
|
||||
--key-path KEY_PATH Path to private key for cert installation or
|
||||
revocation (if account key is missing) (default: None)
|
||||
--fullchain-path FULLCHAIN_PATH
|
||||
Accompanying path to a full certificate chain (cert
|
||||
plus chain). (default: None)
|
||||
--chain-path CHAIN_PATH
|
||||
Accompanying path to a certificate chain. (default:
|
||||
None)
|
||||
--config-dir CONFIG_DIR
|
||||
Configuration directory. (default: /etc/letsencrypt)
|
||||
--work-dir WORK_DIR Working directory. (default: /var/lib/letsencrypt)
|
||||
--logs-dir LOGS_DIR Logs directory. (default: /var/log/letsencrypt)
|
||||
--server SERVER ACME Directory Resource URI. (default:
|
||||
https://acme-v01.api.letsencrypt.org/directory)
|
||||
|
||||
plugins:
|
||||
Certbot client supports an extensible plugins architecture. See 'certbot
|
||||
plugins' for a list of all installed plugins and their names. You can
|
||||
force a particular plugin by setting options provided below. Running
|
||||
--help <plugin_name> will list flags specific to that plugin.
|
||||
|
||||
-a AUTHENTICATOR, --authenticator AUTHENTICATOR
|
||||
Authenticator plugin name. (default: None)
|
||||
-i INSTALLER, --installer INSTALLER
|
||||
Installer plugin name (also used to find domains).
|
||||
(default: None)
|
||||
--configurator CONFIGURATOR
|
||||
Name of the plugin that is both an authenticator and
|
||||
an installer. Should not be used together with
|
||||
--authenticator or --installer. (default: None)
|
||||
--apache Obtain and install certs using Apache (default: False)
|
||||
--nginx Obtain and install certs using Nginx (default: False)
|
||||
--standalone Obtain certs using a "standalone" webserver. (default:
|
||||
False)
|
||||
--manual Provide laborious manual instructions for obtaining a
|
||||
cert (default: False)
|
||||
--webroot Obtain certs by placing files in a webroot directory.
|
||||
(default: False)
|
||||
|
||||
nginx:
|
||||
Nginx Web Server - currently doesn't work
|
||||
|
||||
--nginx-server-root NGINX_SERVER_ROOT
|
||||
Nginx server root directory. (default: /etc/nginx)
|
||||
--nginx-ctl NGINX_CTL
|
||||
Path to the 'nginx' binary, used for 'configtest' and
|
||||
retrieving nginx version number. (default: nginx)
|
||||
|
||||
standalone:
|
||||
Automatically use a temporary webserver
|
||||
|
||||
--standalone-supported-challenges STANDALONE_SUPPORTED_CHALLENGES
|
||||
Supported challenges. Preferred in the order they are
|
||||
listed. (default: tls-sni-01,http-01)
|
||||
|
||||
manual:
|
||||
Manually configure an HTTP server
|
||||
|
||||
--manual-test-mode Test mode. Executes the manual command in subprocess.
|
||||
(default: False)
|
||||
--manual-public-ip-logging-ok
|
||||
Automatically allows public IP logging. (default:
|
||||
False)
|
||||
|
||||
webroot:
|
||||
Place files in webroot directory
|
||||
|
||||
--webroot-path WEBROOT_PATH, -w WEBROOT_PATH
|
||||
public_html / webroot path. This can be specified
|
||||
multiple times to handle different domains; each
|
||||
domain will have the webroot path that preceded it.
|
||||
For instance: `-w /var/www/example -d example.com -d
|
||||
www.example.com -w /var/www/thing -d thing.net -d
|
||||
m.thing.net` (default: [])
|
||||
--webroot-map WEBROOT_MAP
|
||||
JSON dictionary mapping domains to webroot paths; this
|
||||
implies -d for each entry. You may need to escape this
|
||||
from your shell. E.g.: --webroot-map
|
||||
'{"eg1.is,m.eg1.is":"/www/eg1/", "eg2.is":"/www/eg2"}'
|
||||
This option is merged with, but takes precedence over,
|
||||
-w / -d entries. At present, if you put webroot-map in
|
||||
a config file, it needs to be on a single line, like:
|
||||
webroot-map = {"example.com":"/var/www"}. (default:
|
||||
{})
|
||||
|
||||
apache:
|
||||
Apache Web Server - Alpha
|
||||
|
||||
--apache-enmod APACHE_ENMOD
|
||||
Path to the Apache 'a2enmod' binary. (default:
|
||||
a2enmod)
|
||||
--apache-dismod APACHE_DISMOD
|
||||
Path to the Apache 'a2dismod' binary. (default:
|
||||
a2dismod)
|
||||
--apache-le-vhost-ext APACHE_LE_VHOST_EXT
|
||||
SSL vhost configuration extension. (default: -le-
|
||||
ssl.conf)
|
||||
--apache-server-root APACHE_SERVER_ROOT
|
||||
Apache server root directory. (default: /etc/apache2)
|
||||
--apache-vhost-root APACHE_VHOST_ROOT
|
||||
Apache server VirtualHost configuration root (default:
|
||||
/etc/apache2/sites-available)
|
||||
--apache-challenge-location APACHE_CHALLENGE_LOCATION
|
||||
Directory path for challenge configuration. (default:
|
||||
/etc/apache2)
|
||||
--apache-handle-modules APACHE_HANDLE_MODULES
|
||||
Let installer handle enabling required modules for
|
||||
you.(Only Ubuntu/Debian currently) (default: True)
|
||||
--apache-handle-sites APACHE_HANDLE_SITES
|
||||
Let installer handle enabling sites for you.(Only
|
||||
Ubuntu/Debian currently) (default: True)
|
||||
|
||||
null:
|
||||
Null Installer
|
||||
|
|
@ -333,7 +333,7 @@ commands:
|
|||
|
||||
.. code-block:: shell
|
||||
|
||||
make -C docs clean html
|
||||
make -C docs clean html man
|
||||
|
||||
This should generate documentation in the ``docs/_build/html``
|
||||
directory.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
============
|
||||
Introduction
|
||||
============
|
||||
=====================
|
||||
README / Introduction
|
||||
=====================
|
||||
|
||||
.. include:: ../README.rst
|
||||
.. include:: ../CHANGES.rst
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
.. program-output:: certbot --help all
|
||||
.. literalinclude:: cli-help.txt
|
||||
|
|
|
|||
|
|
@ -5,56 +5,28 @@ User Guide
|
|||
.. contents:: Table of Contents
|
||||
:local:
|
||||
|
||||
.. _installation:
|
||||
Getting Certbot
|
||||
===============
|
||||
|
||||
Installation
|
||||
============
|
||||
To get specific instructions for installing Certbot on your OS, we recommend
|
||||
visiting certbot.eff.org_. If you're offline, you can find some general
|
||||
instructions `in the README / Introduction <intro.html#installation>`__
|
||||
|
||||
__ installation_
|
||||
.. _certbot.eff.org: https://certbot.eff.org
|
||||
|
||||
.. _certbot-auto:
|
||||
|
||||
certbot-auto
|
||||
----------------
|
||||
The name of the certbot command
|
||||
-------------------------------
|
||||
|
||||
``certbot-auto`` is a wrapper which installs some dependencies
|
||||
from your OS standard package repositories (e.g. using `apt-get` or
|
||||
`yum`), and for other dependencies it sets up a virtualized Python
|
||||
environment with packages downloaded from PyPI [#venv]_. It also
|
||||
provides automated updates.
|
||||
|
||||
To install and run the client, just type...
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
./certbot-auto
|
||||
|
||||
.. hint:: The Let's Encrypt servers enforce rate
|
||||
limits on the number of certificates issued for one domain. It is recommended
|
||||
to initially use the test server via `--test-cert` until you get the desired
|
||||
certificates.
|
||||
|
||||
Throughout the documentation, whenever you see references to
|
||||
``certbot`` script/binary, you can substitute in
|
||||
``certbot-auto``. For example, to get basic help you would type:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
./certbot-auto --help
|
||||
|
||||
or for full help, type:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
./certbot-auto --help all
|
||||
|
||||
|
||||
``certbot-auto`` is the recommended method of running the Certbot
|
||||
client beta releases on systems that don't have a packaged version. Debian,
|
||||
Arch Linux, Gentoo, FreeBSD, and OpenBSD now have native packages, so on those
|
||||
systems you can just install ``certbot`` (and perhaps
|
||||
``certbot-apache``). If you'd like to run the latest copy from Git, or
|
||||
run your own locally modified copy of the client, follow the instructions in
|
||||
the :doc:`contributing`. Some `other methods of installation`_ are discussed
|
||||
below.
|
||||
Many platforms now have native packages that give you a ``certbot`` or (for
|
||||
older packages) ``letsencrypt`` command you can run. On others, the
|
||||
``certbot-auto`` / ``letsencrypt-auto`` installer and wrapper script is a
|
||||
stand-in. Throughout the documentation, whenever you see references to
|
||||
``certbot`` script/binary, you should substitute in the name of the command
|
||||
that certbot.eff.org_ told you to use on your system (``certbot``,
|
||||
``letsencrypt``, or ``certbot-auto``).
|
||||
|
||||
|
||||
Plugins
|
||||
|
|
@ -291,17 +263,21 @@ Certbot is working hard on improving the renewal process, and we
|
|||
apologize for any inconveniences you encounter in integrating these
|
||||
commands into your individual environment.
|
||||
|
||||
.. _command-line:
|
||||
|
||||
Command line options
|
||||
====================
|
||||
|
||||
Certbot supports a lot of command line options. Here's the full list, from
|
||||
``certbot --help all``:
|
||||
|
||||
.. literalinclude:: cli-help.txt
|
||||
|
||||
.. _where-certs:
|
||||
|
||||
Where are my certificates?
|
||||
==========================
|
||||
|
||||
First of all, we encourage you to use Apache or nginx installers, both
|
||||
which perform the certificate management automatically. If, however,
|
||||
you prefer to manage everything by hand, this section provides
|
||||
information on where to find necessary files.
|
||||
|
||||
All generated keys and issued certificates can be found in
|
||||
``/etc/letsencrypt/live/$domain``. Rather than copying, please point
|
||||
your (web) server configuration directly to those files (or create
|
||||
|
|
@ -361,8 +337,8 @@ will cause nasty errors served through the browsers!
|
|||
|
||||
.. note:: All files are PEM-encoded (as the filename suffix
|
||||
suggests). If you need other format, such as DER or PFX, then you
|
||||
could convert using ``openssl``, but this means you will not
|
||||
benefit from automatic renewal_!
|
||||
could convert using ``openssl``. You can automate that with
|
||||
``--renew-hook`` if you're using automatic renewal_.
|
||||
|
||||
|
||||
.. _config-file:
|
||||
|
|
@ -407,7 +383,7 @@ give us as much information as possible:
|
|||
also might contain personally identifiable information)
|
||||
- copy and paste ``certbot --version`` output
|
||||
- your operating system, including specific version
|
||||
- specify which installation_ method you've chosen
|
||||
- specify which installation method you've chosen
|
||||
|
||||
Other methods of installation
|
||||
=============================
|
||||
|
|
@ -484,7 +460,7 @@ repo, if you have not already done so. Then run:
|
|||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo apt-get install certbot python-certbot-apache -t jessie-backports
|
||||
sudo apt-get install letsencrypt python-letsencrypt-apache -t jessie-backports
|
||||
|
||||
**Fedora**
|
||||
|
||||
|
|
|
|||
|
|
@ -38,17 +38,6 @@ Help for certbot itself cannot be provided until it is installed.
|
|||
|
||||
All arguments are accepted and forwarded to the Certbot client when run."
|
||||
|
||||
while getopts ":hnv" arg; do
|
||||
case $arg in
|
||||
h)
|
||||
HELP=1;;
|
||||
n)
|
||||
ASSUME_YES=1;;
|
||||
v)
|
||||
VERBOSE=1;;
|
||||
esac
|
||||
done
|
||||
|
||||
for arg in "$@" ; do
|
||||
case "$arg" in
|
||||
--debug)
|
||||
|
|
@ -65,9 +54,26 @@ for arg in "$@" ; do
|
|||
ASSUME_YES=1;;
|
||||
--verbose)
|
||||
VERBOSE=1;;
|
||||
-[!-]*)
|
||||
while getopts ":hnv" short_arg $arg; do
|
||||
case "$short_arg" in
|
||||
h)
|
||||
HELP=1;;
|
||||
n)
|
||||
ASSUME_YES=1;;
|
||||
v)
|
||||
VERBOSE=1;;
|
||||
esac
|
||||
done;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $BASENAME = "letsencrypt-auto" ]; then
|
||||
# letsencrypt-auto does not respect --help or --yes for backwards compatibility
|
||||
ASSUME_YES=1
|
||||
HELP=0
|
||||
fi
|
||||
|
||||
# certbot-auto needs root access to bootstrap OS dependencies, and
|
||||
# certbot itself needs root access for almost all modes of operation
|
||||
# The "normal" case is that sudo is used for the steps that need root, but
|
||||
|
|
@ -107,12 +113,6 @@ else
|
|||
SUDO=
|
||||
fi
|
||||
|
||||
if [ $BASENAME = "letsencrypt-auto" ]; then
|
||||
# letsencrypt-auto does not respect --help or --yes for backwards compatibility
|
||||
ASSUME_YES=1
|
||||
HELP=0
|
||||
fi
|
||||
|
||||
ExperimentalBootstrap() {
|
||||
# Arguments: Platform name, bootstrap function name
|
||||
if [ "$DEBUG" = 1 ]; then
|
||||
|
|
@ -435,7 +435,8 @@ BootstrapMac() {
|
|||
# Workaround for _dlopen not finding augeas on OS X
|
||||
if [ "$pkgman" = "port" ] && ! [ -e "/usr/local/lib/libaugeas.dylib" ] && [ -e "/opt/local/lib/libaugeas.dylib" ]; then
|
||||
echo "Applying augeas workaround"
|
||||
$SUDO ln -s /opt/local/lib/libaugeas.dylib /usr/local/lib
|
||||
$SUDO mkdir -p /usr/local/lib/
|
||||
$SUDO ln -s /opt/local/lib/libaugeas.dylib /usr/local/lib/
|
||||
fi
|
||||
|
||||
if ! hash pip 2>/dev/null; then
|
||||
|
|
@ -451,6 +452,11 @@ BootstrapMac() {
|
|||
fi
|
||||
}
|
||||
|
||||
BootstrapSmartOS() {
|
||||
pkgin update
|
||||
pkgin -y install 'gcc49' 'py27-augeas' 'py27-virtualenv'
|
||||
}
|
||||
|
||||
|
||||
# Install required OS packages:
|
||||
Bootstrap() {
|
||||
|
|
@ -483,8 +489,10 @@ Bootstrap() {
|
|||
ExperimentalBootstrap "FreeBSD" BootstrapFreeBsd
|
||||
elif uname | grep -iq Darwin ; then
|
||||
ExperimentalBootstrap "Mac OS X" BootstrapMac
|
||||
elif grep -iq "Amazon Linux" /etc/issue ; then
|
||||
elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then
|
||||
ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon
|
||||
elif [ -f /etc/product ] && grep -q "Joyent Instance" /etc/product ; then
|
||||
ExperimentalBootstrap "Joyent SmartOS Zone" BootstrapSmartOS
|
||||
else
|
||||
echo "Sorry, I don't know how to bootstrap Certbot on your operating system!"
|
||||
echo
|
||||
|
|
@ -890,14 +898,16 @@ UNLIKELY_EOF
|
|||
fi
|
||||
echo "Installation succeeded."
|
||||
fi
|
||||
echo "Requesting root privileges to run certbot..."
|
||||
if [ -n "$SUDO" ]; then
|
||||
# SUDO is su wrapper or sudo
|
||||
echo "Requesting root privileges to run certbot..."
|
||||
echo " $VENV_BIN/letsencrypt" "$@"
|
||||
fi
|
||||
if [ -z "$SUDO_ENV" ] ; then
|
||||
# SUDO is su wrapper / noop
|
||||
echo " " $SUDO "$VENV_BIN/letsencrypt" "$@"
|
||||
$SUDO "$VENV_BIN/letsencrypt" "$@"
|
||||
else
|
||||
# sudo
|
||||
echo " " $SUDO "$SUDO_ENV" "$VENV_BIN/letsencrypt" "$@"
|
||||
$SUDO "$SUDO_ENV" "$VENV_BIN/letsencrypt" "$@"
|
||||
fi
|
||||
|
||||
|
|
@ -923,7 +933,6 @@ else
|
|||
fi
|
||||
|
||||
if [ "$NO_SELF_UPGRADE" != 1 ]; then
|
||||
echo "Checking for new version..."
|
||||
TEMP_DIR=$(TempDir)
|
||||
# ---------------------------------------------------------------------------
|
||||
cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py"
|
||||
|
|
@ -1016,7 +1025,7 @@ def verified_new_le_auto(get, tag, temp_dir):
|
|||
"""
|
||||
le_auto_dir = environ.get(
|
||||
'LE_AUTO_DIR_TEMPLATE',
|
||||
'https://raw.githubusercontent.com/letsencrypt/letsencrypt/%s/'
|
||||
'https://raw.githubusercontent.com/certbot/certbot/%s/'
|
||||
'letsencrypt-auto-source/') % tag
|
||||
write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto')
|
||||
write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig')
|
||||
|
|
|
|||
|
|
@ -38,17 +38,6 @@ Help for certbot itself cannot be provided until it is installed.
|
|||
|
||||
All arguments are accepted and forwarded to the Certbot client when run."
|
||||
|
||||
while getopts ":hnv" arg; do
|
||||
case $arg in
|
||||
h)
|
||||
HELP=1;;
|
||||
n)
|
||||
ASSUME_YES=1;;
|
||||
v)
|
||||
VERBOSE=1;;
|
||||
esac
|
||||
done
|
||||
|
||||
for arg in "$@" ; do
|
||||
case "$arg" in
|
||||
--debug)
|
||||
|
|
@ -65,9 +54,26 @@ for arg in "$@" ; do
|
|||
ASSUME_YES=1;;
|
||||
--verbose)
|
||||
VERBOSE=1;;
|
||||
-[!-]*)
|
||||
while getopts ":hnv" short_arg $arg; do
|
||||
case "$short_arg" in
|
||||
h)
|
||||
HELP=1;;
|
||||
n)
|
||||
ASSUME_YES=1;;
|
||||
v)
|
||||
VERBOSE=1;;
|
||||
esac
|
||||
done;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $BASENAME = "letsencrypt-auto" ]; then
|
||||
# letsencrypt-auto does not respect --help or --yes for backwards compatibility
|
||||
ASSUME_YES=1
|
||||
HELP=0
|
||||
fi
|
||||
|
||||
# certbot-auto needs root access to bootstrap OS dependencies, and
|
||||
# certbot itself needs root access for almost all modes of operation
|
||||
# The "normal" case is that sudo is used for the steps that need root, but
|
||||
|
|
@ -107,12 +113,6 @@ else
|
|||
SUDO=
|
||||
fi
|
||||
|
||||
if [ $BASENAME = "letsencrypt-auto" ]; then
|
||||
# letsencrypt-auto does not respect --help or --yes for backwards compatibility
|
||||
ASSUME_YES=1
|
||||
HELP=0
|
||||
fi
|
||||
|
||||
ExperimentalBootstrap() {
|
||||
# Arguments: Platform name, bootstrap function name
|
||||
if [ "$DEBUG" = 1 ]; then
|
||||
|
|
@ -154,6 +154,7 @@ DeterminePythonVersion() {
|
|||
{{ bootstrappers/gentoo_common.sh }}
|
||||
{{ bootstrappers/free_bsd.sh }}
|
||||
{{ bootstrappers/mac.sh }}
|
||||
{{ bootstrappers/smartos.sh }}
|
||||
|
||||
# Install required OS packages:
|
||||
Bootstrap() {
|
||||
|
|
@ -186,8 +187,10 @@ Bootstrap() {
|
|||
ExperimentalBootstrap "FreeBSD" BootstrapFreeBsd
|
||||
elif uname | grep -iq Darwin ; then
|
||||
ExperimentalBootstrap "Mac OS X" BootstrapMac
|
||||
elif grep -iq "Amazon Linux" /etc/issue ; then
|
||||
elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then
|
||||
ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon
|
||||
elif [ -f /etc/product ] && grep -q "Joyent Instance" /etc/product ; then
|
||||
ExperimentalBootstrap "Joyent SmartOS Zone" BootstrapSmartOS
|
||||
else
|
||||
echo "Sorry, I don't know how to bootstrap Certbot on your operating system!"
|
||||
echo
|
||||
|
|
@ -252,14 +255,16 @@ UNLIKELY_EOF
|
|||
fi
|
||||
echo "Installation succeeded."
|
||||
fi
|
||||
echo "Requesting root privileges to run certbot..."
|
||||
if [ -n "$SUDO" ]; then
|
||||
# SUDO is su wrapper or sudo
|
||||
echo "Requesting root privileges to run certbot..."
|
||||
echo " $VENV_BIN/letsencrypt" "$@"
|
||||
fi
|
||||
if [ -z "$SUDO_ENV" ] ; then
|
||||
# SUDO is su wrapper / noop
|
||||
echo " " $SUDO "$VENV_BIN/letsencrypt" "$@"
|
||||
$SUDO "$VENV_BIN/letsencrypt" "$@"
|
||||
else
|
||||
# sudo
|
||||
echo " " $SUDO "$SUDO_ENV" "$VENV_BIN/letsencrypt" "$@"
|
||||
$SUDO "$SUDO_ENV" "$VENV_BIN/letsencrypt" "$@"
|
||||
fi
|
||||
|
||||
|
|
@ -285,7 +290,6 @@ else
|
|||
fi
|
||||
|
||||
if [ "$NO_SELF_UPGRADE" != 1 ]; then
|
||||
echo "Checking for new version..."
|
||||
TEMP_DIR=$(TempDir)
|
||||
# ---------------------------------------------------------------------------
|
||||
cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ BootstrapMac() {
|
|||
|
||||
$pkgcmd augeas
|
||||
$pkgcmd dialog
|
||||
if [ "$(which python)" = "/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python" ]; then
|
||||
if [ "$(which python)" = "/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python" \
|
||||
-o "$(which python)" = "/usr/bin/python" ]; then
|
||||
# We want to avoid using the system Python because it requires root to use pip.
|
||||
# python.org, MacPorts or HomeBrew Python installations should all be OK.
|
||||
echo "Installing python..."
|
||||
|
|
|
|||
4
letsencrypt-auto-source/pieces/bootstrappers/smartos.sh
Normal file
4
letsencrypt-auto-source/pieces/bootstrappers/smartos.sh
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
BootstrapSmartOS() {
|
||||
pkgin update
|
||||
pkgin -y install 'gcc49' 'py27-augeas' 'py27-virtualenv'
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ def verified_new_le_auto(get, tag, temp_dir):
|
|||
"""
|
||||
le_auto_dir = environ.get(
|
||||
'LE_AUTO_DIR_TEMPLATE',
|
||||
'https://raw.githubusercontent.com/letsencrypt/letsencrypt/%s/'
|
||||
'https://raw.githubusercontent.com/certbot/certbot/%s/'
|
||||
'letsencrypt-auto-source/') % tag
|
||||
write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto')
|
||||
write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig')
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -71,6 +71,7 @@ dev_extras = [
|
|||
'nose',
|
||||
'nosexcover',
|
||||
'pep8',
|
||||
'pkginfo<=1.2.1',
|
||||
'pylint==1.4.2', # upstream #248
|
||||
'tox',
|
||||
'twine',
|
||||
|
|
|
|||
|
|
@ -145,6 +145,9 @@ pip install \
|
|||
kill $!
|
||||
cd ~-
|
||||
|
||||
# get a snapshot of the CLI help for the docs
|
||||
certbot --help all > docs/cli-help.txt
|
||||
|
||||
# freeze before installing anything else, so that we know end-user KGS
|
||||
# make sure "twine upload" doesn't catch "kgs"
|
||||
if [ -d ../kgs ] ; then
|
||||
|
|
@ -197,7 +200,7 @@ mv letsencrypt-auto-source/letsencrypt-auto.asc letsencrypt-auto-source/certbot-
|
|||
cp -p letsencrypt-auto-source/letsencrypt-auto certbot-auto
|
||||
cp -p letsencrypt-auto-source/letsencrypt-auto letsencrypt-auto
|
||||
|
||||
git add certbot-auto letsencrypt-auto letsencrypt-auto-source
|
||||
git add certbot-auto letsencrypt-auto letsencrypt-auto-source docs/cli-help.txt
|
||||
git diff --cached
|
||||
git commit --gpg-sign="$RELEASE_GPG_KEY" -m "Release $version"
|
||||
git tag --local-user "$RELEASE_GPG_KEY" --sign --message "Release $version" "$tag"
|
||||
|
|
|
|||
Loading…
Reference in a new issue