diff --git a/letsencrypt-apache/MANIFEST.in b/letsencrypt-apache/MANIFEST.in index 51c2df858..933cc10ac 100644 --- a/letsencrypt-apache/MANIFEST.in +++ b/letsencrypt-apache/MANIFEST.in @@ -3,3 +3,4 @@ include README.rst recursive-include docs * recursive-include letsencrypt_apache/tests/testdata * include letsencrypt_apache/options-ssl-apache.conf +recursive-include letsencrypt_apache/augeas_lens *.aug diff --git a/letsencrypt-apache/letsencrypt_apache/augeas_configurator.py b/letsencrypt-apache/letsencrypt_apache/augeas_configurator.py index 7557a27c6..b0b15d649 100644 --- a/letsencrypt-apache/letsencrypt_apache/augeas_configurator.py +++ b/letsencrypt-apache/letsencrypt_apache/augeas_configurator.py @@ -7,6 +7,8 @@ from letsencrypt import errors from letsencrypt import reverter from letsencrypt.plugins import common +from letsencrypt_apache import constants + logger = logging.getLogger(__name__) @@ -27,10 +29,12 @@ class AugeasConfigurator(common.Plugin): def __init__(self, *args, **kwargs): super(AugeasConfigurator, self).__init__(*args, **kwargs) - # Set Augeas flags to not save backup (we do it ourselves) - # Set Augeas to not load anything by default - my_flags = augeas.Augeas.NONE | augeas.Augeas.NO_MODL_AUTOLOAD - self.aug = augeas.Augeas(flags=my_flags) + self.aug = augeas.Augeas( + # specify a directory to load our preferred lens from + loadpath=constants.AUGEAS_LENS_DIR, + # Do not save backup (we do it ourselves), do not load + # anything by default + flags=(augeas.Augeas.NONE | augeas.Augeas.NO_MODL_AUTOLOAD)) self.save_notes = "" # See if any temporary changes need to be recovered diff --git a/letsencrypt-apache/letsencrypt_apache/augeas_lens/README b/letsencrypt-apache/letsencrypt_apache/augeas_lens/README new file mode 100644 index 000000000..fc803a776 --- /dev/null +++ b/letsencrypt-apache/letsencrypt_apache/augeas_lens/README @@ -0,0 +1,2 @@ +Let's Encrypt includes the very latest Augeas lenses in order to ship bug fixes +to Apacche configuration handling bugs as quickly as possible diff --git a/letsencrypt-apache/letsencrypt_apache/augeas_lens/httpd.aug b/letsencrypt-apache/letsencrypt_apache/augeas_lens/httpd.aug new file mode 100644 index 000000000..9b50a8f0e --- /dev/null +++ b/letsencrypt-apache/letsencrypt_apache/augeas_lens/httpd.aug @@ -0,0 +1,112 @@ +(* Apache HTTPD lens for Augeas + +Authors: + David Lutterkort + Francis Giraldeau + Raphael Pinson + +About: Reference + Online Apache configuration manual: http://httpd.apache.org/docs/trunk/ + +About: License + This file is licensed under the LGPL v2+. + +About: Lens Usage + Sample usage of this lens in augtool + + Apache configuration is represented by two main structures, nested sections + and directives. Sections are used as labels, while directives are kept as a + value. Sections and directives can have positional arguments inside values + of "arg" nodes. Arguments of sections must be the firsts child of the + section node. + + This lens doesn't support automatic string quoting. Hence, the string must + be quoted when containing a space. + + Create a new VirtualHost section with one directive: + > clear /files/etc/apache2/sites-available/foo/VirtualHost + > set /files/etc/apache2/sites-available/foo/VirtualHost/arg "172.16.0.1:80" + > set /files/etc/apache2/sites-available/foo/VirtualHost/directive "ServerAdmin" + > set /files/etc/apache2/sites-available/foo/VirtualHost/*[self::directive="ServerAdmin"]/arg "admin@example.com" + +About: Configuration files + This lens applies to files in /etc/httpd and /etc/apache2. See . + +*) + + +module Httpd = + +autoload xfm + +(****************************************************************** + * Utilities lens + *****************************************************************) +let dels (s:string) = del s s + +(* deal with continuation lines *) +let sep_spc = del /([ \t]+|[ \t]*\\\\\r?\n[ \t]*)/ " " + +let sep_osp = Sep.opt_space +let sep_eq = del /[ \t]*=[ \t]*/ "=" + +let nmtoken = /[a-zA-Z:_][a-zA-Z0-9:_.-]*/ +let word = /[a-zA-Z][a-zA-Z0-9._-]*/ + +let comment = Util.comment +let eol = Util.doseol +let empty = Util.empty_dos +let indent = Util.indent + +(* borrowed from shellvars.aug *) +let char_arg_dir = /[^\\ '"\t\r\n]|\\\\"|\\\\'/ +let char_arg_sec = /[^ '"\t\r\n>]|\\\\"|\\\\'/ +let cdot = /\\\\./ +let cl = /\\\\\n/ +let dquot = + let no_dquot = /[^"\\\r\n]/ + in /"/ . (no_dquot|cdot|cl)* . /"/ +let squot = + let no_squot = /[^'\\\r\n]/ + in /'/ . (no_squot|cdot|cl)* . /'/ +let comp = /[<>=]?=/ + +(****************************************************************** + * Attributes + *****************************************************************) + +let arg_dir = [ label "arg" . store (char_arg_dir+|dquot|squot) ] +let arg_sec = [ label "arg" . store (char_arg_sec+|comp|dquot|squot) ] + +let argv (l:lens) = l . (sep_spc . l)* + +let directive = [ indent . label "directive" . store word . + (sep_spc . argv arg_dir)? . eol ] + +let section (body:lens) = + (* opt_eol includes empty lines *) + let opt_eol = del /([ \t]*#?\r?\n)*/ "\n" in + let inner = (sep_spc . argv arg_sec)? . sep_osp . + dels ">" . opt_eol . ((body|comment) . (body|empty|comment)*)? . + indent . dels "" ">" . eol ] + +let rec content = section (content|directive) + +let lns = (content|directive|comment|empty)* + +let filter = (incl "/etc/apache2/apache2.conf") . + (incl "/etc/apache2/httpd.conf") . + (incl "/etc/apache2/ports.conf") . + (incl "/etc/apache2/conf.d/*") . + (incl "/etc/apache2/conf-available/*.conf") . + (incl "/etc/apache2/mods-available/*") . + (incl "/etc/apache2/sites-available/*") . + (incl "/etc/httpd/conf.d/*.conf") . + (incl "/etc/httpd/httpd.conf") . + (incl "/etc/httpd/conf/httpd.conf") . + Util.stdexcl + +let xfm = transform lns filter diff --git a/letsencrypt-apache/letsencrypt_apache/constants.py b/letsencrypt-apache/letsencrypt_apache/constants.py index b38e898cf..1c17eacc3 100644 --- a/letsencrypt-apache/letsencrypt_apache/constants.py +++ b/letsencrypt-apache/letsencrypt_apache/constants.py @@ -20,6 +20,10 @@ MOD_SSL_CONF_SRC = pkg_resources.resource_filename( """Path to the Apache mod_ssl config file found in the Let's Encrypt distribution.""" +AUGEAS_LENS_DIR = pkg_resources.resource_filename( + "letsencrypt_apache", "augeas_lens") +"""Path to the Augeas lens directory""" + REWRITE_HTTPS_ARGS = [ "^", "https://%{SERVER_NAME}%{REQUEST_URI}", "[L,QSA,R=permanent]"] """Apache rewrite rule arguments used for redirections to https vhost"""