From 528a816f704b3d359c423425eadc1c66c4d9f181 Mon Sep 17 00:00:00 2001 From: Marius Gedminas Date: Mon, 2 May 2016 09:30:32 +0300 Subject: [PATCH 01/13] Don't fail authentication when vhost cannot be found Should fix #677 and #2600. --- certbot-apache/certbot_apache/tls_sni_01.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/certbot-apache/certbot_apache/tls_sni_01.py b/certbot-apache/certbot_apache/tls_sni_01.py index 1236c2eb9..a8a931fd6 100644 --- a/certbot-apache/certbot_apache/tls_sni_01.py +++ b/certbot-apache/certbot_apache/tls_sni_01.py @@ -4,6 +4,7 @@ import os import logging from certbot.plugins import common +from certbot.errors import PluginError from certbot_apache import obj from certbot_apache import parser @@ -116,12 +117,21 @@ class ApacheTlsSni01(common.TLSSNI01): def _get_addrs(self, achall): """Return the Apache addresses needed for TLS-SNI-01.""" - vhost = self.configurator.choose_vhost(achall.domain, temp=True) # TODO: Checkout _default_ rules. addrs = set() default_addr = obj.Addr(("*", str( self.configurator.config.tls_sni_01_port))) + try: + vhost = self.configurator.choose_vhost(achall.domain, temp=True) + except PluginError: + # We couldn't find the virtualhost for this domain, possibly + # because it's a new vhost that's not configured yet (GH #677), + # or perhaps because there were multiple sections + # in the config file (GH #1042). See also GH #2600. + addrs.add(default_addr) + return addrs + for addr in vhost.addrs: if "_default_" == addr.get_addr(): addrs.add(default_addr) From 8b4f48556d2f3b1614641ddd87ada36586f99e4a Mon Sep 17 00:00:00 2001 From: Marius Gedminas Date: Mon, 2 May 2016 09:45:27 +0300 Subject: [PATCH 02/13] Catch the right exception Conrary to the docstring of choose_vhost(), when you run non-interactive certificate renewals and the Apache plugin fails to discover the correct vhost, it raises MissingCommandlineFlag and not PluginError. --- certbot-apache/certbot_apache/tls_sni_01.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certbot-apache/certbot_apache/tls_sni_01.py b/certbot-apache/certbot_apache/tls_sni_01.py index a8a931fd6..f14f7be0f 100644 --- a/certbot-apache/certbot_apache/tls_sni_01.py +++ b/certbot-apache/certbot_apache/tls_sni_01.py @@ -4,7 +4,7 @@ import os import logging from certbot.plugins import common -from certbot.errors import PluginError +from certbot.errors import PluginError, MissingCommandlineFlag from certbot_apache import obj from certbot_apache import parser @@ -124,7 +124,7 @@ class ApacheTlsSni01(common.TLSSNI01): try: vhost = self.configurator.choose_vhost(achall.domain, temp=True) - except PluginError: + except (PluginError, MissingCommandlineFlag): # We couldn't find the virtualhost for this domain, possibly # because it's a new vhost that's not configured yet (GH #677), # or perhaps because there were multiple sections From d73e2e68ac65a80a4407f83ebd1b2ea1fa25681e Mon Sep 17 00:00:00 2001 From: Marius Gedminas Date: Mon, 2 May 2016 11:45:07 +0300 Subject: [PATCH 03/13] Add a test for #2906 --- .../certbot_apache/tests/tls_sni_01_test.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/certbot-apache/certbot_apache/tests/tls_sni_01_test.py b/certbot-apache/certbot_apache/tests/tls_sni_01_test.py index 17ef92004..aa6a2a09c 100644 --- a/certbot-apache/certbot_apache/tests/tls_sni_01_test.py +++ b/certbot-apache/certbot_apache/tests/tls_sni_01_test.py @@ -4,6 +4,7 @@ import shutil import mock +from certbot import errors from certbot.plugins import common_test from certbot_apache import obj @@ -137,6 +138,16 @@ class TlsSniPerformTest(util.ApacheTest): set([obj.Addr.fromstring("*:443")]), self.sni._get_addrs(self.achalls[0])) + def test_get_addrs_no_vhost_found(self): + self.sni.configurator.choose_vhost = mock.Mock( + side_effect=errors.MissingCommandlineFlag( + "Failed to run Apache plugin non-interactively")) + + # pylint: disable=protected-access + self.assertEqual( + set([obj.Addr.fromstring("*:443")]), + self.sni._get_addrs(self.achalls[0])) + if __name__ == "__main__": unittest.main() # pragma: no cover From 7167a9e108c62a865a0a6d1df2084e404d3cd2ef Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 6 May 2016 16:41:23 -0700 Subject: [PATCH 04/13] fixes #2927 --- certbot/plugins/standalone.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/certbot/plugins/standalone.py b/certbot/plugins/standalone.py index a3bb1d8f0..16e9dc11b 100644 --- a/certbot/plugins/standalone.py +++ b/certbot/plugins/standalone.py @@ -120,6 +120,13 @@ def supported_challenges_validator(data): """ challs = data.split(",") + + # tls-sni-01 was dvsni during private beta + if "dvsni" in challs: + challs = [challenges.TLSSNI01.typ if chall == "dvsni" else chall + for chall in challs] + data = ",".join(challs) + unrecognized = [name for name in challs if name not in challenges.Challenge.TYPES] if unrecognized: From 56d7a97e6aeec9b91d3517f0afa4f0da815983c9 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 6 May 2016 16:44:31 -0700 Subject: [PATCH 05/13] Test dvsni with standalone-supported-challenges --- certbot/plugins/standalone_test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/certbot/plugins/standalone_test.py b/certbot/plugins/standalone_test.py index 9f5b14591..eb6631732 100644 --- a/certbot/plugins/standalone_test.py +++ b/certbot/plugins/standalone_test.py @@ -85,6 +85,11 @@ class SupportedChallengesValidatorTest(unittest.TestCase): def test_not_subset(self): self.assertRaises(argparse.ArgumentTypeError, self._call, "dns") + def test_dvsni(self): + self.assertEqual("tls-sni-01", self._call("dvsni")) + self.assertEqual("http-01,tls-sni-01", self._call("http-01,dvsni")) + self.assertEqual("tls-sni-01,http-01", self._call("dvsni,http-01")) + class AuthenticatorTest(unittest.TestCase): """Tests for certbot.plugins.standalone.Authenticator.""" From 30ae348a8c462a770332046f31c13a8f2cb4b183 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 6 May 2016 16:53:33 -0700 Subject: [PATCH 06/13] Add logger message --- certbot/plugins/standalone.py | 1 + 1 file changed, 1 insertion(+) diff --git a/certbot/plugins/standalone.py b/certbot/plugins/standalone.py index 16e9dc11b..8e1cb72a4 100644 --- a/certbot/plugins/standalone.py +++ b/certbot/plugins/standalone.py @@ -123,6 +123,7 @@ def supported_challenges_validator(data): # tls-sni-01 was dvsni during private beta if "dvsni" in challs: + logger.info("Updating legacy standalone_supported_challenges value") challs = [challenges.TLSSNI01.typ if chall == "dvsni" else chall for chall in challs] data = ",".join(challs) From 4627971dc68f1cf834eb1e836b8b4ad40e39fb0f Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 6 May 2016 17:30:18 -0700 Subject: [PATCH 07/13] s/--letsencrypt/--certbot --- tests/travis-integration.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/travis-integration.sh b/tests/travis-integration.sh index 1b51f0980..c22c346b1 100755 --- a/tests/travis-integration.sh +++ b/tests/travis-integration.sh @@ -12,8 +12,8 @@ cd $GOPATH/src/github.com/letsencrypt/boulder/ # boulder's integration-test.py has code that knows to start and wait for the # boulder processes to start reliably and then will run the certbot -# boulder-interation.sh on its own. The --letsencrypt flag says to run only the +# boulder-interation.sh on its own. The --certbot flag says to run only the # certbot tests (instead of any other client tests it might run). We're # going to want to define a more robust interaction point between the boulder # and certbot tests, but that will be better built off of this. -python test/integration-test.py --letsencrypt +python test/integration-test.py --certbot From 5c0eabcd76fc73e0fd6240cb62466336ad555593 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Fri, 6 May 2016 17:42:25 -0700 Subject: [PATCH 08/13] Rename LETSENCRYPT_PATH to CERTBOT_PATH --- tests/travis-integration.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/travis-integration.sh b/tests/travis-integration.sh index c22c346b1..159a2ef80 100755 --- a/tests/travis-integration.sh +++ b/tests/travis-integration.sh @@ -6,7 +6,7 @@ set -o errexit source .tox/$TOXENV/bin/activate -export LETSENCRYPT_PATH=`pwd` +export CERTBOT_PATH=`pwd` cd $GOPATH/src/github.com/letsencrypt/boulder/ From 9059a4966408fe8a495ea79539a8619728597ddc Mon Sep 17 00:00:00 2001 From: Dominic Cleal Date: Sat, 7 May 2016 18:49:18 +0100 Subject: [PATCH 09/13] Merge Augeas fix for empty section continuations From https://github.com/hercules-team/augeas/commit/568be1bc392bab6089c027de990b857ce962cc26 Fixes #2731 --- .../certbot_apache/augeas_lens/httpd.aug | 4 +- .../section-empty-continuations-2731.conf | 247 ++++++++++++++++++ 2 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 certbot-apache/certbot_apache/tests/apache-conf-files/passing/section-empty-continuations-2731.conf diff --git a/certbot-apache/certbot_apache/augeas_lens/httpd.aug b/certbot-apache/certbot_apache/augeas_lens/httpd.aug index 697d5de89..07974b364 100644 --- a/certbot-apache/certbot_apache/augeas_lens/httpd.aug +++ b/certbot-apache/certbot_apache/augeas_lens/httpd.aug @@ -45,8 +45,8 @@ autoload xfm let dels (s:string) = del s s (* deal with continuation lines *) -let sep_spc = del /([ \t]+|[ \t]*\\\\\r?\n[ \t]*)/ " " -let sep_osp = del /([ \t]*|[ \t]*\\\\\r?\n[ \t]*)/ "" +let sep_spc = del /([ \t]+|[ \t]*\\\\\r?\n[ \t]*)+/ " " +let sep_osp = del /([ \t]*|[ \t]*\\\\\r?\n[ \t]*)*/ "" let sep_eq = del /[ \t]*=[ \t]*/ "=" let nmtoken = /[a-zA-Z:_][a-zA-Z0-9:_.-]*/ diff --git a/certbot-apache/certbot_apache/tests/apache-conf-files/passing/section-empty-continuations-2731.conf b/certbot-apache/certbot_apache/tests/apache-conf-files/passing/section-empty-continuations-2731.conf new file mode 100644 index 000000000..3f2f96965 --- /dev/null +++ b/certbot-apache/certbot_apache/tests/apache-conf-files/passing/section-empty-continuations-2731.conf @@ -0,0 +1,247 @@ +#ATTENTION! +# +#DO NOT MODIFY THIS FILE BECAUSE IT WAS GENERATED AUTOMATICALLY, +#SO ALL YOUR CHANGES WILL BE LOST THE NEXT TIME THE FILE IS GENERATED. + +NameVirtualHost 192.168.100.218:80 +NameVirtualHost 10.128.178.192:80 + +NameVirtualHost 192.168.100.218:443 +NameVirtualHost 10.128.178.192:443 + + +ServerName "254020-web1.example.com" +ServerAdmin "name@example.com" + +DocumentRoot "/tmp" + + + LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" plesklog + + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" plesklog + + + TraceEnable off + +ServerTokens ProductOnly + + + AllowOverride "All" + Options SymLinksIfOwnerMatch + Order allow,deny + Allow from all + + +php_admin_flag engine off + + + +php_admin_flag engine off + + + + + + AllowOverride All + Options SymLinksIfOwnerMatch + Order allow,deny + Allow from all + + php_admin_flag engine off + + + php_admin_flag engine off + + + + + Header add X-Powered-By PleskLin + + + + JkWorkersFile "/etc/httpd/conf/workers.properties" + JkLogFile /var/log/httpd/mod_jk.log + JkLogLevel info + + +#Include "/etc/httpd/conf/plesk.conf.d/ip_default/*.conf" + + + + ServerName "default" + UseCanonicalName Off + DocumentRoot "/tmp" + ScriptAlias /cgi-bin/ "/var/www/vhosts/default/cgi-bin" + + + + SSLEngine off + + + + AllowOverride None + Options None + Order allow,deny + Allow from all + + + + + +php_admin_flag engine on + + + +php_admin_flag engine on + + + + + + + + + + ServerName "default-192_168_100_218" + UseCanonicalName Off + DocumentRoot "/tmp" + ScriptAlias /cgi-bin/ "/var/www/vhosts/default/cgi-bin" + + + SSLEngine on + SSLVerifyClient none + #SSLCertificateFile "/usr/local/psa/var/certificates/cert-9MgutN" + + #SSLCACertificateFile "/usr/local/psa/var/certificates/cert-s6Wx3P" + + + AllowOverride None + Options None + Order allow,deny + Allow from all + + + + + +php_admin_flag engine on + + + +php_admin_flag engine on + + + + + + + ServerName "default-10_128_178_192" + UseCanonicalName Off + DocumentRoot "/tmp" + ScriptAlias /cgi-bin/ "/var/www/vhosts/default/cgi-bin" + + + SSLEngine on + SSLVerifyClient none + #SSLCertificateFile "/usr/local/psa/var/certificates/certxfb6025" + + + + AllowOverride None + Options None + Order allow,deny + Allow from all + + + + + +php_admin_flag engine on + + + +php_admin_flag engine on + + + + + + + + + + + DocumentRoot "/tmp" + ServerName lists + ServerAlias lists.* + UseCanonicalName Off + + ScriptAlias "/mailman/" "/usr/lib/mailman/cgi-bin/" + + Alias "/icons/" "/var/www/icons/" + Alias "/pipermail/" "/var/lib/mailman/archives/public/" + + + SSLEngine off + + + + + Options FollowSymLinks + Order allow,deny + Allow from all + + + + + + + DocumentRoot "/tmp" + ServerName lists + ServerAlias lists.* + UseCanonicalName Off + + ScriptAlias "/mailman/" "/usr/lib/mailman/cgi-bin/" + + Alias "/icons/" "/var/www/icons/" + Alias "/pipermail/" "/var/lib/mailman/archives/public/" + + SSLEngine on + SSLVerifyClient none + #SSLCertificateFile "/usr/local/psa/var/certificates/certxfb6025" + + + + Options FollowSymLinks + Order allow,deny + Allow from all + + + + + + + RPAFproxy_ips 192.168.100.218 10.128.178.192 + + + RPAFproxy_ips 192.168.100.218 10.128.178.192 + From 3d90fb809761deba0ffa18c615c0c5ac00887ba1 Mon Sep 17 00:00:00 2001 From: Dominic Cleal Date: Sat, 7 May 2016 21:55:31 +0100 Subject: [PATCH 10/13] Merge Augeas fix for escaped spaces in arguments From https://github.com/hercules-team/augeas/commit/f741b8b4f23dd9372dcdea18383ef9138f9c161e Fixes #2735 --- certbot-apache/certbot_apache/augeas_lens/httpd.aug | 4 ++-- .../passing/escaped-space-arguments-2735.conf | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 certbot-apache/certbot_apache/tests/apache-conf-files/passing/escaped-space-arguments-2735.conf diff --git a/certbot-apache/certbot_apache/augeas_lens/httpd.aug b/certbot-apache/certbot_apache/augeas_lens/httpd.aug index 697d5de89..f27798efe 100644 --- a/certbot-apache/certbot_apache/augeas_lens/httpd.aug +++ b/certbot-apache/certbot_apache/augeas_lens/httpd.aug @@ -58,8 +58,8 @@ let empty = Util.empty_dos let indent = Util.indent (* borrowed from shellvars.aug *) -let char_arg_dir = /([^\\ '"{\t\r\n]|[^ '"{\t\r\n]+[^\\ \t\r\n])|\\\\"|\\\\'/ -let char_arg_sec = /([^\\ '"\t\r\n>]|[^ '"\t\r\n>]+[^\\ \t\r\n>])|\\\\"|\\\\'/ +let char_arg_dir = /([^\\ '"{\t\r\n]|[^ '"{\t\r\n]+[^\\ \t\r\n])|\\\\"|\\\\'|\\\\ / +let char_arg_sec = /([^\\ '"\t\r\n>]|[^ '"\t\r\n>]+[^\\ \t\r\n>])|\\\\"|\\\\'|\\\\ / let char_arg_wl = /([^\\ '"},\t\r\n]|[^ '"},\t\r\n]+[^\\ '"},\t\r\n])/ let cdot = /\\\\./ diff --git a/certbot-apache/certbot_apache/tests/apache-conf-files/passing/escaped-space-arguments-2735.conf b/certbot-apache/certbot_apache/tests/apache-conf-files/passing/escaped-space-arguments-2735.conf new file mode 100644 index 000000000..1ea53dfab --- /dev/null +++ b/certbot-apache/certbot_apache/tests/apache-conf-files/passing/escaped-space-arguments-2735.conf @@ -0,0 +1,2 @@ +RewriteCond %{HTTP:Content-Disposition} \.php [NC] +RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.+/trackback/?\ HTTP/ [NC] From 555513940c8e541923cb2e28a56d62b684559dd3 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 9 May 2016 14:57:01 -0700 Subject: [PATCH 11/13] Explain *-hook and -q in renewal documentation --- docs/using.rst | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index 60c074d75..7d7b4fbfd 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -215,12 +215,25 @@ expire in less than 30 days. The same plugin and options that were used at the time the certificate was originally issued will be used for the renewal attempt, unless you specify other plugins or options. +You can also specify hooks to be run before or after a certificate is +renewed. For example, if you want to use the standalone_ plugin to renew +your certificates, you may want to use a command like + +``letsencrypt renew --standalone --pre-hook "service nginx stop" --post-hook "service nginx start"`` + +This will stop Nginx so standalone can bind to the necessary ports and +then restart Nginx after the plugin is finished. The hooks will only be +run if a certificate is due for renewal, so you can run this command +frequently without unnecessarily stopping your webserver. More +information about renewal hooks can be found by running +``letsencrypt --help renew``. + If you're sure that this command executes successfully without human intervention, you can add the command to ``crontab`` (since certificates are only renewed when they're determined to be near expiry, the command -can run on a regular basis, like every week or every day); note that -the current version provides detailed output describing either renewal -success or failure. +can run on a regular basis, like every week or every day). You may also +want to use the ``-q`` or ``--quiet`` quiet flag to silence all output +except errors. The ``--force-renew`` flag may be helpful for automating renewal; it causes the expiration time of the certificate(s) to be ignored when From 6fa7eb576bc5042b8455e1da85c60ee858253dac Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 9 May 2016 18:11:36 -0700 Subject: [PATCH 12/13] Use -n when using certonly --- docs/using.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index 7d7b4fbfd..748fae370 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -254,9 +254,11 @@ renewals of that certificate. An alternative form that provides for more fine-grained control over the renewal process (while renewing specified certificates one at a time), is ``letsencrypt certonly`` with the complete set of subject domains of -a specific certificate specified via `-d` flags, like +a specific certificate specified via `-d` flags. You may also want to +include the ``-n`` or ``--noninteractive`` flag to prevent blocking on +user input (which is useful when running the command from cron). -``letsencrypt certonly -d example.com -d www.example.com`` +``letsencrypt certonly -n -d example.com -d www.example.com`` (All of the domains covered by the certificate must be specified in this case in order to renew and replace the old certificate rather From 3ce47282ea37f2c9b87868ae731c0dcacbef0e12 Mon Sep 17 00:00:00 2001 From: Brad Warren Date: Mon, 9 May 2016 18:14:02 -0700 Subject: [PATCH 13/13] Make --quiet suggestion stronger --- docs/using.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/using.rst b/docs/using.rst index 748fae370..e7e0e9474 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -231,9 +231,9 @@ information about renewal hooks can be found by running If you're sure that this command executes successfully without human intervention, you can add the command to ``crontab`` (since certificates are only renewed when they're determined to be near expiry, the command -can run on a regular basis, like every week or every day). You may also -want to use the ``-q`` or ``--quiet`` quiet flag to silence all output -except errors. +can run on a regular basis, like every week or every day). In that case, +you are likely to want to use the ``-q`` or ``--quiet`` quiet flag to +silence all output except errors. The ``--force-renew`` flag may be helpful for automating renewal; it causes the expiration time of the certificate(s) to be ignored when