Delete unused methods or replace with placeholders

This commit is contained in:
yan 2015-04-17 22:22:06 -07:00
parent 0ba12c9f46
commit 2a86936410
3 changed files with 36 additions and 542 deletions

View file

@ -162,10 +162,6 @@ class NginxConfigurator(object):
if cert_chain:
self.save_notes += "\tSSLCertificateChainFile %s\n" % cert_chain
# Make sure vhost is enabled
if not vhost.enabled:
self._enable_site(vhost)
#######################
# Vhost parsing methods
#######################
@ -175,6 +171,9 @@ class NginxConfigurator(object):
.. todo:: This should maybe return list if no obvious answer
is presented.
.. todo:: The special name "$hostname" corresponds to the machine's
hostname. Currently we just ignore this.
:param str target_name: domain name
:returns: ssl vhost associated with name
@ -367,52 +366,6 @@ class NginxConfigurator(object):
######################################
# Nginx server management (IInstaller)
######################################
def _is_site_enabled(self, avail_fp):
"""Checks to see if the given site is enabled.
.. todo:: fix hardcoded sites-enabled, check os.path.samefile
:param str avail_fp: Complete file path of available site
:returns: Success
:rtype: bool
"""
enabled_dir = os.path.join(self.parser.root, "sites-enabled")
for entry in os.listdir(enabled_dir):
if os.path.realpath(os.path.join(enabled_dir, entry)) == avail_fp:
return True
return False
def _enable_site(self, vhost):
"""Enables an available site, Nginx restart required.
.. todo:: This function should number subdomains before the domain vhost
.. todo:: Make sure link is not broken...
:param vhost: vhost to enable
:type vhost: :class:`~letsencrypt.client.plugins.nginx.obj.VirtualHost`
:returns: Success
:rtype: bool
"""
if self._is_site_enabled(vhost.filep):
return True
if "/sites-available/" in vhost.filep:
enabled_path = ("%s/sites-enabled/%s" %
(self.parser.root, os.path.basename(vhost.filep)))
self.reverter.register_file_creation(False, enabled_path)
os.symlink(vhost.filep, enabled_path)
vhost.enabled = True
logging.info("Enabling available site: %s", vhost.filep)
self.save_notes += "Enabled site %s\n" % vhost.filep
return True
return False
def restart(self):
"""Restarts nginx server.

View file

@ -1,208 +0,0 @@
import zope.interface
from letsencrypt.client import augeas_configurator
from letsencrypt.client import CONFIG
from letsencrypt.client import interfaces
# This might be helpful... but feel free to use whatever you want
# class VH(object):
# def __init__(self, filename_path, vh_path, vh_addrs, is_ssl, is_enabled):
# self.file = filename_path
# self.path = vh_path
# self.addrs = vh_addrs
# self.names = []
# self.ssl = is_ssl
# self.enabled = is_enabled
# def set_names(self, listOfNames):
# self.names = listOfNames
# def add_name(self, name):
# self.names.append(name)
class NginxConfigurator(augeas_configurator.AugeasConfigurator):
"""Nginx Configurator class."""
zope.interface.implements(interfaces.IAuthenticator, interfaces.IInstaller)
def __init__(self, server_root=CONFIG.SERVER_ROOT):
super(NginxConfigurator, self).__init__()
self.server_root = server_root
# See if any temporary changes need to be recovered
# This needs to occur before VH objects are setup...
# because this will change the underlying configuration and potential
# vhosts
self.recovery_routine()
# Check for errors in parsing files with Augeas
# TODO - insert nginx lens info here???
#self.check_parsing_errors("httpd.aug")
def deploy_cert(self, vhost, cert, key, cert_chain=None):
"""Deploy cert in nginx"""
def choose_virtual_host(self, name):
"""Chooses a virtual host based on the given domain name"""
def get_all_names(self):
"""Returns all names found in the nginx configuration"""
return set()
# Might be helpful... I know nothing about nginx lens
# def get_include_path(self, cur_dir, arg):
# """
# Converts an Nginx Include directive argument into an Augeas
# searchable path
# Returns path string
# """
# # Sanity check argument - maybe
# # Question: what can the attacker do with control over this string
# # Effect parse file... maybe exploit unknown errors in Augeas
# # If the attacker can Include anything though... and this function
# # only operates on Nginx real config data... then the attacker has
# # already won.
# # Perhaps it is better to simply check the permissions on all
# # included files?
# # check_config to validate nginx config doesn't work because it
# # would create a race condition between the check and this input
# # TODO: Fix this
# # Check to make sure only expected characters are used, maybe remove
# # validChars = re.compile("[a-zA-Z0-9.*?_-/]*")
# # matchObj = validChars.match(arg)
# # if matchObj.group() != arg:
# # logging.error("Error: Invalid regexp characters in %s", arg)
# # return []
# # Standardize the include argument based on server root
# if not arg.startswith("/"):
# arg = cur_dir + arg
# # conf/ is a special variable for ServerRoot in Nginx
# elif arg.startswith("conf/"):
# arg = self.server_root + arg[5:]
# # TODO: Test if Nginx allows ../ or ~/ for Includes
# # Attempts to add a transform to the file if one does not already
# # exist
# self.parse_file(arg)
# # Argument represents an fnmatch regular expression, convert it
# # Split up the path and convert each into an Augeas accepted regex
# # then reassemble
# if "*" in arg or "?" in arg:
# postfix = ""
# splitArg = arg.split("/")
# for idx, split in enumerate(splitArg):
# # * and ? are the two special fnmatch characters
# if "*" in split or "?" in split:
# # Turn it into a augeas regex
# # TODO: Can this be an augeas glob instead of regex
# splitArg[idx] = ("* [label()=~regexp('%s')]" %
# self.fnmatch_to_re(split)
# # Reassemble the argument
# arg = "/".join(splitArg)
# # If the include is a directory, just return the directory as a file
# if arg.endswith("/"):
# return "/files" + arg[:len(arg)-1]
# return "/files"+arg
def enable_redirect(self, ssl_vhost):
"""
Adds Redirect directive to the port 80 equivalent of ssl_vhost
First the function attempts to find the vhost with equivalent
ip addresses that serves on non-ssl ports
The function then adds the directive
"""
return
def enable_ocsp_stapling(self, ssl_vhost):
return False
def enable_hsts(self, ssl_vhost):
return False
def get_all_certs_keys(self):
"""
Retrieve all certs and keys set in VirtualHosts on the Nginx server
returns: list of tuples with form [(cert, key, path)]
"""
return None
# Probably helpful reference
# def get_file_path(self, vhost_path):
# """
# Takes in Augeas path and returns the file name
# """
# # Strip off /files
# avail_fp = vhost_path[6:]
# # This can be optimized...
# while True:
# # Cast both to lowercase to be case insensitive
# find_if = avail_fp.lower().find("/ifmodule")
# if find_if != -1:
# avail_fp = avail_fp[:find_if]
# continue
# find_vh = avail_fp.lower().find("/virtualhost")
# if find_vh != -1:
# avail_fp = avail_fp[:find_vh]
# continue
# break
# return avail_fp
def enable_site(self, vhost):
"""Enables an available site, Nginx restart required"""
return False
# Might be a usefule reference
# def parse_file(self, file_path):
# """
# Checks to see if file_path is parsed by Augeas
# If file_path isn't parsed, the file is added and Augeas is reloaded
# """
# # Test if augeas included file for Httpd.lens
# # Note: This works for augeas globs, ie. *.conf
# incTest = self.aug.match(
# "/augeas/load/Httpd/incl [. ='" + file_path + "']")
# if not incTest:
# # Load up files
# #self.httpd_incl.append(file_path)
# #self.aug.add_transform(
# # "Httpd.lns", self.httpd_incl, None, self.httpd_excl)
# self.__add_httpd_transform(file_path)
# self.aug.load()
# Helpful reference?
# def verify_setup(self):
# """
# Make sure that files/directories are setup with appropriate
# permissions. Aim for defensive coding... make sure all input files
# have permissions of root
# """
# le_util.make_or_verify_dir(CONFIG.CONFIG_DIR, 0o755)
# le_util.make_or_verify_dir(CONFIG.WORK_DIR, 0o755)
# le_util.make_or_verify_dir(CONFIG.BACKUP_DIR, 0o755)
def restart(self, quiet=False):
"""Restarts nginx server"""
# May be of use?
# def __add_httpd_transform(self, incl):
# """
# This function will correctly add a transform to augeas
# The existing augeas.add_transform in python is broken
# """
# lastInclude = self.aug.match("/augeas/load/Httpd/incl [last()]")
# self.aug.insert(lastInclude[0], "incl", False)
# self.aug.set("/augeas/load/Httpd/incl[last()]", incl)
def config_test(self):
"""Check Configuration"""
return False
def main():
return
if __name__ == "__main__":
main()

View file

@ -2,7 +2,6 @@
import glob
import logging
import os
import re
import pyparsing
from letsencrypt.client import errors
@ -155,224 +154,6 @@ class NginxParser(object):
return parsed_server
def add_dir_to_ifmodssl(self, aug_conf_path, directive, val):
"""Adds directive and value to IfMod ssl block.
Adds given directive and value along configuration path within
an IfMod mod_ssl.c block. If the IfMod block does not exist in
the file, it is created.
:param str aug_conf_path: Desired Augeas config path to add directive
:param str directive: Directive you would like to add
:param str val: Value of directive ie. Listen 443, 443 is the value
"""
# TODO: Add error checking code... does the path given even exist?
# Does it throw exceptions?
if_mod_path = self._get_ifmod(aug_conf_path, "mod_ssl.c")
# IfModule can have only one valid argument, so append after
self.aug.insert(if_mod_path + "arg", "directive", False)
nvh_path = if_mod_path + "directive[1]"
self.aug.set(nvh_path, directive)
self.aug.set(nvh_path + "/arg", val)
def _get_ifmod(self, aug_conf_path, mod):
"""Returns the path to <IfMod mod> and creates one if it doesn't exist.
:param str aug_conf_path: Augeas configuration path
:param str mod: module ie. mod_ssl.c
"""
if_mods = self.aug.match(("%s/IfModule/*[self::arg='%s']" %
(aug_conf_path, mod)))
if len(if_mods) == 0:
self.aug.set("%s/IfModule[last() + 1]" % aug_conf_path, "")
self.aug.set("%s/IfModule[last()]/arg" % aug_conf_path, mod)
if_mods = self.aug.match(("%s/IfModule/*[self::arg='%s']" %
(aug_conf_path, mod)))
# Strip off "arg" at end of first ifmod path
return if_mods[0][:len(if_mods[0]) - 3]
def add_dir(self, aug_conf_path, directive, arg):
"""Appends directive to the end fo the file given by aug_conf_path.
.. note:: Not added to AugeasConfigurator because it may depend
on the lens
:param str aug_conf_path: Augeas configuration path to add directive
:param str directive: Directive to add
:param str arg: Value of the directive. ie. Listen 443, 443 is arg
"""
self.aug.set(aug_conf_path + "/directive[last() + 1]", directive)
if isinstance(arg, list):
for i, value in enumerate(arg, 1):
self.aug.set(
"%s/directive[last()]/arg[%d]" % (aug_conf_path, i), value)
else:
self.aug.set(aug_conf_path + "/directive[last()]/arg", arg)
def find_dir(self, directive, arg=None, start=None):
"""Finds directive in the configuration.
Recursively searches through config files to find directives
Directives should be in the form of a case insensitive regex currently
.. todo:: Add order to directives returned. Last directive comes last..
.. todo:: arg should probably be a list
Note: Augeas is inherently case sensitive while Nginx is case
insensitive. Augeas 1.0 allows case insensitive regexes like
regexp(/Listen/, "i"), however the version currently supported
by Ubuntu 0.10 does not. Thus I have included my own case insensitive
transformation by calling case_i() on everything to maintain
compatibility.
:param str directive: Directive to look for
:param arg: Specific value directive must have, None if all should
be considered
:type arg: str or None
:param str start: Beginning Augeas path to begin looking
"""
# Cannot place member variable in the definition of the function so...
if not start:
start = get_aug_path(self.loc["root"])
# Debug code
# print "find_dir:", directive, "arg:", arg, " | Looking in:", start
# No regexp code
# if arg is None:
# matches = self.aug.match(start +
# "//*[self::directive='" + directive + "']/arg")
# else:
# matches = self.aug.match(start +
# "//*[self::directive='" + directive +
# "']/* [self::arg='" + arg + "']")
# includes = self.aug.match(start +
# "//* [self::directive='Include']/* [label()='arg']")
if arg is None:
matches = self.aug.match(("%s//*[self::directive=~regexp('%s')]/arg"
% (start, directive)))
else:
matches = self.aug.match(("%s//*[self::directive=~regexp('%s')]/*"
"[self::arg=~regexp('%s')]" %
(start, directive, arg)))
incl_regex = "(%s)|(%s)" % (case_i('Include'),
case_i('IncludeOptional'))
includes = self.aug.match(("%s//* [self::directive=~regexp('%s')]/* "
"[label()='arg']" % (start, incl_regex)))
# for inc in includes:
# print inc, self.aug.get(inc)
for include in includes:
# start[6:] to strip off /files
matches.extend(self.find_dir(
directive, arg, self._get_include_path(
strip_dir(start[6:]), self.aug.get(include))))
return matches
def _get_include_path(self, cur_dir, arg):
"""Converts an Nginx Include directive into Augeas path.
Converts an Nginx Include directive argument into an Augeas
searchable path
.. todo:: convert to use os.path.join()
:param str cur_dir: current working directory
:param str arg: Argument of Include directive
:returns: Augeas path string
:rtype: str
"""
# Sanity check argument - maybe
# Question: what can the attacker do with control over this string
# Effect parse file... maybe exploit unknown errors in Augeas
# If the attacker can Include anything though... and this function
# only operates on Nginx real config data... then the attacker has
# already won.
# Perhaps it is better to simply check the permissions on all
# included files?
# check_config to validate nginx config doesn't work because it
# would create a race condition between the check and this input
# TODO: Maybe... although I am convinced we have lost if
# Nginx files can't be trusted. The augeas include path
# should be made to be exact.
# Check to make sure only expected characters are used <- maybe remove
# validChars = re.compile("[a-zA-Z0-9.*?_-/]*")
# matchObj = validChars.match(arg)
# if matchObj.group() != arg:
# logging.error("Error: Invalid regexp characters in %s", arg)
# return []
# Standardize the include argument based on server root
if not arg.startswith("/"):
arg = cur_dir + arg
# conf/ is a special variable for ServerRoot in Nginx
elif arg.startswith("conf/"):
arg = self.root + arg[4:]
# TODO: Test if Nginx allows ../ or ~/ for Includes
# Attempts to add a transform to the file if one does not already exist
self._parse_files(arg)
# Argument represents an fnmatch regular expression, convert it
# Split up the path and convert each into an Augeas accepted regex
# then reassemble
if "*" in arg or "?" in arg:
split_arg = arg.split("/")
for idx, split in enumerate(split_arg):
# * and ? are the two special fnmatch characters
if "*" in split or "?" in split:
# Turn it into a augeas regex
# TODO: Can this instead be an augeas glob instead of regex
split_arg[idx] = ("* [label()=~regexp('%s')]" %
self.fnmatch_to_re(split))
# Reassemble the argument
arg = "/".join(split_arg)
# If the include is a directory, just return the directory as a file
if arg.endswith("/"):
return get_aug_path(arg[:len(arg)-1])
return get_aug_path(arg)
def fnmatch_to_re(self, clean_fn_match): # pylint: disable=no-self-use
"""Method converts Nginx's basic fnmatch to regular expression.
:param str clean_fn_match: Nginx style filename match, similar to globs
:returns: regex suitable for augeas
:rtype: str
"""
# Checkout fnmatch.py in venv/local/lib/python2.7/fnmatch.py
regex = ""
for letter in clean_fn_match:
if letter == '.':
regex = regex + r"\."
elif letter == '*':
regex = regex + ".*"
# According to nginx.org ? shouldn't appear
# but in case it is valid...
elif letter == '?':
regex = regex + "."
else:
regex = regex + letter
return regex
def _parse_files(self, filepath):
"""Parse files from a glob
@ -397,27 +178,6 @@ class NginxParser(object):
logging.warn("Could not parse file: %s" % f)
return trees
def _add_httpd_transform(self, incl):
"""Add a transform to Augeas.
This function will correctly add a transform to augeas
The existing augeas.add_transform in python doesn't seem to work for
Travis CI as it loads in libaugeas.so.0.10.0
:param str incl: filepath to include for transform
"""
last_include = self.aug.match("/augeas/load/Httpd/incl [last()]")
if last_include:
# Insert a new node immediately after the last incl
self.aug.insert(last_include[0], "incl", False)
self.aug.set("/augeas/load/Httpd/incl[last()]", incl)
# On first use... must load lens and add file to incl
else:
# Augeas uses base 1 indexing... insert at beginning...
self.aug.set("/augeas/load/Httpd/lens", "Httpd.lns")
self.aug.set("/augeas/load/Httpd/incl", incl)
def _set_locations(self, ssl_options):
"""Set default location for directives.
@ -450,6 +210,39 @@ class NginxParser(object):
raise errors.LetsEncryptNoInstallationError(
"Could not find configuration root")
def add_dir(self, aug_conf_path, directive, arg):
"""Appends directive to the end fo the file given by aug_conf_path.
.. note:: Not added to AugeasConfigurator because it may depend
on the lens
:param str aug_conf_path: Augeas configuration path to add directive
:param str directive: Directive to add
:param str arg: Value of the directive. ie. Listen 443, 443 is arg
"""
pass
def find_dir(self, directive, arg=None, start=None):
"""Finds directive in the configuration.
Recursively searches through config files to find directives
.. todo:: Add order to directives returned. Last directive comes last..
.. todo:: arg should probably be a list
:param str directive: Directive to look for
:param arg: Specific value directive must have, None if all should
be considered
:type arg: str or None
:param str start: Beginning Augeas path to begin looking
:rtype: list
"""
return []
def filedump(self, ext='tmp'):
"""Dumps parsed configurations into files.
@ -468,50 +261,6 @@ class NginxParser(object):
logging.error("Could not open file for writing: %s" % filename)
def case_i(string):
"""Returns case insensitive regex.
Returns a sloppy, but necessary version of a case insensitive regex.
Any string should be able to be submitted and the string is
escaped and then made case insensitive.
May be replaced by a more proper /i once augeas 1.0 is widely
supported.
:param str string: string to make case i regex
"""
return "".join(["["+c.upper()+c.lower()+"]"
if c.isalpha() else c for c in re.escape(string)])
def get_aug_path(file_path):
"""Return augeas path for full filepath.
:param str file_path: Full filepath
"""
return "/files%s" % file_path
def strip_dir(path):
"""Returns directory of file path.
.. todo:: Replace this with Python standard function
:param str path: path is a file path. not an augeas section or
directive path
:returns: directory
:rtype: str
"""
index = path.rfind("/")
if index > 0:
return path[:index+1]
# No directory
return ""
def do_for_subarray(entry, condition, func):
"""Executes a function for a subarray of a nested array if it matches
the given condition.