Merge remote-tracking branch 'upstream/master' into errors

This commit is contained in:
Brad Warren 2015-06-24 18:25:02 -07:00
commit f35d8a5228
20 changed files with 246 additions and 153 deletions

View file

@ -38,7 +38,7 @@ load-plugins=linter_plugin
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=fixme,locally-disabled,abstract-class-not-used,bad-continuation,too-few-public-methods
disable=fixme,locally-disabled,abstract-class-not-used
# abstract-class-not-used cannot be disabled locally (at least in pylint 1.4.1)
@ -101,7 +101,7 @@ function-rgx=[a-z_][a-z0-9_]{2,40}$
function-name-hint=[a-z_][a-z0-9_]{2,40}$
# Regular expression matching correct variable names
variable-rgx=[a-z_][a-z0-9_]{1,30}$
variable-rgx=[a-z_][a-z0-9_]{2,30}$
# Naming hint for variable names
variable-name-hint=[a-z_][a-z0-9_]{2,30}$
@ -228,8 +228,7 @@ max-module-lines=1250
indent-string=' '
# Number of spaces of indent required inside a hanging or continued line.
# This does something silly/broken...
#indent-after-paren=4
indent-after-paren=4
[TYPECHECK]

View file

@ -9,11 +9,14 @@
# - 6.0.10 "squeeze" (x64)
# - 7.8 "wheezy" (x64)
# - 8.0 "jessie" (x64)
# - Raspbian:
# - 7.8 (armhf)
# virtualenv binary can be found in different packages depending on
# distro version (#346)
newer () {
apt-get install -y lsb-release --no-install-recommends
distro=$(lsb_release -si)
# 6.0.10 => 60, 14.04 => 1404
# TODO: in sid version==unstable
@ -29,6 +32,8 @@ newer () {
fi
}
apt-get update
# you can force newer if lsb_release is not available (e.g. Docker
# debian:jessie base image)
if [ "$1" = "newer" ] || newer
@ -43,7 +48,6 @@ fi
# #276, https://github.com/martinpaljak/M2Crypto/issues/62,
# M2Crypto setup.py:add_multiarch_paths
apt-get update
apt-get install -y --no-install-recommends \
git-core \
python \

View file

@ -150,7 +150,7 @@ def run(args, config, plugins):
def auth(args, config, plugins):
"""Authenticate & obtain cert, but do not install it"""
"""Authenticate & obtain cert, but do not install it."""
# XXX: Update for renewer / RenewableCert
acc = _account_init(args, config)
if acc is None:
@ -169,13 +169,13 @@ def auth(args, config, plugins):
# TODO: Handle errors from _common_run?
acme, doms = _common_run(
args, config, acc, authenticator=authenticator, installer=installer)
if not acme.obtain_and_enroll_certificate(doms, authenticator, installer,
plugins):
if not acme.obtain_and_enroll_certificate(
doms, authenticator, installer, plugins):
return "Certificate could not be obtained"
def install(args, config, plugins):
"""Install a previously obtained cert in a server"""
"""Install a previously obtained cert in a server."""
# XXX: Update for renewer/RenewableCert
acc = _account_init(args, config)
if acc is None:
@ -192,7 +192,7 @@ def install(args, config, plugins):
def revoke(args, unused_config, unused_plugins):
"""Revoke a previously obtained certificate"""
"""Revoke a previously obtained certificate."""
if args.rev_cert is None and args.rev_key is None:
return "At least one of --certificate or --key is required"
@ -204,7 +204,7 @@ def revoke(args, unused_config, unused_plugins):
def rollback(args, config, plugins):
"""Rollback server configuration changes made during install"""
"""Rollback server configuration changes made during install."""
client.rollback(args.installer, args.checkpoints, config, plugins)
@ -218,7 +218,7 @@ def config_changes(unused_args, config, unused_plugins):
def plugins_cmd(args, config, plugins): # TODO: Use IDiplay rathern than print
"""List server software plugins"""
"""List server software plugins."""
logging.debug("Expected interfaces: %s", args.ifaces)
ifaces = [] if args.ifaces is None else args.ifaces
@ -264,6 +264,7 @@ def flag_default(name):
"""Default value for CLI flag."""
return constants.CLI_DEFAULTS[name]
def config_help(name, hidden=False):
"""Help message for `.IConfig` attribute."""
if hidden:
@ -271,10 +272,15 @@ def config_help(name, hidden=False):
else:
return interfaces.IConfig[name].__doc__
class SilentParser(object):
"""An a mini parser wrapper that doesn't print help for its
arguments... this one is just needed to the use of callbacks to define
arguments within plugins"""
class SilentParser(object): # pylint: disable=too-few-public-methods
"""Silent wrapper around argparse.
A mini parser wrapper that doesn't print help for its
arguments. This is needed for the use of callbacks to define
arguments within plugins.
"""
def __init__(self, parser):
self.parser = parser
def add_argument(self, *args, **kwargs):
@ -282,12 +288,18 @@ class SilentParser(object):
kwargs["help"] = argparse.SUPPRESS
self.parser.add_argument(*args, **kwargs)
HELP_TOPICS = ["all", "security", "paths", "automation", "testing"]
class HelpfulArgumentParser(object):
"""This class wraps argparse, adding the ability to make --help less
verbose, and request help on specific subcategories at a time, eg
'letsencrypt --help security' for security options."""
HELP_TOPICS = ["all", "security", "paths", "automation", "testing"]
class HelpfulArgumentParser(object):
"""Argparse Wrapper.
This class wraps argparse, adding the ability to make --help less
verbose, and request help on specific subcategories at a time, eg
'letsencrypt --help security' for security options.
"""
def __init__(self, args, plugins):
self.args = args
plugin_names = [name for name, _p in plugins.iteritems()]
@ -316,11 +328,15 @@ class HelpfulArgumentParser(object):
self.add_plugin_args(plugins)
def prescan_for_flag(self, flag, possible_arguments):
"""check for a flag, which accepts a fixed set of possible arguments, in
"""Checks cli input for flags.
Check for a flag, which accepts a fixed set of possible arguments, in
the command line; we will use this information to configure argparse's
help correctly. Return the flag's argument, if it has one that matches
the sequence @possible_arguments; otherwise return whether the flag is
present"""
present.
"""
if flag not in self.args:
return False
pos = self.args.index(flag)
@ -333,10 +349,12 @@ class HelpfulArgumentParser(object):
return True
def add(self, topic, *args, **kwargs):
"""Add a new command line argument. @topic is required, to indicate
which part of the help will document it, but can be None for `always
documented'."""
"""Add a new command line argument.
@topic is required, to indicate which part of the help will document
it, but can be None for `always documented'.
"""
if topic and self.visible_topics[topic]:
group = self.groups[topic]
group.add_argument(*args, **kwargs)
@ -345,10 +363,14 @@ class HelpfulArgumentParser(object):
self.parser.add_argument(*args, **kwargs)
def add_group(self, topic, **kwargs):
"""This has to be called once for every topic; but we leave those calls
"""
This has to be called once for every topic; but we leave those calls
next to the argument definitions for clarity. Return something
arguments can be added to if necessary, either the parser or an argument
group."""
group.
"""
if self.visible_topics[topic]:
#print "Adding visible group " + topic
group = self.parser.add_argument_group(topic, **kwargs)
@ -359,8 +381,12 @@ class HelpfulArgumentParser(object):
return self.silent_parser
def add_plugin_args(self, plugins):
"""Let each of the plugins add its own command line arguments, which
may or may not be displayed as help topics."""
"""
Let each of the plugins add its own command line arguments, which
may or may not be displayed as help topics.
"""
# TODO: plugin_parser should be called for every detected plugin
for name, plugin_ep in plugins.iteritems():
parser_or_group = self.add_group(name, description=plugin_ep.description)
@ -368,9 +394,14 @@ class HelpfulArgumentParser(object):
plugin_ep.plugin_cls.inject_parser_options(parser_or_group, name)
def determine_help_topics(self, chosen_topic):
"""The user may have requested help on a topic, return a dict of which
topics to dislpay. @chosen_topic has prescan_for_flag's return type"""
"""
The user may have requested help on a topic, return a dict of which
topics to display. @chosen_topic has prescan_for_flag's return type
:returns: dict
"""
# topics maps each topic to whether it should be documented by
# argparse on the command line
if chosen_topic == "all":
@ -392,7 +423,8 @@ def create_parser(plugins, args):
"e.g. -vvv.")
# --help is automatically provided by argparse
helpful.add_group("automation",
helpful.add_group(
"automation",
description="Arguments for automating execution & other tweaks")
helpful.add(
"automation", "--version", action="version",
@ -423,9 +455,10 @@ def create_parser(plugins, args):
help=config_help("dvsni_port"))
helpful.add("testing", "--no-simple-http-tls", action="store_true",
help=config_help("no_simple_http_tls"))
help=config_help("no_simple_http_tls"))
subparsers = helpful.parser.add_subparsers(metavar="SUBCOMMAND")
def add_subparser(name, func): # pylint: disable=missing-docstring
subparser = subparsers.add_parser(
name, help=func.__doc__.splitlines()[0], description=func.__doc__)
@ -460,16 +493,17 @@ def create_parser(plugins, args):
helpful.add(None, "-d", "--domains", metavar="DOMAIN", action="append")
helpful.add(None, "-k", "--accountkey", type=read_file,
help="Path to the account key file")
help="Path to the account key file")
helpful.add(None, "-m", "--email", help=config_help("email"))
helpful.add_group(
"security", description="Security parameters & server settings")
helpful.add("security", "-B", "--rsa-key-size", type=int, metavar="N",
default=flag_default("rsa_key_size"),
help=config_help("rsa_key_size"))
helpful.add(
"security", "-B", "--rsa-key-size", type=int, metavar="N",
default=flag_default("rsa_key_size"), help=config_help("rsa_key_size"))
# TODO: resolve - assumes binary logic while client.py assumes ternary.
helpful.add("security", "-r", "--redirect", action="store_true",
helpful.add(
"security", "-r", "--redirect", action="store_true",
help="Automatically redirect all HTTP traffic to HTTPS for the newly "
"authenticated vhost.")
@ -487,7 +521,6 @@ def create_parser(plugins, args):
_paths_parser(helpful)
return helpful.parser
@ -515,6 +548,7 @@ def _paths_parser(helpful):
add("paths", "-s", "--server", default=flag_default("server"),
help=config_help("server"))
def main(args=sys.argv[1:]):
"""Command line argument parsing and main script execution."""
# note: arg parser internally handles --help (and exits afterwards)

View file

@ -257,8 +257,8 @@ class Client(object):
:param certr: ACME "certificate" resource.
:type certr: :class:`acme.messages.Certificate`
:param str cert_path: Path to attempt to save the cert file
:param str chain_path: Path to attempt to save the chain file
:param str cert_path: Candidate path to a certificate.
:param str chain_path: Candidate path to a certificate chain.
:returns: cert_path, chain_path (absolute paths to the actual files)
:rtype: `tuple` of `str`

View file

@ -17,10 +17,15 @@ class NamespaceConfig(object):
:attr:`~letsencrypt.interfaces.IConfig.work_dir` and relative
paths defined in :py:mod:`letsencrypt.constants`:
- ``temp_checkpoint_dir``
- ``in_progress_dir``
- ``cert_key_backup``
- ``rec_token_dir``
- `accounts_dir`
- `account_keys_dir`
- `cert_dir`
- `cert_key_backup`
- `in_progress_dir`
- `key_dir`
- `rec_token_dir`
- `renewer_config_file`
- `temp_checkpoint_dir`
:ivar namespace: Namespace typically produced by
:meth:`argparse.ArgumentParser.parse_args`.
@ -35,27 +40,12 @@ class NamespaceConfig(object):
def __getattr__(self, name):
return getattr(self.namespace, name)
@property
def temp_checkpoint_dir(self): # pylint: disable=missing-docstring
return os.path.join(
self.namespace.work_dir, constants.TEMP_CHECKPOINT_DIR)
@property
def in_progress_dir(self): # pylint: disable=missing-docstring
return os.path.join(self.namespace.work_dir, constants.IN_PROGRESS_DIR)
@property
def server_path(self):
"""File path based on ``server``."""
parsed = urlparse.urlparse(self.namespace.server)
return (parsed.netloc + parsed.path).replace('/', os.path.sep)
@property
def cert_key_backup(self): # pylint: disable=missing-docstring
return os.path.join(
self.namespace.work_dir, constants.CERT_KEY_BACKUP_DIR,
self.server_path)
@property
def accounts_dir(self): #pylint: disable=missing-docstring
return os.path.join(
@ -63,11 +53,40 @@ class NamespaceConfig(object):
@property
def account_keys_dir(self): #pylint: disable=missing-docstring
return os.path.join(
self.namespace.config_dir, constants.ACCOUNTS_DIR,
self.server_path, constants.ACCOUNT_KEYS_DIR)
return os.path.join(self.accounts_dir, constants.ACCOUNT_KEYS_DIR)
@property
def backup_dir(self): # pylint: disable=missing-docstring
return os.path.join(self.namespace.work_dir, constants.BACKUP_DIR)
@property
def cert_key_backup(self): # pylint: disable=missing-docstring
return os.path.join(self.namespace.work_dir,
constants.CERT_KEY_BACKUP_DIR, self.server_path)
@property
def cert_dir(self): # pylint: disable=missing-docstring
return os.path.join(self.namespace.config_dir, constants.CERT_DIR)
@property
def in_progress_dir(self): # pylint: disable=missing-docstring
return os.path.join(self.namespace.work_dir, constants.IN_PROGRESS_DIR)
@property
def key_dir(self): # pylint: disable=missing-docstring
return os.path.join(self.namespace.config_dir, constants.KEY_DIR)
# TODO: This should probably include the server name
@property
def rec_token_dir(self): # pylint: disable=missing-docstring
return os.path.join(self.namespace.work_dir, constants.REC_TOKEN_DIR)
@property
def renewer_config_file(self): # pylint: disable=missing-docstring
return os.path.join(
self.namespace.config_dir, constants.RENEWER_CONFIG_FILENAME)
@property
def temp_checkpoint_dir(self): # pylint: disable=missing-docstring
return os.path.join(
self.namespace.work_dir, constants.TEMP_CHECKPOINT_DIR)

View file

@ -7,7 +7,6 @@ from acme import challenges
SETUPTOOLS_PLUGINS_ENTRY_POINT = "letsencrypt.plugins"
"""Setuptools entry point group name for plugins."""
CLI_DEFAULTS = dict(
config_files=["/etc/letsencrypt/cli.ini"],
verbose_count=-(logging.WARNING / 10),
@ -16,14 +15,16 @@ CLI_DEFAULTS = dict(
rollback_checkpoints=0,
config_dir="/etc/letsencrypt",
work_dir="/var/lib/letsencrypt",
backup_dir="/var/lib/letsencrypt/backups",
key_dir="/etc/letsencrypt/keys",
certs_dir="/etc/letsencrypt/certs",
cert_path="/etc/letsencrypt/certs/cert-letsencrypt.pem",
chain_path="/etc/letsencrypt/certs/chain-letsencrypt.pem",
renewer_config_file="/etc/letsencrypt/renewer.conf",
no_verify_ssl=False,
dvsni_port=challenges.DVSNI.PORT,
# TODO: blocked by #485, values ignored
backup_dir="not used",
key_dir="not used",
certs_dir="not used",
cert_path="not used",
chain_path="not used",
renewer_config_file="not used",
)
"""Defaults for CLI flags and `.IConfig` attributes."""
@ -61,23 +62,36 @@ List of expected options parameters:
CONFIG_DIRS_MODE = 0o755
"""Directory mode for ``.IConfig.config_dir`` et al."""
TEMP_CHECKPOINT_DIR = "temp_checkpoint"
"""Temporary checkpoint directory (relative to IConfig.work_dir)."""
IN_PROGRESS_DIR = "IN_PROGRESS"
"""Directory used before a permanent checkpoint is finalized (relative to
IConfig.work_dir)."""
CERT_KEY_BACKUP_DIR = "keys-certs"
"""Directory where all certificates and keys are stored (relative to
IConfig.work_dir. Used for easy revocation."""
ACCOUNTS_DIR = "accounts"
"""Directory where all accounts are saved."""
ACCOUNT_KEYS_DIR = "keys"
"""Directory where account keys are saved. Relative to ACCOUNTS_DIR."""
"""Directory where account keys are saved. Relative to `ACCOUNTS_DIR`."""
BACKUP_DIR = "backups"
"""Directory (relative to `IConfig.work_dir`) where backups are kept."""
CERT_KEY_BACKUP_DIR = "keys-certs"
"""Directory where all certificates and keys are stored (relative to
`IConfig.work_dir`). Used for easy revocation."""
CERT_DIR = "certs"
"""See `.IConfig.cert_dir`."""
IN_PROGRESS_DIR = "IN_PROGRESS"
"""Directory used before a permanent checkpoint is finalized (relative to
`IConfig.work_dir`)."""
KEY_DIR = "keys"
"""Directory (relative to `IConfig.config_dir`) where keys are saved."""
TEMP_CHECKPOINT_DIR = "temp_checkpoint"
"""Temporary checkpoint directory (relative to `IConfig.work_dir`)."""
REC_TOKEN_DIR = "recovery_tokens"
"""Directory where all recovery tokens are saved (relative to
IConfig.work_dir)."""
`IConfig.work_dir`)."""
RENEWER_CONFIG_FILENAME = "renewer.conf"
"""Renewer config file name (relative to `IConfig.config_dir`)."""

View file

@ -55,7 +55,7 @@ def init_save_key(key_size, key_dir, keyname="key-letsencrypt.pem"):
return le_util.Key(key_path, key_pem)
def init_save_csr(privkey, names, cert_dir, csrname="csr-letsencrypt.pem"):
def init_save_csr(privkey, names, path, csrname="csr-letsencrypt.pem"):
"""Initialize a CSR with the given private key.
:param privkey: Key to include in the CSR
@ -63,7 +63,7 @@ def init_save_csr(privkey, names, cert_dir, csrname="csr-letsencrypt.pem"):
:param set names: `str` names to include in the CSR
:param str cert_dir: Certificate save directory.
:param str path: Certificate save directory.
:returns: CSR
:rtype: :class:`letsencrypt.le_util.CSR`
@ -72,9 +72,9 @@ def init_save_csr(privkey, names, cert_dir, csrname="csr-letsencrypt.pem"):
csr_pem, csr_der = make_csr(privkey.pem, names)
# Save CSR
le_util.make_or_verify_dir(cert_dir, 0o755, os.geteuid())
le_util.make_or_verify_dir(path, 0o755, os.geteuid())
csr_f, csr_filename = le_util.unique_file(
os.path.join(cert_dir, csrname), 0o644)
os.path.join(path, csrname), 0o644)
csr_f.write(csr_pem)
csr_f.close()

View file

@ -155,32 +155,29 @@ class IConfig(zope.interface.Interface):
config_dir = zope.interface.Attribute("Configuration directory.")
work_dir = zope.interface.Attribute("Working directory.")
backup_dir = zope.interface.Attribute("Configuration backups directory.")
temp_checkpoint_dir = zope.interface.Attribute(
"Temporary checkpoint directory.")
in_progress_dir = zope.interface.Attribute(
"Directory used before a permanent checkpoint is finalized.")
cert_key_backup = zope.interface.Attribute(
"Directory where all certificates and keys are stored. "
"Used for easy revocation.")
accounts_dir = zope.interface.Attribute(
"Directory where all account information is stored.")
account_keys_dir = zope.interface.Attribute(
"Directory where all account keys are stored.")
backup_dir = zope.interface.Attribute("Configuration backups directory.")
cert_dir = zope.interface.Attribute(
"Directory where newly generated Certificate Signing Requests "
"(CSRs) and certificates not enrolled in the renewer are saved.")
cert_key_backup = zope.interface.Attribute(
"Directory where all certificates and keys are stored. "
"Used for easy revocation.")
in_progress_dir = zope.interface.Attribute(
"Directory used before a permanent checkpoint is finalized.")
key_dir = zope.interface.Attribute("Keys storage.")
rec_token_dir = zope.interface.Attribute(
"Directory where all recovery tokens are saved.")
key_dir = zope.interface.Attribute("Keys storage.")
cert_dir = zope.interface.Attribute("Certificates storage.")
le_vhost_ext = zope.interface.Attribute(
"SSL vhost configuration extension.")
temp_checkpoint_dir = zope.interface.Attribute(
"Temporary checkpoint directory.")
renewer_config_file = zope.interface.Attribute(
"Location of renewal configuration file.")
cert_path = zope.interface.Attribute("Let's Encrypt certificate file path.")
chain_path = zope.interface.Attribute("Let's Encrypt chain file path.")
no_verify_ssl = zope.interface.Attribute(
"Disable SSL certificate verification.")
dvsni_port = zope.interface.Attribute(
@ -191,6 +188,11 @@ class IConfig(zope.interface.Interface):
no_simple_http_tls = zope.interface.Attribute(
"Do not use TLS when solving SimpleHTTP challenges.")
# TODO: the following are not used, but blocked by #485
le_vhost_ext = zope.interface.Attribute("not used")
cert_path = zope.interface.Attribute("not used")
chain_path = zope.interface.Attribute("not used")
class IInstaller(IPlugin):
"""Generic Let's Encrypt Installer Interface.

View file

@ -175,10 +175,10 @@ class Dvsni(object):
# test utils
def setup_ssl_options(config_dir, mod_ssl_conf):
def setup_ssl_options(config_dir, src, dest):
"""Move the ssl_options into position and return the path."""
option_path = os.path.join(config_dir, "options-ssl.conf")
shutil.copyfile(mod_ssl_conf, option_path)
option_path = os.path.join(config_dir, dest)
shutil.copyfile(src, option_path)
return option_path

View file

@ -30,23 +30,31 @@ class NamespaceConfigTest(unittest.TestCase):
@mock.patch('letsencrypt.configuration.constants')
def test_dynamic_dirs(self, constants):
constants.TEMP_CHECKPOINT_DIR = 't'
constants.IN_PROGRESS_DIR = '../p'
constants.CERT_KEY_BACKUP_DIR = 'c/'
constants.REC_TOKEN_DIR = '/r'
constants.ACCOUNTS_DIR = 'acc'
constants.ACCOUNT_KEYS_DIR = 'keys'
constants.BACKUP_DIR = 'backups'
constants.CERT_KEY_BACKUP_DIR = 'c/'
constants.CERT_DIR = 'certs'
constants.IN_PROGRESS_DIR = '../p'
constants.KEY_DIR = 'keys'
constants.REC_TOKEN_DIR = '/r'
constants.RENEWER_CONFIG_FILENAME = 'r.conf'
constants.TEMP_CHECKPOINT_DIR = 't'
self.assertEqual(self.config.temp_checkpoint_dir, '/tmp/foo/t')
self.assertEqual(self.config.in_progress_dir, '/tmp/foo/../p')
self.assertEqual(
self.config.cert_key_backup, '/tmp/foo/c/acme-server.org:443/new')
self.assertEqual(self.config.rec_token_dir, '/r')
self.assertEqual(
self.config.accounts_dir, '/tmp/config/acc/acme-server.org:443/new')
self.assertEqual(
self.config.account_keys_dir,
'/tmp/config/acc/acme-server.org:443/new/keys')
self.assertEqual(self.config.backup_dir, '/tmp/foo/backups')
self.assertEqual(self.config.cert_dir, '/tmp/config/certs')
self.assertEqual(
self.config.cert_key_backup, '/tmp/foo/c/acme-server.org:443/new')
self.assertEqual(self.config.in_progress_dir, '/tmp/foo/../p')
self.assertEqual(self.config.key_dir, '/tmp/config/keys')
self.assertEqual(self.config.rec_token_dir, '/r')
self.assertEqual(self.config.renewer_config_file, '/tmp/config/r.conf')
self.assertEqual(self.config.temp_checkpoint_dir, '/tmp/foo/t')
if __name__ == '__main__':

View file

@ -89,8 +89,6 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
def add_parser_arguments(cls, add):
add("server-root", default=constants.CLI_DEFAULTS["server_root"],
help="Apache server root directory.")
add("mod-ssl-conf", default=constants.CLI_DEFAULTS["mod_ssl_conf"],
help="Contains standard Apache SSL directives.")
add("ctl", default=constants.CLI_DEFAULTS["ctl"],
help="Path to the 'apache2ctl' binary, used for 'configtest' and "
"retrieving Apache2 version number.")
@ -99,6 +97,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
add("init-script", default=constants.CLI_DEFAULTS["init_script"],
help="Path to the Apache init script (used for server "
"reload/restart).")
add("le-vhost-ext", default=constants.CLI_DEFAULTS["le_vhost_ext"],
help="SSL vhost configuration extension.")
def __init__(self, *args, **kwargs):
"""Initialize an Apache Configurator.
@ -125,10 +126,15 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
self.vhosts = None
self._enhance_func = {"redirect": self._enable_redirect}
@property
def mod_ssl_conf(self):
"""Full absolute path to SSL configuration file."""
return os.path.join(self.config.config_dir, constants.MOD_SSL_CONF_DEST)
def prepare(self):
"""Prepare the authenticator/installer."""
self.parser = parser.ApacheParser(
self.aug, self.conf('server-root'), self.conf('mod-ssl-conf'))
self.aug, self.conf('server-root'), self.mod_ssl_conf)
# Check for errors in parsing files with Augeas
self.check_parsing_errors("httpd.aug")
@ -146,7 +152,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
# on initialization
self._prepare_server_https()
temp_install(self.conf('mod-ssl-conf'))
temp_install(self.mod_ssl_conf)
def deploy_cert(self, domain, cert_path, key_path, chain_path=None):
"""Deploys certificate to specified virtual host.
@ -445,7 +451,8 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
"""Makes an ssl_vhost version of a nonssl_vhost.
Duplicates vhost and adds default ssl options
New vhost will reside as (nonssl_vhost.path) + ``IConfig.le_vhost_ext``
New vhost will reside as (nonssl_vhost.path) +
``letsencrypt_apache.constants.CLI_DEFAULTS["le_vhost_ext"]``
.. note:: This function saves the configuration
@ -459,9 +466,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator):
avail_fp = nonssl_vhost.filep
# Get filepath of new ssl_vhost
if avail_fp.endswith(".conf"):
ssl_fp = avail_fp[:-(len(".conf"))] + self.config.le_vhost_ext
ssl_fp = avail_fp[:-(len(".conf"))] + self.conf("le_vhost_ext")
else:
ssl_fp = avail_fp + self.config.le_vhost_ext
ssl_fp = avail_fp + self.conf("le_vhost_ext")
# First register the creation so that it is properly removed if
# configuration is rolled back
@ -1161,4 +1168,4 @@ def temp_install(options_ssl):
# Check to make sure options-ssl.conf is installed
if not os.path.isfile(options_ssl):
shutil.copyfile(constants.MOD_SSL_CONF, options_ssl)
shutil.copyfile(constants.MOD_SSL_CONF_SRC, options_ssl)

View file

@ -4,15 +4,17 @@ import pkg_resources
CLI_DEFAULTS = dict(
server_root="/etc/apache2",
mod_ssl_conf="/etc/letsencrypt/options-ssl-apache.conf",
ctl="apache2ctl",
enmod="a2enmod",
init_script="/etc/init.d/apache2",
le_vhost_ext="-le-ssl.conf",
)
"""CLI defaults."""
MOD_SSL_CONF_DEST = "options-ssl-apache.conf"
"""Name of the mod_ssl config file as saved in `IConfig.config_dir`."""
MOD_SSL_CONF = pkg_resources.resource_filename(
MOD_SSL_CONF_SRC = pkg_resources.resource_filename(
"letsencrypt_apache", "options-ssl-apache.conf")
"""Path to the Apache mod_ssl config file found in the Let's Encrypt
distribution."""

View file

@ -32,8 +32,7 @@ class TwoVhost80Test(util.ApacheTest):
"mod_loaded") as mock_load:
mock_load.return_value = True
self.config = util.get_apache_configurator(
self.config_path, self.config_dir, self.work_dir,
self.ssl_options)
self.config_path, self.config_dir, self.work_dir)
self.vh_truth = util.get_vh_truth(
self.temp_dir, "debian_apache_2_4/two_vhost_80")

View file

@ -24,8 +24,7 @@ class DvsniPerformTest(util.ApacheTest):
"mod_loaded") as mock_load:
mock_load.return_value = True
config = util.get_apache_configurator(
self.config_path, self.config_dir, self.work_dir,
self.ssl_options)
self.config_path, self.config_dir, self.work_dir)
from letsencrypt_apache import dvsni
self.sni = dvsni.ApacheDvsni(config)

View file

@ -22,7 +22,8 @@ class ApacheTest(unittest.TestCase): # pylint: disable=too-few-public-methods
pkg="letsencrypt_apache.tests")
self.ssl_options = common.setup_ssl_options(
self.config_dir, constants.MOD_SSL_CONF)
self.config_dir, constants.MOD_SSL_CONF_SRC,
constants.MOD_SSL_CONF_DEST)
self.config_path = os.path.join(
self.temp_dir, "debian_apache_2_4/two_vhost_80/apache2")
@ -34,7 +35,7 @@ class ApacheTest(unittest.TestCase): # pylint: disable=too-few-public-methods
def get_apache_configurator(
config_path, config_dir, work_dir, ssl_options, version=(2, 4, 7)):
config_path, config_dir, work_dir, version=(2, 4, 7)):
"""Create an Apache Configurator with the specified options."""
backups = os.path.join(work_dir, "backups")
@ -46,8 +47,7 @@ def get_apache_configurator(
config = configurator.ApacheConfigurator(
config=mock.MagicMock(
apache_server_root=config_path,
apache_mod_ssl_conf=ssl_options,
le_vhost_ext="-le-ssl.conf",
apache_le_vhost_ext=constants.CLI_DEFAULTS["le_vhost_ext"],
backup_dir=backups,
config_dir=config_dir,
temp_checkpoint_dir=os.path.join(work_dir, "temp_checkpoints"),

View file

@ -56,8 +56,6 @@ class NginxConfigurator(common.Plugin):
def add_parser_arguments(cls, add):
add("server-root", default=constants.CLI_DEFAULTS["server_root"],
help="Nginx server root directory.")
add("mod-ssl-conf", default=constants.CLI_DEFAULTS["mod_ssl_conf"],
help="Contains standard nginx SSL directives.")
add("ctl", default=constants.CLI_DEFAULTS["ctl"], help="Path to the "
"'nginx' binary, used for 'configtest' and retrieving nginx "
"version number.")
@ -91,18 +89,22 @@ class NginxConfigurator(common.Plugin):
self.reverter = reverter.Reverter(self.config)
self.reverter.recovery_routine()
@property
def mod_ssl_conf(self):
"""Full absolute path to SSL configuration file."""
return os.path.join(self.config.config_dir, constants.MOD_SSL_CONF_DEST)
# This is called in determine_authenticator and determine_installer
def prepare(self):
"""Prepare the authenticator/installer."""
self.parser = parser.NginxParser(
self.conf('server-root'),
self.conf('mod-ssl-conf'))
self.conf('server-root'), self.mod_ssl_conf)
# Set Version
if self.version is None:
self.version = self.get_version()
temp_install(self.conf('mod-ssl-conf'))
temp_install(self.mod_ssl_conf)
# Entry point in main.py for installing cert
def deploy_cert(self, domain, cert_path, key_path, chain_path=None):
@ -583,4 +585,4 @@ def temp_install(options_ssl):
# Check to make sure options-ssl.conf is installed
if not os.path.isfile(options_ssl):
shutil.copyfile(constants.MOD_SSL_CONF, options_ssl)
shutil.copyfile(constants.MOD_SSL_CONF_SRC, options_ssl)

View file

@ -4,13 +4,15 @@ import pkg_resources
CLI_DEFAULTS = dict(
server_root="/etc/nginx",
mod_ssl_conf="/etc/letsencrypt/options-ssl-nginx.conf",
ctl="nginx",
)
"""CLI defaults."""
MOD_SSL_CONF = pkg_resources.resource_filename(
MOD_SSL_CONF_DEST = "options-ssl-nginx.conf"
"""Name of the mod_ssl config file as saved in `IConfig.config_dir`."""
MOD_SSL_CONF_SRC = pkg_resources.resource_filename(
"letsencrypt_nginx", "options-ssl-nginx.conf")
"""Path to the Nginx mod_ssl config file found in the Let's Encrypt
"""Path to the nginx mod_ssl config file found in the Let's Encrypt
distribution."""

View file

@ -21,8 +21,7 @@ class NginxConfiguratorTest(util.NginxTest):
super(NginxConfiguratorTest, self).setUp()
self.config = util.get_nginx_configurator(
self.config_path, self.config_dir, self.work_dir,
self.ssl_options)
self.config_path, self.config_dir, self.work_dir)
def tearDown(self):
shutil.rmtree(self.temp_dir)

View file

@ -51,8 +51,7 @@ class DvsniPerformTest(util.NginxTest):
super(DvsniPerformTest, self).setUp()
config = util.get_nginx_configurator(
self.config_path, self.config_dir, self.work_dir,
self.ssl_options)
self.config_path, self.config_dir, self.work_dir)
from letsencrypt_nginx import dvsni
self.sni = dvsni.NginxDvsni(config)

View file

@ -20,7 +20,8 @@ class NginxTest(unittest.TestCase): # pylint: disable=too-few-public-methods
"etc_nginx", "letsencrypt_nginx.tests")
self.ssl_options = common.setup_ssl_options(
self.config_dir, constants.MOD_SSL_CONF)
self.config_dir, constants.MOD_SSL_CONF_SRC,
constants.MOD_SSL_CONF_DEST)
self.config_path = os.path.join(self.temp_dir, "etc_nginx")
@ -38,18 +39,21 @@ def get_data_filename(filename):
def get_nginx_configurator(
config_path, config_dir, work_dir, ssl_options, version=(1, 6, 2)):
config_path, config_dir, work_dir, version=(1, 6, 2)):
"""Create an Nginx Configurator with the specified options."""
backups = os.path.join(work_dir, "backups")
config = configurator.NginxConfigurator(
config=mock.MagicMock(
nginx_server_root=config_path, nginx_mod_ssl_conf=ssl_options,
le_vhost_ext="-le-ssl.conf", backup_dir=backups,
config_dir=config_dir, work_dir=work_dir,
nginx_server_root=config_path,
le_vhost_ext="-le-ssl.conf",
config_dir=config_dir,
work_dir=work_dir,
backup_dir=backups,
temp_checkpoint_dir=os.path.join(work_dir, "temp_checkpoints"),
in_progress_dir=os.path.join(backups, "IN_PROGRESS")),
in_progress_dir=os.path.join(backups, "IN_PROGRESS"),
),
name="nginx",
version=version)
config.prepare()