Introduce proper renewer config via constants.py

This commit is contained in:
Seth Schoen 2015-05-18 15:57:12 -07:00
parent 83b0e0a20e
commit 8f25241170
4 changed files with 40 additions and 19 deletions

View file

@ -1,4 +1,5 @@
"""Let's Encrypt constants."""
import configobj
import logging
from acme import challenges
@ -25,6 +26,18 @@ CLI_DEFAULTS = dict(
"""Defaults for CLI flags and `.IConfig` attributes."""
RENEWER_DEFAULTS = configobj.ConfigObj(dict(
renewer_config_file="/etc/letsencrypt/renewer.conf",
renewal_configs_dir="/etc/letsencrypt/configs",
archive_dir="/etc/letsencrypt/archive",
live_dir="/etc/letsencrypt/live",
renewer_enabled="yes",
renew_before_expiry="30 days",
deploy_before_expiry="20 days",
))
"""Defaults for renewer script."""
EXCLUSIVE_CHALLENGES = frozenset([frozenset([
challenges.DVSNI, challenges.SimpleHTTPS])])
"""Mutually exclusive challenges."""

View file

@ -11,17 +11,13 @@ import os
import configobj
from letsencrypt import configuration
from letsencrypt import constants
from letsencrypt import client
from letsencrypt import crypto_util
from letsencrypt import notify
from letsencrypt import storage
from letsencrypt.plugins import disco as plugins_disco
DEFAULTS = configobj.ConfigObj("renewal.conf")
DEFAULTS["renewal_configs_dir"] = "/tmp/etc/letsencrypt/configs"
DEFAULTS["official_archive_dir"] = "/tmp/etc/letsencrypt/archive"
DEFAULTS["live_dir"] = "/tmp/etc/letsencrypt/live"
class AttrDict(dict):
"""A trick to allow accessing dictionary keys as object
@ -91,13 +87,20 @@ def renew(cert, old_version):
# (where fewer than all names were renewed)
def main(config=DEFAULTS):
def main(config=constants.RENEWER_DEFAULTS):
"""main function for autorenewer script."""
# TODO: Distinguish automated invocation from manual invocation,
# perhaps by looking at sys.argv[0] and inhibiting automated
# invocations if /etc/letsencrypt/renewal.conf defaults have
# turned it off. (The boolean parameter should probably be
# called renewer_enabled.)
# This attempts to read the renewer config file and augment or replace
# the renewer defaults with any options contained in that file. If
# renewer_config_file is undefined or if the file is nonexistent or
# empty, this .merge() will have no effect.
config.merge(configobj.ConfigObj(config.get("renewer_config_file", "")))
for i in os.listdir(config["renewal_configs_dir"]):
print "Processing", i
if not i.endswith(".conf"):

View file

@ -13,12 +13,9 @@ import parsedatetime
import pytz
import pyrfc3339
from letsencrypt import constants
from letsencrypt import le_util
DEFAULTS = configobj.ConfigObj("renewal.conf")
DEFAULTS["renewal_configs_dir"] = "/tmp/etc/letsencrypt/configs"
DEFAULTS["official_archive_dir"] = "/tmp/etc/letsencrypt/archive"
DEFAULTS["live_dir"] = "/tmp/etc/letsencrypt/live"
ALL_FOUR = ("cert", "privkey", "chain", "fullchain")
@ -81,7 +78,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
and/or systemwide defaults.
:type configuration: :class:`configobj.ConfigObj`"""
def __init__(self, configfile, defaults=DEFAULTS):
def __init__(self, configfile, defaults=constants.RENEWER_DEFAULTS):
"""Instantiate a RenewableCert object from an existing lineage.
:param :class:`configobj.ConfigObj` configfile: an already-parsed
@ -109,6 +106,9 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
# systemwide renewal configuration; self.configfile should be
# used to make and save changes.
self.configfile = configfile
# TODO: Do we actually use anything from defaults and do we want to
# read further defaults from the systemwide renewal configuration
# file at this stage?
self.configuration = copy.deepcopy(defaults)
self.configuration.merge(self.configfile)
@ -147,7 +147,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
# Each element's link must point within the cert lineage's
# directory within the official archive directory
desired_directory = os.path.join(
self.configuration["official_archive_dir"], self.lineagename)
self.configuration["archive_dir"], self.lineagename)
if not os.path.samefile(os.path.dirname(target),
desired_directory):
return False
@ -479,7 +479,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
@classmethod
def new_lineage(cls, lineagename, cert, privkey, chain,
renewalparams=None, config=DEFAULTS):
renewalparams=None, config=constants.RENEWER_DEFAULTS):
# pylint: disable=too-many-locals,too-many-arguments
"""Create a new certificate lineage.
@ -511,9 +511,15 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
:returns: the newly-created RenewalCert object
:rtype: :class:`storage.renewableCert`"""
# This attempts to read the renewer config file and augment or replace
# the renewer defaults with any options contained in that file. If
# renewer_config_file is undefined or if the file is nonexistent or
# empty, this .merge() will have no effect.
config.merge(configobj.ConfigObj(config.get("renewer_config_file", "")))
# Examine the configuration and find the new lineage's name
configs_dir = config["renewal_configs_dir"]
archive_dir = config["official_archive_dir"]
archive_dir = config["archive_dir"]
live_dir = config["live_dir"]
for i in (configs_dir, archive_dir, live_dir):
if not os.path.exists(i):
@ -594,7 +600,7 @@ class RenewableCert(object): # pylint: disable=too-many-instance-attributes
# Figure out what the new version is and hence where to save things
target_version = self.next_free_version()
archive = self.configuration["official_archive_dir"]
archive = self.configuration["archive_dir"]
prefix = os.path.join(archive, self.lineagename)
target = dict(
[(kind,

View file

@ -38,8 +38,7 @@ class RenewableCertTests(unittest.TestCase):
os.makedirs(os.path.join(self.tempdir, "configs"))
defaults = configobj.ConfigObj()
defaults["live_dir"] = os.path.join(self.tempdir, "live")
defaults["official_archive_dir"] = os.path.join(self.tempdir,
"archive")
defaults["archive_dir"] = os.path.join(self.tempdir, "archive")
defaults["renewal_configs_dir"] = os.path.join(self.tempdir,
"configs")
config = configobj.ConfigObj()
@ -461,7 +460,7 @@ class RenewableCertTests(unittest.TestCase):
"""Test for new_lineage() class method."""
from letsencrypt import storage
config_dir = self.defaults["renewal_configs_dir"]
archive_dir = self.defaults["official_archive_dir"]
archive_dir = self.defaults["archive_dir"]
live_dir = self.defaults["live_dir"]
result = storage.RenewableCert.new_lineage("the-lineage.com", "cert",
"privkey", "chain", None,
@ -500,7 +499,7 @@ class RenewableCertTests(unittest.TestCase):
"""Test that directories can be created if they don't exist."""
from letsencrypt import storage
config_dir = self.defaults["renewal_configs_dir"]
archive_dir = self.defaults["official_archive_dir"]
archive_dir = self.defaults["archive_dir"]
live_dir = self.defaults["live_dir"]
shutil.rmtree(config_dir)
shutil.rmtree(archive_dir)