Refactor nginx file update mechanism in preparation for working with apache plugin (#4720)

* move install_ssl_options_conf functionality to common

* add no cover

* compute current hash instead of saving

* make current hash be computed; switch to list of all canonical hashes

* put message directly into assertion

* don't pass logger

* add docstring

* Add unit tests for certbot.plugins.common.install_ssl_options_conf
This commit is contained in:
ohemorange
2017-06-01 09:04:48 -07:00
committed by Brad Warren
parent c9e9879ad9
commit fc097de5ff
6 changed files with 151 additions and 66 deletions
+51 -7
View File
@@ -1,4 +1,5 @@
"""Plugin common functions."""
import logging
import os
import re
import shutil
@@ -11,9 +12,12 @@ import zope.interface
from acme.jose import util as jose_util
from certbot import constants
from certbot import crypto_util
from certbot import interfaces
from certbot import util
logger = logging.getLogger(__name__)
def option_namespace(name):
"""ArgumentParser options namespace (prefix of all options)."""
@@ -262,17 +266,57 @@ class TLSSNI01(object):
return response
def install_ssl_options_conf(options_ssl, options_ssl_digest, mod_ssl_conf_src,
all_ssl_options_hashes):
"""Copy Certbot's SSL options file into the system's config dir if required.
:param str options_ssl: destination path for file containing ssl options
:param str options_ssl_digest: path to save a digest of options_ssl in
:param str mod_ssl_conf_src: path to file containing ssl options found in distribution
:param list all_ssl_options_hashes: hashes of every released version of options_ssl
"""
current_ssl_options_hash = crypto_util.sha256sum(mod_ssl_conf_src)
def _write_current_hash():
with open(options_ssl_digest, "w") as f:
f.write(current_ssl_options_hash)
def _install_current_file():
shutil.copyfile(mod_ssl_conf_src, options_ssl)
_write_current_hash()
# Check to make sure options-ssl.conf is installed
if not os.path.isfile(options_ssl):
_install_current_file()
return
# there's already a file there. if it's up to date, do nothing. if it's not but
# it matches a known file hash, we can update it.
# otherwise, print a warning once per new version.
active_file_digest = crypto_util.sha256sum(options_ssl)
if active_file_digest == current_ssl_options_hash: # already up to date
return
elif active_file_digest in all_ssl_options_hashes: # safe to update
_install_current_file()
else: # has been manually modified, not safe to update
# did they modify the current version or an old version?
if os.path.isfile(options_ssl_digest):
with open(options_ssl_digest, "r") as f:
saved_digest = f.read()
# they modified it after we either installed or told them about this version, so return
if saved_digest == current_ssl_options_hash:
return
# there's a new version but we couldn't update the file, or they deleted the digest.
# save the current digest so we only print this once, and print a warning
_write_current_hash()
logger.warning("%s has been manually modified; updated ssl configuration options "
"saved to %s. We recommend updating %s for security purposes.",
options_ssl, mod_ssl_conf_src, options_ssl)
# test utils used by certbot_apache/certbot_nginx (hence
# "pragma: no cover") TODO: this might quickly lead to dead code (also
# c.f. #383)
def setup_ssl_options(config_dir, src, dest): # pragma: no cover
"""Move the ssl_options into position and return the path."""
option_path = os.path.join(config_dir, dest)
shutil.copyfile(src, option_path)
return option_path
def dir_setup(test_dir, pkg): # pragma: no cover
"""Setup the directories necessary for the configurator."""
def expanded_tempdir(prefix):