Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/certbot/certbot.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'certbot-apache/tests')
-rw-r--r--certbot-apache/tests/apache-conf-files/NEEDED.txt6
-rwxr-xr-xcertbot-apache/tests/apache-conf-files/apache-conf-test88
-rwxr-xr-xcertbot-apache/tests/apache-conf-files/apache-conf-test-pebble.py27
-rw-r--r--certbot-apache/tests/apache-conf-files/failing/missing-double-quote-1724.conf52
-rw-r--r--certbot-apache/tests/apache-conf-files/failing/multivhost-1093.conf295
-rw-r--r--certbot-apache/tests/apache-conf-files/failing/multivhost-1093b.conf593
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/1626-1531.conf37
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/README.modules6
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/anarcat-1531.conf14
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/comment-continuations-2050.conf428
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/drupal-errordocument-arg-1724.conf116
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/drupal-htaccess-1531.conf149
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/escaped-space-arguments-2735.conf2
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/example-1755.conf36
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/example-ssl.conf136
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/example.conf32
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/finalize-1243.apache2.conf.txt222
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/finalize-1243.conf67
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/graphite-quote-1934.conf21
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/ipv6-1143.conf9
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/ipv6-1143b.conf18
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/ipv6-1143c.conf9
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/ipv6-1143d.conf18
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/missing-quote-1724.conf52
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/modmacro-1385.conf33
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/owncloud-1264.conf13
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/rewrite-quote-1960.conf7
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/roundcube-1222.conf61
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/section-continuations-2525.conf284
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/section-empty-continuations-2731.conf247
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/semacode-1598.conf44
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/sslrequire-wordlist-1827.htaccess1
-rw-r--r--certbot-apache/tests/apache-conf-files/passing/two-blocks-one-line-1693.conf28
-rw-r--r--certbot-apache/tests/autohsts_test.py188
-rw-r--r--certbot-apache/tests/centos6_test.py221
-rw-r--r--certbot-apache/tests/centos_test.py194
-rw-r--r--certbot-apache/tests/complex_parsing_test.py128
-rw-r--r--certbot-apache/tests/configurator_reverter_test.py84
-rw-r--r--certbot-apache/tests/configurator_test.py1769
-rw-r--r--certbot-apache/tests/debian_test.py212
-rw-r--r--certbot-apache/tests/display_ops_test.py104
-rw-r--r--certbot-apache/tests/entrypoint_test.py47
-rw-r--r--certbot-apache/tests/fedora_test.py194
-rw-r--r--certbot-apache/tests/gentoo_test.py138
-rw-r--r--certbot-apache/tests/http_01_test.py226
-rw-r--r--certbot-apache/tests/obj_test.py141
-rw-r--r--certbot-apache/tests/parser_test.py401
-rw-r--r--certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/README9
-rw-r--r--certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/ssl.conf222
-rw-r--r--certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/test.example.com.conf7
-rw-r--r--certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/welcome.conf11
-rw-r--r--certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf/httpd.conf1009
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/README9
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/autoindex.conf94
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/centos.example.com.conf7
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/ssl.conf211
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/userdir.conf36
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/welcome.conf22
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-base.conf77
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-dav.conf3
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-lua.conf1
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-mpm.conf19
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-proxy.conf16
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-ssl.conf1
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-systemd.conf2
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/01-cgi.conf14
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf/httpd.conf353
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf/magic385
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/sites1
-rw-r--r--certbot-apache/tests/testdata/centos7_apache/apache/sysconfig/httpd25
-rw-r--r--certbot-apache/tests/testdata/complex_parsing/apache2.conf55
-rw-r--r--certbot-apache/tests/testdata/complex_parsing/conf-enabled/dummy.conf9
-rw-r--r--certbot-apache/tests/testdata/complex_parsing/test_fnmatch.conf1
-rw-r--r--certbot-apache/tests/testdata/complex_parsing/test_variables.conf66
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/apache2.conf196
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/bad_conf_file.conf3
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/other-vhosts-access-log.conf4
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/security.conf35
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/serve-cgi-bin.conf20
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/other-vhosts-access-log.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/security.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/serve-cgi-bin.conf1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/envvars29
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/authz_svn.load5
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav.load3
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav_svn.conf56
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav_svn.load7
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/rewrite.load1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.conf89
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.load2
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/authz_svn.load1
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav.load1
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav_svn.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav_svn.load1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/ports.conf15
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/another_wildcard.conf11
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/old-and-default.conf12
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/wildcard.conf11
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/another_wildcard.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/old-and-default.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/wildcard.conf1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/sites3
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/apache2.conf198
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/other-vhosts-access-log.conf4
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/security.conf31
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/serve-cgi-bin.conf20
l---------certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/other-vhosts-access-log.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/security.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/serve-cgi-bin.conf1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/envvars28
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.conf89
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.load2
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/ports.conf20
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-available/000-default.conf11
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-available/default-ssl.conf38
l---------certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-enabled/000-default.conf1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/sites1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/apache2.conf196
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/envvars29
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/ports.conf15
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-available/default.conf22
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-available/multi-vhost.conf38
l---------certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-enabled/default.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-enabled/multi-vhost.conf1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/apache2.conf207
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/bad_conf_file.conf3
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/other-vhosts-access-log.conf4
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/security.conf35
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/serve-cgi-bin.conf20
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/other-vhosts-access-log.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/security.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/serve-cgi-bin.conf1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/envvars29
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/authz_svn.load5
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav.load3
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav_svn.conf56
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav_svn.load7
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/rewrite.load1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.conf89
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.load2
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/authz_svn.load1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav.load1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav_svn.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav_svn.load1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/ports.conf15
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/000-default.conf12
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/certbot.conf43
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/default-ssl-port-only.conf36
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/default-ssl.conf40
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/duplicatehttp.conf9
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/duplicatehttps.conf14
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/encryption-example.conf42
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/mod_macro-example.conf15
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/ocsp-ssl.conf36
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/wildcard.conf13
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/000-default.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/certbot.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/default-ssl-port-only.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/default-ssl.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/duplicatehttp.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/duplicatehttps.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/encryption-example.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/mod_macro-example.conf1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/non-symlink.conf9
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/ocsp-ssl.conf1
l---------certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/wildcard.conf1
-rw-r--r--certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/sites3
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/httpd.conf157
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/magic385
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_default_settings.conf131
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_error_documents.conf57
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_languages.conf133
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_autoindex.conf85
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_info.conf10
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_log_config.conf35
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_mime.conf46
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_status.conf15
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_userdir.conf32
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mpm.conf99
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/10_mod_mem_cache.conf10
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/40_mod_ssl.conf67
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/41_mod_http2.conf9
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/45_mod_dav.conf19
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/46_mod_ldap.conf18
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_ssl_vhost.conf191
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_vhost.conf45
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/default_vhost.include71
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/gentoo.example.com.conf7
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/conf.d/apache274
-rw-r--r--certbot-apache/tests/testdata/gentoo_apache/apache/sites3
-rw-r--r--certbot-apache/tests/util.py238
191 files changed, 13825 insertions, 0 deletions
diff --git a/certbot-apache/tests/apache-conf-files/NEEDED.txt b/certbot-apache/tests/apache-conf-files/NEEDED.txt
new file mode 100644
index 000000000..c3606fefe
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/NEEDED.txt
@@ -0,0 +1,6 @@
+Issues for which some kind of test case should be constructable, but we do not
+currently have one:
+
+https://github.com/certbot/certbot/issues/1213
+https://github.com/certbot/certbot/issues/1602
+
diff --git a/certbot-apache/tests/apache-conf-files/apache-conf-test b/certbot-apache/tests/apache-conf-files/apache-conf-test
new file mode 100755
index 000000000..4838a6eee
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/apache-conf-test
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+# A hackish script to see if the client is behaving as expected
+# with each of the "passing" conf files.
+
+if [ -z "$SERVER" ]; then
+ echo "Please set SERVER to the ACME server's directory URL."
+ exit 1
+fi
+
+export EA=/etc/apache2/
+TESTDIR="`dirname $0`"
+cd $TESTDIR/passing
+
+function CleanupExit() {
+ echo control c, exiting tests...
+ if [ "$f" != "" ] ; then
+ Cleanup
+ fi
+ exit 1
+}
+
+function Setup() {
+ if [ "$APPEND_APACHECONF" = "" ] ; then
+ sudo cp "$f" "$EA"/sites-available/
+ sudo ln -sf "$EA/sites-available/$f" "$EA/sites-enabled/$f"
+ echo "
+<VirtualHost *:80>
+ ServerName example.com
+ DocumentRoot /tmp/
+ ErrorLog /tmp/error.log
+ CustomLog /tmp/requests.log combined
+</VirtualHost>" | sudo tee $EA/sites-available/throwaway-example.conf >/dev/null
+ sudo ln -sf $EA/sites-available/throwaway-example.conf $EA/sites-enabled/throwaway-example.conf
+ else
+ TMP="/tmp/`basename \"$APPEND_APACHECONF\"`.$$"
+ sudo cp -a "$APPEND_APACHECONF" "$TMP"
+ sudo bash -c "cat \"$f\" >> \"$APPEND_APACHECONF\""
+ fi
+}
+
+function Cleanup() {
+ if [ "$APPEND_APACHECONF" = "" ] ; then
+ sudo rm /etc/apache2/sites-{enabled,available}/"$f"
+ sudo rm $EA/sites-available/throwaway-example.conf
+ sudo rm $EA/sites-enabled/throwaway-example.conf
+ else
+ sudo mv "$TMP" "$APPEND_APACHECONF"
+ fi
+}
+
+# if our environment asks us to enable modules, do our best!
+if [ "$1" = --debian-modules ] ; then
+ sudo apt-get install -y apache2
+ sudo apt-get install -y libapache2-mod-wsgi
+ sudo apt-get install -y libapache2-mod-macro
+
+ for mod in ssl rewrite macro wsgi deflate userdir version mime setenvif ; do
+ echo -n enabling $mod
+ sudo a2enmod $mod
+ done
+fi
+
+CERTBOT_CMD="sudo $(command -v certbot) --server $SERVER -vvvv"
+CERTBOT_CMD="$CERTBOT_CMD --debug --apache --register-unsafely-without-email"
+CERTBOT_CMD="$CERTBOT_CMD --agree-tos certonly -t --no-verify-ssl"
+
+FAILS=0
+trap CleanupExit INT
+for f in *.conf ; do
+ echo -n testing "$f"...
+ Setup
+ RESULT=`echo c | $CERTBOT_CMD 2>&1`
+ if echo $RESULT | grep -Eq \("Which names would you like"\|"mod_macro is not yet"\) ; then
+ echo passed
+ else
+ echo failed
+ echo $RESULT
+ echo
+ echo
+ FAILS=`expr $FAILS + 1`
+ fi
+ Cleanup
+done
+if [ "$FAILS" -ne 0 ] ; then
+ exit 1
+fi
+exit 0
diff --git a/certbot-apache/tests/apache-conf-files/apache-conf-test-pebble.py b/certbot-apache/tests/apache-conf-files/apache-conf-test-pebble.py
new file mode 100755
index 000000000..68bd6287d
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/apache-conf-test-pebble.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+"""
+This executable script wraps the apache-conf-test bash script, in order to setup a pebble instance
+before its execution. Directory URL is passed through the SERVER environment variable.
+"""
+import os
+import subprocess
+import sys
+
+from certbot_integration_tests.utils import acme_server
+
+SCRIPT_DIRNAME = os.path.dirname(__file__)
+
+
+def main(args=None):
+ if not args:
+ args = sys.argv[1:]
+ with acme_server.ACMEServer('pebble', [], False) as acme_xdist:
+ environ = os.environ.copy()
+ environ['SERVER'] = acme_xdist['directory_url']
+ command = [os.path.join(SCRIPT_DIRNAME, 'apache-conf-test')]
+ command.extend(args)
+ return subprocess.call(command, env=environ)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/certbot-apache/tests/apache-conf-files/failing/missing-double-quote-1724.conf b/certbot-apache/tests/apache-conf-files/failing/missing-double-quote-1724.conf
new file mode 100644
index 000000000..7d97b23d0
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/failing/missing-double-quote-1724.conf
@@ -0,0 +1,52 @@
+<VirtualHost *:443>
+ ServerAdmin webmaster@localhost
+ ServerAlias www.example.com
+ ServerName example.com
+ DocumentRoot /var/www/example.com/www/
+ SSLEngine on
+
+ SSLProtocol all -SSLv2 -SSLv3
+ SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRS$
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+ SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
+
+ <Directory />
+ Options FollowSymLinks
+ AllowOverride All
+ </Directory>
+ <Directory /var/www/example.com/www>
+ Options Indexes FollowSymLinks MultiViews
+ AllowOverride All
+ Order allow,deny
+ allow from all
+ # This directive allows us to have apache2's default start page
+ # in /apache2-default/, but still have / go to the right place
+ </Directory>
+
+ ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+ <Directory "/usr/lib/cgi-bin">
+ AllowOverride None
+ Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ ErrorLog /var/log/apache2/error.log
+
+ # Possible values include: debug, info, notice, warn, error, crit,
+ # alert, emerg.
+ LogLevel warn
+
+ CustomLog /var/log/apache2/access.log combined
+ ServerSignature On
+
+ Alias /apache_doc/ "/usr/share/doc/"
+ <Directory "/usr/share/doc/">
+ Options Indexes MultiViews FollowSymLinks
+ AllowOverride None
+ Order deny,allow
+ Deny from all
+ Allow from 127.0.0.0/255.0.0.0 ::1/128
+ </Directory>
+
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/failing/multivhost-1093.conf b/certbot-apache/tests/apache-conf-files/failing/multivhost-1093.conf
new file mode 100644
index 000000000..444f0dade
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/failing/multivhost-1093.conf
@@ -0,0 +1,295 @@
+<Directory /var/www/sjau.ch>
+ AllowOverride None
+ Require all denied
+ </Directory>
+
+<VirtualHost *:80>
+ DocumentRoot /var/www/sjau.ch/web
+
+ ServerName sjau.ch
+ ServerAlias www.sjau.ch
+ ServerAdmin webmaster@sjau.ch
+
+ ErrorLog /var/log/ispconfig/httpd/sjau.ch/error.log
+
+ Alias /error/ "/var/www/sjau.ch/web/error/"
+ ErrorDocument 400 /error/400.html
+ ErrorDocument 401 /error/401.html
+ ErrorDocument 403 /error/403.html
+ ErrorDocument 404 /error/404.html
+ ErrorDocument 405 /error/405.html
+ ErrorDocument 500 /error/500.html
+ ErrorDocument 502 /error/502.html
+ ErrorDocument 503 /error/503.html
+
+ <IfModule mod_ssl.c>
+ </IfModule>
+
+ <Directory /var/www/sjau.ch/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client1/web2/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+ <IfModule mod_ruby.c>
+ <Directory /var/www/sjau.ch/web>
+ Options +ExecCGI
+ </Directory>
+ RubyRequire apache/ruby-run
+ #RubySafeLevel 0
+ AddType text/html .rb
+ AddType text/html .rbx
+ <Files *.rb>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ <Files *.rbx>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ </IfModule>
+
+
+ <IfModule mod_python.c>
+ <Directory /var/www/sjau.ch/web>
+ <FilesMatch "\.py$">
+ SetHandler mod_python
+ </FilesMatch>
+ PythonHandler mod_python.publisher
+ PythonDebug On
+ </Directory>
+ </IfModule>
+
+ # cgi enabled
+ <Directory /var/www/clients/client1/web2/cgi-bin>
+ Require all granted
+ </Directory>
+ ScriptAlias /cgi-bin/ /var/www/clients/client1/web2/cgi-bin/
+ <FilesMatch "\.(cgi|pl)$">
+ SetHandler cgi-script
+ </FilesMatch>
+ # suexec enabled
+ <IfModule mod_suexec.c>
+ SuexecUserGroup web2 client1
+ </IfModule>
+ # php as fast-cgi enabled
+ # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html
+ <IfModule mod_fcgid.c>
+ IdleTimeout 300
+ ProcessLifeTime 3600
+ # MaxProcessCount 1000
+ DefaultMinClassProcessCount 0
+ DefaultMaxClassProcessCount 100
+ IPCConnectTimeout 3
+ IPCCommTimeout 600
+ BusyTimeout 3600
+ </IfModule>
+ <Directory /var/www/sjau.ch/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client1/web2/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+
+ # add support for apache mpm_itk
+ <IfModule mpm_itk_module>
+ AssignUserId web2 client1
+ </IfModule>
+
+ <IfModule mod_dav_fs.c>
+ # Do not execute PHP files in webdav directory
+ <Directory /var/www/clients/client1/web2/webdav>
+ <ifModule mod_security2.c>
+ SecRuleRemoveById 960015
+ SecRuleRemoveById 960032
+ </ifModule>
+ <FilesMatch "\.ph(p3?|tml)$">
+ SetHandler None
+ </FilesMatch>
+ </Directory>
+ DavLockDB /var/www/clients/client1/web2/tmp/DavLock
+ # DO NOT REMOVE THE COMMENTS!
+ # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE!
+ # WEBDAV BEGIN
+ # WEBDAV END
+ </IfModule>
+
+
+</VirtualHost>
+<VirtualHost [2a01:4f8:160:13a2::1002]:80>
+ DocumentRoot /var/www/sjau.ch/web
+
+ ServerName sjau.ch
+ ServerAlias www.sjau.ch
+ ServerAdmin webmaster@sjau.ch
+
+ ErrorLog /var/log/ispconfig/httpd/sjau.ch/error.log
+
+ Alias /error/ "/var/www/sjau.ch/web/error/"
+ ErrorDocument 400 /error/400.html
+ ErrorDocument 401 /error/401.html
+ ErrorDocument 403 /error/403.html
+ ErrorDocument 404 /error/404.html
+ ErrorDocument 405 /error/405.html
+ ErrorDocument 500 /error/500.html
+ ErrorDocument 502 /error/502.html
+ ErrorDocument 503 /error/503.html
+
+ <IfModule mod_ssl.c>
+ </IfModule>
+
+ <Directory /var/www/sjau.ch/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client1/web2/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+ <IfModule mod_ruby.c>
+ <Directory /var/www/sjau.ch/web>
+ Options +ExecCGI
+ </Directory>
+ RubyRequire apache/ruby-run
+ #RubySafeLevel 0
+ AddType text/html .rb
+ AddType text/html .rbx
+ <Files *.rb>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ <Files *.rbx>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ </IfModule>
+
+
+ <IfModule mod_python.c>
+ <Directory /var/www/sjau.ch/web>
+ <FilesMatch "\.py$">
+ SetHandler mod_python
+ </FilesMatch>
+ PythonHandler mod_python.publisher
+ PythonDebug On
+ </Directory>
+ </IfModule>
+
+ # cgi enabled
+ <Directory /var/www/clients/client1/web2/cgi-bin>
+ Require all granted
+ </Directory>
+ ScriptAlias /cgi-bin/ /var/www/clients/client1/web2/cgi-bin/
+ <FilesMatch "\.(cgi|pl)$">
+ SetHandler cgi-script
+ </FilesMatch>
+ # suexec enabled
+ <IfModule mod_suexec.c>
+ SuexecUserGroup web2 client1
+ </IfModule>
+ # php as fast-cgi enabled
+ # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html
+ <IfModule mod_fcgid.c>
+ IdleTimeout 300
+ ProcessLifeTime 3600
+ # MaxProcessCount 1000
+ DefaultMinClassProcessCount 0
+ DefaultMaxClassProcessCount 100
+ IPCConnectTimeout 3
+ IPCCommTimeout 600
+ BusyTimeout 3600
+ </IfModule>
+ <Directory /var/www/sjau.ch/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client1/web2/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web2/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+
+ # add support for apache mpm_itk
+ <IfModule mpm_itk_module>
+ AssignUserId web2 client1
+ </IfModule>
+
+ <IfModule mod_dav_fs.c>
+ # Do not execute PHP files in webdav directory
+ <Directory /var/www/clients/client1/web2/webdav>
+ <ifModule mod_security2.c>
+ SecRuleRemoveById 960015
+ SecRuleRemoveById 960032
+ </ifModule>
+ <FilesMatch "\.ph(p3?|tml)$">
+ SetHandler None
+ </FilesMatch>
+ </Directory>
+ DavLockDB /var/www/clients/client1/web2/tmp/DavLock
+ # DO NOT REMOVE THE COMMENTS!
+ # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE!
+ # WEBDAV BEGIN
+ # WEBDAV END
+ </IfModule>
+
+
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/failing/multivhost-1093b.conf b/certbot-apache/tests/apache-conf-files/failing/multivhost-1093b.conf
new file mode 100644
index 000000000..0388abc2c
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/failing/multivhost-1093b.conf
@@ -0,0 +1,593 @@
+<Directory /var/www/ensemen.ch>
+ AllowOverride None
+ Require all denied
+ </Directory>
+
+<VirtualHost *:80>
+ DocumentRoot /var/www/ensemen.ch/web
+
+ ServerName ensemen.ch
+ ServerAlias www.ensemen.ch
+ ServerAdmin webmaster@ensemen.ch
+
+ ErrorLog /var/log/ispconfig/httpd/ensemen.ch/error.log
+
+ Alias /error/ "/var/www/ensemen.ch/web/error/"
+ ErrorDocument 400 /error/400.html
+ ErrorDocument 401 /error/401.html
+ ErrorDocument 403 /error/403.html
+ ErrorDocument 404 /error/404.html
+ ErrorDocument 405 /error/405.html
+ ErrorDocument 500 /error/500.html
+ ErrorDocument 502 /error/502.html
+ ErrorDocument 503 /error/503.html
+
+ <IfModule mod_ssl.c>
+ </IfModule>
+
+ <Directory /var/www/ensemen.ch/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client4/web17/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+ <IfModule mod_ruby.c>
+ <Directory /var/www/ensemen.ch/web>
+ Options +ExecCGI
+ </Directory>
+ RubyRequire apache/ruby-run
+ #RubySafeLevel 0
+ AddType text/html .rb
+ AddType text/html .rbx
+ <Files *.rb>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ <Files *.rbx>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ </IfModule>
+
+
+ <IfModule mod_python.c>
+ <Directory /var/www/ensemen.ch/web>
+ <FilesMatch "\.py$">
+ SetHandler mod_python
+ </FilesMatch>
+ PythonHandler mod_python.publisher
+ PythonDebug On
+ </Directory>
+ </IfModule>
+
+ # cgi enabled
+ <Directory /var/www/clients/client4/web17/cgi-bin>
+ Require all granted
+ </Directory>
+ ScriptAlias /cgi-bin/ /var/www/clients/client4/web17/cgi-bin/
+ <FilesMatch "\.(cgi|pl)$">
+ SetHandler cgi-script
+ </FilesMatch>
+ # suexec enabled
+ <IfModule mod_suexec.c>
+ SuexecUserGroup web17 client4
+ </IfModule>
+ # php as fast-cgi enabled
+ # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html
+ <IfModule mod_fcgid.c>
+ IdleTimeout 300
+ ProcessLifeTime 3600
+ # MaxProcessCount 1000
+ DefaultMinClassProcessCount 0
+ DefaultMaxClassProcessCount 100
+ IPCConnectTimeout 3
+ IPCCommTimeout 600
+ BusyTimeout 3600
+ </IfModule>
+ <Directory /var/www/ensemen.ch/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client4/web17/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+
+ # add support for apache mpm_itk
+ <IfModule mpm_itk_module>
+ AssignUserId web17 client4
+ </IfModule>
+
+ <IfModule mod_dav_fs.c>
+ # Do not execute PHP files in webdav directory
+ <Directory /var/www/clients/client4/web17/webdav>
+ <ifModule mod_security2.c>
+ SecRuleRemoveById 960015
+ SecRuleRemoveById 960032
+ </ifModule>
+ <FilesMatch "\.ph(p3?|tml)$">
+ SetHandler None
+ </FilesMatch>
+ </Directory>
+ DavLockDB /var/www/clients/client4/web17/tmp/DavLock
+ # DO NOT REMOVE THE COMMENTS!
+ # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE!
+ # WEBDAV BEGIN
+ # WEBDAV END
+ </IfModule>
+
+
+</VirtualHost>
+<VirtualHost *:443>
+ DocumentRoot /var/www/ensemen.ch/web
+
+ ServerName ensemen.ch
+ ServerAlias www.ensemen.ch
+ ServerAdmin webmaster@ensemen.ch
+
+ ErrorLog /var/log/ispconfig/httpd/ensemen.ch/error.log
+
+ Alias /error/ "/var/www/ensemen.ch/web/error/"
+ ErrorDocument 400 /error/400.html
+ ErrorDocument 401 /error/401.html
+ ErrorDocument 403 /error/403.html
+ ErrorDocument 404 /error/404.html
+ ErrorDocument 405 /error/405.html
+ ErrorDocument 500 /error/500.html
+ ErrorDocument 502 /error/502.html
+ ErrorDocument 503 /error/503.html
+
+ <IfModule mod_ssl.c>
+ SSLEngine on
+ SSLProtocol All -SSLv2 -SSLv3
+ SSLCertificateFile /var/www/clients/client4/web17/ssl/ensemen.ch.crt
+ SSLCertificateKeyFile /var/www/clients/client4/web17/ssl/ensemen.ch.key
+ </IfModule>
+
+ <Directory /var/www/ensemen.ch/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client4/web17/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+ <IfModule mod_ruby.c>
+ <Directory /var/www/ensemen.ch/web>
+ Options +ExecCGI
+ </Directory>
+ RubyRequire apache/ruby-run
+ #RubySafeLevel 0
+ AddType text/html .rb
+ AddType text/html .rbx
+ <Files *.rb>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ <Files *.rbx>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ </IfModule>
+
+
+ <IfModule mod_python.c>
+ <Directory /var/www/ensemen.ch/web>
+ <FilesMatch "\.py$">
+ SetHandler mod_python
+ </FilesMatch>
+ PythonHandler mod_python.publisher
+ PythonDebug On
+ </Directory>
+ </IfModule>
+
+ # cgi enabled
+ <Directory /var/www/clients/client4/web17/cgi-bin>
+ Require all granted
+ </Directory>
+ ScriptAlias /cgi-bin/ /var/www/clients/client4/web17/cgi-bin/
+ <FilesMatch "\.(cgi|pl)$">
+ SetHandler cgi-script
+ </FilesMatch>
+ # suexec enabled
+ <IfModule mod_suexec.c>
+ SuexecUserGroup web17 client4
+ </IfModule>
+ # php as fast-cgi enabled
+ # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html
+ <IfModule mod_fcgid.c>
+ IdleTimeout 300
+ ProcessLifeTime 3600
+ # MaxProcessCount 1000
+ DefaultMinClassProcessCount 0
+ DefaultMaxClassProcessCount 100
+ IPCConnectTimeout 3
+ IPCCommTimeout 600
+ BusyTimeout 3600
+ </IfModule>
+ <Directory /var/www/ensemen.ch/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client4/web17/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+
+ # add support for apache mpm_itk
+ <IfModule mpm_itk_module>
+ AssignUserId web17 client4
+ </IfModule>
+
+ <IfModule mod_dav_fs.c>
+ # Do not execute PHP files in webdav directory
+ <Directory /var/www/clients/client4/web17/webdav>
+ <ifModule mod_security2.c>
+ SecRuleRemoveById 960015
+ SecRuleRemoveById 960032
+ </ifModule>
+ <FilesMatch "\.ph(p3?|tml)$">
+ SetHandler None
+ </FilesMatch>
+ </Directory>
+ DavLockDB /var/www/clients/client4/web17/tmp/DavLock
+ # DO NOT REMOVE THE COMMENTS!
+ # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE!
+ # WEBDAV BEGIN
+ # WEBDAV END
+ </IfModule>
+
+
+</VirtualHost>
+<VirtualHost [2a01:4f8:160:13a2::1017]:80>
+ DocumentRoot /var/www/ensemen.ch/web
+
+ ServerName ensemen.ch
+ ServerAlias www.ensemen.ch
+ ServerAdmin webmaster@ensemen.ch
+
+ ErrorLog /var/log/ispconfig/httpd/ensemen.ch/error.log
+
+ Alias /error/ "/var/www/ensemen.ch/web/error/"
+ ErrorDocument 400 /error/400.html
+ ErrorDocument 401 /error/401.html
+ ErrorDocument 403 /error/403.html
+ ErrorDocument 404 /error/404.html
+ ErrorDocument 405 /error/405.html
+ ErrorDocument 500 /error/500.html
+ ErrorDocument 502 /error/502.html
+ ErrorDocument 503 /error/503.html
+
+ <IfModule mod_ssl.c>
+ </IfModule>
+
+ <Directory /var/www/ensemen.ch/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client4/web17/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+ <IfModule mod_ruby.c>
+ <Directory /var/www/ensemen.ch/web>
+ Options +ExecCGI
+ </Directory>
+ RubyRequire apache/ruby-run
+ #RubySafeLevel 0
+ AddType text/html .rb
+ AddType text/html .rbx
+ <Files *.rb>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ <Files *.rbx>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ </IfModule>
+
+
+ <IfModule mod_python.c>
+ <Directory /var/www/ensemen.ch/web>
+ <FilesMatch "\.py$">
+ SetHandler mod_python
+ </FilesMatch>
+ PythonHandler mod_python.publisher
+ PythonDebug On
+ </Directory>
+ </IfModule>
+
+ # cgi enabled
+ <Directory /var/www/clients/client4/web17/cgi-bin>
+ Require all granted
+ </Directory>
+ ScriptAlias /cgi-bin/ /var/www/clients/client4/web17/cgi-bin/
+ <FilesMatch "\.(cgi|pl)$">
+ SetHandler cgi-script
+ </FilesMatch>
+ # suexec enabled
+ <IfModule mod_suexec.c>
+ SuexecUserGroup web17 client4
+ </IfModule>
+ # php as fast-cgi enabled
+ # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html
+ <IfModule mod_fcgid.c>
+ IdleTimeout 300
+ ProcessLifeTime 3600
+ # MaxProcessCount 1000
+ DefaultMinClassProcessCount 0
+ DefaultMaxClassProcessCount 100
+ IPCConnectTimeout 3
+ IPCCommTimeout 600
+ BusyTimeout 3600
+ </IfModule>
+ <Directory /var/www/ensemen.ch/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client4/web17/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+
+ # add support for apache mpm_itk
+ <IfModule mpm_itk_module>
+ AssignUserId web17 client4
+ </IfModule>
+
+ <IfModule mod_dav_fs.c>
+ # Do not execute PHP files in webdav directory
+ <Directory /var/www/clients/client4/web17/webdav>
+ <ifModule mod_security2.c>
+ SecRuleRemoveById 960015
+ SecRuleRemoveById 960032
+ </ifModule>
+ <FilesMatch "\.ph(p3?|tml)$">
+ SetHandler None
+ </FilesMatch>
+ </Directory>
+ DavLockDB /var/www/clients/client4/web17/tmp/DavLock
+ # DO NOT REMOVE THE COMMENTS!
+ # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE!
+ # WEBDAV BEGIN
+ # WEBDAV END
+ </IfModule>
+
+
+</VirtualHost>
+<VirtualHost [2a01:4f8:160:13a2::1017]:443>
+ DocumentRoot /var/www/ensemen.ch/web
+
+ ServerName ensemen.ch
+ ServerAlias www.ensemen.ch
+ ServerAdmin webmaster@ensemen.ch
+
+ ErrorLog /var/log/ispconfig/httpd/ensemen.ch/error.log
+
+ Alias /error/ "/var/www/ensemen.ch/web/error/"
+ ErrorDocument 400 /error/400.html
+ ErrorDocument 401 /error/401.html
+ ErrorDocument 403 /error/403.html
+ ErrorDocument 404 /error/404.html
+ ErrorDocument 405 /error/405.html
+ ErrorDocument 500 /error/500.html
+ ErrorDocument 502 /error/502.html
+ ErrorDocument 503 /error/503.html
+
+ <IfModule mod_ssl.c>
+ SSLEngine on
+ SSLProtocol All -SSLv2 -SSLv3
+ SSLCertificateFile /var/www/clients/client4/web17/ssl/ensemen.ch.crt
+ SSLCertificateKeyFile /var/www/clients/client4/web17/ssl/ensemen.ch.key
+ </IfModule>
+
+ <Directory /var/www/ensemen.ch/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client4/web17/web>
+ # Clear PHP settings of this website
+ <FilesMatch ".+\.ph(p[345]?|t|tml)$">
+ SetHandler None
+ </FilesMatch>
+ Options +FollowSymLinks
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+ <IfModule mod_ruby.c>
+ <Directory /var/www/ensemen.ch/web>
+ Options +ExecCGI
+ </Directory>
+ RubyRequire apache/ruby-run
+ #RubySafeLevel 0
+ AddType text/html .rb
+ AddType text/html .rbx
+ <Files *.rb>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ <Files *.rbx>
+ SetHandler ruby-object
+ RubyHandler Apache::RubyRun.instance
+ </Files>
+ </IfModule>
+
+
+ <IfModule mod_python.c>
+ <Directory /var/www/ensemen.ch/web>
+ <FilesMatch "\.py$">
+ SetHandler mod_python
+ </FilesMatch>
+ PythonHandler mod_python.publisher
+ PythonDebug On
+ </Directory>
+ </IfModule>
+
+ # cgi enabled
+ <Directory /var/www/clients/client4/web17/cgi-bin>
+ Require all granted
+ </Directory>
+ ScriptAlias /cgi-bin/ /var/www/clients/client4/web17/cgi-bin/
+ <FilesMatch "\.(cgi|pl)$">
+ SetHandler cgi-script
+ </FilesMatch>
+ # suexec enabled
+ <IfModule mod_suexec.c>
+ SuexecUserGroup web17 client4
+ </IfModule>
+ # php as fast-cgi enabled
+ # For config options see: http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html
+ <IfModule mod_fcgid.c>
+ IdleTimeout 300
+ ProcessLifeTime 3600
+ # MaxProcessCount 1000
+ DefaultMinClassProcessCount 0
+ DefaultMaxClassProcessCount 100
+ IPCConnectTimeout 3
+ IPCCommTimeout 600
+ BusyTimeout 3600
+ </IfModule>
+ <Directory /var/www/ensemen.ch/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+ <Directory /var/www/clients/client4/web17/web>
+ <FilesMatch "\.php[345]?$">
+ SetHandler fcgid-script
+ </FilesMatch>
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php3
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php4
+ FCGIWrapper /var/www/php-fcgi-scripts/web17/.php-fcgi-starter .php5
+ Options +ExecCGI
+ AllowOverride All
+ Require all granted
+ </Directory>
+
+
+ # add support for apache mpm_itk
+ <IfModule mpm_itk_module>
+ AssignUserId web17 client4
+ </IfModule>
+
+ <IfModule mod_dav_fs.c>
+ # Do not execute PHP files in webdav directory
+ <Directory /var/www/clients/client4/web17/webdav>
+ <ifModule mod_security2.c>
+ SecRuleRemoveById 960015
+ SecRuleRemoveById 960032
+ </ifModule>
+ <FilesMatch "\.ph(p3?|tml)$">
+ SetHandler None
+ </FilesMatch>
+ </Directory>
+ DavLockDB /var/www/clients/client4/web17/tmp/DavLock
+ # DO NOT REMOVE THE COMMENTS!
+ # IF YOU REMOVE THEM, WEBDAV WILL NOT WORK ANYMORE!
+ # WEBDAV BEGIN
+ # WEBDAV END
+ </IfModule>
+
+
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/1626-1531.conf b/certbot-apache/tests/apache-conf-files/passing/1626-1531.conf
new file mode 100644
index 000000000..1622a57df
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/1626-1531.conf
@@ -0,0 +1,37 @@
+<VirtualHost *:80>
+ ServerAdmin denver@ossguy.com
+ ServerName c-beta.ossguy.com
+
+ Alias /robots.txt /home/denver/www/c-beta.ossguy.com/static/robots.txt
+ Alias /favicon.ico /home/denver/www/c-beta.ossguy.com/static/favicon.ico
+
+ AliasMatch /(.*\.css) /home/denver/www/c-beta.ossguy.com/static/$1
+ AliasMatch /(.*\.js) /home/denver/www/c-beta.ossguy.com/static/$1
+ AliasMatch /(.*\.png) /home/denver/www/c-beta.ossguy.com/static/$1
+ AliasMatch /(.*\.gif) /home/denver/www/c-beta.ossguy.com/static/$1
+ AliasMatch /(.*\.jpg) /home/denver/www/c-beta.ossguy.com/static/$1
+
+ WSGIScriptAlias / /home/denver/www/c-beta.ossguy.com/django.wsgi
+ WSGIDaemonProcess c-beta-ossguy user=www-data group=www-data home=/var/www processes=5 threads=10 maximum-requests=1000 umask=0007 display-name=c-beta-ossguy
+ WSGIProcessGroup c-beta-ossguy
+ WSGIApplicationGroup %{GLOBAL}
+
+ DocumentRoot /home/denver/www/c-beta.ossguy.com/static
+
+ <Directory /home/denver/www/c-beta.ossguy.com/static>
+ Options -Indexes +FollowSymLinks -MultiViews
+ Require all granted
+ AllowOverride None
+ </Directory>
+
+ <Directory /home/denver/www/c-beta.ossguy.com/static/source>
+ Options +Indexes +FollowSymLinks -MultiViews
+ Require all granted
+ AllowOverride None
+ </Directory>
+
+ # Custom log file locations
+ LogLevel warn
+ ErrorLog /tmp/error.log
+ CustomLog /tmp/access.log combined
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/README.modules b/certbot-apache/tests/apache-conf-files/passing/README.modules
new file mode 100644
index 000000000..32c3ef019
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/README.modules
@@ -0,0 +1,6 @@
+# Modules required to parse these conf files:
+ssl
+rewrite
+macro
+wsgi
+deflate
diff --git a/certbot-apache/tests/apache-conf-files/passing/anarcat-1531.conf b/certbot-apache/tests/apache-conf-files/passing/anarcat-1531.conf
new file mode 100644
index 000000000..73a9b746c
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/anarcat-1531.conf
@@ -0,0 +1,14 @@
+<VirtualHost *:80>
+ ServerAdmin root@localhost
+ ServerName anarcat.wiki.orangeseeds.org:80
+
+
+ UserDir disabled
+
+ RewriteEngine On
+ RewriteRule ^/(.*) http\:\/\/anarc\.at\/$1 [L,R,NE]
+
+ ErrorLog /var/log/apache2/1531error.log
+ LogLevel warn
+ CustomLog /var/log/apache2/1531access.log combined
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/comment-continuations-2050.conf b/certbot-apache/tests/apache-conf-files/passing/comment-continuations-2050.conf
new file mode 100644
index 000000000..4c3fa2af1
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/comment-continuations-2050.conf
@@ -0,0 +1,428 @@
+# ---------------------------------------------------------------
+# Core ModSecurity Rule Set ver.2.2.6
+# Copyright (C) 2006-2012 Trustwave All rights reserved.
+#
+# The OWASP ModSecurity Core Rule Set is distributed under
+# Apache Software License (ASL) version 2
+# Please see the enclosed LICENCE file for full details.
+# ---------------------------------------------------------------
+
+
+#
+# -- [[ Recommended Base Configuration ]] -------------------------------------------------
+#
+# The configuration directives/settings in this file are used to control
+# the OWASP ModSecurity CRS. These settings do **NOT** configure the main
+# ModSecurity settings such as:
+#
+# - SecRuleEngine
+# - SecRequestBodyAccess
+# - SecAuditEngine
+# - SecDebugLog
+#
+# You should use the modsecurity.conf-recommended file that comes with the
+# ModSecurity source code archive.
+#
+# Ref: http://mod-security.svn.sourceforge.net/viewvc/mod-security/m2/trunk/modsecurity.conf-recommended
+#
+
+
+#
+# -- [[ Rule Version ]] -------------------------------------------------------------------
+#
+# Rule version data is added to the "Producer" line of Section H of the Audit log:
+#
+# - Producer: ModSecurity for Apache/2.7.0-rc1 (http://www.modsecurity.org/); OWASP_CRS/2.2.4.
+#
+# Ref: https://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual#SecComponentSignature
+#
+#SecComponentSignature "OWASP_CRS/2.2.6"
+
+
+#
+# -- [[ Modes of Operation: Self-Contained vs. Collaborative Detection ]] -----------------
+#
+# Each detection rule uses the "block" action which will inherit the SecDefaultAction
+# specified below. Your settings here will determine which mode of operation you use.
+#
+# -- [[ Self-Contained Mode ]] --
+# Rules inherit the "deny" disruptive action. The first rule that matches will block.
+#
+# -- [[ Collaborative Detection Mode ]] --
+# This is a "delayed blocking" mode of operation where each matching rule will inherit
+# the "pass" action and will only contribute to anomaly scores. Transactional blocking
+# can be applied
+#
+# -- [[ Alert Logging Control ]] --
+# You have three options -
+#
+# - To log to both the Apache error_log and ModSecurity audit_log file use: "log"
+# - To log *only* to the ModSecurity audit_log file use: "nolog,auditlog"
+# - To log *only* to the Apache error_log file use: "log,noauditlog"
+#
+# Ref: http://blog.spiderlabs.com/2010/11/advanced-topic-of-the-week-traditional-vs-anomaly-scoring-detection-modes.html
+# Ref: https://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual#SecDefaultAction
+#
+#SecDefaultAction "phase:1,deny,log"
+
+
+#
+# -- [[ Collaborative Detection Severity Levels ]] ----------------------------------------
+#
+# These are the default scoring points for each severity level. You may
+# adjust these to you liking. These settings will be used in macro expansion
+# in the rules to increment the anomaly scores when rules match.
+#
+# These are the default Severity ratings (with anomaly scores) of the individual rules -
+#
+# - 2: Critical - Anomaly Score of 5.
+# Is the highest severity level possible without correlation. It is
+# normally generated by the web attack rules (40 level files).
+# - 3: Error - Anomaly Score of 4.
+# Is generated mostly from outbound leakage rules (50 level files).
+# - 4: Warning - Anomaly Score of 3.
+# Is generated by malicious client rules (35 level files).
+# - 5: Notice - Anomaly Score of 2.
+# Is generated by the Protocol policy and anomaly files.
+#
+#SecAction \
+ "id:'900001', \
+ phase:1, \
+ t:none, \
+ setvar:tx.critical_anomaly_score=5, \
+ setvar:tx.error_anomaly_score=4, \
+ setvar:tx.warning_anomaly_score=3, \
+ setvar:tx.notice_anomaly_score=2, \
+ nolog, \
+ pass"
+
+
+#
+# -- [[ Collaborative Detection Scoring Threshold Levels ]] ------------------------------
+#
+# These variables are used in macro expansion in the 49 inbound blocking and 59
+# outbound blocking files.
+#
+# **MUST HAVE** ModSecurity v2.5.12 or higher to use macro expansion in numeric
+# operators. If you have an earlier version, edit the 49/59 files directly to
+# set the appropriate anomaly score levels.
+#
+# You should set the score to the proper threshold you would prefer. If set to "5"
+# it will work similarly to previous Mod CRS rules and will create an event in the error_log
+# file if there are any rules that match. If you would like to lessen the number of events
+# generated in the error_log file, you should increase the anomaly score threshold to
+# something like "20". This would only generate an event in the error_log file if
+# there are multiple lower severity rule matches or if any 1 higher severity item matches.
+#
+#SecAction \
+ "id:'900002', \
+ phase:1, \
+ t:none, \
+ setvar:tx.inbound_anomaly_score_level=5, \
+ nolog, \
+ pass"
+
+
+#SecAction \
+ "id:'900003', \
+ phase:1, \
+ t:none, \
+ setvar:tx.outbound_anomaly_score_level=4, \
+ nolog, \
+ pass"
+
+
+#
+# -- [[ Collaborative Detection Blocking ]] -----------------------------------------------
+#
+# This is a collaborative detection mode where each rule will increment an overall
+# anomaly score for the transaction. The scores are then evaluated in the following files:
+#
+# Inbound anomaly score - checked in the modsecurity_crs_49_inbound_blocking.conf file
+# Outbound anomaly score - checked in the modsecurity_crs_59_outbound_blocking.conf file
+#
+# If you want to use anomaly scoring mode, then uncomment this line.
+#
+#SecAction \
+ "id:'900004', \
+ phase:1, \
+ t:none, \
+ setvar:tx.anomaly_score_blocking=on, \
+ nolog, \
+ pass"
+
+
+#
+# -- [[ GeoIP Database ]] -----------------------------------------------------------------
+#
+# There are some rulesets that need to inspect the GEO data of the REMOTE_ADDR data.
+#
+# You must first download the MaxMind GeoIP Lite City DB -
+#
+# http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
+#
+# You then need to define the proper path for the SecGeoLookupDb directive
+#
+# Ref: http://blog.spiderlabs.com/2010/10/detecting-malice-with-modsecurity-geolocation-data.html
+# Ref: http://blog.spiderlabs.com/2010/11/detecting-malice-with-modsecurity-ip-forensics.html
+#
+#SecGeoLookupDb /opt/modsecurity/lib/GeoLiteCity.dat
+
+#
+# -- [[ Regression Testing Mode ]] --------------------------------------------------------
+#
+# If you are going to run the regression testing mode, you should uncomment the
+# following rule. It will enable DetectionOnly mode for the SecRuleEngine and
+# will enable Response Header tagging so that the client testing script can see
+# which rule IDs have matched.
+#
+# You must specify the your source IP address where you will be running the tests
+# from.
+#
+#SecRule REMOTE_ADDR "@ipMatch 192.168.1.100" \
+ "id:'900005', \
+ phase:1, \
+ t:none, \
+ ctl:ruleEngine=DetectionOnly, \
+ setvar:tx.regression_testing=1, \
+ nolog, \
+ pass"
+
+
+#
+# -- [[ HTTP Policy Settings ]] ----------------------------------------------------------
+#
+# Set the following policy settings here and they will be propagated to the 23 rules
+# file (modsecurity_common_23_request_limits.conf) by using macro expansion.
+# If you run into false positives, you can adjust the settings here.
+#
+# Only the max number of args is uncommented by default as there are a high rate
+# of false positives. Uncomment the items you wish to set.
+#
+#
+# -- Maximum number of arguments in request limited
+#SecAction \
+ "id:'900006', \
+ phase:1, \
+ t:none, \
+ setvar:tx.max_num_args=255, \
+ nolog, \
+ pass"
+
+#
+# -- Limit argument name length
+#SecAction \
+ "id:'900007', \
+ phase:1, \
+ t:none, \
+ setvar:tx.arg_name_length=100, \
+ nolog, \
+ pass"
+
+#
+# -- Limit value name length
+#SecAction \
+ "id:'900008', \
+ phase:1, \
+ t:none, \
+ setvar:tx.arg_length=400, \
+ nolog, \
+ pass"
+
+#
+# -- Limit arguments total length
+#SecAction \
+ "id:'900009', \
+ phase:1, \
+ t:none, \
+ setvar:tx.total_arg_length=64000, \
+ nolog, \
+ pass"
+
+#
+# -- Individual file size is limited
+#SecAction \
+ "id:'900010', \
+ phase:1, \
+ t:none, \
+ setvar:tx.max_file_size=1048576, \
+ nolog, \
+ pass"
+
+#
+# -- Combined file size is limited
+#SecAction \
+ "id:'900011', \
+ phase:1, \
+ t:none, \
+ setvar:tx.combined_file_sizes=1048576, \
+ nolog, \
+ pass"
+
+
+#
+# Set the following policy settings here and they will be propagated to the 30 rules
+# file (modsecurity_crs_30_http_policy.conf) by using macro expansion.
+# If you run into false positives, you can adjust the settings here.
+#
+#SecAction \
+ "id:'900012', \
+ phase:1, \
+ t:none, \
+ setvar:'tx.allowed_methods=GET HEAD POST OPTIONS', \
+ setvar:'tx.allowed_request_content_type=application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/x-amf', \
+ setvar:'tx.allowed_http_versions=HTTP/0.9 HTTP/1.0 HTTP/1.1', \
+ setvar:'tx.restricted_extensions=.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .resources/ .resx/ .sql/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/', \
+ setvar:'tx.restricted_headers=/Proxy-Connection/ /Lock-Token/ /Content-Range/ /Translate/ /via/ /if/', \
+ nolog, \
+ pass"
+
+
+#
+# -- [[ Content Security Policy (CSP) Settings ]] -----------------------------------------
+#
+# The purpose of these settings is to send CSP response headers to
+# Mozilla FireFox users so that you can enforce how dynamic content
+# is used. CSP usage helps to prevent XSS attacks against your users.
+#
+# Reference Link:
+#
+# https://developer.mozilla.org/en/Security/CSP
+#
+# Uncomment this SecAction line if you want use CSP enforcement.
+# You need to set the appropriate directives and settings for your site/domain and
+# and activate the CSP file in the experimental_rules directory.
+#
+# Ref: http://blog.spiderlabs.com/2011/04/modsecurity-advanced-topic-of-the-week-integrating-content-security-policy-csp.html
+#
+#SecAction \
+ "id:'900013', \
+ phase:1, \
+ t:none, \
+ setvar:tx.csp_report_only=1, \
+ setvar:tx.csp_report_uri=/csp_violation_report, \
+ setenv:'csp_policy=allow \'self\'; img-src *.yoursite.com; media-src *.yoursite.com; style-src *.yoursite.com; frame-ancestors *.yoursite.com; script-src *.yoursite.com; report-uri %{tx.csp_report_uri}', \
+ nolog, \
+ pass"
+
+
+#
+# -- [[ Brute Force Protection ]] ---------------------------------------------------------
+#
+# If you are using the Brute Force Protection rule set, then uncomment the following
+# lines and set the following variables:
+# - Protected URLs: resources to protect (e.g. login pages) - set to your login page
+# - Burst Time Slice Interval: time interval window to monitor for bursts
+# - Request Threshold: request # threshold to trigger a burst
+# - Block Period: temporary block timeout
+#
+#SecAction \
+ "id:'900014', \
+ phase:1, \
+ t:none, \
+ setvar:'tx.brute_force_protected_urls=/login.jsp /partner_login.php', \
+ setvar:'tx.brute_force_burst_time_slice=60', \
+ setvar:'tx.brute_force_counter_threshold=10', \
+ setvar:'tx.brute_force_block_timeout=300', \
+ nolog, \
+ pass"
+
+
+#
+# -- [[ DoS Protection ]] ----------------------------------------------------------------
+#
+# If you are using the DoS Protection rule set, then uncomment the following
+# lines and set the following variables:
+# - Burst Time Slice Interval: time interval window to monitor for bursts
+# - Request Threshold: request # threshold to trigger a burst
+# - Block Period: temporary block timeout
+#
+#SecAction \
+ "id:'900015', \
+ phase:1, \
+ t:none, \
+ setvar:'tx.dos_burst_time_slice=60', \
+ setvar:'tx.dos_counter_threshold=100', \
+ setvar:'tx.dos_block_timeout=600', \
+ nolog, \
+ pass"
+
+
+#
+# -- [[ Check UTF encoding ]] -----------------------------------------------------------
+#
+# We only want to apply this check if UTF-8 encoding is actually used by the site, otherwise
+# it will result in false positives.
+#
+# Uncomment this line if your site uses UTF8 encoding
+#SecAction \
+ "id:'900016', \
+ phase:1, \
+ t:none, \
+ setvar:tx.crs_validate_utf8_encoding=1, \
+ nolog, \
+ pass"
+
+
+#
+# -- [[ Enable XML Body Parsing ]] -------------------------------------------------------
+#
+# The rules in this file will trigger the XML parser upon an XML request
+#
+# Initiate XML Processor in case of xml content-type
+#
+#SecRule REQUEST_HEADERS:Content-Type "text/xml" \
+ "id:'900017', \
+ phase:1, \
+ t:none,t:lowercase, \
+ nolog, \
+ pass, \
+ chain"
+ #SecRule REQBODY_PROCESSOR "!@streq XML" \
+ "ctl:requestBodyProcessor=XML"
+
+
+#
+# -- [[ Global and IP Collections ]] -----------------------------------------------------
+#
+# Create both Global and IP collections for rules to use
+# There are some CRS rules that assume that these two collections
+# have already been initiated.
+#
+#SecRule REQUEST_HEADERS:User-Agent "^(.*)$" \
+ "id:'900018', \
+ phase:1, \
+ t:none,t:sha1,t:hexEncode, \
+ setvar:tx.ua_hash=%{matched_var}, \
+ nolog, \
+ pass"
+
+
+#SecRule REQUEST_HEADERS:x-forwarded-for "^\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b" \
+ "id:'900019', \
+ phase:1, \
+ t:none, \
+ capture, \
+ setvar:tx.real_ip=%{tx.1}, \
+ nolog, \
+ pass"
+
+
+#SecRule &TX:REAL_IP "!@eq 0" \
+ "id:'900020', \
+ phase:1, \
+ t:none, \
+ initcol:global=global, \
+ initcol:ip=%{tx.real_ip}_%{tx.ua_hash}, \
+ nolog, \
+ pass"
+
+
+#SecRule &TX:REAL_IP "@eq 0" \
+ "id:'900021', \
+ phase:1, \
+ t:none, \
+ initcol:global=global, \
+ initcol:ip=%{remote_addr}_%{tx.ua_hash}, \
+ nolog, \
+ pass"
diff --git a/certbot-apache/tests/apache-conf-files/passing/drupal-errordocument-arg-1724.conf b/certbot-apache/tests/apache-conf-files/passing/drupal-errordocument-arg-1724.conf
new file mode 100644
index 000000000..4733ffa4a
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/drupal-errordocument-arg-1724.conf
@@ -0,0 +1,116 @@
+#
+# Apache/PHP/Drupal settings:
+#
+
+# Protect files and directories from prying eyes.
+<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl|svn-base)$|^(code-style\.pl|Entries.*|Repository|Root|Tag|Template|all-wcprops|entries|format)$">
+ Order allow,deny
+</FilesMatch>
+
+# Don't show directory listings for URLs which map to a directory.
+Options -Indexes
+
+# Follow symbolic links in this directory.
+Options +FollowSymLinks
+
+# Make Drupal handle any 404 errors.
+ErrorDocument 404 /index.php
+
+# Force simple error message for requests for non-existent favicon.ico.
+<Files favicon.ico>
+ # There is no end quote below, for compatibility with Apache 1.3.
+ ErrorDocument 404 "The requested file favicon.ico was not found.
+</Files>
+
+# Set the default handler.
+DirectoryIndex index.php
+
+# Override PHP settings. More in sites/default/settings.php
+# but the following cannot be changed at runtime.
+
+# PHP 4, Apache 1.
+<IfModule mod_php4.c>
+ php_value magic_quotes_gpc 0
+ php_value register_globals 0
+ php_value session.auto_start 0
+ php_value mbstring.http_input pass
+ php_value mbstring.http_output pass
+ php_value mbstring.encoding_translation 0
+</IfModule>
+
+# PHP 4, Apache 2.
+<IfModule sapi_apache2.c>
+ php_value magic_quotes_gpc 0
+ php_value register_globals 0
+ php_value session.auto_start 0
+ php_value mbstring.http_input pass
+ php_value mbstring.http_output pass
+ php_value mbstring.encoding_translation 0
+</IfModule>
+
+# PHP 5, Apache 1 and 2.
+<IfModule mod_php5.c>
+ php_value magic_quotes_gpc 0
+ php_value register_globals 0
+ php_value session.auto_start 0
+ php_value mbstring.http_input pass
+ php_value mbstring.http_output pass
+ php_value mbstring.encoding_translation 0
+</IfModule>
+
+# Requires mod_expires to be enabled.
+<IfModule mod_expires.c>
+ # Enable expirations.
+ ExpiresActive On
+
+ # Cache all files for 2 weeks after access (A).
+ ExpiresDefault A1209600
+
+ <FilesMatch \.php$>
+ # Do not allow PHP scripts to be cached unless they explicitly send cache
+ # headers themselves. Otherwise all scripts would have to overwrite the
+ # headers set by mod_expires if they want another caching behavior. This may
+ # fail if an error occurs early in the bootstrap process, and it may cause
+ # problems if a non-Drupal PHP file is installed in a subdirectory.
+ ExpiresActive Off
+ </FilesMatch>
+</IfModule>
+
+# Various rewrite rules.
+<IfModule mod_rewrite.c>
+ RewriteEngine on
+
+ # If your site can be accessed both with and without the 'www.' prefix, you
+ # can use one of the following settings to redirect users to your preferred
+ # URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option:
+ #
+ # To redirect all users to access the site WITH the 'www.' prefix,
+ # (http://example.com/... will be redirected to http://www.example.com/...)
+ # adapt and uncomment the following:
+ # RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
+ # RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
+ #
+ # To redirect all users to access the site WITHOUT the 'www.' prefix,
+ # (http://www.example.com/... will be redirected to http://example.com/...)
+ # uncomment and adapt the following:
+ # RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
+ # RewriteRule ^(.*)$ http://example.com/$1 [L,R=301]
+
+ # Modify the RewriteBase if you are using Drupal in a subdirectory or in a
+ # VirtualDocumentRoot and the rewrite rules are not working properly.
+ # For example if your site is at http://example.com/drupal uncomment and
+ # modify the following line:
+ # RewriteBase /drupal
+ #
+ # If your site is running in a VirtualDocumentRoot at http://example.com/,
+ # uncomment the following line:
+ # RewriteBase /
+
+ # Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_URI} !=/favicon.ico
+ RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
+</IfModule>
+
+# $Id$
diff --git a/certbot-apache/tests/apache-conf-files/passing/drupal-htaccess-1531.conf b/certbot-apache/tests/apache-conf-files/passing/drupal-htaccess-1531.conf
new file mode 100644
index 000000000..a1aab7a39
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/drupal-htaccess-1531.conf
@@ -0,0 +1,149 @@
+#
+# Apache/PHP/Drupal settings:
+#
+
+# Protect files and directories from prying eyes.
+<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig\.save)$">
+ Order allow,deny
+</FilesMatch>
+
+# Don't show directory listings for URLs which map to a directory.
+Options -Indexes
+
+# Follow symbolic links in this directory.
+Options +FollowSymLinks
+
+# Make Drupal handle any 404 errors.
+ErrorDocument 404 /index.php
+
+# Set the default handler.
+DirectoryIndex index.php index.html index.htm
+
+# Override PHP settings that cannot be changed at runtime. See
+# sites/default/default.settings.php and drupal_environment_initialize() in
+# includes/bootstrap.inc for settings that can be changed at runtime.
+
+# PHP 5, Apache 1 and 2.
+<IfModule mod_php5.c>
+ php_flag magic_quotes_gpc off
+ php_flag magic_quotes_sybase off
+ php_flag register_globals off
+ php_flag session.auto_start off
+ php_value mbstring.http_input pass
+ php_value mbstring.http_output pass
+ php_flag mbstring.encoding_translation off
+</IfModule>
+
+# Requires mod_expires to be enabled.
+<IfModule mod_expires.c>
+ # Enable expirations.
+ ExpiresActive On
+
+ # Cache all files for 2 weeks after access (A).
+ ExpiresDefault A1209600
+
+ <FilesMatch \.php$>
+ # Do not allow PHP scripts to be cached unless they explicitly send cache
+ # headers themselves. Otherwise all scripts would have to overwrite the
+ # headers set by mod_expires if they want another caching behavior. This may
+ # fail if an error occurs early in the bootstrap process, and it may cause
+ # problems if a non-Drupal PHP file is installed in a subdirectory.
+ ExpiresActive Off
+ </FilesMatch>
+</IfModule>
+
+# Various rewrite rules.
+<IfModule mod_rewrite.c>
+ RewriteEngine on
+
+ # Set "protossl" to "s" if we were accessed via https://. This is used later
+ # if you enable "www." stripping or enforcement, in order to ensure that
+ # you don't bounce between http and https.
+ RewriteRule ^ - [E=protossl]
+ RewriteCond %{HTTPS} on
+ RewriteRule ^ - [E=protossl:s]
+
+ # Make sure Authorization HTTP header is available to PHP
+ # even when running as CGI or FastCGI.
+ RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
+
+ # Block access to "hidden" directories whose names begin with a period. This
+ # includes directories used by version control systems such as Subversion or
+ # Git to store control files. Files whose names begin with a period, as well
+ # as the control files used by CVS, are protected by the FilesMatch directive
+ # above.
+ #
+ # NOTE: This only works when mod_rewrite is loaded. Without mod_rewrite, it is
+ # not possible to block access to entire directories from .htaccess, because
+ # <DirectoryMatch> is not allowed here.
+ #
+ # If you do not have mod_rewrite installed, you should remove these
+ # directories from your webroot or otherwise protect them from being
+ # downloaded.
+ RewriteRule "(^|/)\." - [F]
+
+ # If your site can be accessed both with and without the 'www.' prefix, you
+ # can use one of the following settings to redirect users to your preferred
+ # URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option:
+ #
+ # To redirect all users to access the site WITH the 'www.' prefix,
+ # (http://example.com/... will be redirected to http://www.example.com/...)
+ # uncomment the following:
+ # RewriteCond %{HTTP_HOST} .
+ # RewriteCond %{HTTP_HOST} !^www\. [NC]
+ # RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
+ #
+ # To redirect all users to access the site WITHOUT the 'www.' prefix,
+ # (http://www.example.com/... will be redirected to http://example.com/...)
+ # uncomment the following:
+ # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
+ # RewriteRule ^ http%{ENV:protossl}://%1%{REQUEST_URI} [L,R=301]
+
+ # Modify the RewriteBase if you are using Drupal in a subdirectory or in a
+ # VirtualDocumentRoot and the rewrite rules are not working properly.
+ # For example if your site is at http://example.com/drupal uncomment and
+ # modify the following line:
+ # RewriteBase /drupal
+ #
+ # If your site is running in a VirtualDocumentRoot at http://example.com/,
+ # uncomment the following line:
+ # RewriteBase /
+
+ # Pass all requests not referring directly to files in the filesystem to
+ # index.php. Clean URLs are handled in drupal_environment_initialize().
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteCond %{REQUEST_URI} !=/favicon.ico
+ RewriteRule ^ index.php [L]
+
+ # Rules to correctly serve gzip compressed CSS and JS files.
+ # Requires both mod_rewrite and mod_headers to be enabled.
+ <IfModule mod_headers.c>
+ # Serve gzip compressed CSS files if they exist and the client accepts gzip.
+ RewriteCond %{HTTP:Accept-encoding} gzip
+ RewriteCond %{REQUEST_FILENAME}\.gz -s
+ RewriteRule ^(.*)\.css $1\.css\.gz [QSA]
+
+ # Serve gzip compressed JS files if they exist and the client accepts gzip.
+ RewriteCond %{HTTP:Accept-encoding} gzip
+ RewriteCond %{REQUEST_FILENAME}\.gz -s
+ RewriteRule ^(.*)\.js $1\.js\.gz [QSA]
+
+ # Serve correct content types, and prevent mod_deflate double gzip.
+ RewriteRule .css.gz$ - [T=text/css,E=no-gzip:1]
+ RewriteRule .js.gz$ - [T=text/javascript,E=no-gzip:1]
+
+ <FilesMatch "(\.js\.gz|\.css\.gz)$">
+ # Serve correct encoding type.
+ Header set Content-Encoding gzip
+ # Force proxies to cache gzipped & non-gzipped css/js files separately.
+ Header append Vary Accept-Encoding
+ </FilesMatch>
+ </IfModule>
+</IfModule>
+
+# Add headers to all responses.
+<IfModule mod_headers.c>
+ # Disable content sniffing, since it's an attack vector.
+ Header always set X-Content-Type-Options nosniff
+</IfModule>
diff --git a/certbot-apache/tests/apache-conf-files/passing/escaped-space-arguments-2735.conf b/certbot-apache/tests/apache-conf-files/passing/escaped-space-arguments-2735.conf
new file mode 100644
index 000000000..1ea53dfab
--- /dev/null
+++ b/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]
diff --git a/certbot-apache/tests/apache-conf-files/passing/example-1755.conf b/certbot-apache/tests/apache-conf-files/passing/example-1755.conf
new file mode 100644
index 000000000..260029576
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/example-1755.conf
@@ -0,0 +1,36 @@
+<VirtualHost *:80>
+ # The ServerName directive sets the request scheme, hostname and port that
+ # the server uses to identify itself. This is used when creating
+ # redirection URLs. In the context of virtual hosts, the ServerName
+ # specifies what hostname must appear in the request's Host: header to
+ # match this virtual host. For the default virtual host (this file) this
+ # value is not decisive as it is used as a last resort host regardless.
+ # However, you must set it for any further virtual host explicitly.
+ ServerName www.example.com
+ ServerAlias example.com
+SetOutputFilter DEFLATE
+# Do not attempt to compress the following extensions
+SetEnvIfNoCase Request_URI \
+\.(?:gif|jpe?g|png|swf|flv|zip|gz|tar|mp3|mp4|m4v)$ no-gzip dont-vary
+
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/proof
+
+ # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
+ # error, crit, alert, emerg.
+ # It is also possible to configure the loglevel for particular
+ # modules, e.g.
+ #LogLevel info ssl:warn
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ # For most configuration files from conf-available/, which are
+ # enabled or disabled at a global level, it is possible to
+ # include a line for only one particular virtual host. For example the
+ # following line enables the CGI configuration for this host only
+ # after it has been globally disabled with "a2disconf".
+ #Include conf-available/serve-cgi-bin.conf
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/apache-conf-files/passing/example-ssl.conf b/certbot-apache/tests/apache-conf-files/passing/example-ssl.conf
new file mode 100644
index 000000000..31deb7647
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/example-ssl.conf
@@ -0,0 +1,136 @@
+<VirtualHost *:443>
+ ServerName example.com
+ ServerAlias www.example.com
+ ServerAdmin webmaster@localhost
+
+ DocumentRoot /var/www/html
+
+ # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
+ # error, crit, alert, emerg.
+ # It is also possible to configure the loglevel for particular
+ # modules, e.g.
+ #LogLevel info ssl:warn
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ # For most configuration files from conf-available/, which are
+ # enabled or disabled at a global level, it is possible to
+ # include a line for only one particular virtual host. For example the
+ # following line enables the CGI configuration for this host only
+ # after it has been globally disabled with "a2disconf".
+ #Include conf-available/serve-cgi-bin.conf
+
+ # SSL Engine Switch:
+ # Enable/Disable SSL for this virtual host.
+ SSLEngine on
+
+ # A self-signed (snakeoil) certificate can be created by installing
+ # the ssl-cert package. See
+ # /usr/share/doc/apache2/README.Debian.gz for more info.
+ # If both key and certificate are stored in the same file, only the
+ # SSLCertificateFile directive is needed.
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+ SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
+
+ # Server Certificate Chain:
+ # Point SSLCertificateChainFile at a file containing the
+ # concatenation of PEM encoded CA certificates which form the
+ # certificate chain for the server certificate. Alternatively
+ # the referenced file can be the same as SSLCertificateFile
+ # when the CA certificates are directly appended to the server
+ # certificate for convenience.
+ #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
+
+ # Certificate Authority (CA):
+ # Set the CA certificate verification path where to find CA
+ # certificates for client authentication or alternatively one
+ # huge file containing all of them (file must be PEM encoded)
+ # Note: Inside SSLCACertificatePath you need hash symlinks
+ # to point to the certificate files. Use the provided
+ # Makefile to update the hash symlinks after changes.
+ #SSLCACertificatePath /etc/ssl/certs/
+ #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
+
+ # Certificate Revocation Lists (CRL):
+ # Set the CA revocation path where to find CA CRLs for client
+ # authentication or alternatively one huge file containing all
+ # of them (file must be PEM encoded)
+ # Note: Inside SSLCARevocationPath you need hash symlinks
+ # to point to the certificate files. Use the provided
+ # Makefile to update the hash symlinks after changes.
+ #SSLCARevocationPath /etc/apache2/ssl.crl/
+ #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl
+
+ # Client Authentication (Type):
+ # Client certificate verification type and depth. Types are
+ # none, optional, require and optional_no_ca. Depth is a
+ # number which specifies how deeply to verify the certificate
+ # issuer chain before deciding the certificate is not valid.
+ #SSLVerifyClient require
+ #SSLVerifyDepth 10
+
+ # SSL Engine Options:
+ # Set various options for the SSL engine.
+ # o FakeBasicAuth:
+ # Translate the client X.509 into a Basic Authorisation. This means that
+ # the standard Auth/DBMAuth methods can be used for access control. The
+ # user name is the `one line' version of the client's X.509 certificate.
+ # Note that no password is obtained from the user. Every entry in the user
+ # file needs this password: `xxj31ZMTZzkVA'.
+ # o ExportCertData:
+ # This exports two additional environment variables: SSL_CLIENT_CERT and
+ # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
+ # server (always existing) and the client (only existing when client
+ # authentication is used). This can be used to import the certificates
+ # into CGI scripts.
+ # o StdEnvVars:
+ # This exports the standard SSL/TLS related `SSL_*' environment variables.
+ # Per default this exportation is switched off for performance reasons,
+ # because the extraction step is an expensive operation and is usually
+ # useless for serving static content. So one usually enables the
+ # exportation for CGI and SSI requests only.
+ # o OptRenegotiate:
+ # This enables optimized SSL connection renegotiation handling when SSL
+ # directives are used in per-directory context.
+ #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
+ <FilesMatch "\.(cgi|shtml|phtml|php)$">
+ SSLOptions +StdEnvVars
+ </FilesMatch>
+ <Directory /usr/lib/cgi-bin>
+ SSLOptions +StdEnvVars
+ </Directory>
+
+ # SSL Protocol Adjustments:
+ # The safe and default but still SSL/TLS standard compliant shutdown
+ # approach is that mod_ssl sends the close notify alert but doesn't wait for
+ # the close notify alert from client. When you need a different shutdown
+ # approach you can use one of the following variables:
+ # o ssl-unclean-shutdown:
+ # This forces an unclean shutdown when the connection is closed, i.e. no
+ # SSL close notify alert is send or allowed to received. This violates
+ # the SSL/TLS standard but is needed for some brain-dead browsers. Use
+ # this when you receive I/O errors because of the standard approach where
+ # mod_ssl sends the close notify alert.
+ # o ssl-accurate-shutdown:
+ # This forces an accurate shutdown when the connection is closed, i.e. a
+ # SSL close notify alert is send and mod_ssl waits for the close notify
+ # alert of the client. This is 100% SSL/TLS standard compliant, but in
+ # practice often causes hanging connections with brain-dead browsers. Use
+ # this only for browsers where you know that their SSL implementation
+ # works correctly.
+ # Notice: Most problems of broken clients are also related to the HTTP
+ # keep-alive facility, so you usually additionally want to disable
+ # keep-alive for those clients, too. Use variable "nokeepalive" for this.
+ # Similarly, one has to force some clients to use HTTP/1.0 to workaround
+ # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
+ # "force-response-1.0" for this.
+ BrowserMatch "MSIE [2-6]" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+ # MSIE 7 and newer should be able to use keepalive
+ BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
+
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/apache-conf-files/passing/example.conf b/certbot-apache/tests/apache-conf-files/passing/example.conf
new file mode 100644
index 000000000..60bdeead6
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/example.conf
@@ -0,0 +1,32 @@
+<VirtualHost *:80>
+ # The ServerName directive sets the request scheme, hostname and port that
+ # the server uses to identify itself. This is used when creating
+ # redirection URLs. In the context of virtual hosts, the ServerName
+ # specifies what hostname must appear in the request's Host: header to
+ # match this virtual host. For the default virtual host (this file) this
+ # value is not decisive as it is used as a last resort host regardless.
+ # However, you must set it for any further virtual host explicitly.
+ ServerName www.example.com
+ ServerAlias example.com
+
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
+ # error, crit, alert, emerg.
+ # It is also possible to configure the loglevel for particular
+ # modules, e.g.
+ #LogLevel info ssl:warn
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ # For most configuration files from conf-available/, which are
+ # enabled or disabled at a global level, it is possible to
+ # include a line for only one particular virtual host. For example the
+ # following line enables the CGI configuration for this host only
+ # after it has been globally disabled with "a2disconf".
+ #Include conf-available/serve-cgi-bin.conf
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/apache-conf-files/passing/finalize-1243.apache2.conf.txt b/certbot-apache/tests/apache-conf-files/passing/finalize-1243.apache2.conf.txt
new file mode 100644
index 000000000..73dc64223
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/finalize-1243.apache2.conf.txt
@@ -0,0 +1,222 @@
+# This is the main Apache server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See http://httpd.apache.org/docs/2.4/ for detailed information about
+# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
+# hints.
+#
+#
+# Summary of how the Apache 2 configuration works in Debian:
+# The Apache 2 web server configuration in Debian is quite different to
+# upstream's suggested way to configure the web server. This is because Debian's
+# default Apache2 installation attempts to make adding and removing modules,
+# virtual hosts, and extra configuration directives as flexible as possible, in
+# order to make automating the changes and administering the server as easy as
+# possible.
+
+# It is split into several files forming the configuration hierarchy outlined
+# below, all located in the /etc/apache2/ directory:
+#
+# /etc/apache2/
+# |-- apache2.conf
+# | `-- ports.conf
+# |-- mods-enabled
+# | |-- *.load
+# | `-- *.conf
+# |-- conf-enabled
+# | `-- *.conf
+# `-- sites-enabled
+# `-- *.conf
+#
+#
+# * apache2.conf is the main configuration file (this file). It puts the pieces
+# together by including all remaining configuration files when starting up the
+# web server.
+#
+# * ports.conf is always included from the main configuration file. It is
+# supposed to determine listening ports for incoming connections which can be
+# customized anytime.
+#
+# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
+# directories contain particular configuration snippets which manage modules,
+# global configuration fragments, or virtual host configurations,
+# respectively.
+#
+# They are activated by symlinking available configuration files from their
+# respective *-available/ counterparts. These should be managed by using our
+# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
+# their respective man pages for detailed information.
+#
+# * The binary is called apache2. Due to the use of environment variables, in
+# the default configuration, apache2 needs to be started/stopped with
+# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
+# work with the default configuration.
+
+
+# Global configuration
+#
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# NOTE! If you intend to place this on an NFS (or otherwise network)
+# mounted filesystem then please read the Mutex documentation (available
+# at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>);
+# you will save yourself a lot of trouble.
+#
+# Do NOT add a slash at the end of the directory path.
+#
+#ServerRoot "/etc/apache2"
+
+#
+# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
+#
+Mutex file:${APACHE_LOCK_DIR} default
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+# This needs to be set in /etc/apache2/envvars
+#
+PidFile ${APACHE_PID_FILE}
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 300
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive On
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 5
+
+
+# These need to be set in /etc/apache2/envvars
+User ${APACHE_RUN_USER}
+Group ${APACHE_RUN_GROUP}
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog ${APACHE_LOG_DIR}/error.log
+
+#
+# LogLevel: Control the severity of messages logged to the error_log.
+# Available values: trace8, ..., trace1, debug, info, notice, warn,
+# error, crit, alert, emerg.
+# It is also possible to configure the log level for particular modules, e.g.
+# "LogLevel info ssl:warn"
+#
+LogLevel warn
+
+# Include module configuration:
+IncludeOptional mods-enabled/*.load
+IncludeOptional mods-enabled/*.conf
+
+# Include list of ports to listen on
+Include ports.conf
+
+
+# Sets the default security model of the Apache2 HTTPD server. It does
+# not allow access to the root filesystem outside of /usr/share and /var/www.
+# The former is used by web applications packaged in Debian,
+# the latter may be used for local directories served by the web server. If
+# your system is serving content from a sub-directory in /srv you must allow
+# access here, or in any related virtual host.
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+ Require all denied
+</Directory>
+
+<Directory /usr/share>
+ AllowOverride None
+ Require all granted
+</Directory>
+
+<Directory /var/www/>
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+</Directory>
+
+#<Directory /srv/>
+# Options Indexes FollowSymLinks
+# AllowOverride None
+# Require all granted
+#</Directory>
+
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives. See also the AllowOverride
+# directive.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<FilesMatch "^\.ht">
+ Require all denied
+</FilesMatch>
+
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive.
+#
+# These deviate from the Common Log Format definitions in that they use %O
+# (the actual bytes sent including headers) instead of %b (the size of the
+# requested file), because the latter makes it impossible to detect partial
+# requests.
+#
+# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.
+# Use mod_remoteip instead.
+#
+#LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
+LogFormat "%t \"%r\" %>s %O \"%{User-Agent}i\"" vhost_combined
+
+#LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
+#LogFormat "%h %l %u %t \"%r\" %>s %O" common
+LogFormat "- %t \"%r\" %>s %b" noip
+
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+# Include of directories ignores editors' and dpkg's backup files,
+# see README.Debian for details.
+
+# Include generic snippets of statements
+IncludeOptional conf-enabled/*.conf
+
+# Include the virtual host configurations:
+#IncludeOptional sites-enabled/*.conf
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/apache-conf-files/passing/finalize-1243.conf b/certbot-apache/tests/apache-conf-files/passing/finalize-1243.conf
new file mode 100644
index 000000000..dbfae3765
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/finalize-1243.conf
@@ -0,0 +1,67 @@
+#LoadModule ssl_module modules/mod_ssl.so
+
+Listen 4443
+<VirtualHost *:4443>
+ # The ServerName directive sets the request scheme, hostname and port that
+ # the server uses to identify itself. This is used when creating
+ # redirection URLs. In the context of virtual hosts, the ServerName
+ # specifies what hostname must appear in the request's Host: header to
+ # match this virtual host. For the default virtual host (this file) this
+ # value is not decisive as it is used as a last resort host regardless.
+ # However, you must set it for any further virtual host explicitly.
+ ServerName www.eiserneketten.de
+
+ SSLEngine on
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
+ # error, crit, alert, emerg.
+ # It is also possible to configure the loglevel for particular
+ # modules, e.g.
+ #LogLevel info ssl:warn
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log noip
+
+ # For most configuration files from conf-available/, which are
+ # enabled or disabled at a global level, it is possible to
+ # include a line for only one particular virtual host. For example the
+ # following line enables the CGI configuration for this host only
+ # after it has been globally disabled with "a2disconf".
+ #Include conf-available/serve-cgi-bin.conf
+ <Directory />
+ Options FollowSymLinks
+ AllowOverride None
+ Order Deny,Allow
+ #Deny from All
+ </Directory>
+
+ Alias / /eiserneketten/pages/eiserneketten.html
+SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
+SSLCertificateChainFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+Include /etc/letsencrypt/options-ssl-apache.conf
+
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
+
+#
+# Directives to allow use of AWStats as a CGI
+#
+Alias /awstatsclasses "/usr/local/awstats/wwwroot/classes/"
+Alias /awstatscss "/usr/local/awstats/wwwroot/css/"
+Alias /awstatsicons "/usr/local/awstats/wwwroot/icon/"
+ScriptAlias /awstats/ "/usr/local/awstats/wwwroot/cgi-bin/"
+
+#
+# This is to permit URL access to scripts/files in AWStats directory.
+#
+<Directory "/usr/local/awstats/wwwroot">
+ Options None
+ AllowOverride None
+ Order allow,deny
+ Allow from all
+</Directory>
+
diff --git a/certbot-apache/tests/apache-conf-files/passing/graphite-quote-1934.conf b/certbot-apache/tests/apache-conf-files/passing/graphite-quote-1934.conf
new file mode 100644
index 000000000..f257dd9a8
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/graphite-quote-1934.conf
@@ -0,0 +1,21 @@
+<VirtualHost *:80>
+
+ WSGIDaemonProcess _graphite processes=5 threads=5 display-name='%{GROUP}' inactivity-timeout=120 user=www-data group=www-data
+ WSGIProcessGroup _graphite
+ WSGIImportScript /usr/share/graphite-web/graphite.wsgi process-group=_graphite application-group=%{GLOBAL}
+ WSGIScriptAlias / /usr/share/graphite-web/graphite.wsgi
+
+ Alias /content/ /usr/share/graphite-web/static/
+ <Location "/content/">
+ SetHandler None
+ </Location>
+
+ ErrorLog ${APACHE_LOG_DIR}/graphite-web_error.log
+
+ # Possible values include: debug, info, notice, warn, error, crit,
+ # alert, emerg.
+ LogLevel warn
+
+ CustomLog ${APACHE_LOG_DIR}/graphite-web_access.log combined
+
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/ipv6-1143.conf b/certbot-apache/tests/apache-conf-files/passing/ipv6-1143.conf
new file mode 100644
index 000000000..ad988dc05
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/ipv6-1143.conf
@@ -0,0 +1,9 @@
+<VirtualHost *:80 [::]:80>
+DocumentRoot /tmp
+ServerName example.com
+ServerAlias www.example.com
+CustomLog ${APACHE_LOG_DIR}/example.log combined
+<Directory "/tmp">
+ AllowOverride All
+</Directory>
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/ipv6-1143b.conf b/certbot-apache/tests/apache-conf-files/passing/ipv6-1143b.conf
new file mode 100644
index 000000000..e2b4fd3da
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/ipv6-1143b.conf
@@ -0,0 +1,18 @@
+<VirtualHost *:443 [::]:443>
+DocumentRoot /tmp
+ServerName example.com
+ServerAlias www.example.com
+CustomLog ${APACHE_LOG_DIR}/example.log combined
+<Directory "/tmp">
+ AllowOverride All
+</Directory>
+
+ SSLEngine on
+
+ SSLHonorCipherOrder On
+ SSLProtocol all -SSLv2 -SSLv3
+ SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH +aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
+
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+ SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/ipv6-1143c.conf b/certbot-apache/tests/apache-conf-files/passing/ipv6-1143c.conf
new file mode 100644
index 000000000..f2d2ecbea
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/ipv6-1143c.conf
@@ -0,0 +1,9 @@
+<VirtualHost [::]:80 *:80>
+DocumentRoot /tmp
+ServerName example.com
+ServerAlias www.example.com
+CustomLog ${APACHE_LOG_DIR}/example.log combined
+<Directory "/tmp">
+ AllowOverride All
+</Directory>
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/ipv6-1143d.conf b/certbot-apache/tests/apache-conf-files/passing/ipv6-1143d.conf
new file mode 100644
index 000000000..f5b7a2b45
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/ipv6-1143d.conf
@@ -0,0 +1,18 @@
+<VirtualHost [::]:443 *:443>
+DocumentRoot /tmp
+ServerName example.com
+ServerAlias www.example.com
+CustomLog ${APACHE_LOG_DIR}/example.log combined
+<Directory "/tmp">
+ AllowOverride All
+</Directory>
+
+ SSLEngine on
+
+ SSLHonorCipherOrder On
+ SSLProtocol all -SSLv2 -SSLv3
+ SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH +aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
+
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+ SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/missing-quote-1724.conf b/certbot-apache/tests/apache-conf-files/passing/missing-quote-1724.conf
new file mode 100644
index 000000000..7d97b23d0
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/missing-quote-1724.conf
@@ -0,0 +1,52 @@
+<VirtualHost *:443>
+ ServerAdmin webmaster@localhost
+ ServerAlias www.example.com
+ ServerName example.com
+ DocumentRoot /var/www/example.com/www/
+ SSLEngine on
+
+ SSLProtocol all -SSLv2 -SSLv3
+ SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRS$
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+ SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
+
+ <Directory />
+ Options FollowSymLinks
+ AllowOverride All
+ </Directory>
+ <Directory /var/www/example.com/www>
+ Options Indexes FollowSymLinks MultiViews
+ AllowOverride All
+ Order allow,deny
+ allow from all
+ # This directive allows us to have apache2's default start page
+ # in /apache2-default/, but still have / go to the right place
+ </Directory>
+
+ ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+ <Directory "/usr/lib/cgi-bin">
+ AllowOverride None
+ Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ ErrorLog /var/log/apache2/error.log
+
+ # Possible values include: debug, info, notice, warn, error, crit,
+ # alert, emerg.
+ LogLevel warn
+
+ CustomLog /var/log/apache2/access.log combined
+ ServerSignature On
+
+ Alias /apache_doc/ "/usr/share/doc/"
+ <Directory "/usr/share/doc/">
+ Options Indexes MultiViews FollowSymLinks
+ AllowOverride None
+ Order deny,allow
+ Deny from all
+ Allow from 127.0.0.0/255.0.0.0 ::1/128
+ </Directory>
+
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/modmacro-1385.conf b/certbot-apache/tests/apache-conf-files/passing/modmacro-1385.conf
new file mode 100644
index 000000000..d327c9421
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/modmacro-1385.conf
@@ -0,0 +1,33 @@
+<Macro Vhost $host $port $dir>
+ <VirtualHost *:$port>
+ # The ServerName directive sets the request scheme, hostname and port that
+ # the server uses to identify itself. This is used when creating
+ # redirection URLs. In the context of virtual hosts, the ServerName
+ # specifies what hostname must appear in the request's Host: header to
+ # match this virtual host. For the default virtual host (this file) this
+ # value is not decisive as it is used as a last resort host regardless.
+ # However, you must set it for any further virtual host explicitly.
+ ServerName $host
+
+ ServerAdmin webmaster@localhost
+ DocumentRoot $dir
+
+ # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
+ # error, crit, alert, emerg.
+ # It is also possible to configure the loglevel for particular
+ # modules, e.g.
+ #LogLevel info ssl:warn
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ # For most configuration files from conf-available/, which are
+ # enabled or disabled at a global level, it is possible to
+ # include a line for only one particular virtual host. For example the
+ # following line enables the CGI configuration for this host only
+ # after it has been globally disabled with "a2disconf".
+ #Include conf-available/serve-cgi-bin.conf
+ </VirtualHost>
+</Macro>
+Use Vhost goxogle.com 80 /var/www/goxogle/
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/apache-conf-files/passing/owncloud-1264.conf b/certbot-apache/tests/apache-conf-files/passing/owncloud-1264.conf
new file mode 100644
index 000000000..d0ac81fa3
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/owncloud-1264.conf
@@ -0,0 +1,13 @@
+Alias /owncloud /usr/share/owncloud
+
+<Directory /usr/share/owncloud/>
+ Options +FollowSymLinks
+ AllowOverride All
+ <IfVersion < 2.3>
+ order allow,deny
+ allow from all
+ </IfVersion>
+ <IfVersion >= 2.3>
+ Require all granted
+ </IfVersion>
+</Directory>
diff --git a/certbot-apache/tests/apache-conf-files/passing/rewrite-quote-1960.conf b/certbot-apache/tests/apache-conf-files/passing/rewrite-quote-1960.conf
new file mode 100644
index 000000000..26214e7b0
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/rewrite-quote-1960.conf
@@ -0,0 +1,7 @@
+<IfModule mod_rewrite.c>
+ RewriteEngine On
+ RewriteCond %{REQUEST_URI} ^.*(,|;|:|<|>|">|"<|/|\\\.\.\\).* [NC,OR]
+ RewriteCond %{REQUEST_URI} ^.*(\=|\@|\[|\]|\^|\`|\{|\}|\~).* [NC,OR]
+ RewriteCond %{REQUEST_URI} ^.*(\'|%0A|%0D|%27|%3C|%3E|%00).* [NC]
+ RewriteRule ^(.*)$ - [F,L]
+</IfModule>
diff --git a/certbot-apache/tests/apache-conf-files/passing/roundcube-1222.conf b/certbot-apache/tests/apache-conf-files/passing/roundcube-1222.conf
new file mode 100644
index 000000000..72ced7fb3
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/roundcube-1222.conf
@@ -0,0 +1,61 @@
+# Those aliases do not work properly with several hosts on your apache server
+# Uncomment them to use it or adapt them to your configuration
+# Alias /roundcube/program/js/tiny_mce/ /usr/share/tinymce/www/
+# Alias /roundcube /var/lib/roundcube
+
+# Access to tinymce files
+<Directory "/usr/share/tinymce/www/">
+ Options Indexes MultiViews FollowSymLinks
+ AllowOverride None
+ <IfVersion >= 2.3>
+ Require all granted
+ </IfVersion>
+ <IfVersion < 2.3>
+ Order allow,deny
+ Allow from all
+ </IfVersion>
+</Directory>
+
+<Directory /var/lib/roundcube/>
+ Options +FollowSymLinks
+ # This is needed to parse /var/lib/roundcube/.htaccess. See its
+ # content before setting AllowOverride to None.
+ AllowOverride All
+ <IfVersion >= 2.3>
+ Require all granted
+ </IfVersion>
+ <IfVersion < 2.3>
+ Order allow,deny
+ Allow from all
+ </IfVersion>
+</Directory>
+
+# Protecting basic directories:
+<Directory /var/lib/roundcube/config>
+ Options -FollowSymLinks
+ AllowOverride None
+</Directory>
+
+<Directory /var/lib/roundcube/temp>
+ Options -FollowSymLinks
+ AllowOverride None
+ <IfVersion >= 2.3>
+ Require all denied
+ </IfVersion>
+ <IfVersion < 2.3>
+ Order allow,deny
+ Deny from all
+ </IfVersion>
+</Directory>
+
+<Directory /var/lib/roundcube/logs>
+ Options -FollowSymLinks
+ AllowOverride None
+ <IfVersion >= 2.3>
+ Require all denied
+ </IfVersion>
+ <IfVersion < 2.3>
+ Order allow,deny
+ Deny from all
+ </IfVersion>
+</Directory>
diff --git a/certbot-apache/tests/apache-conf-files/passing/section-continuations-2525.conf b/certbot-apache/tests/apache-conf-files/passing/section-continuations-2525.conf
new file mode 100644
index 000000000..8f65e4773
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/section-continuations-2525.conf
@@ -0,0 +1,284 @@
+
+NameVirtualHost 0.0.0.0:7080
+NameVirtualHost [00000:000:000:000::0]:7080
+NameVirtualHost 0.0.0.0:7080
+
+NameVirtualHost 127.0.0.1:7080
+NameVirtualHost 0.0.0.0:7081
+NameVirtualHost [0000:000:000:000::2]:7081
+NameVirtualHost 0.0.0.0:7081
+
+NameVirtualHost 127.0.0.1:7081
+
+ServerName "example.com"
+ServerAdmin "srv@example.com"
+
+DocumentRoot /tmp
+
+<IfModule mod_logio.c>
+ LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" plesklog
+</IfModule>
+<IfModule !mod_logio.c>
+ LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" plesklog
+</IfModule>
+
+TraceEnable off
+
+ServerTokens ProductOnly
+
+<Directory "/var/www/vhosts">
+ AllowOverride "All"
+ Options SymLinksIfOwnerMatch
+ Order allow,deny
+ Allow from all
+
+ <IfModule sapi_apache2.c>
+ php_admin_flag engine off
+ </IfModule>
+
+ <IfModule mod_php5.c>
+ php_admin_flag engine off
+ </IfModule>
+
+</Directory>
+
+<Directory "/usr/lib/mailman">
+ AllowOverride "All"
+ Options SymLinksIfOwnerMatch
+ Order allow,deny
+ Allow from all
+ <IfModule sapi_apache2.c>
+ php_admin_flag engine off
+ </IfModule>
+ <IfModule mod_php5.c>
+ php_admin_flag engine off
+ </IfModule>
+</Directory>
+
+<IfModule mod_headers.c>
+ Header add X-Powered-By PleskLin
+</IfModule>
+
+<IfModule mod_security2.c>
+ SecRuleEngine DetectionOnly
+ SecRequestBodyAccess On
+ SecRequestBodyLimit 134217728
+ SecResponseBodyAccess Off
+ SecResponseBodyLimit 524288
+ SecAuditEngine On
+ SecAuditLog "/var/log/modsec_audit.log"
+ SecAuditLogType serial
+</IfModule>
+
+#Include "/etc/httpd/conf/plesk.conf.d/ip_default/*.conf"
+
+<VirtualHost \
+ 0.0.0.0:7080 \
+ [00000:000:000:0000::2]:7080 \
+ 0.0.0.0:7080 \
+ 127.0.0.1:7080 \
+ >
+ ServerName "default"
+ UseCanonicalName Off
+ DocumentRoot /tmp
+ ScriptAlias "/cgi-bin/" "/var/www/vhosts/default/cgi-bin"
+
+ <IfModule mod_ssl.c>
+ SSLEngine off
+ </IfModule>
+
+ <Directory "/var/www/vhosts/default/cgi-bin">
+ AllowOverride None
+ Options None
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ <Directory "/var/www/vhosts/default/htdocs">
+
+ <IfModule sapi_apache2.c>
+ php_admin_flag engine on
+ </IfModule>
+
+ <IfModule mod_php5.c>
+ php_admin_flag engine on
+ </IfModule>
+
+ </Directory>
+
+</VirtualHost>
+
+<IfModule mod_ssl.c>
+
+ <VirtualHost \
+ 0.0.0.0:7081 \
+ 127.0.0.1:7081 \
+ >
+ ServerName "default-0_0_0_0"
+ UseCanonicalName Off
+ DocumentRoot /tmp
+ ScriptAlias "/cgi-bin/" "/var/www/vhosts/default/cgi-bin"
+
+ SSLEngine on
+ SSLVerifyClient none
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+
+ <Directory "/var/www/vhosts/default/cgi-bin">
+ AllowOverride None
+ Options None
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ <Directory "/var/www/vhosts/default/htdocs">
+
+ <IfModule sapi_apache2.c>
+ php_admin_flag engine on
+ </IfModule>
+
+ <IfModule mod_php5.c>
+ php_admin_flag engine on
+ </IfModule>
+
+ </Directory>
+
+ </VirtualHost>
+ <VirtualHost \
+ [00000:000:000:000::2]:7081 \
+ 127.0.0.1:7081 \
+ >
+ ServerName "default-0000_000_000_00000__2"
+ UseCanonicalName Off
+ DocumentRoot /tmp
+ ScriptAlias "/cgi-bin/" "/var/www/vhosts/default/cgi-bin"
+
+ SSLEngine on
+ SSLVerifyClient none
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+
+ <Directory "/var/www/vhosts/default/cgi-bin">
+ AllowOverride None
+ Options None
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ <Directory "/var/www/vhosts/default/htdocs">
+
+ <IfModule sapi_apache2.c>
+ php_admin_flag engine on
+ </IfModule>
+
+ <IfModule mod_php5.c>
+ php_admin_flag engine on
+ </IfModule>
+
+ </Directory>
+
+ </VirtualHost>
+ <VirtualHost \
+ 0.0.0.0:7081 \
+ 127.0.0.1:7081 \
+ >
+ ServerName "default-0_0_0_0"
+ UseCanonicalName Off
+ DocumentRoot /tmp
+ ScriptAlias "/cgi-bin/" "/var/www/vhosts/default/cgi-bin"
+
+ SSLEngine on
+ SSLVerifyClient none
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+
+ #SSLCACertificateFile "/usr/local/psa/var/certificates/cert-nLy6Z1"
+
+ <Directory "/var/www/vhosts/default/cgi-bin">
+ AllowOverride None
+ Options None
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ <Directory "/var/www/vhosts/default/htdocs">
+
+ <IfModule sapi_apache2.c>
+ php_admin_flag engine on
+ </IfModule>
+
+ <IfModule mod_php5.c>
+ php_admin_flag engine on
+ </IfModule>
+
+ </Directory>
+
+ </VirtualHost>
+
+</IfModule>
+
+<VirtualHost \
+ 0.0.0.0:7080 \
+ [0000:000:000:000::2]:7080 \
+ 0.0.0.0:7080 \
+ 127.0.0.1:7080 \
+ >
+ 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/"
+
+ <IfModule mod_ssl.c>
+ SSLEngine off
+ </IfModule>
+
+ <Directory "/var/lib/mailman/archives/">
+ Options FollowSymLinks
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+</VirtualHost>
+
+<IfModule mod_ssl.c>
+ <VirtualHost \
+ 0.0.0.0:7081 \
+ [00000:000:000:0000::2]:7081 \
+ 0.0.0.0:7081 \
+ 127.0.0.1:7081 \
+ >
+ 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 /etc/ssl/certs/ssl-cert-snakeoil.pem
+
+ <Directory "/var/lib/mailman/archives/">
+ Options FollowSymLinks
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ </VirtualHost>
+</IfModule>
+
+<IfModule mod_rpaf.c>
+ RPAFproxy_ips 0.0.0.0 [00000:000:000:00000::2] 0.0.0.0
+</IfModule>
+<IfModule mod_rpaf-2.0.c>
+ RPAFproxy_ips 0.0.0.0 [0000:000:000:0000::2] 0.0.0.0
+</IfModule>
+<IfModule mod_remoteip.c>
+ RemoteIPInternalProxy 0.0.0.0 [0000:000:000:0000::2] 0.0.0.0
+ RemoteIPHeader X-Forwarded-For
+</IfModule>
diff --git a/certbot-apache/tests/apache-conf-files/passing/section-empty-continuations-2731.conf b/certbot-apache/tests/apache-conf-files/passing/section-empty-continuations-2731.conf
new file mode 100644
index 000000000..3f2f96965
--- /dev/null
+++ b/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"
+
+<IfModule mod_logio.c>
+ LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" plesklog
+</IfModule>
+<IfModule !mod_logio.c>
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" plesklog
+</IfModule>
+
+ TraceEnable off
+
+ServerTokens ProductOnly
+
+<Directory "/var/www/vhosts">
+ AllowOverride "All"
+ Options SymLinksIfOwnerMatch
+ Order allow,deny
+ Allow from all
+
+<IfModule sapi_apache2.c>
+php_admin_flag engine off
+</IfModule>
+
+<IfModule mod_php5.c>
+php_admin_flag engine off
+</IfModule>
+
+</Directory>
+
+<Directory "/usr/lib/mailman">
+ AllowOverride All
+ Options SymLinksIfOwnerMatch
+ Order allow,deny
+ Allow from all
+ <IfModule sapi_apache2.c>
+ php_admin_flag engine off
+ </IfModule>
+ <IfModule mod_php5.c>
+ php_admin_flag engine off
+ </IfModule>
+</Directory>
+
+<IfModule mod_headers.c>
+ Header add X-Powered-By PleskLin
+</IfModule>
+
+<IfModule mod_jk.c>
+ JkWorkersFile "/etc/httpd/conf/workers.properties"
+ JkLogFile /var/log/httpd/mod_jk.log
+ JkLogLevel info
+</IfModule>
+
+#Include "/etc/httpd/conf/plesk.conf.d/ip_default/*.conf"
+
+
+ <VirtualHost \
+ 192.168.100.218:80 \
+ 10.128.178.192:80 \
+ \
+ >
+ ServerName "default"
+ UseCanonicalName Off
+ DocumentRoot "/tmp"
+ ScriptAlias /cgi-bin/ "/var/www/vhosts/default/cgi-bin"
+
+
+ <IfModule mod_ssl.c>
+ SSLEngine off
+ </IfModule>
+
+ <Directory "/var/www/vhosts/default/cgi-bin">
+ AllowOverride None
+ Options None
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ <Directory /var/www/vhosts/default/htdocs>
+
+<IfModule sapi_apache2.c>
+php_admin_flag engine on
+</IfModule>
+
+<IfModule mod_php5.c>
+php_admin_flag engine on
+</IfModule>
+
+ </Directory>
+
+ </VirtualHost>
+
+<IfModule mod_ssl.c>
+
+ <VirtualHost \
+ 192.168.100.218:443 \
+ \
+ >
+ 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"
+
+ <Directory "/var/www/vhosts/default/cgi-bin">
+ AllowOverride None
+ Options None
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ <Directory /var/www/vhosts/default/htdocs>
+
+<IfModule sapi_apache2.c>
+php_admin_flag engine on
+</IfModule>
+
+<IfModule mod_php5.c>
+php_admin_flag engine on
+</IfModule>
+
+ </Directory>
+
+ </VirtualHost>
+ <VirtualHost \
+ 10.128.178.192:443 \
+ \
+ >
+ 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"
+
+
+ <Directory "/var/www/vhosts/default/cgi-bin">
+ AllowOverride None
+ Options None
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ <Directory /var/www/vhosts/default/htdocs>
+
+<IfModule sapi_apache2.c>
+php_admin_flag engine on
+</IfModule>
+
+<IfModule mod_php5.c>
+php_admin_flag engine on
+</IfModule>
+
+ </Directory>
+
+ </VirtualHost>
+
+</IfModule>
+
+
+<VirtualHost \
+ 192.168.100.218:80 \
+ 10.128.178.192:80 \
+ \
+>
+ 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/"
+
+ <IfModule mod_ssl.c>
+ SSLEngine off
+ </IfModule>
+
+
+ <Directory /var/lib/mailman/archives/>
+ Options FollowSymLinks
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ </VirtualHost>
+
+<IfModule mod_ssl.c>
+<VirtualHost \
+ 192.168.100.218:443 \
+ 10.128.178.192:443 \
+ \
+>
+ 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"
+
+
+ <Directory /var/lib/mailman/archives/>
+ Options FollowSymLinks
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ </VirtualHost>
+</IfModule>
+
+<IfModule mod_rpaf.c>
+ RPAFproxy_ips 192.168.100.218 10.128.178.192
+</IfModule>
+<IfModule mod_rpaf-2.0.c>
+ RPAFproxy_ips 192.168.100.218 10.128.178.192
+</IfModule>
diff --git a/certbot-apache/tests/apache-conf-files/passing/semacode-1598.conf b/certbot-apache/tests/apache-conf-files/passing/semacode-1598.conf
new file mode 100644
index 000000000..89e2fb25c
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/semacode-1598.conf
@@ -0,0 +1,44 @@
+<VirtualHost *:80>
+ ServerName semacode.com
+ ServerAlias www.semacode.com
+ DocumentRoot /tmp/
+ TransferLog /tmp/access
+ ErrorLog /tmp/error
+ Redirect /posts/rss http://semacode.com/feed
+ Redirect permanent /weblog http://semacode.com/blog
+
+#ProxyPreserveHost On
+# ProxyPass /past http://old.semacode.com
+ #ProxyPassReverse /past http://old.semacode.com
+#<proxy>
+ # Order allow,deny
+ #Allow from all
+#</proxy>
+
+ Redirect /stylesheets/inside.css http://old.semacode.com/stylesheets/inside.css
+ RedirectMatch /images/portal/(.*) http://old.semacode.com/images/portal/$1
+ Redirect /images/invisible.gif http://old.semacode.com/images/invisible.gif
+ RedirectMatch /javascripts/(.*) http://old.semacode.com/javascripts/$1
+
+ RewriteEngine on
+ RewriteRule ^/past/(.*) http://old.semacode.com/past/$1 [L,P]
+ RewriteCond %{HTTP_HOST} !^semacode\.com$ [NC]
+ RewriteCond %{HTTP_HOST} !^$
+ RewriteRule ^/(.*) http://semacode.com/$1 [L,R]
+
+</VirtualHost>
+
+
+<VirtualHost *:80>
+ ServerName old.semacode.com
+ ServerAlias www.old.semacode.com
+ DocumentRoot /home/simon/semacode-server/semacode/website/trunk/public
+ TransferLog /tmp/access-old
+ ErrorLog /tmp/error-old
+ <Directory "/home/simon/semacode-server/semacode/website/trunk/public">
+ Options FollowSymLinks
+ AllowOverride None
+ Order allow,deny
+ Allow from all
+ </Directory>
+</VirtualHost>
diff --git a/certbot-apache/tests/apache-conf-files/passing/sslrequire-wordlist-1827.htaccess b/certbot-apache/tests/apache-conf-files/passing/sslrequire-wordlist-1827.htaccess
new file mode 100644
index 000000000..1c06d5497
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/sslrequire-wordlist-1827.htaccess
@@ -0,0 +1 @@
+SSLRequire %{SSL_CLIENT_S_DN_CN} in {"foo@bar.com", "bar@foo.com"}
diff --git a/certbot-apache/tests/apache-conf-files/passing/two-blocks-one-line-1693.conf b/certbot-apache/tests/apache-conf-files/passing/two-blocks-one-line-1693.conf
new file mode 100644
index 000000000..5d3cef423
--- /dev/null
+++ b/certbot-apache/tests/apache-conf-files/passing/two-blocks-one-line-1693.conf
@@ -0,0 +1,28 @@
+<IfModule mod_ssl.c>
+ <VirtualHost *:443>
+ ServerAdmin info@somethingnewentertainment.com
+ ServerName somethingnewentertainment.com
+ DocumentRoot /var/www/html
+
+ ErrorLog /var/log/apache2/error.log
+ CustomLog /var/log/apache2/access.log combined
+
+ SSLEngine on
+ SSLProtocol all -SSLv2 -SSLv3
+ SSLHonorCipherOrder on
+ SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EEC DH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRS A RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"
+
+ SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
+ SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
+
+ <FilesMatch "\.(cgi|shtml|phtml|php)$">
+ SSLOptions +StdEnvVars
+ </FilesMatch>
+ <Directory /usr/lib/cgi-bin>
+ SSLOptions +StdEnvVars
+ </Directory>
+ BrowserMatch "MSIE [2-6]" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+ BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
+ </VirtualHost> </IfModule>
diff --git a/certbot-apache/tests/autohsts_test.py b/certbot-apache/tests/autohsts_test.py
new file mode 100644
index 000000000..c9901ecdb
--- /dev/null
+++ b/certbot-apache/tests/autohsts_test.py
@@ -0,0 +1,188 @@
+# pylint: disable=too-many-lines
+"""Test for certbot_apache._internal.configurator AutoHSTS functionality"""
+import re
+import unittest
+
+import mock
+import six # pylint: disable=unused-import # six is used in mock.patch()
+
+from certbot import errors
+from certbot_apache._internal import constants
+import util
+
+
+class AutoHSTSTest(util.ApacheTest):
+ """Tests for AutoHSTS feature"""
+ # pylint: disable=protected-access
+
+ def setUp(self): # pylint: disable=arguments-differ
+ super(AutoHSTSTest, self).setUp()
+
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir)
+ self.config.parser.modules.add("headers_module")
+ self.config.parser.modules.add("mod_headers.c")
+ self.config.parser.modules.add("ssl_module")
+ self.config.parser.modules.add("mod_ssl.c")
+
+ self.vh_truth = util.get_vh_truth(
+ self.temp_dir, "debian_apache_2_4/multiple_vhosts")
+
+ def get_autohsts_value(self, vh_path):
+ """ Get value from Strict-Transport-Security header """
+ header_path = self.config.parser.find_dir("Header", None, vh_path)
+ if header_path:
+ pat = '(?:[ "]|^)(strict-transport-security)(?:[ "]|$)'
+ for head in header_path:
+ if re.search(pat, self.config.parser.aug.get(head).lower()):
+ return self.config.parser.aug.get(
+ head.replace("arg[3]", "arg[4]"))
+ return None # pragma: no cover
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.enable_mod")
+ def test_autohsts_enable_headers_mod(self, mock_enable, _restart):
+ self.config.parser.modules.discard("headers_module")
+ self.config.parser.modules.discard("mod_header.c")
+ self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"])
+ self.assertTrue(mock_enable.called)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ def test_autohsts_deploy_already_exists(self, _restart):
+ self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"])
+ self.assertRaises(errors.PluginEnhancementAlreadyPresent,
+ self.config.enable_autohsts,
+ mock.MagicMock(), ["ocspvhost.com"])
+
+ @mock.patch("certbot_apache._internal.constants.AUTOHSTS_FREQ", 0)
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.prepare")
+ def test_autohsts_increase(self, mock_prepare, _mock_restart):
+ self.config._prepared = False
+ maxage = "\"max-age={0}\""
+ initial_val = maxage.format(constants.AUTOHSTS_STEPS[0])
+ inc_val = maxage.format(constants.AUTOHSTS_STEPS[1])
+
+ self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"])
+ # Verify initial value
+ self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path),
+ initial_val)
+ # Increase
+ self.config.update_autohsts(mock.MagicMock())
+ # Verify increased value
+ self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path),
+ inc_val)
+ self.assertTrue(mock_prepare.called)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._autohsts_increase")
+ def test_autohsts_increase_noop(self, mock_increase, _restart):
+ maxage = "\"max-age={0}\""
+ initial_val = maxage.format(constants.AUTOHSTS_STEPS[0])
+ self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"])
+ # Verify initial value
+ self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path),
+ initial_val)
+
+ self.config.update_autohsts(mock.MagicMock())
+ # Freq not patched, so value shouldn't increase
+ self.assertFalse(mock_increase.called)
+
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ @mock.patch("certbot_apache._internal.constants.AUTOHSTS_FREQ", 0)
+ def test_autohsts_increase_no_header(self, _restart):
+ self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"])
+ # Remove the header
+ dir_locs = self.config.parser.find_dir("Header", None,
+ self.vh_truth[7].path)
+ dir_loc = "/".join(dir_locs[0].split("/")[:-1])
+ self.config.parser.aug.remove(dir_loc)
+ self.assertRaises(errors.PluginError,
+ self.config.update_autohsts,
+ mock.MagicMock())
+
+ @mock.patch("certbot_apache._internal.constants.AUTOHSTS_FREQ", 0)
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ def test_autohsts_increase_and_make_permanent(self, _mock_restart):
+ maxage = "\"max-age={0}\""
+ max_val = maxage.format(constants.AUTOHSTS_PERMANENT)
+ mock_lineage = mock.MagicMock()
+ mock_lineage.key_path = "/etc/apache2/ssl/key-certbot_15.pem"
+ self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"])
+ for i in range(len(constants.AUTOHSTS_STEPS)-1):
+ # Ensure that value is not made permanent prematurely
+ self.config.deploy_autohsts(mock_lineage)
+ self.assertNotEqual(self.get_autohsts_value(self.vh_truth[7].path),
+ max_val)
+ self.config.update_autohsts(mock.MagicMock())
+ # Value should match pre-permanent increment step
+ cur_val = maxage.format(constants.AUTOHSTS_STEPS[i+1])
+ self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path),
+ cur_val)
+ # Ensure that the value is raised to max
+ self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path),
+ maxage.format(constants.AUTOHSTS_STEPS[-1]))
+ # Make permanent
+ self.config.deploy_autohsts(mock_lineage)
+ self.assertEqual(self.get_autohsts_value(self.vh_truth[7].path),
+ max_val)
+
+ def test_autohsts_update_noop(self):
+ with mock.patch("time.time") as mock_time:
+ # Time mock is used to make sure that the execution does not
+ # continue when no autohsts entries exist in pluginstorage
+ self.config.update_autohsts(mock.MagicMock())
+ self.assertFalse(mock_time.called)
+
+ def test_autohsts_make_permanent_noop(self):
+ self.config.storage.put = mock.MagicMock()
+ self.config.deploy_autohsts(mock.MagicMock())
+ # Make sure that the execution does not continue when no entries in store
+ self.assertFalse(self.config.storage.put.called)
+
+ @mock.patch("certbot_apache._internal.display_ops.select_vhost")
+ def test_autohsts_no_ssl_vhost(self, mock_select):
+ mock_select.return_value = self.vh_truth[0]
+ with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log:
+ self.assertRaises(errors.PluginError,
+ self.config.enable_autohsts,
+ mock.MagicMock(), "invalid.example.com")
+ self.assertTrue(
+ "Certbot was not able to find SSL" in mock_log.call_args[0][0])
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.add_vhost_id")
+ def test_autohsts_dont_enhance_twice(self, mock_id, _restart):
+ mock_id.return_value = "1234567"
+ self.config.enable_autohsts(mock.MagicMock(),
+ ["ocspvhost.com", "ocspvhost.com"])
+ self.assertEqual(mock_id.call_count, 1)
+
+ def test_autohsts_remove_orphaned(self):
+ # pylint: disable=protected-access
+ self.config._autohsts_fetch_state()
+ self.config._autohsts["orphan_id"] = {"laststep": 0, "timestamp": 0}
+
+ self.config._autohsts_save_state()
+ self.config.update_autohsts(mock.MagicMock())
+ self.assertFalse("orphan_id" in self.config._autohsts)
+ # Make sure it's removed from the pluginstorage file as well
+ self.config._autohsts = None
+ self.config._autohsts_fetch_state()
+ self.assertFalse(self.config._autohsts)
+
+ def test_autohsts_make_permanent_vhost_not_found(self):
+ # pylint: disable=protected-access
+ self.config._autohsts_fetch_state()
+ self.config._autohsts["orphan_id"] = {"laststep": 999, "timestamp": 0}
+ self.config._autohsts_save_state()
+ with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log:
+ self.config.deploy_autohsts(mock.MagicMock())
+ self.assertTrue(mock_log.called)
+ self.assertTrue(
+ "VirtualHost with id orphan_id was not" in mock_log.call_args[0][0])
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/centos6_test.py b/certbot-apache/tests/centos6_test.py
new file mode 100644
index 000000000..15d086600
--- /dev/null
+++ b/certbot-apache/tests/centos6_test.py
@@ -0,0 +1,221 @@
+"""Test for certbot_apache._internal.configurator for CentOS 6 overrides"""
+import unittest
+
+from certbot.compat import os
+from certbot.errors import MisconfigurationError
+from certbot_apache._internal import obj
+from certbot_apache._internal import override_centos
+from certbot_apache._internal import parser
+import util
+
+
+def get_vh_truth(temp_dir, config_name):
+ """Return the ground truth for the specified directory."""
+ prefix = os.path.join(
+ temp_dir, config_name, "httpd/conf.d")
+
+ aug_pre = "/files" + prefix
+ vh_truth = [
+ obj.VirtualHost(
+ os.path.join(prefix, "test.example.com.conf"),
+ os.path.join(aug_pre, "test.example.com.conf/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "test.example.com"),
+ obj.VirtualHost(
+ os.path.join(prefix, "ssl.conf"),
+ os.path.join(aug_pre, "ssl.conf/VirtualHost"),
+ set([obj.Addr.fromstring("_default_:443")]),
+ True, True, None)
+ ]
+ return vh_truth
+
+class CentOS6Tests(util.ApacheTest):
+ """Tests for CentOS 6"""
+
+ def setUp(self): # pylint: disable=arguments-differ
+ test_dir = "centos6_apache/apache"
+ config_root = "centos6_apache/apache/httpd"
+ vhost_root = "centos6_apache/apache/httpd/conf.d"
+ super(CentOS6Tests, self).setUp(test_dir=test_dir,
+ config_root=config_root,
+ vhost_root=vhost_root)
+
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir,
+ version=(2, 2, 15), os_info="centos")
+ self.vh_truth = get_vh_truth(
+ self.temp_dir, "centos6_apache/apache")
+
+ def test_get_parser(self):
+ self.assertTrue(isinstance(self.config.parser,
+ override_centos.CentOSParser))
+
+ def test_get_virtual_hosts(self):
+ """Make sure all vhosts are being properly found."""
+ vhs = self.config.get_virtual_hosts()
+ self.assertEqual(len(vhs), 2)
+ found = 0
+
+ for vhost in vhs:
+ for centos_truth in self.vh_truth:
+ if vhost == centos_truth:
+ found += 1
+ break
+ else:
+ raise Exception("Missed: %s" % vhost) # pragma: no cover
+ self.assertEqual(found, 2)
+
+ def test_loadmod_default(self):
+ ssl_loadmods = self.config.parser.find_dir(
+ "LoadModule", "ssl_module", exclude=False)
+ self.assertEqual(len(ssl_loadmods), 1)
+ # Make sure the LoadModule ssl_module is in ssl.conf (default)
+ self.assertTrue("ssl.conf" in ssl_loadmods[0])
+ # ...and that it's not inside of <IfModule>
+ self.assertFalse("IfModule" in ssl_loadmods[0])
+
+ # Get the example vhost
+ self.config.assoc["test.example.com"] = self.vh_truth[0]
+ self.config.deploy_cert(
+ "random.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+ self.config.save()
+
+ post_loadmods = self.config.parser.find_dir(
+ "LoadModule", "ssl_module", exclude=False)
+
+ # We should now have LoadModule ssl_module in root conf and ssl.conf
+ self.assertEqual(len(post_loadmods), 2)
+ for lm in post_loadmods:
+ # lm[:-7] removes "/arg[#]" from the path
+ arguments = self.config.parser.get_all_args(lm[:-7])
+ self.assertEqual(arguments, ["ssl_module", "modules/mod_ssl.so"])
+ # ...and both of them should be wrapped in <IfModule !mod_ssl.c>
+ # lm[:-17] strips off /directive/arg[1] from the path.
+ ifmod_args = self.config.parser.get_all_args(lm[:-17])
+ self.assertTrue("!mod_ssl.c" in ifmod_args)
+
+ def test_loadmod_multiple(self):
+ sslmod_args = ["ssl_module", "modules/mod_ssl.so"]
+ # Adds another LoadModule to main httpd.conf in addtition to ssl.conf
+ self.config.parser.add_dir(self.config.parser.loc["default"], "LoadModule",
+ sslmod_args)
+ self.config.save()
+ pre_loadmods = self.config.parser.find_dir(
+ "LoadModule", "ssl_module", exclude=False)
+ # LoadModules are not within IfModule blocks
+ self.assertFalse(any(["ifmodule" in m.lower() for m in pre_loadmods]))
+ self.config.assoc["test.example.com"] = self.vh_truth[0]
+ self.config.deploy_cert(
+ "random.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+ post_loadmods = self.config.parser.find_dir(
+ "LoadModule", "ssl_module", exclude=False)
+
+ for mod in post_loadmods:
+ self.assertTrue(self.config.parser.not_modssl_ifmodule(mod)) #pylint: disable=no-member
+
+ def test_loadmod_rootconf_exists(self):
+ sslmod_args = ["ssl_module", "modules/mod_ssl.so"]
+ rootconf_ifmod = self.config.parser.get_ifmod(
+ parser.get_aug_path(self.config.parser.loc["default"]),
+ "!mod_ssl.c", beginning=True)
+ self.config.parser.add_dir(rootconf_ifmod[:-1], "LoadModule", sslmod_args)
+ self.config.save()
+ # Get the example vhost
+ self.config.assoc["test.example.com"] = self.vh_truth[0]
+ self.config.deploy_cert(
+ "random.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+ self.config.save()
+
+ root_loadmods = self.config.parser.find_dir(
+ "LoadModule", "ssl_module",
+ start=parser.get_aug_path(self.config.parser.loc["default"]),
+ exclude=False)
+
+ mods = [lm for lm in root_loadmods if self.config.parser.loc["default"] in lm]
+
+ self.assertEqual(len(mods), 1)
+ # [:-7] removes "/arg[#]" from the path
+ self.assertEqual(
+ self.config.parser.get_all_args(mods[0][:-7]),
+ sslmod_args)
+
+ def test_neg_loadmod_already_on_path(self):
+ loadmod_args = ["ssl_module", "modules/mod_ssl.so"]
+ ifmod = self.config.parser.get_ifmod(
+ self.vh_truth[1].path, "!mod_ssl.c", beginning=True)
+ self.config.parser.add_dir(ifmod[:-1], "LoadModule", loadmod_args)
+ self.config.parser.add_dir(self.vh_truth[1].path, "LoadModule", loadmod_args)
+ self.config.save()
+ pre_loadmods = self.config.parser.find_dir(
+ "LoadModule", "ssl_module", start=self.vh_truth[1].path, exclude=False)
+ self.assertEqual(len(pre_loadmods), 2)
+ # The ssl.conf now has two LoadModule directives, one inside of
+ # !mod_ssl.c IfModule
+ self.config.assoc["test.example.com"] = self.vh_truth[0]
+ self.config.deploy_cert(
+ "random.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+ self.config.save()
+ # Ensure that the additional LoadModule wasn't written into the IfModule
+ post_loadmods = self.config.parser.find_dir(
+ "LoadModule", "ssl_module", start=self.vh_truth[1].path, exclude=False)
+ self.assertEqual(len(post_loadmods), 1)
+
+ def test_loadmod_non_duplicate(self):
+ # the modules/mod_ssl.so exists in ssl.conf
+ sslmod_args = ["ssl_module", "modules/mod_somethingelse.so"]
+ rootconf_ifmod = self.config.parser.get_ifmod(
+ parser.get_aug_path(self.config.parser.loc["default"]),
+ "!mod_ssl.c", beginning=True)
+ self.config.parser.add_dir(rootconf_ifmod[:-1], "LoadModule", sslmod_args)
+ self.config.save()
+ self.config.assoc["test.example.com"] = self.vh_truth[0]
+ pre_matches = self.config.parser.find_dir("LoadModule",
+ "ssl_module", exclude=False)
+
+ self.assertRaises(MisconfigurationError, self.config.deploy_cert,
+ "random.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+
+ post_matches = self.config.parser.find_dir("LoadModule",
+ "ssl_module", exclude=False)
+ # Make sure that none was changed
+ self.assertEqual(pre_matches, post_matches)
+
+ def test_loadmod_not_found(self):
+ # Remove all existing LoadModule ssl_module... directives
+ orig_loadmods = self.config.parser.find_dir("LoadModule",
+ "ssl_module",
+ exclude=False)
+ for mod in orig_loadmods:
+ noarg_path = mod.rpartition("/")[0]
+ self.config.parser.aug.remove(noarg_path)
+ self.config.save()
+ self.config.deploy_cert(
+ "random.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+
+ post_loadmods = self.config.parser.find_dir("LoadModule",
+ "ssl_module",
+ exclude=False)
+ self.assertFalse(post_loadmods)
+
+ def test_no_ifmod_search_false(self):
+ #pylint: disable=no-member
+
+ self.assertFalse(self.config.parser.not_modssl_ifmodule(
+ "/path/does/not/include/ifmod"
+ ))
+ self.assertFalse(self.config.parser.not_modssl_ifmodule(
+ ""
+ ))
+ self.assertFalse(self.config.parser.not_modssl_ifmodule(
+ "/path/includes/IfModule/but/no/arguments"
+ ))
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/centos_test.py b/certbot-apache/tests/centos_test.py
new file mode 100644
index 000000000..8959d73b8
--- /dev/null
+++ b/certbot-apache/tests/centos_test.py
@@ -0,0 +1,194 @@
+"""Test for certbot_apache._internal.configurator for Centos overrides"""
+import unittest
+
+import mock
+
+from certbot import errors
+from certbot.compat import filesystem
+from certbot.compat import os
+from certbot_apache._internal import obj
+from certbot_apache._internal import override_centos
+import util
+
+
+def get_vh_truth(temp_dir, config_name):
+ """Return the ground truth for the specified directory."""
+ prefix = os.path.join(
+ temp_dir, config_name, "httpd/conf.d")
+
+ aug_pre = "/files" + prefix
+ vh_truth = [
+ obj.VirtualHost(
+ os.path.join(prefix, "centos.example.com.conf"),
+ os.path.join(aug_pre, "centos.example.com.conf/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "centos.example.com"),
+ obj.VirtualHost(
+ os.path.join(prefix, "ssl.conf"),
+ os.path.join(aug_pre, "ssl.conf/VirtualHost"),
+ set([obj.Addr.fromstring("_default_:443")]),
+ True, True, None)
+ ]
+ return vh_truth
+
+class FedoraRestartTest(util.ApacheTest):
+ """Tests for Fedora specific self-signed certificate override"""
+
+ def setUp(self): # pylint: disable=arguments-differ
+ test_dir = "centos7_apache/apache"
+ config_root = "centos7_apache/apache/httpd"
+ vhost_root = "centos7_apache/apache/httpd/conf.d"
+ super(FedoraRestartTest, self).setUp(test_dir=test_dir,
+ config_root=config_root,
+ vhost_root=vhost_root)
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir,
+ os_info="fedora_old")
+ self.vh_truth = get_vh_truth(
+ self.temp_dir, "centos7_apache/apache")
+
+ def _run_fedora_test(self):
+ self.assertIsInstance(self.config, override_centos.CentOSConfigurator)
+ with mock.patch("certbot.util.get_os_info") as mock_info:
+ mock_info.return_value = ["fedora", "28"]
+ self.config.config_test()
+
+ def test_non_fedora_error(self):
+ c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
+ with mock.patch(c_test) as mock_test:
+ mock_test.side_effect = errors.MisconfigurationError
+ with mock.patch("certbot.util.get_os_info") as mock_info:
+ mock_info.return_value = ["not_fedora"]
+ self.assertRaises(errors.MisconfigurationError,
+ self.config.config_test)
+
+ def test_fedora_restart_error(self):
+ c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
+ with mock.patch(c_test) as mock_test:
+ # First call raises error, second doesn't
+ mock_test.side_effect = [errors.MisconfigurationError, '']
+ with mock.patch("certbot.util.run_script") as mock_run:
+ mock_run.side_effect = errors.SubprocessError
+ self.assertRaises(errors.MisconfigurationError,
+ self._run_fedora_test)
+
+ def test_fedora_restart(self):
+ c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
+ with mock.patch(c_test) as mock_test:
+ with mock.patch("certbot.util.run_script") as mock_run:
+ # First call raises error, second doesn't
+ mock_test.side_effect = [errors.MisconfigurationError, '']
+ self._run_fedora_test()
+ self.assertEqual(mock_test.call_count, 2)
+ self.assertEqual(mock_run.call_args[0][0],
+ ['systemctl', 'restart', 'httpd'])
+
+
+class MultipleVhostsTestCentOS(util.ApacheTest):
+ """Multiple vhost tests for CentOS / RHEL family of distros"""
+
+ _multiprocess_can_split_ = True
+
+ def setUp(self): # pylint: disable=arguments-differ
+ test_dir = "centos7_apache/apache"
+ config_root = "centos7_apache/apache/httpd"
+ vhost_root = "centos7_apache/apache/httpd/conf.d"
+ super(MultipleVhostsTestCentOS, self).setUp(test_dir=test_dir,
+ config_root=config_root,
+ vhost_root=vhost_root)
+
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir,
+ os_info="centos")
+ self.vh_truth = get_vh_truth(
+ self.temp_dir, "centos7_apache/apache")
+
+ def test_get_parser(self):
+ self.assertIsInstance(self.config.parser, override_centos.CentOSParser)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_opportunistic_httpd_runtime_parsing(self, mock_get):
+ define_val = (
+ 'Define: TEST1\n'
+ 'Define: TEST2\n'
+ 'Define: DUMP_RUN_CFG\n'
+ )
+ mod_val = (
+ 'Loaded Modules:\n'
+ ' mock_module (static)\n'
+ ' another_module (static)\n'
+ )
+ def mock_get_cfg(command):
+ """Mock httpd process stdout"""
+ if command == ['apachectl', '-t', '-D', 'DUMP_RUN_CFG']:
+ return define_val
+ elif command == ['apachectl', '-t', '-D', 'DUMP_MODULES']:
+ return mod_val
+ return ""
+ mock_get.side_effect = mock_get_cfg
+ self.config.parser.modules = set()
+ self.config.parser.variables = {}
+
+ with mock.patch("certbot.util.get_os_info") as mock_osi:
+ # Make sure we have the have the CentOS httpd constants
+ mock_osi.return_value = ("centos", "7")
+ self.config.parser.update_runtime_variables()
+
+ self.assertEqual(mock_get.call_count, 3)
+ self.assertEqual(len(self.config.parser.modules), 4)
+ self.assertEqual(len(self.config.parser.variables), 2)
+ self.assertTrue("TEST2" in self.config.parser.variables.keys())
+ self.assertTrue("mod_another.c" in self.config.parser.modules)
+
+ def test_get_virtual_hosts(self):
+ """Make sure all vhosts are being properly found."""
+ vhs = self.config.get_virtual_hosts()
+ self.assertEqual(len(vhs), 2)
+ found = 0
+
+ for vhost in vhs:
+ for centos_truth in self.vh_truth:
+ if vhost == centos_truth:
+ found += 1
+ break
+ else:
+ raise Exception("Missed: %s" % vhost) # pragma: no cover
+ self.assertEqual(found, 2)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_get_sysconfig_vars(self, mock_cfg):
+ """Make sure we read the sysconfig OPTIONS variable correctly"""
+ # Return nothing for the process calls
+ mock_cfg.return_value = ""
+ self.config.parser.sysconfig_filep = filesystem.realpath(
+ os.path.join(self.config.parser.root, "../sysconfig/httpd"))
+ self.config.parser.variables = {}
+
+ with mock.patch("certbot.util.get_os_info") as mock_osi:
+ # Make sure we have the have the CentOS httpd constants
+ mock_osi.return_value = ("centos", "7")
+ self.config.parser.update_runtime_variables()
+
+ self.assertTrue("mock_define" in self.config.parser.variables.keys())
+ self.assertTrue("mock_define_too" in self.config.parser.variables.keys())
+ self.assertTrue("mock_value" in self.config.parser.variables.keys())
+ self.assertEqual("TRUE", self.config.parser.variables["mock_value"])
+ self.assertTrue("MOCK_NOSEP" in self.config.parser.variables.keys())
+ self.assertEqual("NOSEP_VAL", self.config.parser.variables["NOSEP_TWO"])
+
+ @mock.patch("certbot_apache._internal.configurator.util.run_script")
+ def test_alt_restart_works(self, mock_run_script):
+ mock_run_script.side_effect = [None, errors.SubprocessError, None]
+ self.config.restart()
+ self.assertEqual(mock_run_script.call_count, 3)
+
+ @mock.patch("certbot_apache._internal.configurator.util.run_script")
+ def test_alt_restart_errors(self, mock_run_script):
+ mock_run_script.side_effect = [None,
+ errors.SubprocessError,
+ errors.SubprocessError]
+ self.assertRaises(errors.MisconfigurationError, self.config.restart)
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/complex_parsing_test.py b/certbot-apache/tests/complex_parsing_test.py
new file mode 100644
index 000000000..8b795b0b6
--- /dev/null
+++ b/certbot-apache/tests/complex_parsing_test.py
@@ -0,0 +1,128 @@
+"""Tests for certbot_apache._internal.parser."""
+import shutil
+import unittest
+
+from certbot import errors
+from certbot.compat import os
+import util
+
+
+class ComplexParserTest(util.ParserTest):
+ """Apache Parser Test."""
+
+ def setUp(self): # pylint: disable=arguments-differ
+ super(ComplexParserTest, self).setUp(
+ "complex_parsing", "complex_parsing")
+
+ self.setup_variables()
+ # This needs to happen after due to setup_variables not being run
+ # until after
+ self.parser.parse_modules() # pylint: disable=protected-access
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+ shutil.rmtree(self.config_dir)
+ shutil.rmtree(self.work_dir)
+
+ def setup_variables(self):
+ """Set up variables for parser."""
+ self.parser.variables.update(
+ {
+ "COMPLEX": "",
+ "tls_port": "1234",
+ "fnmatch_filename": "test_fnmatch.conf",
+ "tls_port_str": "1234"
+ }
+ )
+
+ def test_filter_args_num(self):
+ """Note: This may also fail do to Include conf-enabled/ syntax."""
+ matches = self.parser.find_dir("TestArgsDirective")
+
+ self.assertEqual(len(self.parser.filter_args_num(matches, 1)), 3)
+ self.assertEqual(len(self.parser.filter_args_num(matches, 2)), 2)
+ self.assertEqual(len(self.parser.filter_args_num(matches, 3)), 1)
+
+ def test_basic_variable_parsing(self):
+ matches = self.parser.find_dir("TestVariablePort")
+
+ self.assertEqual(len(matches), 1)
+ self.assertEqual(self.parser.get_arg(matches[0]), "1234")
+
+ def test_basic_variable_parsing_quotes(self):
+ matches = self.parser.find_dir("TestVariablePortStr")
+
+ self.assertEqual(len(matches), 1)
+ self.assertEqual(self.parser.get_arg(matches[0]), "1234")
+
+ def test_invalid_variable_parsing(self):
+ del self.parser.variables["tls_port"]
+
+ matches = self.parser.find_dir("TestVariablePort")
+ self.assertRaises(
+ errors.PluginError, self.parser.get_arg, matches[0])
+
+ def test_basic_ifdefine(self):
+ self.assertEqual(len(self.parser.find_dir("VAR_DIRECTIVE")), 2)
+ self.assertEqual(len(self.parser.find_dir("INVALID_VAR_DIRECTIVE")), 0)
+
+ def test_basic_ifmodule(self):
+ self.assertEqual(len(self.parser.find_dir("MOD_DIRECTIVE")), 2)
+ self.assertEqual(
+ len(self.parser.find_dir("INVALID_MOD_DIRECTIVE")), 0)
+
+ def test_nested(self):
+ self.assertEqual(len(self.parser.find_dir("NESTED_DIRECTIVE")), 3)
+ self.assertEqual(
+ len(self.parser.find_dir("INVALID_NESTED_DIRECTIVE")), 0)
+
+ def test_load_modules(self):
+ """If only first is found, there is bad variable parsing."""
+ self.assertTrue("status_module" in self.parser.modules)
+ self.assertTrue("mod_status.c" in self.parser.modules)
+
+ # This is in an IfDefine
+ self.assertTrue("ssl_module" in self.parser.modules)
+ self.assertTrue("mod_ssl.c" in self.parser.modules)
+
+ def verify_fnmatch(self, arg, hit=True):
+ """Test if Include was correctly parsed."""
+ from certbot_apache._internal import parser
+ self.parser.add_dir(parser.get_aug_path(self.parser.loc["default"]),
+ "Include", [arg])
+ if hit:
+ self.assertTrue(self.parser.find_dir("FNMATCH_DIRECTIVE"))
+ else:
+ self.assertFalse(self.parser.find_dir("FNMATCH_DIRECTIVE"))
+
+ # NOTE: Only run one test per function otherwise you will have
+ # inf recursion
+ def test_include(self):
+ self.verify_fnmatch("test_fnmatch.?onf")
+
+ def test_include_complex(self):
+ self.verify_fnmatch("../complex_parsing/[te][te]st_*.?onf")
+
+ def test_include_fullpath(self):
+ self.verify_fnmatch(os.path.join(self.config_path,
+ "test_fnmatch.conf"))
+
+ def test_include_fullpath_trailing_slash(self):
+ self.verify_fnmatch(self.config_path + "//")
+
+ def test_include_single_quotes(self):
+ self.verify_fnmatch("'" + self.config_path + "'")
+
+ def test_include_double_quotes(self):
+ self.verify_fnmatch('"' + self.config_path + '"')
+
+ def test_include_variable(self):
+ self.verify_fnmatch("../complex_parsing/${fnmatch_filename}")
+
+ def test_include_missing(self):
+ # This should miss
+ self.verify_fnmatch("test_*.onf", False)
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/configurator_reverter_test.py b/certbot-apache/tests/configurator_reverter_test.py
new file mode 100644
index 000000000..ad8e73347
--- /dev/null
+++ b/certbot-apache/tests/configurator_reverter_test.py
@@ -0,0 +1,84 @@
+"""Test for certbot_apache._internal.configurator implementations of reverter"""
+import shutil
+import unittest
+
+import mock
+
+from certbot import errors
+import util
+
+
+class ConfiguratorReverterTest(util.ApacheTest):
+ """Test for ApacheConfigurator reverter methods"""
+
+
+ def setUp(self): # pylint: disable=arguments-differ
+ super(ConfiguratorReverterTest, self).setUp()
+
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir)
+
+ self.vh_truth = util.get_vh_truth(
+ self.temp_dir, "debian_apache_2_4/multiple_vhosts")
+
+ def tearDown(self):
+ shutil.rmtree(self.config_dir)
+ shutil.rmtree(self.work_dir)
+ shutil.rmtree(self.temp_dir)
+
+ def test_bad_save_checkpoint(self):
+ self.config.reverter.add_to_checkpoint = mock.Mock(
+ side_effect=errors.ReverterError)
+ self.config.parser.add_dir(
+ self.vh_truth[0].path, "Test", "bad_save_ckpt")
+ self.assertRaises(errors.PluginError, self.config.save)
+
+ def test_bad_save_finalize_checkpoint(self):
+ self.config.reverter.finalize_checkpoint = mock.Mock(
+ side_effect=errors.ReverterError)
+ self.config.parser.add_dir(
+ self.vh_truth[0].path, "Test", "bad_save_ckpt")
+ self.assertRaises(errors.PluginError, self.config.save, "Title")
+
+ def test_finalize_save(self):
+ mock_finalize = mock.Mock()
+ self.config.reverter = mock_finalize
+ self.config.save("Example Title")
+
+ self.assertTrue(mock_finalize.is_called)
+
+ def test_revert_challenge_config(self):
+ mock_load = mock.Mock()
+ self.config.parser.aug.load = mock_load
+
+ self.config.revert_challenge_config()
+ self.assertEqual(mock_load.call_count, 1)
+
+ def test_revert_challenge_config_error(self):
+ self.config.reverter.revert_temporary_config = mock.Mock(
+ side_effect=errors.ReverterError)
+
+ self.assertRaises(
+ errors.PluginError, self.config.revert_challenge_config)
+
+ def test_rollback_checkpoints(self):
+ mock_load = mock.Mock()
+ self.config.parser.aug.load = mock_load
+
+ self.config.rollback_checkpoints()
+ self.assertEqual(mock_load.call_count, 1)
+
+ def test_rollback_error(self):
+ self.config.reverter.rollback_checkpoints = mock.Mock(
+ side_effect=errors.ReverterError)
+ self.assertRaises(errors.PluginError, self.config.rollback_checkpoints)
+
+ def test_recovery_routine_reload(self):
+ mock_load = mock.Mock()
+ self.config.parser.aug.load = mock_load
+ self.config.recovery_routine()
+ self.assertEqual(mock_load.call_count, 1)
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/configurator_test.py b/certbot-apache/tests/configurator_test.py
new file mode 100644
index 000000000..9fab5ea5d
--- /dev/null
+++ b/certbot-apache/tests/configurator_test.py
@@ -0,0 +1,1769 @@
+# pylint: disable=too-many-lines
+"""Test for certbot_apache._internal.configurator."""
+import copy
+import shutil
+import socket
+import tempfile
+import unittest
+
+import mock
+import six # pylint: disable=unused-import # six is used in mock.patch()
+
+from acme import challenges
+from certbot import achallenges
+from certbot import crypto_util
+from certbot import errors
+from certbot.compat import filesystem
+from certbot.compat import os
+from certbot.tests import acme_util
+from certbot.tests import util as certbot_util
+from certbot_apache._internal import apache_util
+from certbot_apache._internal import constants
+from certbot_apache._internal import obj
+from certbot_apache._internal import parser
+import util
+
+
+class MultipleVhostsTest(util.ApacheTest):
+ """Test two standard well-configured HTTP vhosts."""
+
+ def setUp(self): # pylint: disable=arguments-differ
+ super(MultipleVhostsTest, self).setUp()
+
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir)
+ self.config = self.mock_deploy_cert(self.config)
+ self.vh_truth = util.get_vh_truth(
+ self.temp_dir, "debian_apache_2_4/multiple_vhosts")
+
+ def mock_deploy_cert(self, config):
+ """A test for a mock deploy cert"""
+ config.real_deploy_cert = self.config.deploy_cert
+
+ def mocked_deploy_cert(*args, **kwargs):
+ """a helper to mock a deployed cert"""
+ g_mod = "certbot_apache._internal.configurator.ApacheConfigurator.enable_mod"
+ with mock.patch(g_mod):
+ config.real_deploy_cert(*args, **kwargs)
+ self.config.deploy_cert = mocked_deploy_cert
+ return self.config
+
+ @mock.patch("certbot_apache._internal.configurator.path_surgery")
+ def test_prepare_no_install(self, mock_surgery):
+ silly_path = {"PATH": "/tmp/nothingness2342"}
+ mock_surgery.return_value = False
+ with mock.patch.dict('os.environ', silly_path):
+ self.assertRaises(errors.NoInstallationError, self.config.prepare)
+ self.assertEqual(mock_surgery.call_count, 1)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser")
+ @mock.patch("certbot_apache._internal.configurator.util.exe_exists")
+ def test_prepare_version(self, mock_exe_exists, _):
+ mock_exe_exists.return_value = True
+ self.config.version = None
+ self.config.config_test = mock.Mock()
+ self.config.get_version = mock.Mock(return_value=(1, 1))
+
+ self.assertRaises(
+ errors.NotSupportedError, self.config.prepare)
+
+ def test_prepare_locked(self):
+ server_root = self.config.conf("server-root")
+ self.config.config_test = mock.Mock()
+ os.remove(os.path.join(server_root, ".certbot.lock"))
+ certbot_util.lock_and_call(self._test_prepare_locked, server_root)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser")
+ @mock.patch("certbot_apache._internal.configurator.util.exe_exists")
+ def _test_prepare_locked(self, unused_parser, unused_exe_exists):
+ try:
+ self.config.prepare()
+ except errors.PluginError as err:
+ err_msg = str(err)
+ self.assertTrue("lock" in err_msg)
+ self.assertTrue(self.config.conf("server-root") in err_msg)
+ else: # pragma: no cover
+ self.fail("Exception wasn't raised!")
+
+ def test_add_parser_arguments(self): # pylint: disable=no-self-use
+ from certbot_apache._internal.configurator import ApacheConfigurator
+ # Weak test..
+ ApacheConfigurator.add_parser_arguments(mock.MagicMock())
+
+ def test_docs_parser_arguments(self):
+ os.environ["CERTBOT_DOCS"] = "1"
+ from certbot_apache._internal.configurator import ApacheConfigurator
+ mock_add = mock.MagicMock()
+ ApacheConfigurator.add_parser_arguments(mock_add)
+ parserargs = ["server_root", "enmod", "dismod", "le_vhost_ext",
+ "vhost_root", "logs_root", "challenge_location",
+ "handle_modules", "handle_sites", "ctl"]
+ exp = dict()
+
+ for k in ApacheConfigurator.OS_DEFAULTS:
+ if k in parserargs:
+ exp[k.replace("_", "-")] = ApacheConfigurator.OS_DEFAULTS[k]
+ # Special cases
+ exp["vhost-root"] = None
+
+ found = set()
+ for call in mock_add.call_args_list:
+ found.add(call[0][0])
+
+ # Make sure that all (and only) the expected values exist
+ self.assertEqual(len(mock_add.call_args_list), len(found))
+ for e in exp:
+ self.assertTrue(e in found)
+
+ del os.environ["CERTBOT_DOCS"]
+
+ def test_add_parser_arguments_all_configurators(self): # pylint: disable=no-self-use
+ from certbot_apache._internal.entrypoint import OVERRIDE_CLASSES
+ for cls in OVERRIDE_CLASSES.values():
+ cls.add_parser_arguments(mock.MagicMock())
+
+ def test_all_configurators_defaults_defined(self):
+ from certbot_apache._internal.entrypoint import OVERRIDE_CLASSES
+ from certbot_apache._internal.configurator import ApacheConfigurator
+ parameters = set(ApacheConfigurator.OS_DEFAULTS.keys())
+ for cls in OVERRIDE_CLASSES.values():
+ self.assertTrue(parameters.issubset(set(cls.OS_DEFAULTS.keys())))
+
+ def test_constant(self):
+ self.assertTrue("debian_apache_2_4/multiple_vhosts/apache" in
+ self.config.option("server_root"))
+ self.assertEqual(self.config.option("nonexistent"), None)
+
+ @certbot_util.patch_get_utility()
+ def test_get_all_names(self, mock_getutility):
+ mock_utility = mock_getutility()
+ mock_utility.notification = mock.MagicMock(return_value=True)
+ names = self.config.get_all_names()
+ self.assertEqual(names, set(
+ ["certbot.demo", "ocspvhost.com", "encryption-example.demo",
+ "nonsym.link", "vhost.in.rootconf", "www.certbot.demo",
+ "duplicate.example.com"]
+ ))
+
+ @certbot_util.patch_get_utility()
+ @mock.patch("certbot_apache._internal.configurator.socket.gethostbyaddr")
+ def test_get_all_names_addrs(self, mock_gethost, mock_getutility):
+ mock_gethost.side_effect = [("google.com", "", ""), socket.error]
+ mock_utility = mock_getutility()
+ mock_utility.notification.return_value = True
+ vhost = obj.VirtualHost(
+ "fp", "ap",
+ set([obj.Addr(("8.8.8.8", "443")),
+ obj.Addr(("zombo.com",)),
+ obj.Addr(("192.168.1.2"))]),
+ True, False)
+
+ self.config.vhosts.append(vhost)
+
+ names = self.config.get_all_names()
+ self.assertEqual(len(names), 9)
+ self.assertTrue("zombo.com" in names)
+ self.assertTrue("google.com" in names)
+ self.assertTrue("certbot.demo" in names)
+
+ def test_get_bad_path(self):
+ self.assertEqual(apache_util.get_file_path(None), None)
+ self.assertEqual(apache_util.get_file_path("nonexistent"), None)
+ self.assertEqual(self.config._create_vhost("nonexistent"), None) # pylint: disable=protected-access
+
+ def test_get_aug_internal_path(self):
+ from certbot_apache._internal.apache_util import get_internal_aug_path
+ internal_paths = [
+ "Virtualhost", "IfModule/VirtualHost", "VirtualHost", "VirtualHost",
+ "Macro/VirtualHost", "IfModule/VirtualHost", "VirtualHost",
+ "IfModule/VirtualHost"]
+
+ for i, internal_path in enumerate(internal_paths):
+ self.assertEqual(
+ get_internal_aug_path(self.vh_truth[i].path), internal_path)
+
+ def test_bad_servername_alias(self):
+ ssl_vh1 = obj.VirtualHost(
+ "fp1", "ap1", set([obj.Addr(("*", "443"))]),
+ True, False)
+ # pylint: disable=protected-access
+ self.config._add_servernames(ssl_vh1)
+ self.assertTrue(
+ self.config._add_servername_alias("oy_vey", ssl_vh1) is None)
+
+ def test_add_servernames_alias(self):
+ self.config.parser.add_dir(
+ self.vh_truth[2].path, "ServerAlias", ["*.le.co"])
+ # pylint: disable=protected-access
+ self.config._add_servernames(self.vh_truth[2])
+ self.assertEqual(
+ self.vh_truth[2].get_names(), set(["*.le.co", "ip-172-30-0-17"]))
+
+ def test_get_virtual_hosts(self):
+ """Make sure all vhosts are being properly found."""
+ vhs = self.config.get_virtual_hosts()
+ self.assertEqual(len(vhs), 12)
+ found = 0
+
+ for vhost in vhs:
+ for truth in self.vh_truth:
+ if vhost == truth:
+ found += 1
+ break
+ else:
+ raise Exception("Missed: %s" % vhost) # pragma: no cover
+
+ self.assertEqual(found, 12)
+
+ # Handle case of non-debian layout get_virtual_hosts
+ with mock.patch(
+ "certbot_apache._internal.configurator.ApacheConfigurator.conf"
+ ) as mock_conf:
+ mock_conf.return_value = False
+ vhs = self.config.get_virtual_hosts()
+ self.assertEqual(len(vhs), 12)
+
+ @mock.patch("certbot_apache._internal.display_ops.select_vhost")
+ def test_choose_vhost_none_avail(self, mock_select):
+ mock_select.return_value = None
+ self.assertRaises(
+ errors.PluginError, self.config.choose_vhost, "none.com")
+
+ @mock.patch("certbot_apache._internal.display_ops.select_vhost")
+ def test_choose_vhost_select_vhost_ssl(self, mock_select):
+ mock_select.return_value = self.vh_truth[1]
+ self.assertEqual(
+ self.vh_truth[1], self.config.choose_vhost("none.com"))
+
+ @mock.patch("certbot_apache._internal.display_ops.select_vhost")
+ @mock.patch("certbot_apache._internal.obj.VirtualHost.conflicts")
+ def test_choose_vhost_select_vhost_non_ssl(self, mock_conf, mock_select):
+ mock_select.return_value = self.vh_truth[0]
+ mock_conf.return_value = False
+ chosen_vhost = self.config.choose_vhost("none.com")
+ self.vh_truth[0].aliases.add("none.com")
+ self.assertEqual(
+ self.vh_truth[0].get_names(), chosen_vhost.get_names())
+
+ # Make sure we go from HTTP -> HTTPS
+ self.assertFalse(self.vh_truth[0].ssl)
+ self.assertTrue(chosen_vhost.ssl)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._find_best_vhost")
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.add_dir")
+ def test_choose_vhost_and_servername_addition(self, mock_add, mock_find):
+ ret_vh = self.vh_truth[8]
+ ret_vh.enabled = False
+ mock_find.return_value = self.vh_truth[8]
+ self.config.choose_vhost("whatever.com")
+ self.assertTrue(mock_add.called)
+
+ @mock.patch("certbot_apache._internal.display_ops.select_vhost")
+ def test_choose_vhost_select_vhost_with_temp(self, mock_select):
+ mock_select.return_value = self.vh_truth[0]
+ chosen_vhost = self.config.choose_vhost("none.com", create_if_no_ssl=False)
+ self.assertEqual(self.vh_truth[0], chosen_vhost)
+
+ @mock.patch("certbot_apache._internal.display_ops.select_vhost")
+ def test_choose_vhost_select_vhost_conflicting_non_ssl(self, mock_select):
+ mock_select.return_value = self.vh_truth[3]
+ conflicting_vhost = obj.VirtualHost(
+ "path", "aug_path", set([obj.Addr.fromstring("*:443")]),
+ True, True)
+ self.config.vhosts.append(conflicting_vhost)
+
+ self.assertRaises(
+ errors.PluginError, self.config.choose_vhost, "none.com")
+
+ def test_find_best_http_vhost_default(self):
+ vh = obj.VirtualHost(
+ "fp", "ap", set([obj.Addr.fromstring("_default_:80")]), False, True)
+ self.config.vhosts = [vh]
+ self.assertEqual(self.config.find_best_http_vhost("foo.bar", False), vh)
+
+ def test_find_best_http_vhost_port(self):
+ port = "8080"
+ vh = obj.VirtualHost(
+ "fp", "ap", set([obj.Addr.fromstring("*:" + port)]),
+ False, True, "encryption-example.demo")
+ self.config.vhosts.append(vh)
+ self.assertEqual(self.config.find_best_http_vhost("foo.bar", False, port), vh)
+
+ def test_findbest_continues_on_short_domain(self):
+ # pylint: disable=protected-access
+ chosen_vhost = self.config._find_best_vhost("purple.com")
+ self.assertEqual(None, chosen_vhost)
+
+ def test_findbest_continues_on_long_domain(self):
+ # pylint: disable=protected-access
+ chosen_vhost = self.config._find_best_vhost("green.red.purple.com")
+ self.assertEqual(None, chosen_vhost)
+
+ def test_find_best_vhost(self):
+ # pylint: disable=protected-access
+ self.assertEqual(
+ self.vh_truth[3], self.config._find_best_vhost("certbot.demo"))
+ self.assertEqual(
+ self.vh_truth[0],
+ self.config._find_best_vhost("encryption-example.demo"))
+ self.assertEqual(
+ self.config._find_best_vhost("does-not-exist.com"), None)
+
+ def test_find_best_vhost_variety(self):
+ # pylint: disable=protected-access
+ ssl_vh = obj.VirtualHost(
+ "fp", "ap", set([obj.Addr(("*", "443")),
+ obj.Addr(("zombo.com",))]),
+ True, False)
+ self.config.vhosts.append(ssl_vh)
+ self.assertEqual(self.config._find_best_vhost("zombo.com"), ssl_vh)
+
+ def test_find_best_vhost_default(self):
+ # pylint: disable=protected-access
+ # Assume only the two default vhosts.
+ self.config.vhosts = [
+ vh for vh in self.config.vhosts
+ if vh.name not in ["certbot.demo", "nonsym.link",
+ "encryption-example.demo", "duplicate.example.com",
+ "ocspvhost.com", "vhost.in.rootconf"]
+ and "*.blue.purple.com" not in vh.aliases
+ ]
+ self.assertEqual(
+ self.config._find_best_vhost("encryption-example.demo"),
+ self.vh_truth[2])
+
+ def test_non_default_vhosts(self):
+ # pylint: disable=protected-access
+ vhosts = self.config._non_default_vhosts(self.config.vhosts)
+ self.assertEqual(len(vhosts), 10)
+
+ def test_deploy_cert_enable_new_vhost(self):
+ # Create
+ ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0])
+ self.config.parser.modules.add("ssl_module")
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("socache_shmcb_module")
+
+ self.assertFalse(ssl_vhost.enabled)
+ self.config.deploy_cert(
+ "encryption-example.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+ self.assertTrue(ssl_vhost.enabled)
+
+ def test_no_duplicate_include(self):
+ def mock_find_dir(directive, argument, _):
+ """Mock method for parser.find_dir"""
+ if directive == "Include" and argument.endswith("options-ssl-apache.conf"):
+ return ["/path/to/whatever"]
+ return None # pragma: no cover
+
+ mock_add = mock.MagicMock()
+ self.config.parser.add_dir = mock_add
+ self.config._add_dummy_ssl_directives(self.vh_truth[0]) # pylint: disable=protected-access
+ tried_to_add = False
+ for a in mock_add.call_args_list:
+ if a[0][1] == "Include" and a[0][2] == self.config.mod_ssl_conf:
+ tried_to_add = True
+ # Include should be added, find_dir is not patched, and returns falsy
+ self.assertTrue(tried_to_add)
+
+ self.config.parser.find_dir = mock_find_dir
+ mock_add.reset_mock()
+ self.config._add_dummy_ssl_directives(self.vh_truth[0]) # pylint: disable=protected-access
+ for a in mock_add.call_args_list:
+ if a[0][1] == "Include" and a[0][2] == self.config.mod_ssl_conf:
+ self.fail("Include shouldn't be added, as patched find_dir 'finds' existing one") \
+ # pragma: no cover
+
+ def test_deploy_cert(self):
+ self.config.parser.modules.add("ssl_module")
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("socache_shmcb_module")
+ # Patch _add_dummy_ssl_directives to make sure we write them correctly
+ # pylint: disable=protected-access
+ orig_add_dummy = self.config._add_dummy_ssl_directives
+ def mock_add_dummy_ssl(vhostpath):
+ """Mock method for _add_dummy_ssl_directives"""
+ def find_args(path, directive):
+ """Return list of arguments in requested directive at path"""
+ f_args = []
+ dirs = self.config.parser.find_dir(directive, None,
+ path)
+ for d in dirs:
+ f_args.append(self.config.parser.get_arg(d))
+ return f_args
+ # Verify that the dummy directives do not exist
+ self.assertFalse(
+ "insert_cert_file_path" in find_args(vhostpath,
+ "SSLCertificateFile"))
+ self.assertFalse(
+ "insert_key_file_path" in find_args(vhostpath,
+ "SSLCertificateKeyFile"))
+ orig_add_dummy(vhostpath)
+ # Verify that the dummy directives exist
+ self.assertTrue(
+ "insert_cert_file_path" in find_args(vhostpath,
+ "SSLCertificateFile"))
+ self.assertTrue(
+ "insert_key_file_path" in find_args(vhostpath,
+ "SSLCertificateKeyFile"))
+ # pylint: disable=protected-access
+ self.config._add_dummy_ssl_directives = mock_add_dummy_ssl
+
+ # Get the default 443 vhost
+ self.config.assoc["random.demo"] = self.vh_truth[1]
+ self.config.deploy_cert(
+ "random.demo",
+ "example/cert.pem", "example/key.pem", "example/cert_chain.pem")
+ self.config.save()
+
+ # Verify ssl_module was enabled.
+ self.assertTrue(self.vh_truth[1].enabled)
+ self.assertTrue("ssl_module" in self.config.parser.modules)
+
+ loc_cert = self.config.parser.find_dir(
+ "sslcertificatefile", "example/cert.pem", self.vh_truth[1].path)
+ loc_key = self.config.parser.find_dir(
+ "sslcertificateKeyfile", "example/key.pem", self.vh_truth[1].path)
+ loc_chain = self.config.parser.find_dir(
+ "SSLCertificateChainFile", "example/cert_chain.pem",
+ self.vh_truth[1].path)
+
+ # Verify one directive was found in the correct file
+ self.assertEqual(len(loc_cert), 1)
+ self.assertEqual(
+ apache_util.get_file_path(loc_cert[0]),
+ self.vh_truth[1].filep)
+
+ self.assertEqual(len(loc_key), 1)
+ self.assertEqual(
+ apache_util.get_file_path(loc_key[0]),
+ self.vh_truth[1].filep)
+
+ self.assertEqual(len(loc_chain), 1)
+ self.assertEqual(
+ apache_util.get_file_path(loc_chain[0]),
+ self.vh_truth[1].filep)
+
+ # One more time for chain directive setting
+ self.config.deploy_cert(
+ "random.demo",
+ "two/cert.pem", "two/key.pem", "two/cert_chain.pem")
+ self.assertTrue(self.config.parser.find_dir(
+ "SSLCertificateChainFile", "two/cert_chain.pem",
+ self.vh_truth[1].path))
+
+ def test_deploy_cert_invalid_vhost(self):
+ """For test cases where the `ApacheConfigurator` class' `_deploy_cert`
+ method is called with an invalid vhost parameter. Currently this tests
+ that a PluginError is appropriately raised when important directives
+ are missing in an SSL module."""
+ self.config.parser.modules.add("ssl_module")
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("socache_shmcb_module")
+
+ def side_effect(*args):
+ """Mocks case where an SSLCertificateFile directive can be found
+ but an SSLCertificateKeyFile directive is missing."""
+ if "SSLCertificateFile" in args:
+ return ["example/cert.pem"]
+ return []
+
+ mock_find_dir = mock.MagicMock(return_value=[])
+ mock_find_dir.side_effect = side_effect
+
+ self.config.parser.find_dir = mock_find_dir
+
+ # Get the default 443 vhost
+ self.config.assoc["random.demo"] = self.vh_truth[1]
+
+ self.assertRaises(
+ errors.PluginError, self.config.deploy_cert, "random.demo",
+ "example/cert.pem", "example/key.pem", "example/cert_chain.pem")
+
+ # Remove side_effect to mock case where both SSLCertificateFile
+ # and SSLCertificateKeyFile directives are missing
+ self.config.parser.find_dir.side_effect = None
+ self.assertRaises(
+ errors.PluginError, self.config.deploy_cert, "random.demo",
+ "example/cert.pem", "example/key.pem", "example/cert_chain.pem")
+
+ def test_is_name_vhost(self):
+ addr = obj.Addr.fromstring("*:80")
+ self.assertTrue(self.config.is_name_vhost(addr))
+ self.config.version = (2, 2)
+ self.assertFalse(self.config.is_name_vhost(addr))
+
+ def test_add_name_vhost(self):
+ self.config.add_name_vhost(obj.Addr.fromstring("*:443"))
+ self.config.add_name_vhost(obj.Addr.fromstring("*:80"))
+ self.assertTrue(self.config.parser.find_dir(
+ "NameVirtualHost", "*:443", exclude=False))
+ self.assertTrue(self.config.parser.find_dir(
+ "NameVirtualHost", "*:80"))
+
+ def test_add_listen_80(self):
+ mock_find = mock.Mock()
+ mock_add_dir = mock.Mock()
+ mock_find.return_value = []
+ self.config.parser.find_dir = mock_find
+ self.config.parser.add_dir = mock_add_dir
+ self.config.ensure_listen("80")
+ self.assertTrue(mock_add_dir.called)
+ self.assertTrue(mock_find.called)
+ self.assertEqual(mock_add_dir.call_args[0][1], "Listen")
+ self.assertEqual(mock_add_dir.call_args[0][2], "80")
+
+ def test_add_listen_80_named(self):
+ mock_find = mock.Mock()
+ mock_find.return_value = ["test1", "test2", "test3"]
+ mock_get = mock.Mock()
+ mock_get.side_effect = ["1.2.3.4:80", "[::1]:80", "1.1.1.1:443"]
+ mock_add_dir = mock.Mock()
+
+ self.config.parser.find_dir = mock_find
+ self.config.parser.get_arg = mock_get
+ self.config.parser.add_dir = mock_add_dir
+
+ self.config.ensure_listen("80")
+ self.assertEqual(mock_add_dir.call_count, 0)
+
+ # Reset return lists and inputs
+ mock_add_dir.reset_mock()
+ mock_get.side_effect = ["1.2.3.4:80", "[::1]:80", "1.1.1.1:443"]
+
+ # Test
+ self.config.ensure_listen("8080")
+ self.assertEqual(mock_add_dir.call_count, 3)
+ self.assertTrue(mock_add_dir.called)
+ self.assertEqual(mock_add_dir.call_args[0][1], "Listen")
+ call_found = False
+ for mock_call in mock_add_dir.mock_calls:
+ if mock_call[1][2] == ['1.2.3.4:8080']:
+ call_found = True
+ self.assertTrue(call_found)
+
+ def test_prepare_server_https(self):
+ mock_enable = mock.Mock()
+ self.config.enable_mod = mock_enable
+
+ mock_find = mock.Mock()
+ mock_add_dir = mock.Mock()
+ mock_find.return_value = []
+
+ # This will test the Add listen
+ self.config.parser.find_dir = mock_find
+ self.config.parser.add_dir_to_ifmodssl = mock_add_dir
+ self.config.prepare_server_https("443")
+ # Changing the order these modules are enabled breaks the reverter
+ self.assertEqual(mock_enable.call_args_list[0][0][0], "socache_shmcb")
+ self.assertEqual(mock_enable.call_args[0][0], "ssl")
+ self.assertEqual(mock_enable.call_args[1], {"temp": False})
+
+ self.config.prepare_server_https("8080", temp=True)
+ # Changing the order these modules are enabled breaks the reverter
+ self.assertEqual(mock_enable.call_args_list[2][0][0], "socache_shmcb")
+ self.assertEqual(mock_enable.call_args[0][0], "ssl")
+ # Enable mod is temporary
+ self.assertEqual(mock_enable.call_args[1], {"temp": True})
+
+ self.assertEqual(mock_add_dir.call_count, 2)
+
+ def test_prepare_server_https_named_listen(self):
+ mock_find = mock.Mock()
+ mock_find.return_value = ["test1", "test2", "test3"]
+ mock_get = mock.Mock()
+ mock_get.side_effect = ["1.2.3.4:80", "[::1]:80", "1.1.1.1:443"]
+ mock_add_dir = mock.Mock()
+ mock_enable = mock.Mock()
+
+ self.config.parser.find_dir = mock_find
+ self.config.parser.get_arg = mock_get
+ self.config.parser.add_dir_to_ifmodssl = mock_add_dir
+ self.config.enable_mod = mock_enable
+
+ # Test Listen statements with specific ip listeed
+ self.config.prepare_server_https("443")
+ # Should be 0 as one interface already listens to 443
+ self.assertEqual(mock_add_dir.call_count, 0)
+
+ # Reset return lists and inputs
+ mock_add_dir.reset_mock()
+ mock_get.side_effect = ["1.2.3.4:80", "[::1]:80", "1.1.1.1:443"]
+
+ # Test
+ self.config.prepare_server_https("8080", temp=True)
+ self.assertEqual(mock_add_dir.call_count, 3)
+ call_args_list = [mock_add_dir.call_args_list[i][0][2] for i in range(3)]
+ self.assertEqual(
+ sorted(call_args_list),
+ sorted([["1.2.3.4:8080", "https"],
+ ["[::1]:8080", "https"],
+ ["1.1.1.1:8080", "https"]]))
+
+ # mock_get.side_effect = ["1.2.3.4:80", "[::1]:80"]
+ # mock_find.return_value = ["test1", "test2", "test3"]
+ # self.config.parser.get_arg = mock_get
+ # self.config.prepare_server_https("8080", temp=True)
+ # self.assertEqual(self.listens, 0)
+
+ def test_prepare_server_https_needed_listen(self):
+ mock_find = mock.Mock()
+ mock_find.return_value = ["test1", "test2"]
+ mock_get = mock.Mock()
+ mock_get.side_effect = ["1.2.3.4:8080", "80"]
+ mock_add_dir = mock.Mock()
+ mock_enable = mock.Mock()
+
+ self.config.parser.find_dir = mock_find
+ self.config.parser.get_arg = mock_get
+ self.config.parser.add_dir_to_ifmodssl = mock_add_dir
+ self.config.enable_mod = mock_enable
+
+ self.config.prepare_server_https("443")
+ self.assertEqual(mock_add_dir.call_count, 1)
+
+ def test_prepare_server_https_mixed_listen(self):
+
+ mock_find = mock.Mock()
+ mock_find.return_value = ["test1", "test2"]
+ mock_get = mock.Mock()
+ mock_get.side_effect = ["1.2.3.4:8080", "443"]
+ mock_add_dir = mock.Mock()
+ mock_enable = mock.Mock()
+
+ self.config.parser.find_dir = mock_find
+ self.config.parser.get_arg = mock_get
+ self.config.parser.add_dir_to_ifmodssl = mock_add_dir
+ self.config.enable_mod = mock_enable
+
+ # Test Listen statements with specific ip listeed
+ self.config.prepare_server_https("443")
+ # Should only be 2 here, as the third interface
+ # already listens to the correct port
+ self.assertEqual(mock_add_dir.call_count, 0)
+
+ def test_make_vhost_ssl_with_mock_span(self):
+ # span excludes the closing </VirtualHost> tag in older versions
+ # of Augeas
+ return_value = [self.vh_truth[0].filep, 1, 12, 0, 0, 0, 1142]
+ with mock.patch.object(self.config.parser.aug, 'span') as mock_span:
+ mock_span.return_value = return_value
+ self.test_make_vhost_ssl()
+
+ def test_make_vhost_ssl_with_mock_span2(self):
+ # span includes the closing </VirtualHost> tag in newer versions
+ # of Augeas
+ return_value = [self.vh_truth[0].filep, 1, 12, 0, 0, 0, 1157]
+ with mock.patch.object(self.config.parser.aug, 'span') as mock_span:
+ mock_span.return_value = return_value
+ self.test_make_vhost_ssl()
+
+ def test_make_vhost_ssl_nonsymlink(self):
+ ssl_vhost_slink = self.config.make_vhost_ssl(self.vh_truth[8])
+ self.assertTrue(ssl_vhost_slink.ssl)
+ self.assertTrue(ssl_vhost_slink.enabled)
+ self.assertEqual(ssl_vhost_slink.name, "nonsym.link")
+
+ def test_make_vhost_ssl_nonexistent_vhost_path(self):
+ ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[1])
+ self.assertEqual(os.path.dirname(ssl_vhost.filep),
+ os.path.dirname(filesystem.realpath(self.vh_truth[1].filep)))
+
+ def test_make_vhost_ssl(self):
+ ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0])
+
+ self.assertEqual(
+ ssl_vhost.filep,
+ os.path.join(self.config_path, "sites-available",
+ "encryption-example-le-ssl.conf"))
+
+ self.assertEqual(ssl_vhost.path,
+ "/files" + ssl_vhost.filep + "/IfModule/Virtualhost")
+ self.assertEqual(len(ssl_vhost.addrs), 1)
+ self.assertEqual(set([obj.Addr.fromstring("*:443")]), ssl_vhost.addrs)
+ self.assertEqual(ssl_vhost.name, "encryption-example.demo")
+ self.assertTrue(ssl_vhost.ssl)
+ self.assertFalse(ssl_vhost.enabled)
+
+ self.assertEqual(self.config.is_name_vhost(self.vh_truth[0]),
+ self.config.is_name_vhost(ssl_vhost))
+
+ self.assertEqual(len(self.config.vhosts), 13)
+
+ def test_clean_vhost_ssl(self):
+ # pylint: disable=protected-access
+ for directive in ["SSLCertificateFile", "SSLCertificateKeyFile",
+ "SSLCertificateChainFile", "SSLCACertificatePath"]:
+ for _ in range(10):
+ self.config.parser.add_dir(self.vh_truth[1].path,
+ directive, ["bogus"])
+ self.config.save()
+
+ self.config._clean_vhost(self.vh_truth[1])
+ self.config.save()
+
+ loc_cert = self.config.parser.find_dir(
+ 'SSLCertificateFile', None, self.vh_truth[1].path, False)
+ loc_key = self.config.parser.find_dir(
+ 'SSLCertificateKeyFile', None, self.vh_truth[1].path, False)
+ loc_chain = self.config.parser.find_dir(
+ 'SSLCertificateChainFile', None, self.vh_truth[1].path, False)
+ loc_cacert = self.config.parser.find_dir(
+ 'SSLCACertificatePath', None, self.vh_truth[1].path, False)
+
+ self.assertEqual(len(loc_cert), 1)
+ self.assertEqual(len(loc_key), 1)
+
+ self.assertEqual(len(loc_chain), 0)
+
+ self.assertEqual(len(loc_cacert), 10)
+
+ def test_deduplicate_directives(self):
+ # pylint: disable=protected-access
+ DIRECTIVE = "Foo"
+ for _ in range(10):
+ self.config.parser.add_dir(self.vh_truth[1].path,
+ DIRECTIVE, ["bar"])
+ self.config.save()
+
+ self.config._deduplicate_directives(self.vh_truth[1].path, [DIRECTIVE])
+ self.config.save()
+
+ self.assertEqual(
+ len(self.config.parser.find_dir(
+ DIRECTIVE, None, self.vh_truth[1].path, False)), 1)
+
+ def test_remove_directives(self):
+ # pylint: disable=protected-access
+ DIRECTIVES = ["Foo", "Bar"]
+ for directive in DIRECTIVES:
+ for _ in range(10):
+ self.config.parser.add_dir(self.vh_truth[2].path,
+ directive, ["baz"])
+ self.config.save()
+
+ self.config._remove_directives(self.vh_truth[2].path, DIRECTIVES)
+ self.config.save()
+
+ for directive in DIRECTIVES:
+ self.assertEqual(
+ len(self.config.parser.find_dir(
+ directive, None, self.vh_truth[2].path, False)), 0)
+
+ def test_make_vhost_ssl_bad_write(self):
+ mock_open = mock.mock_open()
+ # This calls open
+ self.config.reverter.register_file_creation = mock.Mock()
+ mock_open.side_effect = IOError
+ with mock.patch("six.moves.builtins.open", mock_open):
+ self.assertRaises(
+ errors.PluginError,
+ self.config.make_vhost_ssl, self.vh_truth[0])
+
+ def test_get_ssl_vhost_path(self):
+ # pylint: disable=protected-access
+ self.assertTrue(
+ self.config._get_ssl_vhost_path("example_path").endswith(".conf"))
+
+ def test_add_name_vhost_if_necessary(self):
+ # pylint: disable=protected-access
+ self.config.add_name_vhost = mock.Mock()
+ self.config.version = (2, 2)
+ self.config._add_name_vhost_if_necessary(self.vh_truth[0])
+ self.assertTrue(self.config.add_name_vhost.called)
+
+ new_addrs = set()
+ for addr in self.vh_truth[0].addrs:
+ new_addrs.add(obj.Addr(("_default_", addr.get_port(),)))
+
+ self.vh_truth[0].addrs = new_addrs
+ self.config._add_name_vhost_if_necessary(self.vh_truth[0])
+ self.assertEqual(self.config.add_name_vhost.call_count, 2)
+
+ @mock.patch("certbot_apache._internal.configurator.http_01.ApacheHttp01.perform")
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ def test_perform(self, mock_restart, mock_http_perform):
+ # Only tests functionality specific to configurator.perform
+ # Note: As more challenges are offered this will have to be expanded
+ account_key, achalls = self.get_key_and_achalls()
+
+ expected = [achall.response(account_key) for achall in achalls]
+ mock_http_perform.return_value = expected
+
+ responses = self.config.perform(achalls)
+
+ self.assertEqual(mock_http_perform.call_count, 1)
+ self.assertEqual(responses, expected)
+
+ self.assertEqual(mock_restart.call_count, 1)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_cleanup(self, mock_cfg, mock_restart):
+ mock_cfg.return_value = ""
+ _, achalls = self.get_key_and_achalls()
+
+ for achall in achalls:
+ self.config._chall_out.add(achall) # pylint: disable=protected-access
+
+ for i, achall in enumerate(achalls):
+ self.config.cleanup([achall])
+ if i == len(achalls) - 1:
+ self.assertTrue(mock_restart.called)
+ else:
+ self.assertFalse(mock_restart.called)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_cleanup_no_errors(self, mock_cfg, mock_restart):
+ mock_cfg.return_value = ""
+ _, achalls = self.get_key_and_achalls()
+ self.config.http_doer = mock.MagicMock()
+
+ for achall in achalls:
+ self.config._chall_out.add(achall) # pylint: disable=protected-access
+
+ self.config.cleanup([achalls[-1]])
+ self.assertFalse(mock_restart.called)
+
+ self.config.cleanup(achalls)
+ self.assertTrue(mock_restart.called)
+
+ @mock.patch("certbot.util.run_script")
+ def test_get_version(self, mock_script):
+ mock_script.return_value = (
+ "Server Version: Apache/2.4.2 (Debian)", "")
+ self.assertEqual(self.config.get_version(), (2, 4, 2))
+
+ mock_script.return_value = (
+ "Server Version: Apache/2 (Linux)", "")
+ self.assertEqual(self.config.get_version(), (2,))
+
+ mock_script.return_value = (
+ "Server Version: Apache (Debian)", "")
+ self.assertRaises(errors.PluginError, self.config.get_version)
+
+ mock_script.return_value = (
+ "Server Version: Apache/2.3{0} Apache/2.4.7".format(
+ os.linesep), "")
+ self.assertRaises(errors.PluginError, self.config.get_version)
+
+ mock_script.side_effect = errors.SubprocessError("Can't find program")
+ self.assertRaises(errors.PluginError, self.config.get_version)
+
+ @mock.patch("certbot_apache._internal.configurator.util.run_script")
+ def test_restart(self, _):
+ self.config.restart()
+
+ @mock.patch("certbot_apache._internal.configurator.util.run_script")
+ def test_restart_bad_process(self, mock_run_script):
+ mock_run_script.side_effect = [None, errors.SubprocessError]
+
+ self.assertRaises(errors.MisconfigurationError, self.config.restart)
+
+ @mock.patch("certbot.util.run_script")
+ def test_config_test(self, _):
+ self.config.config_test()
+
+ @mock.patch("certbot.util.run_script")
+ def test_config_test_bad_process(self, mock_run_script):
+ mock_run_script.side_effect = errors.SubprocessError
+
+ self.assertRaises(errors.MisconfigurationError,
+ self.config.config_test)
+
+ def test_more_info(self):
+ self.assertTrue(self.config.more_info())
+
+ def test_get_chall_pref(self):
+ self.assertTrue(isinstance(self.config.get_chall_pref(""), list))
+
+ def test_install_ssl_options_conf(self):
+ path = os.path.join(self.work_dir, "test_it")
+ other_path = os.path.join(self.work_dir, "other_test_it")
+ self.config.install_ssl_options_conf(path, other_path)
+ self.assertTrue(os.path.isfile(path))
+ self.assertTrue(os.path.isfile(other_path))
+
+ # TEST ENHANCEMENTS
+ def test_supported_enhancements(self):
+ self.assertTrue(isinstance(self.config.supported_enhancements(), list))
+
+ def test_find_http_vhost_without_ancestor(self):
+ # pylint: disable=protected-access
+ vhost = self.vh_truth[0]
+ vhost.ssl = True
+ vhost.ancestor = None
+ res = self.config._get_http_vhost(vhost)
+ self.assertEqual(self.vh_truth[0].name, res.name)
+ self.assertEqual(self.vh_truth[0].aliases, res.aliases)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._get_http_vhost")
+ @mock.patch("certbot_apache._internal.display_ops.select_vhost")
+ @mock.patch("certbot.util.exe_exists")
+ def test_enhance_unknown_vhost(self, mock_exe, mock_sel_vhost, mock_get):
+ self.config.parser.modules.add("rewrite_module")
+ mock_exe.return_value = True
+ ssl_vh1 = obj.VirtualHost(
+ "fp1", "ap1", set([obj.Addr(("*", "443"))]),
+ True, False)
+ ssl_vh1.name = "satoshi.com"
+ self.config.vhosts.append(ssl_vh1)
+ mock_sel_vhost.return_value = None
+ mock_get.return_value = None
+
+ self.assertRaises(
+ errors.PluginError,
+ self.config.enhance, "satoshi.com", "redirect")
+
+ def test_enhance_unknown_enhancement(self):
+ self.assertRaises(
+ errors.PluginError,
+ self.config.enhance, "certbot.demo", "unknown_enhancement")
+
+ def test_enhance_no_ssl_vhost(self):
+ with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log:
+ self.assertRaises(errors.PluginError, self.config.enhance,
+ "certbot.demo", "redirect")
+ # Check that correct logger.warning was printed
+ self.assertTrue("not able to find" in mock_log.call_args[0][0])
+ self.assertTrue("\"redirect\"" in mock_log.call_args[0][0])
+
+ mock_log.reset_mock()
+
+ self.assertRaises(errors.PluginError, self.config.enhance,
+ "certbot.demo", "ensure-http-header", "Test")
+ # Check that correct logger.warning was printed
+ self.assertTrue("not able to find" in mock_log.call_args[0][0])
+ self.assertTrue("Test" in mock_log.call_args[0][0])
+
+ @mock.patch("certbot.util.exe_exists")
+ def test_ocsp_stapling(self, mock_exe):
+ self.config.parser.update_runtime_variables = mock.Mock()
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("socache_shmcb_module")
+ self.config.get_version = mock.Mock(return_value=(2, 4, 7))
+ mock_exe.return_value = True
+
+ # This will create an ssl vhost for certbot.demo
+ self.config.choose_vhost("certbot.demo")
+ self.config.enhance("certbot.demo", "staple-ocsp")
+
+ # Get the ssl vhost for certbot.demo
+ ssl_vhost = self.config.assoc["certbot.demo"]
+
+ ssl_use_stapling_aug_path = self.config.parser.find_dir(
+ "SSLUseStapling", "on", ssl_vhost.path)
+
+ self.assertEqual(len(ssl_use_stapling_aug_path), 1)
+
+ ssl_vhost_aug_path = parser.get_aug_path(ssl_vhost.filep)
+ stapling_cache_aug_path = self.config.parser.find_dir('SSLStaplingCache',
+ "shmcb:/var/run/apache2/stapling_cache(128000)",
+ ssl_vhost_aug_path)
+
+ self.assertEqual(len(stapling_cache_aug_path), 1)
+
+ @mock.patch("certbot.util.exe_exists")
+ def test_ocsp_stapling_twice(self, mock_exe):
+ self.config.parser.update_runtime_variables = mock.Mock()
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("socache_shmcb_module")
+ self.config.get_version = mock.Mock(return_value=(2, 4, 7))
+ mock_exe.return_value = True
+
+ # Checking the case with already enabled ocsp stapling configuration
+ self.config.choose_vhost("ocspvhost.com")
+ self.config.enhance("ocspvhost.com", "staple-ocsp")
+
+ # Get the ssl vhost for letsencrypt.demo
+ ssl_vhost = self.config.assoc["ocspvhost.com"]
+
+ ssl_use_stapling_aug_path = self.config.parser.find_dir(
+ "SSLUseStapling", "on", ssl_vhost.path)
+
+ self.assertEqual(len(ssl_use_stapling_aug_path), 1)
+ ssl_vhost_aug_path = parser.get_aug_path(ssl_vhost.filep)
+ stapling_cache_aug_path = self.config.parser.find_dir('SSLStaplingCache',
+ "shmcb:/var/run/apache2/stapling_cache(128000)",
+ ssl_vhost_aug_path)
+
+ self.assertEqual(len(stapling_cache_aug_path), 1)
+
+
+ @mock.patch("certbot.util.exe_exists")
+ def test_ocsp_unsupported_apache_version(self, mock_exe):
+ mock_exe.return_value = True
+ self.config.parser.update_runtime_variables = mock.Mock()
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("socache_shmcb_module")
+ self.config.get_version = mock.Mock(return_value=(2, 2, 0))
+ self.config.choose_vhost("certbot.demo")
+
+ self.assertRaises(errors.PluginError,
+ self.config.enhance, "certbot.demo", "staple-ocsp")
+
+
+ def test_get_http_vhost_third_filter(self):
+ ssl_vh = obj.VirtualHost(
+ "fp", "ap", set([obj.Addr(("*", "443"))]),
+ True, False)
+ ssl_vh.name = "satoshi.com"
+ self.config.vhosts.append(ssl_vh)
+
+ # pylint: disable=protected-access
+ http_vh = self.config._get_http_vhost(ssl_vh)
+ self.assertFalse(http_vh.ssl)
+
+ @mock.patch("certbot.util.run_script")
+ @mock.patch("certbot.util.exe_exists")
+ def test_http_header_hsts(self, mock_exe, _):
+ self.config.parser.update_runtime_variables = mock.Mock()
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("headers_module")
+ mock_exe.return_value = True
+
+ # This will create an ssl vhost for certbot.demo
+ self.config.choose_vhost("certbot.demo")
+ self.config.enhance("certbot.demo", "ensure-http-header",
+ "Strict-Transport-Security")
+
+ # Get the ssl vhost for certbot.demo
+ ssl_vhost = self.config.assoc["certbot.demo"]
+
+ # These are not immediately available in find_dir even with save() and
+ # load(). They must be found in sites-available
+ hsts_header = self.config.parser.find_dir(
+ "Header", None, ssl_vhost.path)
+
+ # four args to HSTS header
+ self.assertEqual(len(hsts_header), 4)
+
+ def test_http_header_hsts_twice(self):
+ self.config.parser.modules.add("mod_ssl.c")
+ # skip the enable mod
+ self.config.parser.modules.add("headers_module")
+
+ # This will create an ssl vhost for encryption-example.demo
+ self.config.choose_vhost("encryption-example.demo")
+ self.config.enhance("encryption-example.demo", "ensure-http-header",
+ "Strict-Transport-Security")
+
+ self.assertRaises(
+ errors.PluginEnhancementAlreadyPresent,
+ self.config.enhance, "encryption-example.demo",
+ "ensure-http-header", "Strict-Transport-Security")
+
+ @mock.patch("certbot.util.run_script")
+ @mock.patch("certbot.util.exe_exists")
+ def test_http_header_uir(self, mock_exe, _):
+ self.config.parser.update_runtime_variables = mock.Mock()
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("headers_module")
+
+ mock_exe.return_value = True
+
+ # This will create an ssl vhost for certbot.demo
+ self.config.choose_vhost("certbot.demo")
+ self.config.enhance("certbot.demo", "ensure-http-header",
+ "Upgrade-Insecure-Requests")
+
+ self.assertTrue("headers_module" in self.config.parser.modules)
+
+ # Get the ssl vhost for certbot.demo
+ ssl_vhost = self.config.assoc["certbot.demo"]
+
+ # These are not immediately available in find_dir even with save() and
+ # load(). They must be found in sites-available
+ uir_header = self.config.parser.find_dir(
+ "Header", None, ssl_vhost.path)
+
+ # four args to HSTS header
+ self.assertEqual(len(uir_header), 4)
+
+ def test_http_header_uir_twice(self):
+ self.config.parser.modules.add("mod_ssl.c")
+ # skip the enable mod
+ self.config.parser.modules.add("headers_module")
+
+ # This will create an ssl vhost for encryption-example.demo
+ self.config.choose_vhost("encryption-example.demo")
+ self.config.enhance("encryption-example.demo", "ensure-http-header",
+ "Upgrade-Insecure-Requests")
+
+ self.assertRaises(
+ errors.PluginEnhancementAlreadyPresent,
+ self.config.enhance, "encryption-example.demo",
+ "ensure-http-header", "Upgrade-Insecure-Requests")
+
+ @mock.patch("certbot.util.run_script")
+ @mock.patch("certbot.util.exe_exists")
+ def test_redirect_well_formed_http(self, mock_exe, _):
+ self.config.parser.modules.add("rewrite_module")
+ self.config.parser.update_runtime_variables = mock.Mock()
+ mock_exe.return_value = True
+ self.config.get_version = mock.Mock(return_value=(2, 2))
+
+ # This will create an ssl vhost for certbot.demo
+ self.config.choose_vhost("certbot.demo")
+ self.config.enhance("certbot.demo", "redirect")
+
+ # These are not immediately available in find_dir even with save() and
+ # load(). They must be found in sites-available
+ rw_engine = self.config.parser.find_dir(
+ "RewriteEngine", "on", self.vh_truth[3].path)
+ rw_rule = self.config.parser.find_dir(
+ "RewriteRule", None, self.vh_truth[3].path)
+
+ self.assertEqual(len(rw_engine), 1)
+ # three args to rw_rule
+ self.assertEqual(len(rw_rule), 3)
+
+ # [:-3] to remove the vhost index number
+ self.assertTrue(rw_engine[0].startswith(self.vh_truth[3].path[:-3]))
+ self.assertTrue(rw_rule[0].startswith(self.vh_truth[3].path[:-3]))
+
+ def test_rewrite_rule_exists(self):
+ # Skip the enable mod
+ self.config.parser.modules.add("rewrite_module")
+ self.config.get_version = mock.Mock(return_value=(2, 3, 9))
+ self.config.parser.add_dir(
+ self.vh_truth[3].path, "RewriteRule", ["Unknown"])
+ # pylint: disable=protected-access
+ self.assertTrue(self.config._is_rewrite_exists(self.vh_truth[3]))
+
+ def test_rewrite_engine_exists(self):
+ # Skip the enable mod
+ self.config.parser.modules.add("rewrite_module")
+ self.config.get_version = mock.Mock(return_value=(2, 3, 9))
+ self.config.parser.add_dir(
+ self.vh_truth[3].path, "RewriteEngine", "on")
+ # pylint: disable=protected-access
+ self.assertTrue(self.config._is_rewrite_engine_on(self.vh_truth[3]))
+
+ @mock.patch("certbot.util.run_script")
+ @mock.patch("certbot.util.exe_exists")
+ def test_redirect_with_existing_rewrite(self, mock_exe, _):
+ self.config.parser.modules.add("rewrite_module")
+ self.config.parser.update_runtime_variables = mock.Mock()
+ mock_exe.return_value = True
+ self.config.get_version = mock.Mock(return_value=(2, 2, 0))
+
+ # Create a preexisting rewrite rule
+ self.config.parser.add_dir(
+ self.vh_truth[3].path, "RewriteRule", ["UnknownPattern",
+ "UnknownTarget"])
+ self.config.save()
+
+ # This will create an ssl vhost for certbot.demo
+ self.config.choose_vhost("certbot.demo")
+ self.config.enhance("certbot.demo", "redirect")
+
+ # These are not immediately available in find_dir even with save() and
+ # load(). They must be found in sites-available
+ rw_engine = self.config.parser.find_dir(
+ "RewriteEngine", "on", self.vh_truth[3].path)
+ rw_rule = self.config.parser.find_dir(
+ "RewriteRule", None, self.vh_truth[3].path)
+
+ self.assertEqual(len(rw_engine), 1)
+ # three args to rw_rule + 1 arg for the pre existing rewrite
+ self.assertEqual(len(rw_rule), 5)
+ # [:-3] to remove the vhost index number
+ self.assertTrue(rw_engine[0].startswith(self.vh_truth[3].path[:-3]))
+ self.assertTrue(rw_rule[0].startswith(self.vh_truth[3].path[:-3]))
+
+ self.assertTrue("rewrite_module" in self.config.parser.modules)
+
+ @mock.patch("certbot.util.run_script")
+ @mock.patch("certbot.util.exe_exists")
+ def test_redirect_with_old_https_redirection(self, mock_exe, _):
+ self.config.parser.modules.add("rewrite_module")
+ self.config.parser.update_runtime_variables = mock.Mock()
+ mock_exe.return_value = True
+ self.config.get_version = mock.Mock(return_value=(2, 2, 0))
+
+ ssl_vhost = self.config.choose_vhost("certbot.demo")
+
+ # pylint: disable=protected-access
+ http_vhost = self.config._get_http_vhost(ssl_vhost)
+
+ # Create an old (previously suppoorted) https redirectoin rewrite rule
+ self.config.parser.add_dir(
+ http_vhost.path, "RewriteRule",
+ ["^",
+ "https://%{SERVER_NAME}%{REQUEST_URI}",
+ "[L,QSA,R=permanent]"])
+
+ self.config.save()
+
+ try:
+ self.config.enhance("certbot.demo", "redirect")
+ except errors.PluginEnhancementAlreadyPresent:
+ args_paths = self.config.parser.find_dir(
+ "RewriteRule", None, http_vhost.path, False)
+ arg_vals = [self.config.parser.aug.get(x) for x in args_paths]
+ self.assertEqual(arg_vals, constants.REWRITE_HTTPS_ARGS)
+
+
+ def test_redirect_with_conflict(self):
+ self.config.parser.modules.add("rewrite_module")
+ ssl_vh = obj.VirtualHost(
+ "fp", "ap", set([obj.Addr(("*", "443")),
+ obj.Addr(("zombo.com",))]),
+ True, False)
+ # No names ^ this guy should conflict.
+
+ # pylint: disable=protected-access
+ self.assertRaises(
+ errors.PluginError, self.config._enable_redirect, ssl_vh, "")
+
+ def test_redirect_two_domains_one_vhost(self):
+ # Skip the enable mod
+ self.config.parser.modules.add("rewrite_module")
+ self.config.get_version = mock.Mock(return_value=(2, 3, 9))
+
+ # Creates ssl vhost for the domain
+ self.config.choose_vhost("red.blue.purple.com")
+
+ self.config.enhance("red.blue.purple.com", "redirect")
+ verify_no_redirect = ("certbot_apache._internal.configurator."
+ "ApacheConfigurator._verify_no_certbot_redirect")
+ with mock.patch(verify_no_redirect) as mock_verify:
+ self.config.enhance("green.blue.purple.com", "redirect")
+ self.assertFalse(mock_verify.called)
+
+ def test_redirect_from_previous_run(self):
+ # Skip the enable mod
+ self.config.parser.modules.add("rewrite_module")
+ self.config.get_version = mock.Mock(return_value=(2, 3, 9))
+ self.config.choose_vhost("red.blue.purple.com")
+ self.config.enhance("red.blue.purple.com", "redirect")
+ # Clear state about enabling redirect on this run
+ # pylint: disable=protected-access
+ self.config._enhanced_vhosts["redirect"].clear()
+
+ self.assertRaises(
+ errors.PluginEnhancementAlreadyPresent,
+ self.config.enhance, "green.blue.purple.com", "redirect")
+
+ def test_create_own_redirect(self):
+ self.config.parser.modules.add("rewrite_module")
+ self.config.get_version = mock.Mock(return_value=(2, 3, 9))
+ # For full testing... give names...
+ self.vh_truth[1].name = "default.com"
+ self.vh_truth[1].aliases = set(["yes.default.com"])
+
+ # pylint: disable=protected-access
+ self.config._enable_redirect(self.vh_truth[1], "")
+ self.assertEqual(len(self.config.vhosts), 13)
+
+ def test_create_own_redirect_for_old_apache_version(self):
+ self.config.parser.modules.add("rewrite_module")
+ self.config.get_version = mock.Mock(return_value=(2, 2))
+ # For full testing... give names...
+ self.vh_truth[1].name = "default.com"
+ self.vh_truth[1].aliases = set(["yes.default.com"])
+
+ # pylint: disable=protected-access
+ self.config._enable_redirect(self.vh_truth[1], "")
+ self.assertEqual(len(self.config.vhosts), 13)
+
+ def test_sift_rewrite_rule(self):
+ # pylint: disable=protected-access
+ small_quoted_target = "RewriteRule ^ \"http://\""
+ self.assertFalse(self.config._sift_rewrite_rule(small_quoted_target))
+
+ https_target = "RewriteRule ^ https://satoshi"
+ self.assertTrue(self.config._sift_rewrite_rule(https_target))
+
+ normal_target = "RewriteRule ^/(.*) http://www.a.com:1234/$1 [L,R]"
+ self.assertFalse(self.config._sift_rewrite_rule(normal_target))
+
+ not_rewriterule = "NotRewriteRule ^ ..."
+ self.assertFalse(self.config._sift_rewrite_rule(not_rewriterule))
+
+ def get_key_and_achalls(self):
+ """Return testing achallenges."""
+ account_key = self.rsa512jwk
+ achall1 = achallenges.KeyAuthorizationAnnotatedChallenge(
+ challb=acme_util.chall_to_challb(
+ challenges.HTTP01(
+ token=b"jIq_Xy1mXGN37tb4L6Xj_es58fW571ZNyXekdZzhh7Q"),
+ "pending"),
+ domain="encryption-example.demo", account_key=account_key)
+ achall2 = achallenges.KeyAuthorizationAnnotatedChallenge(
+ challb=acme_util.chall_to_challb(
+ challenges.HTTP01(
+ token=b"uqnaPzxtrndteOqtrXb0Asl5gOJfWAnnx6QJyvcmlDU"),
+ "pending"),
+ domain="certbot.demo", account_key=account_key)
+ achall3 = achallenges.KeyAuthorizationAnnotatedChallenge(
+ challb=acme_util.chall_to_challb(
+ challenges.HTTP01(token=(b'x' * 16)), "pending"),
+ domain="example.org", account_key=account_key)
+
+ return account_key, (achall1, achall2, achall3)
+
+ def test_enable_site_nondebian(self):
+ inc_path = "/path/to/wherever"
+ vhost = self.vh_truth[0]
+ vhost.enabled = False
+ vhost.filep = inc_path
+ self.assertFalse(self.config.parser.find_dir("Include", inc_path))
+ self.assertFalse(
+ os.path.dirname(inc_path) in self.config.parser.existing_paths)
+ self.config.enable_site(vhost)
+ self.assertTrue(self.config.parser.find_dir("Include", inc_path))
+ self.assertTrue(
+ os.path.dirname(inc_path) in self.config.parser.existing_paths)
+ self.assertTrue(
+ os.path.basename(inc_path) in self.config.parser.existing_paths[
+ os.path.dirname(inc_path)])
+
+ def test_deploy_cert_not_parsed_path(self):
+ # Make sure that we add include to root config for vhosts when
+ # handle-sites is false
+ self.config.parser.modules.add("ssl_module")
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("socache_shmcb_module")
+ tmp_path = filesystem.realpath(tempfile.mkdtemp("vhostroot"))
+ filesystem.chmod(tmp_path, 0o755)
+ mock_p = "certbot_apache._internal.configurator.ApacheConfigurator._get_ssl_vhost_path"
+ mock_a = "certbot_apache._internal.parser.ApacheParser.add_include"
+
+ with mock.patch(mock_p) as mock_path:
+ mock_path.return_value = os.path.join(tmp_path, "whatever.conf")
+ with mock.patch(mock_a) as mock_add:
+ self.config.deploy_cert(
+ "encryption-example.demo",
+ "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem")
+ # Test that we actually called add_include
+ self.assertTrue(mock_add.called)
+ shutil.rmtree(tmp_path)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.parsed_in_original")
+ def test_choose_vhost_and_servername_addition_parsed(self, mock_parsed):
+ ret_vh = self.vh_truth[8]
+ ret_vh.enabled = True
+ self.config.enable_site(ret_vh)
+ # Make sure that we return early
+ self.assertFalse(mock_parsed.called)
+
+ def test_enable_mod_unsupported(self):
+ self.assertRaises(errors.MisconfigurationError,
+ self.config.enable_mod,
+ "whatever")
+
+ def test_wildcard_domain(self):
+ # pylint: disable=protected-access
+ cases = {u"*.example.org": True, b"*.x.example.org": True,
+ u"a.example.org": False, b"a.x.example.org": False}
+ for key in cases:
+ self.assertEqual(self.config._wildcard_domain(key), cases[key])
+
+ def test_choose_vhosts_wildcard(self):
+ # pylint: disable=protected-access
+ mock_path = "certbot_apache._internal.display_ops.select_vhost_multiple"
+ with mock.patch(mock_path) as mock_select_vhs:
+ mock_select_vhs.return_value = [self.vh_truth[3]]
+ vhs = self.config._choose_vhosts_wildcard("*.certbot.demo",
+ create_ssl=True)
+ # Check that the dialog was called with one vh: certbot.demo
+ self.assertEqual(mock_select_vhs.call_args[0][0][0], self.vh_truth[3])
+ self.assertEqual(len(mock_select_vhs.call_args_list), 1)
+
+ # And the actual returned values
+ self.assertEqual(len(vhs), 1)
+ self.assertTrue(vhs[0].name == "certbot.demo")
+ self.assertTrue(vhs[0].ssl)
+
+ self.assertFalse(vhs[0] == self.vh_truth[3])
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.make_vhost_ssl")
+ def test_choose_vhosts_wildcard_no_ssl(self, mock_makessl):
+ # pylint: disable=protected-access
+ mock_path = "certbot_apache._internal.display_ops.select_vhost_multiple"
+ with mock.patch(mock_path) as mock_select_vhs:
+ mock_select_vhs.return_value = [self.vh_truth[1]]
+ vhs = self.config._choose_vhosts_wildcard("*.certbot.demo",
+ create_ssl=False)
+ self.assertFalse(mock_makessl.called)
+ self.assertEqual(vhs[0], self.vh_truth[1])
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._vhosts_for_wildcard")
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.make_vhost_ssl")
+ def test_choose_vhosts_wildcard_already_ssl(self, mock_makessl, mock_vh_for_w):
+ # pylint: disable=protected-access
+ # Already SSL vhost
+ mock_vh_for_w.return_value = [self.vh_truth[7]]
+ mock_path = "certbot_apache._internal.display_ops.select_vhost_multiple"
+ with mock.patch(mock_path) as mock_select_vhs:
+ mock_select_vhs.return_value = [self.vh_truth[7]]
+ vhs = self.config._choose_vhosts_wildcard("whatever",
+ create_ssl=True)
+ self.assertEqual(mock_select_vhs.call_args[0][0][0], self.vh_truth[7])
+ self.assertEqual(len(mock_select_vhs.call_args_list), 1)
+ # Ensure that make_vhost_ssl was not called, vhost.ssl == true
+ self.assertFalse(mock_makessl.called)
+
+ # And the actual returned values
+ self.assertEqual(len(vhs), 1)
+ self.assertTrue(vhs[0].ssl)
+ self.assertEqual(vhs[0], self.vh_truth[7])
+
+
+ def test_deploy_cert_wildcard(self):
+ # pylint: disable=protected-access
+ mock_choose_vhosts = mock.MagicMock()
+ mock_choose_vhosts.return_value = [self.vh_truth[7]]
+ self.config._choose_vhosts_wildcard = mock_choose_vhosts
+ mock_d = "certbot_apache._internal.configurator.ApacheConfigurator._deploy_cert"
+ with mock.patch(mock_d) as mock_dep:
+ self.config.deploy_cert("*.wildcard.example.org", "/tmp/path",
+ "/tmp/path", "/tmp/path", "/tmp/path")
+ self.assertTrue(mock_dep.called)
+ self.assertEqual(len(mock_dep.call_args_list), 1)
+ self.assertEqual(self.vh_truth[7], mock_dep.call_args_list[0][0][0])
+
+ @mock.patch("certbot_apache._internal.display_ops.select_vhost_multiple")
+ def test_deploy_cert_wildcard_no_vhosts(self, mock_dialog):
+ # pylint: disable=protected-access
+ mock_dialog.return_value = []
+ self.assertRaises(errors.PluginError,
+ self.config.deploy_cert,
+ "*.wild.cat", "/tmp/path", "/tmp/path",
+ "/tmp/path", "/tmp/path")
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._choose_vhosts_wildcard")
+ def test_enhance_wildcard_after_install(self, mock_choose):
+ # pylint: disable=protected-access
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("headers_module")
+ self.vh_truth[3].ssl = True
+ self.config._wildcard_vhosts["*.certbot.demo"] = [self.vh_truth[3]]
+ self.config.enhance("*.certbot.demo", "ensure-http-header",
+ "Upgrade-Insecure-Requests")
+ self.assertFalse(mock_choose.called)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._choose_vhosts_wildcard")
+ def test_enhance_wildcard_no_install(self, mock_choose):
+ self.vh_truth[3].ssl = True
+ mock_choose.return_value = [self.vh_truth[3]]
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.parser.modules.add("headers_module")
+ self.config.enhance("*.certbot.demo", "ensure-http-header",
+ "Upgrade-Insecure-Requests")
+ self.assertTrue(mock_choose.called)
+
+ def test_add_vhost_id(self):
+ for vh in [self.vh_truth[0], self.vh_truth[1], self.vh_truth[2]]:
+ vh_id = self.config.add_vhost_id(vh)
+ self.assertEqual(vh, self.config.find_vhost_by_id(vh_id))
+
+ def test_find_vhost_by_id_404(self):
+ self.assertRaises(errors.PluginError,
+ self.config.find_vhost_by_id,
+ "nonexistent")
+
+ def test_add_vhost_id_already_exists(self):
+ first_id = self.config.add_vhost_id(self.vh_truth[0])
+ second_id = self.config.add_vhost_id(self.vh_truth[0])
+ self.assertEqual(first_id, second_id)
+
+ def test_realpath_replaces_symlink(self):
+ orig_match = self.config.parser.aug.match
+ mock_vhost = copy.deepcopy(self.vh_truth[0])
+ mock_vhost.filep = mock_vhost.filep.replace('sites-enabled', u'sites-available')
+ mock_vhost.path = mock_vhost.path.replace('sites-enabled', 'sites-available')
+ mock_vhost.enabled = False
+ self.config.parser.parse_file(mock_vhost.filep)
+
+ def mock_match(aug_expr):
+ """Return a mocked match list of VirtualHosts"""
+ if "/mocked/path" in aug_expr:
+ return [self.vh_truth[1].path, self.vh_truth[0].path, mock_vhost.path]
+ return orig_match(aug_expr)
+
+ self.config.parser.parser_paths = ["/mocked/path"]
+ self.config.parser.aug.match = mock_match
+ vhs = self.config.get_virtual_hosts()
+ self.assertEqual(len(vhs), 2)
+ self.assertTrue(vhs[0] == self.vh_truth[1])
+ # mock_vhost should have replaced the vh_truth[0], because its filepath
+ # isn't a symlink
+ self.assertTrue(vhs[1] == mock_vhost)
+
+
+class AugeasVhostsTest(util.ApacheTest):
+ """Test vhosts with illegal names dependent on augeas version."""
+ # pylint: disable=protected-access
+
+ def setUp(self): # pylint: disable=arguments-differ
+ td = "debian_apache_2_4/augeas_vhosts"
+ cr = "debian_apache_2_4/augeas_vhosts/apache2"
+ vr = "debian_apache_2_4/augeas_vhosts/apache2/sites-available"
+ super(AugeasVhostsTest, self).setUp(test_dir=td,
+ config_root=cr,
+ vhost_root=vr)
+
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir,
+ self.work_dir)
+
+ def test_choosevhost_with_illegal_name(self):
+ self.config.parser.aug = mock.MagicMock()
+ self.config.parser.aug.match.side_effect = RuntimeError
+ path = "debian_apache_2_4/augeas_vhosts/apache2/sites-available/old-and-default.conf"
+ chosen_vhost = self.config._create_vhost(path)
+ self.assertEqual(None, chosen_vhost)
+
+ def test_choosevhost_works(self):
+ path = "debian_apache_2_4/augeas_vhosts/apache2/sites-available/old-and-default.conf"
+ chosen_vhost = self.config._create_vhost(path)
+ self.assertTrue(chosen_vhost is None or chosen_vhost.path == path)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._create_vhost")
+ def test_get_vhost_continue(self, mock_vhost):
+ mock_vhost.return_value = None
+ vhs = self.config.get_virtual_hosts()
+ self.assertEqual([], vhs)
+
+ def test_choose_vhost_with_matching_wildcard(self):
+ names = (
+ "an.example.net", "another.example.net", "an.other.example.net")
+ for name in names:
+ self.assertFalse(name in self.config.choose_vhost(name).aliases)
+
+ @mock.patch("certbot_apache._internal.obj.VirtualHost.conflicts")
+ def test_choose_vhost_without_matching_wildcard(self, mock_conflicts):
+ mock_conflicts.return_value = False
+ mock_path = "certbot_apache._internal.display_ops.select_vhost"
+ with mock.patch(mock_path, lambda _, vhosts: vhosts[0]):
+ for name in ("a.example.net", "other.example.net"):
+ self.assertTrue(name in self.config.choose_vhost(name).aliases)
+
+ @mock.patch("certbot_apache._internal.obj.VirtualHost.conflicts")
+ def test_choose_vhost_wildcard_not_found(self, mock_conflicts):
+ mock_conflicts.return_value = False
+ mock_path = "certbot_apache._internal.display_ops.select_vhost"
+ names = (
+ "abc.example.net", "not.there.tld", "aa.wildcard.tld"
+ )
+ with mock.patch(mock_path) as mock_select:
+ mock_select.return_value = self.config.vhosts[0]
+ for name in names:
+ orig_cc = mock_select.call_count
+ self.config.choose_vhost(name)
+ self.assertEqual(mock_select.call_count - orig_cc, 1)
+
+ def test_choose_vhost_wildcard_found(self):
+ mock_path = "certbot_apache._internal.display_ops.select_vhost"
+ names = (
+ "ab.example.net", "a.wildcard.tld", "yetanother.example.net"
+ )
+ with mock.patch(mock_path) as mock_select:
+ mock_select.return_value = self.config.vhosts[0]
+ for name in names:
+ self.config.choose_vhost(name)
+ self.assertEqual(mock_select.call_count, 0)
+
+ def test_augeas_span_error(self):
+ broken_vhost = self.config.vhosts[0]
+ broken_vhost.path = broken_vhost.path + "/nonexistent"
+ self.assertRaises(errors.PluginError, self.config.make_vhost_ssl,
+ broken_vhost)
+
+class MultiVhostsTest(util.ApacheTest):
+ """Test configuration with multiple virtualhosts in a single file."""
+ # pylint: disable=protected-access
+
+ def setUp(self): # pylint: disable=arguments-differ
+ td = "debian_apache_2_4/multi_vhosts"
+ cr = "debian_apache_2_4/multi_vhosts/apache2"
+ vr = "debian_apache_2_4/multi_vhosts/apache2/sites-available"
+ super(MultiVhostsTest, self).setUp(test_dir=td,
+ config_root=cr,
+ vhost_root=vr)
+
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path,
+ self.config_dir, self.work_dir, conf_vhost_path=self.vhost_path)
+ self.vh_truth = util.get_vh_truth(
+ self.temp_dir, "debian_apache_2_4/multi_vhosts")
+
+ def test_make_vhost_ssl(self):
+ ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[1])
+
+ self.assertEqual(
+ ssl_vhost.filep,
+ os.path.join(self.config_path, "sites-available",
+ "default-le-ssl.conf"))
+
+ self.assertEqual(ssl_vhost.path,
+ "/files" + ssl_vhost.filep + "/IfModule/VirtualHost")
+ self.assertEqual(len(ssl_vhost.addrs), 1)
+ self.assertEqual(set([obj.Addr.fromstring("*:443")]), ssl_vhost.addrs)
+ self.assertEqual(ssl_vhost.name, "banana.vomit.com")
+ self.assertTrue(ssl_vhost.ssl)
+ self.assertFalse(ssl_vhost.enabled)
+
+
+ self.assertEqual(self.config.is_name_vhost(self.vh_truth[1]),
+ self.config.is_name_vhost(ssl_vhost))
+
+ mock_path = "certbot_apache._internal.configurator.ApacheConfigurator._get_new_vh_path"
+ with mock.patch(mock_path) as mock_getpath:
+ mock_getpath.return_value = None
+ self.assertRaises(errors.PluginError, self.config.make_vhost_ssl,
+ self.vh_truth[1])
+
+ def test_get_new_path(self):
+ with_index_1 = ["/path[1]/section[1]"]
+ without_index = ["/path/section"]
+ with_index_2 = ["/path[2]/section[2]"]
+ self.assertEqual(self.config._get_new_vh_path(without_index,
+ with_index_1),
+ None)
+ self.assertEqual(self.config._get_new_vh_path(without_index,
+ with_index_2),
+ with_index_2[0])
+
+ both = with_index_1 + with_index_2
+ self.assertEqual(self.config._get_new_vh_path(without_index, both),
+ with_index_2[0])
+
+ @certbot_util.patch_get_utility()
+ def test_make_vhost_ssl_with_existing_rewrite_rule(self, mock_get_utility):
+ self.config.parser.modules.add("rewrite_module")
+
+ ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[4])
+
+ self.assertTrue(self.config.parser.find_dir(
+ "RewriteEngine", "on", ssl_vhost.path, False))
+
+ with open(ssl_vhost.filep) as the_file:
+ conf_text = the_file.read()
+ commented_rewrite_rule = ("# RewriteRule \"^/secrets/(.+)\" "
+ "\"https://new.example.com/docs/$1\" [R,L]")
+ uncommented_rewrite_rule = ("RewriteRule \"^/docs/(.+)\" "
+ "\"http://new.example.com/docs/$1\" [R,L]")
+ self.assertTrue(commented_rewrite_rule in conf_text)
+ self.assertTrue(uncommented_rewrite_rule in conf_text)
+ mock_get_utility().add_message.assert_called_once_with(mock.ANY,
+ mock.ANY)
+
+ @certbot_util.patch_get_utility()
+ def test_make_vhost_ssl_with_existing_rewrite_conds(self, mock_get_utility):
+ self.config.parser.modules.add("rewrite_module")
+
+ ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[3])
+
+ with open(ssl_vhost.filep) as the_file:
+ conf_lines = the_file.readlines()
+ conf_line_set = [l.strip() for l in conf_lines]
+ not_commented_cond1 = ("RewriteCond "
+ "%{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f")
+ not_commented_rewrite_rule = ("RewriteRule "
+ "^(.*)$ b://u%{REQUEST_URI} [P,NE,L]")
+
+ commented_cond1 = "# RewriteCond %{HTTPS} !=on"
+ commented_cond2 = "# RewriteCond %{HTTPS} !^$"
+ commented_rewrite_rule = ("# RewriteRule ^ "
+ "https://%{SERVER_NAME}%{REQUEST_URI} "
+ "[L,NE,R=permanent]")
+
+ self.assertTrue(not_commented_cond1 in conf_line_set)
+ self.assertTrue(not_commented_rewrite_rule in conf_line_set)
+
+ self.assertTrue(commented_cond1 in conf_line_set)
+ self.assertTrue(commented_cond2 in conf_line_set)
+ self.assertTrue(commented_rewrite_rule in conf_line_set)
+ mock_get_utility().add_message.assert_called_once_with(mock.ANY,
+ mock.ANY)
+
+
+class InstallSslOptionsConfTest(util.ApacheTest):
+ """Test that the options-ssl-nginx.conf file is installed and updated properly."""
+
+ def setUp(self): # pylint: disable=arguments-differ
+ super(InstallSslOptionsConfTest, self).setUp()
+
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir)
+
+ def _call(self):
+ self.config.install_ssl_options_conf(self.config.mod_ssl_conf,
+ self.config.updated_mod_ssl_conf_digest)
+
+ def _current_ssl_options_hash(self):
+ return crypto_util.sha256sum(self.config.option("MOD_SSL_CONF_SRC"))
+
+ def _assert_current_file(self):
+ self.assertTrue(os.path.isfile(self.config.mod_ssl_conf))
+ self.assertEqual(crypto_util.sha256sum(self.config.mod_ssl_conf),
+ self._current_ssl_options_hash())
+
+ def test_no_file(self):
+ # prepare should have placed a file there
+ self._assert_current_file()
+ os.remove(self.config.mod_ssl_conf)
+ self.assertFalse(os.path.isfile(self.config.mod_ssl_conf))
+ self._call()
+ self._assert_current_file()
+
+ def test_current_file(self):
+ self._assert_current_file()
+ self._call()
+ self._assert_current_file()
+
+ def test_prev_file_updates_to_current(self):
+ from certbot_apache._internal.constants import ALL_SSL_OPTIONS_HASHES
+ ALL_SSL_OPTIONS_HASHES.insert(0, "test_hash_does_not_match")
+ with mock.patch('certbot.crypto_util.sha256sum') as mock_sha256:
+ mock_sha256.return_value = ALL_SSL_OPTIONS_HASHES[0]
+ self._call()
+ self._assert_current_file()
+
+ def test_manually_modified_current_file_does_not_update(self):
+ with open(self.config.mod_ssl_conf, "a") as mod_ssl_conf:
+ mod_ssl_conf.write("a new line for the wrong hash\n")
+ with mock.patch("certbot.plugins.common.logger") as mock_logger:
+ self._call()
+ self.assertFalse(mock_logger.warning.called)
+ self.assertTrue(os.path.isfile(self.config.mod_ssl_conf))
+ self.assertEqual(crypto_util.sha256sum(
+ self.config.option("MOD_SSL_CONF_SRC")),
+ self._current_ssl_options_hash())
+ self.assertNotEqual(crypto_util.sha256sum(self.config.mod_ssl_conf),
+ self._current_ssl_options_hash())
+
+ def test_manually_modified_past_file_warns(self):
+ with open(self.config.mod_ssl_conf, "a") as mod_ssl_conf:
+ mod_ssl_conf.write("a new line for the wrong hash\n")
+ with open(self.config.updated_mod_ssl_conf_digest, "w") as f:
+ f.write("hashofanoldversion")
+ with mock.patch("certbot.plugins.common.logger") as mock_logger:
+ self._call()
+ self.assertEqual(mock_logger.warning.call_args[0][0],
+ "%s has been manually modified; updated file "
+ "saved to %s. We recommend updating %s for security purposes.")
+ self.assertEqual(crypto_util.sha256sum(
+ self.config.option("MOD_SSL_CONF_SRC")),
+ self._current_ssl_options_hash())
+ # only print warning once
+ with mock.patch("certbot.plugins.common.logger") as mock_logger:
+ self._call()
+ self.assertFalse(mock_logger.warning.called)
+
+ def test_current_file_hash_in_all_hashes(self):
+ from certbot_apache._internal.constants import ALL_SSL_OPTIONS_HASHES
+ self.assertTrue(self._current_ssl_options_hash() in ALL_SSL_OPTIONS_HASHES,
+ "Constants.ALL_SSL_OPTIONS_HASHES must be appended"
+ " with the sha256 hash of self.config.mod_ssl_conf when it is updated.")
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/debian_test.py b/certbot-apache/tests/debian_test.py
new file mode 100644
index 000000000..6e63a9bd3
--- /dev/null
+++ b/certbot-apache/tests/debian_test.py
@@ -0,0 +1,212 @@
+"""Test for certbot_apache._internal.configurator for Debian overrides"""
+import shutil
+import unittest
+
+import mock
+
+from certbot import errors
+from certbot.compat import os
+from certbot_apache._internal import apache_util
+from certbot_apache._internal import obj
+import util
+
+
+class MultipleVhostsTestDebian(util.ApacheTest):
+ """Multiple vhost tests for Debian family of distros"""
+
+ _multiprocess_can_split_ = True
+
+ def setUp(self): # pylint: disable=arguments-differ
+ super(MultipleVhostsTestDebian, self).setUp()
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir,
+ os_info="debian")
+ self.config = self.mock_deploy_cert(self.config)
+ self.vh_truth = util.get_vh_truth(self.temp_dir,
+ "debian_apache_2_4/multiple_vhosts")
+
+ def mock_deploy_cert(self, config):
+ """A test for a mock deploy cert"""
+ config.real_deploy_cert = self.config.deploy_cert
+
+ def mocked_deploy_cert(*args, **kwargs):
+ """a helper to mock a deployed cert"""
+ g_mod = "certbot_apache._internal.configurator.ApacheConfigurator.enable_mod"
+ d_mod = "certbot_apache._internal.override_debian.DebianConfigurator.enable_mod"
+ with mock.patch(g_mod):
+ with mock.patch(d_mod):
+ config.real_deploy_cert(*args, **kwargs)
+ self.config.deploy_cert = mocked_deploy_cert
+ return self.config
+
+ def test_enable_mod_unsupported_dirs(self):
+ shutil.rmtree(os.path.join(self.config.parser.root, "mods-enabled"))
+ self.assertRaises(
+ errors.NotSupportedError, self.config.enable_mod, "ssl")
+
+ @mock.patch("certbot.util.run_script")
+ @mock.patch("certbot.util.exe_exists")
+ @mock.patch("certbot_apache._internal.parser.subprocess.Popen")
+ def test_enable_mod(self, mock_popen, mock_exe_exists, mock_run_script):
+ mock_popen().communicate.return_value = ("Define: DUMP_RUN_CFG", "")
+ mock_popen().returncode = 0
+ mock_exe_exists.return_value = True
+
+ self.config.enable_mod("ssl")
+ self.assertTrue("ssl_module" in self.config.parser.modules)
+ self.assertTrue("mod_ssl.c" in self.config.parser.modules)
+
+ self.assertTrue(mock_run_script.called)
+
+ def test_deploy_cert_enable_new_vhost(self):
+ # Create
+ ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0])
+ self.config.parser.modules.add("ssl_module")
+ self.config.parser.modules.add("mod_ssl.c")
+ self.assertFalse(ssl_vhost.enabled)
+ self.config.deploy_cert(
+ "encryption-example.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+ self.assertTrue(ssl_vhost.enabled)
+ # Make sure that we don't error out if symlink already exists
+ ssl_vhost.enabled = False
+ self.assertFalse(ssl_vhost.enabled)
+ self.config.deploy_cert(
+ "encryption-example.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+ self.assertTrue(ssl_vhost.enabled)
+
+ def test_enable_site_failure(self):
+ self.config.parser.root = "/tmp/nonexistent"
+ with mock.patch("certbot.compat.os.path.isdir") as mock_dir:
+ mock_dir.return_value = True
+ with mock.patch("certbot.compat.os.path.islink") as mock_link:
+ mock_link.return_value = False
+ self.assertRaises(
+ errors.NotSupportedError,
+ self.config.enable_site,
+ obj.VirtualHost("asdf", "afsaf", set(), False, False))
+
+ def test_deploy_cert_newssl(self):
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir,
+ self.work_dir, version=(2, 4, 16))
+ self.config = self.mock_deploy_cert(self.config)
+ self.config.parser.modules.add("ssl_module")
+ self.config.parser.modules.add("mod_ssl.c")
+
+ # Get the default 443 vhost
+ self.config.assoc["random.demo"] = self.vh_truth[1]
+ self.config.deploy_cert(
+ "random.demo", "example/cert.pem", "example/key.pem",
+ "example/cert_chain.pem", "example/fullchain.pem")
+ self.config.save()
+
+ # Verify ssl_module was enabled.
+ self.assertTrue(self.vh_truth[1].enabled)
+ self.assertTrue("ssl_module" in self.config.parser.modules)
+
+ loc_cert = self.config.parser.find_dir(
+ "sslcertificatefile", "example/fullchain.pem",
+ self.vh_truth[1].path)
+ loc_key = self.config.parser.find_dir(
+ "sslcertificateKeyfile", "example/key.pem", self.vh_truth[1].path)
+
+ # Verify one directive was found in the correct file
+ self.assertEqual(len(loc_cert), 1)
+ self.assertEqual(
+ apache_util.get_file_path(loc_cert[0]),
+ self.vh_truth[1].filep)
+
+ self.assertEqual(len(loc_key), 1)
+ self.assertEqual(
+ apache_util.get_file_path(loc_key[0]),
+ self.vh_truth[1].filep)
+
+ def test_deploy_cert_newssl_no_fullchain(self):
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir,
+ self.work_dir, version=(2, 4, 16))
+ self.config = self.mock_deploy_cert(self.config)
+ self.config.parser.modules.add("ssl_module")
+ self.config.parser.modules.add("mod_ssl.c")
+
+ # Get the default 443 vhost
+ self.config.assoc["random.demo"] = self.vh_truth[1]
+ self.assertRaises(errors.PluginError,
+ lambda: self.config.deploy_cert(
+ "random.demo", "example/cert.pem",
+ "example/key.pem"))
+
+ def test_deploy_cert_old_apache_no_chain(self):
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir,
+ self.work_dir, version=(2, 4, 7))
+ self.config = self.mock_deploy_cert(self.config)
+ self.config.parser.modules.add("ssl_module")
+ self.config.parser.modules.add("mod_ssl.c")
+
+ # Get the default 443 vhost
+ self.config.assoc["random.demo"] = self.vh_truth[1]
+ self.assertRaises(errors.PluginError,
+ lambda: self.config.deploy_cert(
+ "random.demo", "example/cert.pem",
+ "example/key.pem"))
+
+ @mock.patch("certbot.util.run_script")
+ @mock.patch("certbot.util.exe_exists")
+ def test_ocsp_stapling_enable_mod(self, mock_exe, _):
+ self.config.parser.update_runtime_variables = mock.Mock()
+ self.config.parser.modules.add("mod_ssl.c")
+ self.config.get_version = mock.Mock(return_value=(2, 4, 7))
+ mock_exe.return_value = True
+ # This will create an ssl vhost for certbot.demo
+ self.config.choose_vhost("certbot.demo")
+ self.config.enhance("certbot.demo", "staple-ocsp")
+ self.assertTrue("socache_shmcb_module" in self.config.parser.modules)
+
+ @mock.patch("certbot.util.run_script")
+ @mock.patch("certbot.util.exe_exists")
+ def test_ensure_http_header_enable_mod(self, mock_exe, _):
+ self.config.parser.update_runtime_variables = mock.Mock()
+ self.config.parser.modules.add("mod_ssl.c")
+ mock_exe.return_value = True
+
+ # This will create an ssl vhost for certbot.demo
+ self.config.choose_vhost("certbot.demo")
+ self.config.enhance("certbot.demo", "ensure-http-header",
+ "Strict-Transport-Security")
+ self.assertTrue("headers_module" in self.config.parser.modules)
+
+ @mock.patch("certbot.util.run_script")
+ @mock.patch("certbot.util.exe_exists")
+ def test_redirect_enable_mod(self, mock_exe, _):
+ self.config.parser.update_runtime_variables = mock.Mock()
+ mock_exe.return_value = True
+ self.config.get_version = mock.Mock(return_value=(2, 2))
+ # This will create an ssl vhost for certbot.demo
+ self.config.choose_vhost("certbot.demo")
+ self.config.enhance("certbot.demo", "redirect")
+ self.assertTrue("rewrite_module" in self.config.parser.modules)
+
+ def test_enable_site_already_enabled(self):
+ self.assertTrue(self.vh_truth[1].enabled)
+ self.config.enable_site(self.vh_truth[1])
+
+ def test_enable_site_call_parent(self):
+ with mock.patch(
+ "certbot_apache._internal.configurator.ApacheConfigurator.enable_site") as e_s:
+ self.config.parser.root = "/tmp/nonexistent"
+ vh = self.vh_truth[0]
+ vh.enabled = False
+ self.config.enable_site(vh)
+ self.assertTrue(e_s.called)
+
+ @mock.patch("certbot.util.exe_exists")
+ def test_enable_mod_no_disable(self, mock_exe_exists):
+ mock_exe_exists.return_value = False
+ self.assertRaises(
+ errors.MisconfigurationError, self.config.enable_mod, "ssl")
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/display_ops_test.py b/certbot-apache/tests/display_ops_test.py
new file mode 100644
index 000000000..50bdc03cf
--- /dev/null
+++ b/certbot-apache/tests/display_ops_test.py
@@ -0,0 +1,104 @@
+"""Test certbot_apache._internal.display_ops."""
+import unittest
+
+import mock
+
+from certbot import errors
+from certbot.display import util as display_util
+from certbot.tests import util as certbot_util
+from certbot_apache._internal import obj
+from certbot_apache._internal.display_ops import select_vhost_multiple
+import util
+
+
+class SelectVhostMultiTest(unittest.TestCase):
+ """Tests for certbot_apache._internal.display_ops.select_vhost_multiple."""
+
+ def setUp(self):
+ self.base_dir = "/example_path"
+ self.vhosts = util.get_vh_truth(
+ self.base_dir, "debian_apache_2_4/multiple_vhosts")
+
+ def test_select_no_input(self):
+ self.assertFalse(select_vhost_multiple([]))
+
+ @certbot_util.patch_get_utility()
+ def test_select_correct(self, mock_util):
+ mock_util().checklist.return_value = (
+ display_util.OK, [self.vhosts[3].display_repr(),
+ self.vhosts[2].display_repr()])
+ vhs = select_vhost_multiple([self.vhosts[3],
+ self.vhosts[2],
+ self.vhosts[1]])
+ self.assertTrue(self.vhosts[2] in vhs)
+ self.assertTrue(self.vhosts[3] in vhs)
+ self.assertFalse(self.vhosts[1] in vhs)
+
+ @certbot_util.patch_get_utility()
+ def test_select_cancel(self, mock_util):
+ mock_util().checklist.return_value = (display_util.CANCEL, "whatever")
+ vhs = select_vhost_multiple([self.vhosts[2], self.vhosts[3]])
+ self.assertFalse(vhs)
+
+class SelectVhostTest(unittest.TestCase):
+ """Tests for certbot_apache._internal.display_ops.select_vhost."""
+
+ def setUp(self):
+ self.base_dir = "/example_path"
+ self.vhosts = util.get_vh_truth(
+ self.base_dir, "debian_apache_2_4/multiple_vhosts")
+
+ @classmethod
+ def _call(cls, vhosts):
+ from certbot_apache._internal.display_ops import select_vhost
+ return select_vhost("example.com", vhosts)
+
+ @certbot_util.patch_get_utility()
+ def test_successful_choice(self, mock_util):
+ mock_util().menu.return_value = (display_util.OK, 3)
+ self.assertEqual(self.vhosts[3], self._call(self.vhosts))
+
+ @certbot_util.patch_get_utility()
+ def test_noninteractive(self, mock_util):
+ mock_util().menu.side_effect = errors.MissingCommandlineFlag("no vhost default")
+ try:
+ self._call(self.vhosts)
+ except errors.MissingCommandlineFlag as e:
+ self.assertTrue("vhost ambiguity" in str(e))
+
+ @certbot_util.patch_get_utility()
+ def test_more_info_cancel(self, mock_util):
+ mock_util().menu.side_effect = [
+ (display_util.CANCEL, -1),
+ ]
+
+ self.assertEqual(None, self._call(self.vhosts))
+
+ def test_no_vhosts(self):
+ self.assertEqual(self._call([]), None)
+
+ @mock.patch("certbot_apache._internal.display_ops.display_util")
+ @certbot_util.patch_get_utility()
+ @mock.patch("certbot_apache._internal.display_ops.logger")
+ def test_small_display(self, mock_logger, mock_util, mock_display_util):
+ mock_display_util.WIDTH = 20
+ mock_util().menu.return_value = (display_util.OK, 0)
+ self._call(self.vhosts)
+
+ self.assertEqual(mock_logger.debug.call_count, 1)
+
+ @certbot_util.patch_get_utility()
+ def test_multiple_names(self, mock_util):
+ mock_util().menu.return_value = (display_util.OK, 5)
+
+ self.vhosts.append(
+ obj.VirtualHost(
+ "path", "aug_path", set([obj.Addr.fromstring("*:80")]),
+ False, False,
+ "wildcard.com", set(["*.wildcard.com"])))
+
+ self.assertEqual(self.vhosts[5], self._call(self.vhosts))
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/entrypoint_test.py b/certbot-apache/tests/entrypoint_test.py
new file mode 100644
index 000000000..04c393bdf
--- /dev/null
+++ b/certbot-apache/tests/entrypoint_test.py
@@ -0,0 +1,47 @@
+"""Test for certbot_apache._internal.entrypoint for override class resolution"""
+import unittest
+
+import mock
+
+from certbot_apache._internal import configurator
+from certbot_apache._internal import entrypoint
+
+
+class EntryPointTest(unittest.TestCase):
+ """Entrypoint tests"""
+
+ _multiprocess_can_split_ = True
+
+ def test_get_configurator(self):
+
+ with mock.patch("certbot.util.get_os_info") as mock_info:
+ for distro in entrypoint.OVERRIDE_CLASSES:
+ return_value = (distro, "whatever")
+ if distro == 'fedora_old':
+ return_value = ('fedora', '28')
+ elif distro == 'fedora':
+ return_value = ('fedora', '29')
+ mock_info.return_value = return_value
+ self.assertEqual(entrypoint.get_configurator(),
+ entrypoint.OVERRIDE_CLASSES[distro])
+
+ def test_nonexistent_like(self):
+ with mock.patch("certbot.util.get_os_info") as mock_info:
+ mock_info.return_value = ("nonexistent", "irrelevant")
+ with mock.patch("certbot.util.get_systemd_os_like") as mock_like:
+ for like in entrypoint.OVERRIDE_CLASSES:
+ mock_like.return_value = [like]
+ self.assertEqual(entrypoint.get_configurator(),
+ entrypoint.OVERRIDE_CLASSES[like])
+
+ def test_nonexistent_generic(self):
+ with mock.patch("certbot.util.get_os_info") as mock_info:
+ mock_info.return_value = ("nonexistent", "irrelevant")
+ with mock.patch("certbot.util.get_systemd_os_like") as mock_like:
+ mock_like.return_value = ["unknonwn"]
+ self.assertEqual(entrypoint.get_configurator(),
+ configurator.ApacheConfigurator)
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/fedora_test.py b/certbot-apache/tests/fedora_test.py
new file mode 100644
index 000000000..2bfd6babb
--- /dev/null
+++ b/certbot-apache/tests/fedora_test.py
@@ -0,0 +1,194 @@
+"""Test for certbot_apache._internal.configurator for Fedora 29+ overrides"""
+import unittest
+
+import mock
+
+from certbot import errors
+from certbot.compat import filesystem
+from certbot.compat import os
+from certbot_apache._internal import obj
+from certbot_apache._internal import override_fedora
+import util
+
+
+def get_vh_truth(temp_dir, config_name):
+ """Return the ground truth for the specified directory."""
+ prefix = os.path.join(
+ temp_dir, config_name, "httpd/conf.d")
+
+ aug_pre = "/files" + prefix
+ # TODO: eventually, these tests should have a dedicated configuration instead
+ # of reusing the ones from centos_test
+ vh_truth = [
+ obj.VirtualHost(
+ os.path.join(prefix, "centos.example.com.conf"),
+ os.path.join(aug_pre, "centos.example.com.conf/VirtualHost"),
+ {obj.Addr.fromstring("*:80")},
+ False, True, "centos.example.com"),
+ obj.VirtualHost(
+ os.path.join(prefix, "ssl.conf"),
+ os.path.join(aug_pre, "ssl.conf/VirtualHost"),
+ {obj.Addr.fromstring("_default_:443")},
+ True, True, None)
+ ]
+ return vh_truth
+
+
+class FedoraRestartTest(util.ApacheTest):
+ """Tests for Fedora specific self-signed certificate override"""
+
+ # TODO: eventually, these tests should have a dedicated configuration instead
+ # of reusing the ones from centos_test
+ def setUp(self): # pylint: disable=arguments-differ
+ test_dir = "centos7_apache/apache"
+ config_root = "centos7_apache/apache/httpd"
+ vhost_root = "centos7_apache/apache/httpd/conf.d"
+ super(FedoraRestartTest, self).setUp(test_dir=test_dir,
+ config_root=config_root,
+ vhost_root=vhost_root)
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir,
+ os_info="fedora")
+ self.vh_truth = get_vh_truth(
+ self.temp_dir, "centos7_apache/apache")
+
+ def _run_fedora_test(self):
+ self.assertIsInstance(self.config, override_fedora.FedoraConfigurator)
+ self.config.config_test()
+
+ def test_fedora_restart_error(self):
+ c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
+ with mock.patch(c_test) as mock_test:
+ # First call raises error, second doesn't
+ mock_test.side_effect = [errors.MisconfigurationError, '']
+ with mock.patch("certbot.util.run_script") as mock_run:
+ mock_run.side_effect = errors.SubprocessError
+ self.assertRaises(errors.MisconfigurationError,
+ self._run_fedora_test)
+
+ def test_fedora_restart(self):
+ c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
+ with mock.patch(c_test) as mock_test:
+ with mock.patch("certbot.util.run_script") as mock_run:
+ # First call raises error, second doesn't
+ mock_test.side_effect = [errors.MisconfigurationError, '']
+ self._run_fedora_test()
+ self.assertEqual(mock_test.call_count, 2)
+ self.assertEqual(mock_run.call_args[0][0],
+ ['systemctl', 'restart', 'httpd'])
+
+
+class MultipleVhostsTestFedora(util.ApacheTest):
+ """Multiple vhost tests for CentOS / RHEL family of distros"""
+
+ _multiprocess_can_split_ = True
+
+ def setUp(self): # pylint: disable=arguments-differ
+ test_dir = "centos7_apache/apache"
+ config_root = "centos7_apache/apache/httpd"
+ vhost_root = "centos7_apache/apache/httpd/conf.d"
+ super(MultipleVhostsTestFedora, self).setUp(test_dir=test_dir,
+ config_root=config_root,
+ vhost_root=vhost_root)
+
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir,
+ os_info="fedora")
+ self.vh_truth = get_vh_truth(
+ self.temp_dir, "centos7_apache/apache")
+
+ def test_get_parser(self):
+ self.assertIsInstance(self.config.parser, override_fedora.FedoraParser)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_opportunistic_httpd_runtime_parsing(self, mock_get):
+ define_val = (
+ 'Define: TEST1\n'
+ 'Define: TEST2\n'
+ 'Define: DUMP_RUN_CFG\n'
+ )
+ mod_val = (
+ 'Loaded Modules:\n'
+ ' mock_module (static)\n'
+ ' another_module (static)\n'
+ )
+ def mock_get_cfg(command):
+ """Mock httpd process stdout"""
+ if command == ['httpd', '-t', '-D', 'DUMP_RUN_CFG']:
+ return define_val
+ elif command == ['httpd', '-t', '-D', 'DUMP_MODULES']:
+ return mod_val
+ return ""
+ mock_get.side_effect = mock_get_cfg
+ self.config.parser.modules = set()
+ self.config.parser.variables = {}
+
+ with mock.patch("certbot.util.get_os_info") as mock_osi:
+ # Make sure we have the have the CentOS httpd constants
+ mock_osi.return_value = ("fedora", "29")
+ self.config.parser.update_runtime_variables()
+
+ self.assertEqual(mock_get.call_count, 3)
+ self.assertEqual(len(self.config.parser.modules), 4)
+ self.assertEqual(len(self.config.parser.variables), 2)
+ self.assertTrue("TEST2" in self.config.parser.variables.keys())
+ self.assertTrue("mod_another.c" in self.config.parser.modules)
+
+ @mock.patch("certbot_apache._internal.configurator.util.run_script")
+ def test_get_version(self, mock_run_script):
+ mock_run_script.return_value = ('', None)
+ self.assertRaises(errors.PluginError, self.config.get_version)
+ self.assertEqual(mock_run_script.call_args[0][0][0], 'httpd')
+
+ def test_get_virtual_hosts(self):
+ """Make sure all vhosts are being properly found."""
+ vhs = self.config.get_virtual_hosts()
+ self.assertEqual(len(vhs), 2)
+ found = 0
+
+ for vhost in vhs:
+ for centos_truth in self.vh_truth:
+ if vhost == centos_truth:
+ found += 1
+ break
+ else:
+ raise Exception("Missed: %s" % vhost) # pragma: no cover
+ self.assertEqual(found, 2)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_get_sysconfig_vars(self, mock_cfg):
+ """Make sure we read the sysconfig OPTIONS variable correctly"""
+ # Return nothing for the process calls
+ mock_cfg.return_value = ""
+ self.config.parser.sysconfig_filep = filesystem.realpath(
+ os.path.join(self.config.parser.root, "../sysconfig/httpd"))
+ self.config.parser.variables = {}
+
+ with mock.patch("certbot.util.get_os_info") as mock_osi:
+ # Make sure we have the have the CentOS httpd constants
+ mock_osi.return_value = ("fedora", "29")
+ self.config.parser.update_runtime_variables()
+
+ self.assertTrue("mock_define" in self.config.parser.variables.keys())
+ self.assertTrue("mock_define_too" in self.config.parser.variables.keys())
+ self.assertTrue("mock_value" in self.config.parser.variables.keys())
+ self.assertEqual("TRUE", self.config.parser.variables["mock_value"])
+ self.assertTrue("MOCK_NOSEP" in self.config.parser.variables.keys())
+ self.assertEqual("NOSEP_VAL", self.config.parser.variables["NOSEP_TWO"])
+
+ @mock.patch("certbot_apache._internal.configurator.util.run_script")
+ def test_alt_restart_works(self, mock_run_script):
+ mock_run_script.side_effect = [None, errors.SubprocessError, None]
+ self.config.restart()
+ self.assertEqual(mock_run_script.call_count, 3)
+
+ @mock.patch("certbot_apache._internal.configurator.util.run_script")
+ def test_alt_restart_errors(self, mock_run_script):
+ mock_run_script.side_effect = [None,
+ errors.SubprocessError,
+ errors.SubprocessError]
+ self.assertRaises(errors.MisconfigurationError, self.config.restart)
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/gentoo_test.py b/certbot-apache/tests/gentoo_test.py
new file mode 100644
index 000000000..90a163fd3
--- /dev/null
+++ b/certbot-apache/tests/gentoo_test.py
@@ -0,0 +1,138 @@
+"""Test for certbot_apache._internal.configurator for Gentoo overrides"""
+import unittest
+
+import mock
+
+from certbot import errors
+from certbot.compat import filesystem
+from certbot.compat import os
+from certbot_apache._internal import obj
+from certbot_apache._internal import override_gentoo
+import util
+
+
+def get_vh_truth(temp_dir, config_name):
+ """Return the ground truth for the specified directory."""
+ prefix = os.path.join(
+ temp_dir, config_name, "apache2/vhosts.d")
+
+ aug_pre = "/files" + prefix
+ vh_truth = [
+ obj.VirtualHost(
+ os.path.join(prefix, "gentoo.example.com.conf"),
+ os.path.join(aug_pre, "gentoo.example.com.conf/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "gentoo.example.com"),
+ obj.VirtualHost(
+ os.path.join(prefix, "00_default_vhost.conf"),
+ os.path.join(aug_pre, "00_default_vhost.conf/IfDefine/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "localhost"),
+ obj.VirtualHost(
+ os.path.join(prefix, "00_default_ssl_vhost.conf"),
+ os.path.join(aug_pre,
+ "00_default_ssl_vhost.conf" +
+ "/IfDefine/IfDefine/IfModule/VirtualHost"),
+ set([obj.Addr.fromstring("_default_:443")]),
+ True, True, "localhost")
+ ]
+ return vh_truth
+
+class MultipleVhostsTestGentoo(util.ApacheTest):
+ """Multiple vhost tests for non-debian distro"""
+
+ _multiprocess_can_split_ = True
+
+ def setUp(self): # pylint: disable=arguments-differ
+ test_dir = "gentoo_apache/apache"
+ config_root = "gentoo_apache/apache/apache2"
+ vhost_root = "gentoo_apache/apache/apache2/vhosts.d"
+ super(MultipleVhostsTestGentoo, self).setUp(test_dir=test_dir,
+ config_root=config_root,
+ vhost_root=vhost_root)
+
+ # pylint: disable=line-too-long
+ with mock.patch("certbot_apache._internal.override_gentoo.GentooParser.update_runtime_variables"):
+ self.config = util.get_apache_configurator(
+ self.config_path, self.vhost_path, self.config_dir, self.work_dir,
+ os_info="gentoo")
+ self.vh_truth = get_vh_truth(
+ self.temp_dir, "gentoo_apache/apache")
+
+ def test_get_parser(self):
+ self.assertTrue(isinstance(self.config.parser,
+ override_gentoo.GentooParser))
+
+ def test_get_virtual_hosts(self):
+ """Make sure all vhosts are being properly found."""
+ vhs = self.config.get_virtual_hosts()
+ self.assertEqual(len(vhs), 3)
+ found = 0
+
+ for vhost in vhs:
+ for gentoo_truth in self.vh_truth:
+ if vhost == gentoo_truth:
+ found += 1
+ break
+ else:
+ raise Exception("Missed: %s" % vhost) # pragma: no cover
+ self.assertEqual(found, 3)
+
+ def test_get_sysconfig_vars(self):
+ """Make sure we read the Gentoo APACHE2_OPTS variable correctly"""
+ defines = ['DEFAULT_VHOST', 'INFO',
+ 'SSL', 'SSL_DEFAULT_VHOST', 'LANGUAGE']
+ self.config.parser.apacheconfig_filep = filesystem.realpath(
+ os.path.join(self.config.parser.root, "../conf.d/apache2"))
+ self.config.parser.variables = {}
+ with mock.patch("certbot_apache._internal.override_gentoo.GentooParser.update_modules"):
+ self.config.parser.update_runtime_variables()
+ for define in defines:
+ self.assertTrue(define in self.config.parser.variables.keys())
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.parse_from_subprocess")
+ def test_no_binary_configdump(self, mock_subprocess):
+ """Make sure we don't call binary dumps other than modules from Apache
+ as this is not supported in Gentoo currently"""
+
+ with mock.patch("certbot_apache._internal.override_gentoo.GentooParser.update_modules"):
+ self.config.parser.update_runtime_variables()
+ self.config.parser.reset_modules()
+ self.assertFalse(mock_subprocess.called)
+
+ self.config.parser.update_runtime_variables()
+ self.config.parser.reset_modules()
+ self.assertTrue(mock_subprocess.called)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_opportunistic_httpd_runtime_parsing(self, mock_get):
+ mod_val = (
+ 'Loaded Modules:\n'
+ ' mock_module (static)\n'
+ ' another_module (static)\n'
+ )
+ def mock_get_cfg(command):
+ """Mock httpd process stdout"""
+ if command == ['apache2ctl', 'modules']:
+ return mod_val
+ return None # pragma: no cover
+ mock_get.side_effect = mock_get_cfg
+ self.config.parser.modules = set()
+
+ with mock.patch("certbot.util.get_os_info") as mock_osi:
+ # Make sure we have the have the Gentoo httpd constants
+ mock_osi.return_value = ("gentoo", "123")
+ self.config.parser.update_runtime_variables()
+
+ self.assertEqual(mock_get.call_count, 1)
+ self.assertEqual(len(self.config.parser.modules), 4)
+ self.assertTrue("mod_another.c" in self.config.parser.modules)
+
+ @mock.patch("certbot_apache._internal.configurator.util.run_script")
+ def test_alt_restart_works(self, mock_run_script):
+ mock_run_script.side_effect = [None, errors.SubprocessError, None]
+ self.config.restart()
+ self.assertEqual(mock_run_script.call_count, 3)
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/http_01_test.py b/certbot-apache/tests/http_01_test.py
new file mode 100644
index 000000000..643a6bdd5
--- /dev/null
+++ b/certbot-apache/tests/http_01_test.py
@@ -0,0 +1,226 @@
+"""Test for certbot_apache._internal.http_01."""
+import unittest
+
+import mock
+
+from acme import challenges
+from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module
+from certbot import achallenges
+from certbot import errors
+from certbot.compat import filesystem
+from certbot.compat import os
+from certbot.tests import acme_util
+from certbot_apache._internal.parser import get_aug_path
+import util
+
+NUM_ACHALLS = 3
+
+
+class ApacheHttp01Test(util.ApacheTest):
+ """Test for certbot_apache._internal.http_01.ApacheHttp01."""
+
+ def setUp(self, *args, **kwargs): # pylint: disable=arguments-differ
+ super(ApacheHttp01Test, self).setUp(*args, **kwargs)
+
+ self.account_key = self.rsa512jwk
+ self.achalls = [] # type: List[achallenges.KeyAuthorizationAnnotatedChallenge]
+ vh_truth = util.get_vh_truth(
+ self.temp_dir, "debian_apache_2_4/multiple_vhosts")
+ # Takes the vhosts for encryption-example.demo, certbot.demo
+ # and vhost.in.rootconf
+ self.vhosts = [vh_truth[0], vh_truth[3], vh_truth[10]]
+
+ for i in range(NUM_ACHALLS):
+ self.achalls.append(
+ achallenges.KeyAuthorizationAnnotatedChallenge(
+ challb=acme_util.chall_to_challb(
+ challenges.HTTP01(token=((chr(ord('a') + i).encode() * 16))),
+ "pending"),
+ domain=self.vhosts[i].name, account_key=self.account_key))
+
+ modules = ["ssl", "rewrite", "authz_core", "authz_host"]
+ for mod in modules:
+ self.config.parser.modules.add("mod_{0}.c".format(mod))
+ self.config.parser.modules.add(mod + "_module")
+
+ from certbot_apache._internal.http_01 import ApacheHttp01
+ self.http = ApacheHttp01(self.config)
+
+ def test_empty_perform(self):
+ self.assertFalse(self.http.perform())
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.enable_mod")
+ def test_enable_modules_apache_2_2(self, mock_enmod):
+ self.config.version = (2, 2)
+ self.config.parser.modules.remove("authz_host_module")
+ self.config.parser.modules.remove("mod_authz_host.c")
+
+ enmod_calls = self.common_enable_modules_test(mock_enmod)
+ self.assertEqual(enmod_calls[0][0][0], "authz_host")
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.enable_mod")
+ def test_enable_modules_apache_2_4(self, mock_enmod):
+ self.config.parser.modules.remove("authz_core_module")
+ self.config.parser.modules.remove("mod_authz_core.c")
+
+ enmod_calls = self.common_enable_modules_test(mock_enmod)
+ self.assertEqual(enmod_calls[0][0][0], "authz_core")
+
+ def common_enable_modules_test(self, mock_enmod):
+ """Tests enabling mod_rewrite and other modules."""
+ self.config.parser.modules.remove("rewrite_module")
+ self.config.parser.modules.remove("mod_rewrite.c")
+
+ self.http.prepare_http01_modules()
+
+ self.assertTrue(mock_enmod.called)
+ calls = mock_enmod.call_args_list
+ other_calls = []
+ for call in calls:
+ if call[0][0] != "rewrite":
+ other_calls.append(call)
+
+ # If these lists are equal, we never enabled mod_rewrite
+ self.assertNotEqual(calls, other_calls)
+ return other_calls
+
+ def test_same_vhost(self):
+ vhost = next(v for v in self.config.vhosts if v.name == "certbot.demo")
+ achalls = [
+ achallenges.KeyAuthorizationAnnotatedChallenge(
+ challb=acme_util.chall_to_challb(
+ challenges.HTTP01(token=((b'a' * 16))),
+ "pending"),
+ domain=vhost.name, account_key=self.account_key),
+ achallenges.KeyAuthorizationAnnotatedChallenge(
+ challb=acme_util.chall_to_challb(
+ challenges.HTTP01(token=((b'b' * 16))),
+ "pending"),
+ domain=next(iter(vhost.aliases)), account_key=self.account_key)
+ ]
+ self.common_perform_test(achalls, [vhost])
+
+ def test_anonymous_vhost(self):
+ vhosts = [v for v in self.config.vhosts if not v.ssl]
+ achalls = [
+ achallenges.KeyAuthorizationAnnotatedChallenge(
+ challb=acme_util.chall_to_challb(
+ challenges.HTTP01(token=((b'a' * 16))),
+ "pending"),
+ domain="something.nonexistent", account_key=self.account_key)]
+ self.common_perform_test(achalls, vhosts)
+
+ def test_configure_multiple_vhosts(self):
+ vhosts = [v for v in self.config.vhosts if "duplicate.example.com" in v.get_names()]
+ self.assertEqual(len(vhosts), 2)
+ achalls = [
+ achallenges.KeyAuthorizationAnnotatedChallenge(
+ challb=acme_util.chall_to_challb(
+ challenges.HTTP01(token=((b'a' * 16))),
+ "pending"),
+ domain="duplicate.example.com", account_key=self.account_key)]
+ self.common_perform_test(achalls, vhosts)
+
+ def test_no_vhost(self):
+ for achall in self.achalls:
+ self.http.add_chall(achall)
+ self.config.config.http01_port = 12345
+ self.assertRaises(errors.PluginError, self.http.perform)
+
+ def test_perform_1_achall_apache_2_2(self):
+ self.combinations_perform_test(num_achalls=1, minor_version=2)
+
+ def test_perform_1_achall_apache_2_4(self):
+ self.combinations_perform_test(num_achalls=1, minor_version=4)
+
+ def test_perform_2_achall_apache_2_2(self):
+ self.combinations_perform_test(num_achalls=2, minor_version=2)
+
+ def test_perform_2_achall_apache_2_4(self):
+ self.combinations_perform_test(num_achalls=2, minor_version=4)
+
+ def test_perform_3_achall_apache_2_2(self):
+ self.combinations_perform_test(num_achalls=3, minor_version=2)
+
+ def test_perform_3_achall_apache_2_4(self):
+ self.combinations_perform_test(num_achalls=3, minor_version=4)
+
+ def test_activate_disabled_vhost(self):
+ vhosts = [v for v in self.config.vhosts if v.name == "certbot.demo"]
+ achalls = [
+ achallenges.KeyAuthorizationAnnotatedChallenge(
+ challb=acme_util.chall_to_challb(
+ challenges.HTTP01(token=((b'a' * 16))),
+ "pending"),
+ domain="certbot.demo", account_key=self.account_key)]
+ vhosts[0].enabled = False
+ self.common_perform_test(achalls, vhosts)
+ matches = self.config.parser.find_dir(
+ "Include", vhosts[0].filep,
+ get_aug_path(self.config.parser.loc["default"]))
+ self.assertEqual(len(matches), 1)
+
+ def combinations_perform_test(self, num_achalls, minor_version):
+ """Test perform with the given achall count and Apache version."""
+ achalls = self.achalls[:num_achalls]
+ vhosts = self.vhosts[:num_achalls]
+ self.config.version = (2, minor_version)
+ self.common_perform_test(achalls, vhosts)
+
+ def common_perform_test(self, achalls, vhosts):
+ """Tests perform with the given achalls."""
+ challenge_dir = self.http.challenge_dir
+ self.assertFalse(os.path.exists(challenge_dir))
+ for achall in achalls:
+ self.http.add_chall(achall)
+
+ expected_response = [
+ achall.response(self.account_key) for achall in achalls]
+ self.assertEqual(self.http.perform(), expected_response)
+
+ self.assertTrue(os.path.isdir(self.http.challenge_dir))
+ self.assertTrue(filesystem.has_min_permissions(self.http.challenge_dir, 0o755))
+ self._test_challenge_conf()
+
+ for achall in achalls:
+ self._test_challenge_file(achall)
+
+ for vhost in vhosts:
+ matches = self.config.parser.find_dir("Include",
+ self.http.challenge_conf_pre,
+ vhost.path)
+ self.assertEqual(len(matches), 1)
+ matches = self.config.parser.find_dir("Include",
+ self.http.challenge_conf_post,
+ vhost.path)
+ self.assertEqual(len(matches), 1)
+
+ self.assertTrue(os.path.exists(challenge_dir))
+
+ def _test_challenge_conf(self):
+ with open(self.http.challenge_conf_pre) as f:
+ pre_conf_contents = f.read()
+
+ with open(self.http.challenge_conf_post) as f:
+ post_conf_contents = f.read()
+
+ self.assertTrue("RewriteEngine on" in pre_conf_contents)
+ self.assertTrue("RewriteRule" in pre_conf_contents)
+
+ self.assertTrue(self.http.challenge_dir in post_conf_contents)
+ if self.config.version < (2, 4):
+ self.assertTrue("Allow from all" in post_conf_contents)
+ else:
+ self.assertTrue("Require all granted" in post_conf_contents)
+
+ def _test_challenge_file(self, achall):
+ name = os.path.join(self.http.challenge_dir, achall.chall.encode("token"))
+ validation = achall.validation(self.account_key)
+
+ self.assertTrue(filesystem.has_min_permissions(name, 0o644))
+ with open(name, 'rb') as f:
+ self.assertEqual(f.read(), validation.encode())
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/obj_test.py b/certbot-apache/tests/obj_test.py
new file mode 100644
index 000000000..1761b9c94
--- /dev/null
+++ b/certbot-apache/tests/obj_test.py
@@ -0,0 +1,141 @@
+"""Tests for certbot_apache._internal.obj."""
+import unittest
+
+
+class VirtualHostTest(unittest.TestCase):
+ """Test the VirtualHost class."""
+
+ def setUp(self):
+ from certbot_apache._internal.obj import Addr
+ from certbot_apache._internal.obj import VirtualHost
+
+ self.addr1 = Addr.fromstring("127.0.0.1")
+ self.addr2 = Addr.fromstring("127.0.0.1:443")
+ self.addr_default = Addr.fromstring("_default_:443")
+
+ self.vhost1 = VirtualHost(
+ "filep", "vh_path", set([self.addr1]), False, False, "localhost")
+
+ self.vhost1b = VirtualHost(
+ "filep", "vh_path", set([self.addr1]), False, False, "localhost")
+
+ self.vhost2 = VirtualHost(
+ "fp", "vhp", set([self.addr2]), False, False, "localhost")
+
+ def test_repr(self):
+ self.assertEqual(repr(self.addr2),
+ "certbot_apache._internal.obj.Addr(('127.0.0.1', '443'))")
+
+ def test_eq(self):
+ self.assertTrue(self.vhost1b == self.vhost1)
+ self.assertFalse(self.vhost1 == self.vhost2)
+ self.assertEqual(str(self.vhost1b), str(self.vhost1))
+ self.assertFalse(self.vhost1b == 1234)
+
+ def test_ne(self):
+ self.assertTrue(self.vhost1 != self.vhost2)
+ self.assertFalse(self.vhost1 != self.vhost1b)
+
+ def test_conflicts(self):
+ from certbot_apache._internal.obj import Addr
+ from certbot_apache._internal.obj import VirtualHost
+
+ complex_vh = VirtualHost(
+ "fp", "vhp",
+ set([Addr.fromstring("*:443"), Addr.fromstring("1.2.3.4:443")]),
+ False, False)
+ self.assertTrue(complex_vh.conflicts([self.addr1]))
+ self.assertTrue(complex_vh.conflicts([self.addr2]))
+ self.assertFalse(complex_vh.conflicts([self.addr_default]))
+
+ self.assertTrue(self.vhost1.conflicts([self.addr2]))
+ self.assertFalse(self.vhost1.conflicts([self.addr_default]))
+
+ self.assertFalse(self.vhost2.conflicts([self.addr1,
+ self.addr_default]))
+
+ def test_same_server(self):
+ from certbot_apache._internal.obj import VirtualHost
+ no_name1 = VirtualHost(
+ "fp", "vhp", set([self.addr1]), False, False, None)
+ no_name2 = VirtualHost(
+ "fp", "vhp", set([self.addr2]), False, False, None)
+ no_name3 = VirtualHost(
+ "fp", "vhp", set([self.addr_default]),
+ False, False, None)
+ no_name4 = VirtualHost(
+ "fp", "vhp", set([self.addr2, self.addr_default]),
+ False, False, None)
+
+ self.assertTrue(self.vhost1.same_server(self.vhost2))
+ self.assertTrue(no_name1.same_server(no_name2))
+
+ self.assertFalse(self.vhost1.same_server(no_name1))
+ self.assertFalse(no_name1.same_server(no_name3))
+ self.assertFalse(no_name1.same_server(no_name4))
+
+
+class AddrTest(unittest.TestCase):
+ """Test obj.Addr."""
+ def setUp(self):
+ from certbot_apache._internal.obj import Addr
+ self.addr = Addr.fromstring("*:443")
+
+ self.addr1 = Addr.fromstring("127.0.0.1")
+ self.addr2 = Addr.fromstring("127.0.0.1:*")
+
+ self.addr_defined = Addr.fromstring("127.0.0.1:443")
+ self.addr_default = Addr.fromstring("_default_:443")
+
+ def test_wildcard(self):
+ self.assertFalse(self.addr.is_wildcard())
+ self.assertTrue(self.addr1.is_wildcard())
+ self.assertTrue(self.addr2.is_wildcard())
+
+ def test_get_sni_addr(self):
+ from certbot_apache._internal.obj import Addr
+ self.assertEqual(
+ self.addr.get_sni_addr("443"), Addr.fromstring("*:443"))
+ self.assertEqual(
+ self.addr.get_sni_addr("225"), Addr.fromstring("*:225"))
+ self.assertEqual(
+ self.addr1.get_sni_addr("443"), Addr.fromstring("127.0.0.1"))
+
+ def test_conflicts(self):
+ # Note: Defined IP is more important than defined port in match
+ self.assertTrue(self.addr.conflicts(self.addr1))
+ self.assertTrue(self.addr.conflicts(self.addr2))
+ self.assertTrue(self.addr.conflicts(self.addr_defined))
+ self.assertFalse(self.addr.conflicts(self.addr_default))
+
+ self.assertFalse(self.addr1.conflicts(self.addr))
+ self.assertTrue(self.addr1.conflicts(self.addr_defined))
+ self.assertFalse(self.addr1.conflicts(self.addr_default))
+
+ self.assertFalse(self.addr_defined.conflicts(self.addr1))
+ self.assertFalse(self.addr_defined.conflicts(self.addr2))
+ self.assertFalse(self.addr_defined.conflicts(self.addr))
+ self.assertFalse(self.addr_defined.conflicts(self.addr_default))
+
+ self.assertTrue(self.addr_default.conflicts(self.addr))
+ self.assertTrue(self.addr_default.conflicts(self.addr1))
+ self.assertTrue(self.addr_default.conflicts(self.addr_defined))
+
+ # Self test
+ self.assertTrue(self.addr.conflicts(self.addr))
+ self.assertTrue(self.addr1.conflicts(self.addr1))
+ # This is a tricky one...
+ self.assertTrue(self.addr1.conflicts(self.addr2))
+
+ def test_equal(self):
+ self.assertTrue(self.addr1 == self.addr2)
+ self.assertFalse(self.addr == self.addr1)
+ self.assertFalse(self.addr == 123)
+
+ def test_not_equal(self):
+ self.assertFalse(self.addr1 != self.addr2)
+ self.assertTrue(self.addr != self.addr1)
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/parser_test.py b/certbot-apache/tests/parser_test.py
new file mode 100644
index 000000000..b334ce52e
--- /dev/null
+++ b/certbot-apache/tests/parser_test.py
@@ -0,0 +1,401 @@
+"""Tests for certbot_apache._internal.parser."""
+import shutil
+import unittest
+
+import mock
+
+from certbot import errors
+from certbot.compat import os
+import util
+
+
+class BasicParserTest(util.ParserTest):
+ """Apache Parser Test."""
+
+ def setUp(self): # pylint: disable=arguments-differ
+ super(BasicParserTest, self).setUp()
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+ shutil.rmtree(self.config_dir)
+ shutil.rmtree(self.work_dir)
+
+ def test_bad_parse(self):
+ self.parser.parse_file(os.path.join(self.parser.root,
+ "conf-available", "bad_conf_file.conf"))
+ self.assertRaises(
+ errors.PluginError, self.parser.check_parsing_errors, "httpd.aug")
+
+ def test_bad_save(self):
+ mock_save = mock.Mock()
+ mock_save.side_effect = IOError
+ self.parser.aug.save = mock_save
+ self.assertRaises(errors.PluginError, self.parser.unsaved_files)
+
+ def test_aug_version(self):
+ mock_match = mock.Mock(return_value=["something"])
+ self.parser.aug.match = mock_match
+ # pylint: disable=protected-access
+ self.assertEqual(self.parser.check_aug_version(),
+ ["something"])
+ self.parser.aug.match.side_effect = RuntimeError
+ self.assertFalse(self.parser.check_aug_version())
+
+ def test_find_config_root_no_root(self):
+ # pylint: disable=protected-access
+ os.remove(self.parser.loc["root"])
+ self.assertRaises(
+ errors.NoInstallationError, self.parser._find_config_root)
+
+ def test_parse_file(self):
+ """Test parse_file.
+
+ certbot.conf is chosen as the test file as it will not be
+ included during the normal course of execution.
+
+ """
+ file_path = os.path.join(
+ self.config_path, "not-parsed-by-default", "certbot.conf")
+
+ self.parser.parse_file(file_path) # pylint: disable=protected-access
+
+ # search for the httpd incl
+ matches = self.parser.aug.match(
+ "/augeas/load/Httpd/incl [. ='%s']" % file_path)
+
+ self.assertTrue(matches)
+
+ def test_find_dir(self):
+ test = self.parser.find_dir("Listen", "80")
+ # This will only look in enabled hosts
+ test2 = self.parser.find_dir("documentroot")
+
+ self.assertEqual(len(test), 1)
+ self.assertEqual(len(test2), 8)
+
+ def test_add_dir(self):
+ aug_default = "/files" + self.parser.loc["default"]
+ self.parser.add_dir(aug_default, "AddDirective", "test")
+
+ self.assertTrue(
+ self.parser.find_dir("AddDirective", "test", aug_default))
+
+ self.parser.add_dir(aug_default, "AddList", ["1", "2", "3", "4"])
+ matches = self.parser.find_dir("AddList", None, aug_default)
+ for i, match in enumerate(matches):
+ self.assertEqual(self.parser.aug.get(match), str(i + 1))
+
+ def test_add_dir_beginning(self):
+ aug_default = "/files" + self.parser.loc["default"]
+ self.parser.add_dir_beginning(aug_default,
+ "AddDirectiveBeginning",
+ "testBegin")
+
+ self.assertTrue(
+ self.parser.find_dir("AddDirectiveBeginning", "testBegin", aug_default))
+
+ self.assertEqual(
+ self.parser.aug.get(aug_default+"/directive[1]"),
+ "AddDirectiveBeginning")
+ self.parser.add_dir_beginning(aug_default, "AddList", ["1", "2", "3", "4"])
+ matches = self.parser.find_dir("AddList", None, aug_default)
+ for i, match in enumerate(matches):
+ self.assertEqual(self.parser.aug.get(match), str(i + 1))
+
+ def test_empty_arg(self):
+ self.assertEqual(None,
+ self.parser.get_arg("/files/whatever/nonexistent"))
+
+ def test_add_dir_to_ifmodssl(self):
+ """test add_dir_to_ifmodssl.
+
+ Path must be valid before attempting to add to augeas
+
+ """
+ from certbot_apache._internal.parser import get_aug_path
+ # This makes sure that find_dir will work
+ self.parser.modules.add("mod_ssl.c")
+
+ self.parser.add_dir_to_ifmodssl(
+ get_aug_path(self.parser.loc["default"]),
+ "FakeDirective", ["123"])
+
+ matches = self.parser.find_dir("FakeDirective", "123")
+
+ self.assertEqual(len(matches), 1)
+ self.assertTrue("IfModule" in matches[0])
+
+ def test_add_dir_to_ifmodssl_multiple(self):
+ from certbot_apache._internal.parser import get_aug_path
+ # This makes sure that find_dir will work
+ self.parser.modules.add("mod_ssl.c")
+
+ self.parser.add_dir_to_ifmodssl(
+ get_aug_path(self.parser.loc["default"]),
+ "FakeDirective", ["123", "456", "789"])
+
+ matches = self.parser.find_dir("FakeDirective")
+
+ self.assertEqual(len(matches), 3)
+ self.assertTrue("IfModule" in matches[0])
+
+ def test_get_aug_path(self):
+ from certbot_apache._internal.parser import get_aug_path
+ self.assertEqual("/files/etc/apache", get_aug_path("/etc/apache"))
+
+ def test_set_locations(self):
+ with mock.patch("certbot_apache._internal.parser.os.path") as mock_path:
+
+ mock_path.isfile.side_effect = [False, False]
+
+ # pylint: disable=protected-access
+ results = self.parser._set_locations()
+
+ self.assertEqual(results["default"], results["listen"])
+ self.assertEqual(results["default"], results["name"])
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.get_arg")
+ def test_parse_modules_bad_syntax(self, mock_arg, mock_find):
+ mock_find.return_value = ["1", "2", "3", "4", "5", "6", "7", "8"]
+ mock_arg.return_value = None
+ with mock.patch("certbot_apache._internal.parser.logger") as mock_logger:
+ self.parser.parse_modules()
+ # Make sure that we got None return value and logged the file
+ self.assertTrue(mock_logger.debug.called)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_update_runtime_variables(self, mock_cfg, _):
+ define_val = (
+ 'ServerRoot: "/etc/apache2"\n'
+ 'Main DocumentRoot: "/var/www"\n'
+ 'Main ErrorLog: "/var/log/apache2/error.log"\n'
+ 'Mutex ssl-stapling: using_defaults\n'
+ 'Mutex ssl-cache: using_defaults\n'
+ 'Mutex default: dir="/var/lock/apache2" mechanism=fcntl\n'
+ 'Mutex watchdog-callback: using_defaults\n'
+ 'PidFile: "/var/run/apache2/apache2.pid"\n'
+ 'Define: TEST\n'
+ 'Define: DUMP_RUN_CFG\n'
+ 'Define: U_MICH\n'
+ 'Define: TLS=443\n'
+ 'Define: example_path=Documents/path\n'
+ 'User: name="www-data" id=33 not_used\n'
+ 'Group: name="www-data" id=33 not_used\n'
+ )
+ inc_val = (
+ 'Included configuration files:\n'
+ ' (*) /etc/apache2/apache2.conf\n'
+ ' (146) /etc/apache2/mods-enabled/access_compat.load\n'
+ ' (146) /etc/apache2/mods-enabled/alias.load\n'
+ ' (146) /etc/apache2/mods-enabled/auth_basic.load\n'
+ ' (146) /etc/apache2/mods-enabled/authn_core.load\n'
+ ' (146) /etc/apache2/mods-enabled/authn_file.load\n'
+ ' (146) /etc/apache2/mods-enabled/authz_core.load\n'
+ ' (146) /etc/apache2/mods-enabled/authz_host.load\n'
+ ' (146) /etc/apache2/mods-enabled/authz_user.load\n'
+ ' (146) /etc/apache2/mods-enabled/autoindex.load\n'
+ ' (146) /etc/apache2/mods-enabled/deflate.load\n'
+ ' (146) /etc/apache2/mods-enabled/dir.load\n'
+ ' (146) /etc/apache2/mods-enabled/env.load\n'
+ ' (146) /etc/apache2/mods-enabled/filter.load\n'
+ ' (146) /etc/apache2/mods-enabled/mime.load\n'
+ ' (146) /etc/apache2/mods-enabled/mpm_event.load\n'
+ ' (146) /etc/apache2/mods-enabled/negotiation.load\n'
+ ' (146) /etc/apache2/mods-enabled/reqtimeout.load\n'
+ ' (146) /etc/apache2/mods-enabled/setenvif.load\n'
+ ' (146) /etc/apache2/mods-enabled/socache_shmcb.load\n'
+ ' (146) /etc/apache2/mods-enabled/ssl.load\n'
+ ' (146) /etc/apache2/mods-enabled/status.load\n'
+ ' (147) /etc/apache2/mods-enabled/alias.conf\n'
+ ' (147) /etc/apache2/mods-enabled/autoindex.conf\n'
+ ' (147) /etc/apache2/mods-enabled/deflate.conf\n'
+ )
+ mod_val = (
+ 'Loaded Modules:\n'
+ ' core_module (static)\n'
+ ' so_module (static)\n'
+ ' watchdog_module (static)\n'
+ ' http_module (static)\n'
+ ' log_config_module (static)\n'
+ ' logio_module (static)\n'
+ ' version_module (static)\n'
+ ' unixd_module (static)\n'
+ ' access_compat_module (shared)\n'
+ ' alias_module (shared)\n'
+ ' auth_basic_module (shared)\n'
+ ' authn_core_module (shared)\n'
+ ' authn_file_module (shared)\n'
+ ' authz_core_module (shared)\n'
+ ' authz_host_module (shared)\n'
+ ' authz_user_module (shared)\n'
+ ' autoindex_module (shared)\n'
+ ' deflate_module (shared)\n'
+ ' dir_module (shared)\n'
+ ' env_module (shared)\n'
+ ' filter_module (shared)\n'
+ ' mime_module (shared)\n'
+ ' mpm_event_module (shared)\n'
+ ' negotiation_module (shared)\n'
+ ' reqtimeout_module (shared)\n'
+ ' setenvif_module (shared)\n'
+ ' socache_shmcb_module (shared)\n'
+ ' ssl_module (shared)\n'
+ ' status_module (shared)\n'
+ )
+
+ def mock_get_vars(cmd):
+ """Mock command output"""
+ if cmd[-1] == "DUMP_RUN_CFG":
+ return define_val
+ elif cmd[-1] == "DUMP_INCLUDES":
+ return inc_val
+ elif cmd[-1] == "DUMP_MODULES":
+ return mod_val
+ return None # pragma: no cover
+
+ mock_cfg.side_effect = mock_get_vars
+
+ expected_vars = {"TEST": "", "U_MICH": "", "TLS": "443",
+ "example_path": "Documents/path"}
+
+ self.parser.modules = set()
+ with mock.patch(
+ "certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse:
+ self.parser.update_runtime_variables()
+ self.assertEqual(self.parser.variables, expected_vars)
+ self.assertEqual(len(self.parser.modules), 58)
+ # None of the includes in inc_val should be in parsed paths.
+ # Make sure we tried to include them all.
+ self.assertEqual(mock_parse.call_count, 25)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_update_runtime_variables_alt_values(self, mock_cfg, _):
+ inc_val = (
+ 'Included configuration files:\n'
+ ' (*) {0}\n'
+ ' (146) /etc/apache2/mods-enabled/access_compat.load\n'
+ ' (146) {1}/mods-enabled/alias.load\n'
+ ).format(self.parser.loc["root"],
+ os.path.dirname(self.parser.loc["root"]))
+
+ mock_cfg.return_value = inc_val
+ self.parser.modules = set()
+
+ with mock.patch(
+ "certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse:
+ self.parser.update_runtime_variables()
+ # No matching modules should have been found
+ self.assertEqual(len(self.parser.modules), 0)
+ # Only one of the three includes do not exist in already parsed
+ # path derived from root configuration Include statements
+ self.assertEqual(mock_parse.call_count, 1)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_update_runtime_vars_bad_output(self, mock_cfg):
+ mock_cfg.return_value = "Define: TLS=443=24"
+ self.parser.update_runtime_variables()
+
+ mock_cfg.return_value = "Define: DUMP_RUN_CFG\nDefine: TLS=443=24"
+ self.assertRaises(
+ errors.PluginError, self.parser.update_runtime_variables)
+
+ @mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.option")
+ @mock.patch("certbot_apache._internal.parser.subprocess.Popen")
+ def test_update_runtime_vars_bad_ctl(self, mock_popen, mock_opt):
+ mock_popen.side_effect = OSError
+ mock_opt.return_value = "nonexistent"
+ self.assertRaises(
+ errors.MisconfigurationError,
+ self.parser.update_runtime_variables)
+
+ @mock.patch("certbot_apache._internal.parser.subprocess.Popen")
+ def test_update_runtime_vars_bad_exit(self, mock_popen):
+ mock_popen().communicate.return_value = ("", "")
+ mock_popen.returncode = -1
+ self.assertRaises(
+ errors.MisconfigurationError,
+ self.parser.update_runtime_variables)
+
+ def test_add_comment(self):
+ from certbot_apache._internal.parser import get_aug_path
+ self.parser.add_comment(get_aug_path(self.parser.loc["name"]), "123456")
+ comm = self.parser.find_comments("123456")
+ self.assertEqual(len(comm), 1)
+ self.assertTrue(self.parser.loc["name"] in comm[0])
+
+
+class ParserInitTest(util.ApacheTest):
+ def setUp(self): # pylint: disable=arguments-differ
+ super(ParserInitTest, self).setUp()
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+ shutil.rmtree(self.config_dir)
+ shutil.rmtree(self.work_dir)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser.init_augeas")
+ def test_prepare_no_augeas(self, mock_init_augeas):
+ from certbot_apache._internal.parser import ApacheParser
+ mock_init_augeas.side_effect = errors.NoInstallationError
+ self.config.config_test = mock.Mock()
+ self.assertRaises(
+ errors.NoInstallationError, ApacheParser,
+ os.path.relpath(self.config_path), "/dummy/vhostpath",
+ version=(2, 4, 22), configurator=self.config)
+
+ def test_init_old_aug(self):
+ from certbot_apache._internal.parser import ApacheParser
+ with mock.patch("certbot_apache._internal.parser.ApacheParser.check_aug_version") as mock_c:
+ mock_c.return_value = False
+ self.assertRaises(
+ errors.NotSupportedError,
+ ApacheParser, os.path.relpath(self.config_path),
+ "/dummy/vhostpath", version=(2, 4, 22), configurator=self.config)
+
+ @mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
+ def test_unparseable(self, mock_cfg):
+ from certbot_apache._internal.parser import ApacheParser
+ mock_cfg.return_value = ('Define: TEST')
+ self.assertRaises(
+ errors.PluginError,
+ ApacheParser, os.path.relpath(self.config_path),
+ "/dummy/vhostpath", version=(2, 2, 22), configurator=self.config)
+
+ def test_root_normalized(self):
+ from certbot_apache._internal.parser import ApacheParser
+
+ with mock.patch("certbot_apache._internal.parser.ApacheParser."
+ "update_runtime_variables"):
+ path = os.path.join(
+ self.temp_dir,
+ "debian_apache_2_4/////multiple_vhosts/../multiple_vhosts/apache2")
+
+ parser = ApacheParser(path, "/dummy/vhostpath", configurator=self.config)
+
+ self.assertEqual(parser.root, self.config_path)
+
+ def test_root_absolute(self):
+ from certbot_apache._internal.parser import ApacheParser
+ with mock.patch("certbot_apache._internal.parser.ApacheParser."
+ "update_runtime_variables"):
+ parser = ApacheParser(
+ os.path.relpath(self.config_path),
+ "/dummy/vhostpath", configurator=self.config)
+
+ self.assertEqual(parser.root, self.config_path)
+
+ def test_root_no_trailing_slash(self):
+ from certbot_apache._internal.parser import ApacheParser
+ with mock.patch("certbot_apache._internal.parser.ApacheParser."
+ "update_runtime_variables"):
+ parser = ApacheParser(
+ self.config_path + os.path.sep,
+ "/dummy/vhostpath", configurator=self.config)
+ self.assertEqual(parser.root, self.config_path)
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/README b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/README
new file mode 100644
index 000000000..c12e149f2
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/README
@@ -0,0 +1,9 @@
+
+This directory holds Apache 2.0 module-specific configuration files;
+any files in this directory which have the ".conf" extension will be
+processed as Apache configuration files.
+
+Files are processed in alphabetical order, so if using configuration
+directives which depend on, say, mod_perl being loaded, ensure that
+these are placed in a filename later in the sort order than "perl.conf".
+
diff --git a/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/ssl.conf b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/ssl.conf
new file mode 100644
index 000000000..abe07dd0c
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/ssl.conf
@@ -0,0 +1,222 @@
+#
+# This is the Apache server configuration file providing SSL support.
+# It contains the configuration directives to instruct the server how to
+# serve pages over an https connection. For detailing information about these
+# directives see <URL:http://httpd.apache.org/docs/2.2/mod/mod_ssl.html>
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+
+LoadModule ssl_module modules/mod_ssl.so
+
+#
+# When we also provide SSL we have to listen to the
+# the HTTPS port in addition.
+#
+Listen 443
+
+##
+## SSL Global Context
+##
+## All SSL configuration in this context applies both to
+## the main server and all SSL-enabled virtual hosts.
+##
+
+# Pass Phrase Dialog:
+# Configure the pass phrase gathering process.
+# The filtering dialog program (`builtin' is an internal
+# terminal dialog) has to provide the pass phrase on stdout.
+SSLPassPhraseDialog builtin
+
+# Inter-Process Session Cache:
+# Configure the SSL Session Cache: First the mechanism
+# to use and second the expiring timeout (in seconds).
+SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000)
+SSLSessionCacheTimeout 300
+
+# Semaphore:
+# Configure the path to the mutual exclusion semaphore the
+# SSL engine uses internally for inter-process synchronization.
+SSLMutex default
+
+# Pseudo Random Number Generator (PRNG):
+# Configure one or more sources to seed the PRNG of the
+# SSL library. The seed data should be of good random quality.
+# WARNING! On some platforms /dev/random blocks if not enough entropy
+# is available. This means you then cannot use the /dev/random device
+# because it would lead to very long connection times (as long as
+# it requires to make more entropy available). But usually those
+# platforms additionally provide a /dev/urandom device which doesn't
+# block. So, if available, use this one instead. Read the mod_ssl User
+# Manual for more details.
+SSLRandomSeed startup file:/dev/urandom 256
+SSLRandomSeed connect builtin
+#SSLRandomSeed startup file:/dev/random 512
+#SSLRandomSeed connect file:/dev/random 512
+#SSLRandomSeed connect file:/dev/urandom 512
+
+#
+# Use "SSLCryptoDevice" to enable any supported hardware
+# accelerators. Use "openssl engine -v" to list supported
+# engine names. NOTE: If you enable an accelerator and the
+# server does not start, consult the error logs and ensure
+# your accelerator is functioning properly.
+#
+SSLCryptoDevice builtin
+#SSLCryptoDevice ubsec
+
+##
+## SSL Virtual Host Context
+##
+
+<VirtualHost _default_:443>
+
+# General setup for the virtual host, inherited from global configuration
+#DocumentRoot "/var/www/html"
+#ServerName www.example.com:443
+
+# Use separate log files for the SSL virtual host; note that LogLevel
+# is not inherited from httpd.conf.
+ErrorLog logs/ssl_error_log
+TransferLog logs/ssl_access_log
+LogLevel warn
+
+# SSL Engine Switch:
+# Enable/Disable SSL for this virtual host.
+SSLEngine on
+
+# SSL Protocol support:
+# List the enable protocol levels with which clients will be able to
+# connect. Disable SSLv2 access by default:
+SSLProtocol all -SSLv2
+
+# SSL Cipher Suite:
+# List the ciphers that the client is permitted to negotiate.
+# See the mod_ssl documentation for a complete list.
+SSLCipherSuite DEFAULT:!EXP:!SSLv2:!DES:!IDEA:!SEED:+3DES
+
+# Server Certificate:
+# Point SSLCertificateFile at a PEM encoded certificate. If
+# the certificate is encrypted, then you will be prompted for a
+# pass phrase. Note that a kill -HUP will prompt again. A new
+# certificate can be generated using the genkey(1) command.
+SSLCertificateFile /etc/pki/tls/certs/localhost.crt
+
+# Server Private Key:
+# If the key is not combined with the certificate, use this
+# directive to point at the key file. Keep in mind that if
+# you've both a RSA and a DSA private key you can configure
+# both in parallel (to also allow the use of DSA ciphers, etc.)
+SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
+
+# Server Certificate Chain:
+# Point SSLCertificateChainFile at a file containing the
+# concatenation of PEM encoded CA certificates which form the
+# certificate chain for the server certificate. Alternatively
+# the referenced file can be the same as SSLCertificateFile
+# when the CA certificates are directly appended to the server
+# certificate for convinience.
+#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
+
+# Certificate Authority (CA):
+# Set the CA certificate verification path where to find CA
+# certificates for client authentication or alternatively one
+# huge file containing all of them (file must be PEM encoded)
+#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
+
+# Client Authentication (Type):
+# Client certificate verification type and depth. Types are
+# none, optional, require and optional_no_ca. Depth is a
+# number which specifies how deeply to verify the certificate
+# issuer chain before deciding the certificate is not valid.
+#SSLVerifyClient require
+#SSLVerifyDepth 10
+
+# Access Control:
+# With SSLRequire you can do per-directory access control based
+# on arbitrary complex boolean expressions containing server
+# variable checks and other lookup directives. The syntax is a
+# mixture between C and Perl. See the mod_ssl documentation
+# for more details.
+#<Location />
+#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
+# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
+# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
+# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
+# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
+# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
+#</Location>
+
+# SSL Engine Options:
+# Set various options for the SSL engine.
+# o FakeBasicAuth:
+# Translate the client X.509 into a Basic Authorisation. This means that
+# the standard Auth/DBMAuth methods can be used for access control. The
+# user name is the `one line' version of the client's X.509 certificate.
+# Note that no password is obtained from the user. Every entry in the user
+# file needs this password: `xxj31ZMTZzkVA'.
+# o ExportCertData:
+# This exports two additional environment variables: SSL_CLIENT_CERT and
+# SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
+# server (always existing) and the client (only existing when client
+# authentication is used). This can be used to import the certificates
+# into CGI scripts.
+# o StdEnvVars:
+# This exports the standard SSL/TLS related `SSL_*' environment variables.
+# Per default this exportation is switched off for performance reasons,
+# because the extraction step is an expensive operation and is usually
+# useless for serving static content. So one usually enables the
+# exportation for CGI and SSI requests only.
+# o StrictRequire:
+# This denies access when "SSLRequireSSL" or "SSLRequire" applied even
+# under a "Satisfy any" situation, i.e. when it applies access is denied
+# and no other module can change it.
+# o OptRenegotiate:
+# This enables optimized SSL connection renegotiation handling when SSL
+# directives are used in per-directory context.
+#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
+<Files ~ "\.(cgi|shtml|phtml|php3?)$">
+ SSLOptions +StdEnvVars
+</Files>
+<Directory "/var/www/cgi-bin">
+ SSLOptions +StdEnvVars
+</Directory>
+
+# SSL Protocol Adjustments:
+# The safe and default but still SSL/TLS standard compliant shutdown
+# approach is that mod_ssl sends the close notify alert but doesn't wait for
+# the close notify alert from client. When you need a different shutdown
+# approach you can use one of the following variables:
+# o ssl-unclean-shutdown:
+# This forces an unclean shutdown when the connection is closed, i.e. no
+# SSL close notify alert is send or allowed to received. This violates
+# the SSL/TLS standard but is needed for some brain-dead browsers. Use
+# this when you receive I/O errors because of the standard approach where
+# mod_ssl sends the close notify alert.
+# o ssl-accurate-shutdown:
+# This forces an accurate shutdown when the connection is closed, i.e. a
+# SSL close notify alert is send and mod_ssl waits for the close notify
+# alert of the client. This is 100% SSL/TLS standard compliant, but in
+# practice often causes hanging connections with brain-dead browsers. Use
+# this only for browsers where you know that their SSL implementation
+# works correctly.
+# Notice: Most problems of broken clients are also related to the HTTP
+# keep-alive facility, so you usually additionally want to disable
+# keep-alive for those clients, too. Use variable "nokeepalive" for this.
+# Similarly, one has to force some clients to use HTTP/1.0 to workaround
+# their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
+# "force-response-1.0" for this.
+SetEnvIf User-Agent ".*MSIE.*" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+
+# Per-Server Logging:
+# The home of a custom SSL log file. Use this when you want a
+# compact non-error SSL logfile on a virtual host basis.
+CustomLog logs/ssl_request_log \
+ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
+
+</VirtualHost>
+
diff --git a/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/test.example.com.conf b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/test.example.com.conf
new file mode 100644
index 000000000..3dd7b18f1
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/test.example.com.conf
@@ -0,0 +1,7 @@
+<VirtualHost *:80>
+ ServerName test.example.com
+ ServerAdmin webmaster@dummy-host.example.com
+ DocumentRoot /var/www/htdocs
+ ErrorLog logs/dummy-host.example.com-error_log
+ CustomLog logs/dummy-host.example.com-access_log common
+</VirtualHost>
diff --git a/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/welcome.conf b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/welcome.conf
new file mode 100644
index 000000000..c1d23c512
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf.d/welcome.conf
@@ -0,0 +1,11 @@
+#
+# This configuration file enables the default "Welcome"
+# page if there is no default index page present for
+# the root URL. To disable the Welcome page, comment
+# out all the lines below.
+#
+<LocationMatch "^/+$">
+ Options -Indexes
+ ErrorDocument 403 /error/noindex.html
+</LocationMatch>
+
diff --git a/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf/httpd.conf b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf/httpd.conf
new file mode 100644
index 000000000..eac6143da
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos6_apache/apache/httpd/conf/httpd.conf
@@ -0,0 +1,1009 @@
+#
+# This is the main Apache server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/2.2/> for detailed information.
+# In particular, see
+# <URL:http://httpd.apache.org/docs/2.2/mod/directives.html>
+# for a discussion of each configuration directive.
+#
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+# The configuration directives are grouped into three basic sections:
+# 1. Directives that control the operation of the Apache server process as a
+# whole (the 'global environment').
+# 2. Directives that define the parameters of the 'main' or 'default' server,
+# which responds to requests that aren't handled by a virtual host.
+# These directives also provide default values for the settings
+# of all virtual hosts.
+# 3. Settings for virtual hosts, which allow Web requests to be sent to
+# different IP addresses or hostnames and have them handled by the
+# same Apache server process.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path. If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "logs/foo.log"
+# with ServerRoot set to "/etc/httpd" will be interpreted by the
+# server as "/etc/httpd/logs/foo.log".
+#
+
+### Section 1: Global Environment
+#
+# The directives in this section affect the overall operation of Apache,
+# such as the number of concurrent requests it can handle or where it
+# can find its configuration files.
+#
+
+#
+# Don't give away too much information about all the subcomponents
+# we are running. Comment out this line if you don't mind remote sites
+# finding out what major optional modules you are running
+ServerTokens OS
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# NOTE! If you intend to place this on an NFS (or otherwise network)
+# mounted filesystem then please read the LockFile documentation
+# (available at <URL:http://httpd.apache.org/docs/2.2/mod/mpm_common.html#lockfile>);
+# you will save yourself a lot of trouble.
+#
+# Do NOT add a slash at the end of the directory path.
+#
+ServerRoot "/etc/httpd"
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts. Note the PIDFILE variable in
+# /etc/sysconfig/httpd must be set appropriately if this location is
+# changed.
+#
+PidFile run/httpd.pid
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 60
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive Off
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 15
+
+##
+## Server-Pool Size Regulation (MPM specific)
+##
+
+# prefork MPM
+# StartServers: number of server processes to start
+# MinSpareServers: minimum number of server processes which are kept spare
+# MaxSpareServers: maximum number of server processes which are kept spare
+# ServerLimit: maximum value for MaxClients for the lifetime of the server
+# MaxClients: maximum number of server processes allowed to start
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule prefork.c>
+StartServers 8
+MinSpareServers 5
+MaxSpareServers 20
+ServerLimit 256
+MaxClients 256
+MaxRequestsPerChild 4000
+</IfModule>
+
+# worker MPM
+# StartServers: initial number of server processes to start
+# MaxClients: maximum number of simultaneous client connections
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule worker.c>
+StartServers 4
+MaxClients 300
+MinSpareThreads 25
+MaxSpareThreads 75
+ThreadsPerChild 25
+MaxRequestsPerChild 0
+</IfModule>
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, in addition to the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to
+# prevent Apache from glomming onto all bound IP addresses (0.0.0.0)
+#
+#Listen 12.34.56.78:80
+Listen 80
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+LoadModule auth_basic_module modules/mod_auth_basic.so
+LoadModule auth_digest_module modules/mod_auth_digest.so
+LoadModule authn_file_module modules/mod_authn_file.so
+LoadModule authn_alias_module modules/mod_authn_alias.so
+LoadModule authn_anon_module modules/mod_authn_anon.so
+LoadModule authn_dbm_module modules/mod_authn_dbm.so
+LoadModule authn_default_module modules/mod_authn_default.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_user_module modules/mod_authz_user.so
+LoadModule authz_owner_module modules/mod_authz_owner.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_dbm_module modules/mod_authz_dbm.so
+LoadModule authz_default_module modules/mod_authz_default.so
+LoadModule ldap_module modules/mod_ldap.so
+LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
+LoadModule include_module modules/mod_include.so
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule logio_module modules/mod_logio.so
+LoadModule env_module modules/mod_env.so
+LoadModule ext_filter_module modules/mod_ext_filter.so
+LoadModule mime_magic_module modules/mod_mime_magic.so
+LoadModule expires_module modules/mod_expires.so
+LoadModule deflate_module modules/mod_deflate.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule usertrack_module modules/mod_usertrack.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule dav_module modules/mod_dav.so
+LoadModule status_module modules/mod_status.so
+LoadModule autoindex_module modules/mod_autoindex.so
+LoadModule info_module modules/mod_info.so
+LoadModule dav_fs_module modules/mod_dav_fs.so
+LoadModule vhost_alias_module modules/mod_vhost_alias.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule dir_module modules/mod_dir.so
+LoadModule actions_module modules/mod_actions.so
+LoadModule speling_module modules/mod_speling.so
+LoadModule userdir_module modules/mod_userdir.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule substitute_module modules/mod_substitute.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule proxy_module modules/mod_proxy.so
+LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
+LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
+LoadModule proxy_http_module modules/mod_proxy_http.so
+LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
+LoadModule proxy_connect_module modules/mod_proxy_connect.so
+LoadModule cache_module modules/mod_cache.so
+LoadModule suexec_module modules/mod_suexec.so
+LoadModule disk_cache_module modules/mod_disk_cache.so
+LoadModule cgi_module modules/mod_cgi.so
+LoadModule version_module modules/mod_version.so
+
+#
+# The following modules are not loaded by default:
+#
+#LoadModule asis_module modules/mod_asis.so
+#LoadModule authn_dbd_module modules/mod_authn_dbd.so
+#LoadModule cern_meta_module modules/mod_cern_meta.so
+#LoadModule cgid_module modules/mod_cgid.so
+#LoadModule dbd_module modules/mod_dbd.so
+#LoadModule dumpio_module modules/mod_dumpio.so
+#LoadModule filter_module modules/mod_filter.so
+#LoadModule ident_module modules/mod_ident.so
+#LoadModule log_forensic_module modules/mod_log_forensic.so
+#LoadModule unique_id_module modules/mod_unique_id.so
+#
+
+#
+# Load config files from the config directory "/etc/httpd/conf.d".
+#
+Include conf.d/*.conf
+
+#
+# ExtendedStatus controls whether Apache will generate "full" status
+# information (ExtendedStatus On) or just basic information (ExtendedStatus
+# Off) when the "server-status" handler is called. The default is Off.
+#
+#ExtendedStatus On
+
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# . On SCO (ODT 3) use "User nouser" and "Group nogroup".
+# . On HPUX you may not be able to use shared memory as nobody, and the
+# suggested workaround is to create a user www and use that user.
+# NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET)
+# when the value of (unsigned)Group is above 60000;
+# don't use Group #-1 on these systems!
+#
+User apache
+Group apache
+
+### Section 2: 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition. These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed. This address appears on some server-generated pages, such
+# as error documents. e.g. admin@your-domain.com
+#
+ServerAdmin root@localhost
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If this is not set to valid DNS name for your host, server-generated
+# redirections will not work. See also the UseCanonicalName directive.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+# You will have to access it by its address anyway, and this will make
+# redirections work in a sensible way.
+#
+#ServerName www.example.com:80
+
+#
+# UseCanonicalName: Determines how Apache constructs self-referencing
+# URLs and the SERVER_NAME and SERVER_PORT variables.
+# When set "Off", Apache will use the Hostname and Port supplied
+# by the client. When set "On", Apache will use the value of the
+# ServerName directive.
+#
+UseCanonicalName Off
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/var/www/html"
+
+#
+# Each directory to which Apache has access can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories).
+#
+# First, we configure the "default" to be a very restrictive set of
+# features.
+#
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# This should be changed to whatever you set DocumentRoot to.
+#
+<Directory "/var/www/html">
+
+#
+# Possible values for the Options directive are "None", "All",
+# or any combination of:
+# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+#
+# Note that "MultiViews" must be named *explicitly* --- "Options All"
+# doesn't give it to you.
+#
+# The Options directive is both complicated and important. Please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#options
+# for more information.
+#
+ Options Indexes FollowSymLinks
+
+#
+# AllowOverride controls what directives may be placed in .htaccess files.
+# It can be "All", "None", or any combination of the keywords:
+# Options FileInfo AuthConfig Limit
+#
+ AllowOverride None
+
+#
+# Controls who can get stuff from this server.
+#
+ Order allow,deny
+ Allow from all
+
+</Directory>
+
+#
+# UserDir: The name of the directory that is appended onto a user's home
+# directory if a ~user request is received.
+#
+# The path to the end user account 'public_html' directory must be
+# accessible to the webserver userid. This usually means that ~userid
+# must have permissions of 711, ~userid/public_html must have permissions
+# of 755, and documents contained therein must be world-readable.
+# Otherwise, the client will only receive a "403 Forbidden" message.
+#
+# See also: http://httpd.apache.org/docs/misc/FAQ.html#forbidden
+#
+<IfModule mod_userdir.c>
+ #
+ # UserDir is disabled by default since it can confirm the presence
+ # of a username on the system (depending on home directory
+ # permissions).
+ #
+ UserDir disabled
+
+ #
+ # To enable requests to /~user/ to serve the user's public_html
+ # directory, remove the "UserDir disabled" line above, and uncomment
+ # the following line instead:
+ #
+ #UserDir public_html
+
+</IfModule>
+
+#
+# Control access to UserDir directories. The following is an example
+# for a site where these directories are restricted to read-only.
+#
+#<Directory /home/*/public_html>
+# AllowOverride FileInfo AuthConfig Limit
+# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+# <Limit GET POST OPTIONS>
+# Order allow,deny
+# Allow from all
+# </Limit>
+# <LimitExcept GET POST OPTIONS>
+# Order deny,allow
+# Deny from all
+# </LimitExcept>
+#</Directory>
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+# The index.html.var file (a type-map) is used to deliver content-
+# negotiated documents. The MultiViews Option can be used for the
+# same purpose, but it is much slower.
+#
+DirectoryIndex index.html index.html.var
+
+#
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives. See also the AllowOverride
+# directive.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<Files ~ "^\.ht">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Files>
+
+#
+# TypesConfig describes where the mime.types file (or equivalent) is
+# to be found.
+#
+TypesConfig /etc/mime.types
+
+#
+# DefaultType is the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value. If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+#
+# The mod_mime_magic module allows the server to use various hints from the
+# contents of the file itself to determine its type. The MIMEMagicFile
+# directive tells the module where the hint definitions are located.
+#
+<IfModule mod_mime_magic.c>
+# MIMEMagicFile /usr/share/magic.mime
+ MIMEMagicFile conf/magic
+</IfModule>
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+#
+# EnableMMAP: Control whether memory-mapping is used to deliver
+# files (assuming that the underlying OS supports it).
+# The default is on; turn this off if you serve from NFS-mounted
+# filesystems. On some systems, turning it off (regardless of
+# filesystem) can improve performance; for details, please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#enablemmap
+#
+#EnableMMAP off
+
+#
+# EnableSendfile: Control whether the sendfile kernel support is
+# used to deliver files (assuming that the OS supports it).
+# The default is on; turn this off if you serve from NFS-mounted
+# filesystems. Please see
+# http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile
+#
+#EnableSendfile off
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog logs/error_log
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+# "combinedio" includes actual counts of actual bytes received (%I) and sent (%O); this
+# requires the mod_logio module to be loaded.
+#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+
+#
+# The location and format of the access logfile (Common Logfile Format).
+# If you do not define any access logfiles within a <VirtualHost>
+# container, they will be logged here. Contrariwise, if you *do*
+# define per-<VirtualHost> access logfiles, transactions will be
+# logged therein and *not* in this file.
+#
+#CustomLog logs/access_log common
+
+#
+# If you would like to have separate agent and referer logfiles, uncomment
+# the following directives.
+#
+#CustomLog logs/referer_log referer
+#CustomLog logs/agent_log agent
+
+#
+# For a single logfile with access, agent, and referer information
+# (Combined Logfile Format), use the following directive:
+#
+CustomLog logs/access_log combined
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#
+ServerSignature On
+
+#
+# Aliases: Add here as many aliases as you need (with no limit). The format is
+# Alias fakename realname
+#
+# Note that if you include a trailing / on fakename then the server will
+# require it to be present in the URL. So "/icons" isn't aliased in this
+# example, only "/icons/". If the fakename is slash-terminated, then the
+# realname must also be slash terminated, and if the fakename omits the
+# trailing slash, the realname must also omit it.
+#
+# We include the /icons/ alias for FancyIndexed directory listings. If you
+# do not use FancyIndexing, you may comment this out.
+#
+Alias /icons/ "/var/www/icons/"
+
+<Directory "/var/www/icons">
+ Options Indexes MultiViews FollowSymLinks
+ AllowOverride None
+ Order allow,deny
+ Allow from all
+</Directory>
+
+#
+# WebDAV module configuration section.
+#
+<IfModule mod_dav_fs.c>
+ # Location of the WebDAV lock database.
+ DAVLockDB /var/lib/dav/lockdb
+</IfModule>
+
+#
+# ScriptAlias: This controls which directories contain server scripts.
+# ScriptAliases are essentially the same as Aliases, except that
+# documents in the realname directory are treated as applications and
+# run by the server when requested rather than as documents sent to the client.
+# The same rules about trailing "/" apply to ScriptAlias directives as to
+# Alias.
+#
+ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+
+#
+# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+#
+<Directory "/var/www/cgi-bin">
+ AllowOverride None
+ Options None
+ Order allow,deny
+ Allow from all
+</Directory>
+
+#
+# Redirect allows you to tell clients about documents which used to exist in
+# your server's namespace, but do not anymore. This allows you to tell the
+# clients where to look for the relocated document.
+# Example:
+# Redirect permanent /foo http://www.example.com/bar
+
+#
+# Directives controlling the display of server-generated directory listings.
+#
+
+#
+# IndexOptions: Controls the appearance of server-generated directory
+# listings.
+#
+IndexOptions FancyIndexing VersionSort NameWidth=* HTMLTable Charset=UTF-8
+
+#
+# AddIcon* directives tell the server which icon to show for different
+# files or filename extensions. These are only displayed for
+# FancyIndexed directories.
+#
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+AddIcon /icons/bomb.gif /core
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+#
+# DefaultIcon is which icon to show for files which do not have an icon
+# explicitly set.
+#
+DefaultIcon /icons/unknown.gif
+
+#
+# AddDescription allows you to place a short description after a file in
+# server-generated indexes. These are only displayed for FancyIndexed
+# directories.
+# Format: AddDescription "description" filename
+#
+#AddDescription "GZIP compressed document" .gz
+#AddDescription "tar archive" .tar
+#AddDescription "GZIP compressed tar archive" .tgz
+
+#
+# ReadmeName is the name of the README file the server will look for by
+# default, and append to directory listings.
+#
+# HeaderName is the name of a file which should be prepended to
+# directory indexes.
+ReadmeName README.html
+HeaderName HEADER.html
+
+#
+# IndexIgnore is a set of filenames which directory indexing should ignore
+# and not include in the listing. Shell-style wildcarding is permitted.
+#
+IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
+
+#
+# DefaultLanguage and AddLanguage allows you to specify the language of
+# a document. You can then use content negotiation to give a browser a
+# file in a language the user can understand.
+#
+# Specify a default language. This means that all data
+# going out without a specific language tag (see below) will
+# be marked with this one. You probably do NOT want to set
+# this unless you are sure it is correct for all cases.
+#
+# * It is generally better to not mark a page as
+# * being a certain language than marking it with the wrong
+# * language!
+#
+# DefaultLanguage nl
+#
+# Note 1: The suffix does not have to be the same as the language
+# keyword --- those with documents in Polish (whose net-standard
+# language code is pl) may wish to use "AddLanguage pl .po" to
+# avoid the ambiguity with the common suffix for perl scripts.
+#
+# Note 2: The example entries below illustrate that in some cases
+# the two character 'Language' abbreviation is not identical to
+# the two character 'Country' code for its country,
+# E.g. 'Danmark/dk' versus 'Danish/da'.
+#
+# Note 3: In the case of 'ltz' we violate the RFC by using a three char
+# specifier. There is 'work in progress' to fix this and get
+# the reference data for rfc1766 cleaned up.
+#
+# Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl)
+# English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de)
+# Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja)
+# Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn)
+# Norwegian (no) - Polish (pl) - Portuguese (pt)
+# Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv)
+# Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW)
+#
+AddLanguage ca .ca
+AddLanguage cs .cz .cs
+AddLanguage da .dk
+AddLanguage de .de
+AddLanguage el .el
+AddLanguage en .en
+AddLanguage eo .eo
+AddLanguage es .es
+AddLanguage et .et
+AddLanguage fr .fr
+AddLanguage he .he
+AddLanguage hr .hr
+AddLanguage it .it
+AddLanguage ja .ja
+AddLanguage ko .ko
+AddLanguage ltz .ltz
+AddLanguage nl .nl
+AddLanguage nn .nn
+AddLanguage no .no
+AddLanguage pl .po
+AddLanguage pt .pt
+AddLanguage pt-BR .pt-br
+AddLanguage ru .ru
+AddLanguage sv .sv
+AddLanguage zh-CN .zh-cn
+AddLanguage zh-TW .zh-tw
+
+#
+# LanguagePriority allows you to give precedence to some languages
+# in case of a tie during content negotiation.
+#
+# Just list the languages in decreasing order of preference. We have
+# more or less alphabetized them here. You probably want to change this.
+#
+LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
+
+#
+# ForceLanguagePriority allows you to serve a result page rather than
+# MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback)
+# [in case no accepted languages matched the available variants]
+#
+ForceLanguagePriority Prefer Fallback
+
+#
+# Specify a default charset for all content served; this enables
+# interpretation of all content as UTF-8 by default. To use the
+# default browser choice (ISO-8859-1), or to allow the META tags
+# in HTML content to override this choice, comment out this
+# directive:
+#
+AddDefaultCharset UTF-8
+
+#
+# AddType allows you to add to or override the MIME configuration
+# file mime.types for specific file types.
+#
+#AddType application/x-tar .tgz
+
+#
+# AddEncoding allows you to have certain browsers uncompress
+# information on the fly. Note: Not all browsers support this.
+# Despite the name similarity, the following Add* directives have nothing
+# to do with the FancyIndexing customization directives above.
+#
+#AddEncoding x-compress .Z
+#AddEncoding x-gzip .gz .tgz
+
+# If the AddEncoding directives above are commented-out, then you
+# probably should define those extensions to indicate media types:
+#
+AddType application/x-compress .Z
+AddType application/x-gzip .gz .tgz
+
+#
+# MIME-types for downloading Certificates and CRLs
+#
+AddType application/x-x509-ca-cert .crt
+AddType application/x-pkcs7-crl .crl
+
+#
+# AddHandler allows you to map certain file extensions to "handlers":
+# actions unrelated to filetype. These can be either built into the server
+# or added with the Action directive (see below)
+#
+# To use CGI scripts outside of ScriptAliased directories:
+# (You will also need to add "ExecCGI" to the "Options" directive.)
+#
+#AddHandler cgi-script .cgi
+
+#
+# For files that include their own HTTP headers:
+#
+#AddHandler send-as-is asis
+
+#
+# For type maps (negotiated resources):
+# (This is enabled by default to allow the Apache "It Worked" page
+# to be distributed in multiple languages.)
+#
+AddHandler type-map var
+
+#
+# Filters allow you to process content before it is sent to the client.
+#
+# To parse .shtml files for server-side includes (SSI):
+# (You will also need to add "Includes" to the "Options" directive.)
+#
+AddType text/html .shtml
+AddOutputFilter INCLUDES .shtml
+
+#
+# Action lets you define media types that will execute a script whenever
+# a matching file is called. This eliminates the need for repeated URL
+# pathnames for oft-used CGI file processors.
+# Format: Action media/type /cgi-script/location
+# Format: Action handler-name /cgi-script/location
+#
+
+#
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# Putting this all together, we can internationalize error responses.
+#
+# We use Alias to redirect any /error/HTTP_<error>.html.var response to
+# our collection of by-error message multi-language collections. We use
+# includes to substitute the appropriate text.
+#
+# You can modify the messages' appearance without changing any of the
+# default HTTP_<error>.html.var files by adding the line:
+#
+# Alias /error/include/ "/your/include/path/"
+#
+# which allows you to create your own set of files by starting with the
+# /var/www/error/include/ files and
+# copying them to /your/include/path/, even on a per-VirtualHost basis.
+#
+
+Alias /error/ "/var/www/error/"
+
+<IfModule mod_negotiation.c>
+<IfModule mod_include.c>
+ <Directory "/var/www/error">
+ AllowOverride None
+ Options IncludesNoExec
+ AddOutputFilter Includes html
+ AddHandler type-map var
+ Order allow,deny
+ Allow from all
+ LanguagePriority en es de fr
+ ForceLanguagePriority Prefer Fallback
+ </Directory>
+
+# ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
+# ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
+# ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
+# ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
+# ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
+# ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
+# ErrorDocument 410 /error/HTTP_GONE.html.var
+# ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
+# ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
+# ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
+# ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
+# ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
+# ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
+# ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
+# ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
+# ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
+# ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
+
+</IfModule>
+</IfModule>
+
+#
+# The following directives modify normal HTTP response behavior to
+# handle known problems with browser implementations.
+#
+BrowserMatch "Mozilla/2" nokeepalive
+BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+BrowserMatch "RealPlayer 4\.0" force-response-1.0
+BrowserMatch "Java/1\.0" force-response-1.0
+BrowserMatch "JDK/1\.0" force-response-1.0
+
+#
+# The following directive disables redirects on non-GET requests for
+# a directory that does not include the trailing slash. This fixes a
+# problem with Microsoft WebFolders which does not appropriately handle
+# redirects for folders with DAV methods.
+# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV.
+#
+BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
+BrowserMatch "MS FrontPage" redirect-carefully
+BrowserMatch "^WebDrive" redirect-carefully
+BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully
+BrowserMatch "^gnome-vfs/1.0" redirect-carefully
+BrowserMatch "^XML Spy" redirect-carefully
+BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
+
+#
+# Allow server status reports generated by mod_status,
+# with the URL of http://servername/server-status
+# Change the ".example.com" to match your domain to enable.
+#
+#<Location /server-status>
+# SetHandler server-status
+# Order deny,allow
+# Deny from all
+# Allow from .example.com
+#</Location>
+
+#
+# Allow remote server configuration reports, with the URL of
+# http://servername/server-info (requires that mod_info.c be loaded).
+# Change the ".example.com" to match your domain to enable.
+#
+#<Location /server-info>
+# SetHandler server-info
+# Order deny,allow
+# Deny from all
+# Allow from .example.com
+#</Location>
+
+#
+# Proxy Server directives. Uncomment the following lines to
+# enable the proxy server:
+#
+#<IfModule mod_proxy.c>
+#ProxyRequests On
+#
+#<Proxy *>
+# Order deny,allow
+# Deny from all
+# Allow from .example.com
+#</Proxy>
+
+#
+# Enable/disable the handling of HTTP/1.1 "Via:" headers.
+# ("Full" adds the server version; "Block" removes all outgoing Via: headers)
+# Set to one of: Off | On | Full | Block
+#
+#ProxyVia On
+
+#
+# To enable a cache of proxied content, uncomment the following lines.
+# See http://httpd.apache.org/docs/2.2/mod/mod_cache.html for more details.
+#
+#<IfModule mod_disk_cache.c>
+# CacheEnable disk /
+# CacheRoot "/var/cache/mod_proxy"
+#</IfModule>
+#
+
+#</IfModule>
+# End of proxy directives.
+
+### Section 3: Virtual Hosts
+#
+# VirtualHost: If you want to maintain multiple domains/hostnames on your
+# machine you can setup VirtualHost containers for them. Most configurations
+# use only name-based virtual hosts so the server doesn't need to worry about
+# IP addresses. This is indicated by the asterisks in the directives below.
+#
+# Please see the documentation at
+# <URL:http://httpd.apache.org/docs/2.2/vhosts/>
+# for further details before you try to setup virtual hosts.
+#
+# You may use the command line option '-S' to verify your virtual host
+# configuration.
+
+#
+# Use name-based virtual hosting.
+#
+#NameVirtualHost *:80
+#
+# NOTE: NameVirtualHost cannot be used without a port specifier
+# (e.g. :80) if mod_ssl is being used, due to the nature of the
+# SSL protocol.
+#
+
+#
+# VirtualHost example:
+# Almost any Apache directive may go into a VirtualHost container.
+# The first VirtualHost section is used for requests without a known
+# server name.
+#
+#<VirtualHost *:80>
+# ServerAdmin webmaster@dummy-host.example.com
+# DocumentRoot /www/docs/dummy-host.example.com
+# ServerName dummy-host.example.com
+# ErrorLog logs/dummy-host.example.com-error_log
+# CustomLog logs/dummy-host.example.com-access_log common
+#</VirtualHost>
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/README b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/README
new file mode 100644
index 000000000..f5e96615a
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/README
@@ -0,0 +1,9 @@
+
+This directory holds configuration files for the Apache HTTP Server;
+any files in this directory which have the ".conf" extension will be
+processed as httpd configuration files. The directory is used in
+addition to the directory /etc/httpd/conf.modules.d/, which contains
+configuration files necessary to load modules.
+
+Files are processed in alphabetical order.
+
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/autoindex.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/autoindex.conf
new file mode 100644
index 000000000..a85cf5dca
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/autoindex.conf
@@ -0,0 +1,94 @@
+#
+# Directives controlling the display of server-generated directory listings.
+#
+# Required modules: mod_authz_core, mod_authz_host,
+# mod_autoindex, mod_alias
+#
+# To see the listing of a directory, the Options directive for the
+# directory must include "Indexes", and the directory must not contain
+# a file matching those listed in the DirectoryIndex directive.
+#
+
+#
+# IndexOptions: Controls the appearance of server-generated directory
+# listings.
+#
+IndexOptions FancyIndexing HTMLTable VersionSort
+
+# We include the /icons/ alias for FancyIndexed directory listings. If
+# you do not use FancyIndexing, you may comment this out.
+#
+Alias /icons/ "/usr/share/httpd/icons/"
+
+<Directory "/usr/share/httpd/icons">
+ Options Indexes MultiViews FollowSymlinks
+ AllowOverride None
+ Require all granted
+</Directory>
+
+#
+# AddIcon* directives tell the server which icon to show for different
+# files or filename extensions. These are only displayed for
+# FancyIndexed directories.
+#
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+AddIcon /icons/bomb.gif /core
+AddIcon /icons/bomb.gif */core.*
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+#
+# DefaultIcon is which icon to show for files which do not have an icon
+# explicitly set.
+#
+DefaultIcon /icons/unknown.gif
+
+#
+# AddDescription allows you to place a short description after a file in
+# server-generated indexes. These are only displayed for FancyIndexed
+# directories.
+# Format: AddDescription "description" filename
+#
+#AddDescription "GZIP compressed document" .gz
+#AddDescription "tar archive" .tar
+#AddDescription "GZIP compressed tar archive" .tgz
+
+#
+# ReadmeName is the name of the README file the server will look for by
+# default, and append to directory listings.
+#
+# HeaderName is the name of a file which should be prepended to
+# directory indexes.
+ReadmeName README.html
+HeaderName HEADER.html
+
+#
+# IndexIgnore is a set of filenames which directory indexing should ignore
+# and not include in the listing. Shell-style wildcarding is permitted.
+#
+IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
+
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/centos.example.com.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/centos.example.com.conf
new file mode 100644
index 000000000..de7ac2777
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/centos.example.com.conf
@@ -0,0 +1,7 @@
+<VirtualHost *:80>
+ ServerName centos.example.com
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/ssl.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/ssl.conf
new file mode 100644
index 000000000..c90fc780f
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/ssl.conf
@@ -0,0 +1,211 @@
+#
+# When we also provide SSL we have to listen to the
+# the HTTPS port in addition.
+#
+Listen 443 https
+
+##
+## SSL Global Context
+##
+## All SSL configuration in this context applies both to
+## the main server and all SSL-enabled virtual hosts.
+##
+
+# Pass Phrase Dialog:
+# Configure the pass phrase gathering process.
+# The filtering dialog program (`builtin' is an internal
+# terminal dialog) has to provide the pass phrase on stdout.
+SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
+
+# Inter-Process Session Cache:
+# Configure the SSL Session Cache: First the mechanism
+# to use and second the expiring timeout (in seconds).
+SSLSessionCache shmcb:/run/httpd/sslcache(512000)
+SSLSessionCacheTimeout 300
+
+# Pseudo Random Number Generator (PRNG):
+# Configure one or more sources to seed the PRNG of the
+# SSL library. The seed data should be of good random quality.
+# WARNING! On some platforms /dev/random blocks if not enough entropy
+# is available. This means you then cannot use the /dev/random device
+# because it would lead to very long connection times (as long as
+# it requires to make more entropy available). But usually those
+# platforms additionally provide a /dev/urandom device which doesn't
+# block. So, if available, use this one instead. Read the mod_ssl User
+# Manual for more details.
+SSLRandomSeed startup file:/dev/urandom 256
+SSLRandomSeed connect builtin
+#SSLRandomSeed startup file:/dev/random 512
+#SSLRandomSeed connect file:/dev/random 512
+#SSLRandomSeed connect file:/dev/urandom 512
+
+#
+# Use "SSLCryptoDevice" to enable any supported hardware
+# accelerators. Use "openssl engine -v" to list supported
+# engine names. NOTE: If you enable an accelerator and the
+# server does not start, consult the error logs and ensure
+# your accelerator is functioning properly.
+#
+SSLCryptoDevice builtin
+#SSLCryptoDevice ubsec
+
+##
+## SSL Virtual Host Context
+##
+
+<VirtualHost _default_:443>
+
+# General setup for the virtual host, inherited from global configuration
+#DocumentRoot "/var/www/html"
+#ServerName www.example.com:443
+
+# Use separate log files for the SSL virtual host; note that LogLevel
+# is not inherited from httpd.conf.
+ErrorLog logs/ssl_error_log
+TransferLog logs/ssl_access_log
+LogLevel warn
+
+# SSL Engine Switch:
+# Enable/Disable SSL for this virtual host.
+SSLEngine on
+
+# SSL Protocol support:
+# List the enable protocol levels with which clients will be able to
+# connect. Disable SSLv2 access by default:
+SSLProtocol all -SSLv2
+
+# SSL Cipher Suite:
+# List the ciphers that the client is permitted to negotiate.
+# See the mod_ssl documentation for a complete list.
+SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA
+
+# Speed-optimized SSL Cipher configuration:
+# If speed is your main concern (on busy HTTPS servers e.g.),
+# you might want to force clients to specific, performance
+# optimized ciphers. In this case, prepend those ciphers
+# to the SSLCipherSuite list, and enable SSLHonorCipherOrder.
+# Caveat: by giving precedence to RC4-SHA and AES128-SHA
+# (as in the example below), most connections will no longer
+# have perfect forward secrecy - if the server's key is
+# compromised, captures of past or future traffic must be
+# considered compromised, too.
+#SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5
+#SSLHonorCipherOrder on
+
+# Server Certificate:
+# Point SSLCertificateFile at a PEM encoded certificate. If
+# the certificate is encrypted, then you will be prompted for a
+# pass phrase. Note that a kill -HUP will prompt again. A new
+# certificate can be generated using the genkey(1) command.
+
+# Server Private Key:
+# If the key is not combined with the certificate, use this
+# directive to point at the key file. Keep in mind that if
+# you've both a RSA and a DSA private key you can configure
+# both in parallel (to also allow the use of DSA ciphers, etc.)
+
+# Server Certificate Chain:
+# Point SSLCertificateChainFile at a file containing the
+# concatenation of PEM encoded CA certificates which form the
+# certificate chain for the server certificate. Alternatively
+# the referenced file can be the same as SSLCertificateFile
+# when the CA certificates are directly appended to the server
+# certificate for convinience.
+#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
+
+# Certificate Authority (CA):
+# Set the CA certificate verification path where to find CA
+# certificates for client authentication or alternatively one
+# huge file containing all of them (file must be PEM encoded)
+#SSLCACertificateFile /etc/pki/tls/certs/ca-bundle.crt
+
+# Client Authentication (Type):
+# Client certificate verification type and depth. Types are
+# none, optional, require and optional_no_ca. Depth is a
+# number which specifies how deeply to verify the certificate
+# issuer chain before deciding the certificate is not valid.
+#SSLVerifyClient require
+#SSLVerifyDepth 10
+
+# Access Control:
+# With SSLRequire you can do per-directory access control based
+# on arbitrary complex boolean expressions containing server
+# variable checks and other lookup directives. The syntax is a
+# mixture between C and Perl. See the mod_ssl documentation
+# for more details.
+#<Location />
+#SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
+# and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
+# and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
+# and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
+# and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
+# or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
+#</Location>
+
+# SSL Engine Options:
+# Set various options for the SSL engine.
+# o FakeBasicAuth:
+# Translate the client X.509 into a Basic Authorisation. This means that
+# the standard Auth/DBMAuth methods can be used for access control. The
+# user name is the `one line' version of the client's X.509 certificate.
+# Note that no password is obtained from the user. Every entry in the user
+# file needs this password: `xxj31ZMTZzkVA'.
+# o ExportCertData:
+# This exports two additional environment variables: SSL_CLIENT_CERT and
+# SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
+# server (always existing) and the client (only existing when client
+# authentication is used). This can be used to import the certificates
+# into CGI scripts.
+# o StdEnvVars:
+# This exports the standard SSL/TLS related `SSL_*' environment variables.
+# Per default this exportation is switched off for performance reasons,
+# because the extraction step is an expensive operation and is usually
+# useless for serving static content. So one usually enables the
+# exportation for CGI and SSI requests only.
+# o StrictRequire:
+# This denies access when "SSLRequireSSL" or "SSLRequire" applied even
+# under a "Satisfy any" situation, i.e. when it applies access is denied
+# and no other module can change it.
+# o OptRenegotiate:
+# This enables optimized SSL connection renegotiation handling when SSL
+# directives are used in per-directory context.
+#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
+<Files ~ "\.(cgi|shtml|phtml|php3?)$">
+ SSLOptions +StdEnvVars
+</Files>
+<Directory "/var/www/cgi-bin">
+ SSLOptions +StdEnvVars
+</Directory>
+
+# SSL Protocol Adjustments:
+# The safe and default but still SSL/TLS standard compliant shutdown
+# approach is that mod_ssl sends the close notify alert but doesn't wait for
+# the close notify alert from client. When you need a different shutdown
+# approach you can use one of the following variables:
+# o ssl-unclean-shutdown:
+# This forces an unclean shutdown when the connection is closed, i.e. no
+# SSL close notify alert is send or allowed to received. This violates
+# the SSL/TLS standard but is needed for some brain-dead browsers. Use
+# this when you receive I/O errors because of the standard approach where
+# mod_ssl sends the close notify alert.
+# o ssl-accurate-shutdown:
+# This forces an accurate shutdown when the connection is closed, i.e. a
+# SSL close notify alert is send and mod_ssl waits for the close notify
+# alert of the client. This is 100% SSL/TLS standard compliant, but in
+# practice often causes hanging connections with brain-dead browsers. Use
+# this only for browsers where you know that their SSL implementation
+# works correctly.
+# Notice: Most problems of broken clients are also related to the HTTP
+# keep-alive facility, so you usually additionally want to disable
+# keep-alive for those clients, too. Use variable "nokeepalive" for this.
+# Similarly, one has to force some clients to use HTTP/1.0 to workaround
+# their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
+# "force-response-1.0" for this.
+BrowserMatch "MSIE [2-5]" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
+
+# Per-Server Logging:
+# The home of a custom SSL log file. Use this when you want a
+# compact non-error SSL logfile on a virtual host basis.
+CustomLog logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
+</VirtualHost>
+
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/userdir.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/userdir.conf
new file mode 100644
index 000000000..b5d7a49ef
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/userdir.conf
@@ -0,0 +1,36 @@
+#
+# UserDir: The name of the directory that is appended onto a user's home
+# directory if a ~user request is received.
+#
+# The path to the end user account 'public_html' directory must be
+# accessible to the webserver userid. This usually means that ~userid
+# must have permissions of 711, ~userid/public_html must have permissions
+# of 755, and documents contained therein must be world-readable.
+# Otherwise, the client will only receive a "403 Forbidden" message.
+#
+<IfModule mod_userdir.c>
+ #
+ # UserDir is disabled by default since it can confirm the presence
+ # of a username on the system (depending on home directory
+ # permissions).
+ #
+ UserDir disabled
+
+ #
+ # To enable requests to /~user/ to serve the user's public_html
+ # directory, remove the "UserDir disabled" line above, and uncomment
+ # the following line instead:
+ #
+ #UserDir public_html
+</IfModule>
+
+#
+# Control access to UserDir directories. The following is an example
+# for a site where these directories are restricted to read-only.
+#
+<Directory "/home/*/public_html">
+ AllowOverride FileInfo AuthConfig Limit Indexes
+ Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+ Require method GET POST OPTIONS
+</Directory>
+
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/welcome.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/welcome.conf
new file mode 100644
index 000000000..c1b6c11d9
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.d/welcome.conf
@@ -0,0 +1,22 @@
+#
+# This configuration file enables the default "Welcome" page if there
+# is no default index page present for the root URL. To disable the
+# Welcome page, comment out all the lines below.
+#
+# NOTE: if this file is removed, it will be restored on upgrades.
+#
+<LocationMatch "^/+$">
+ Options -Indexes
+ ErrorDocument 403 /.noindex.html
+</LocationMatch>
+
+<Directory /usr/share/httpd/noindex>
+ AllowOverride None
+ Require all granted
+</Directory>
+
+Alias /.noindex.html /usr/share/httpd/noindex/index.html
+Alias /noindex/css/bootstrap.min.css /usr/share/httpd/noindex/css/bootstrap.min.css
+Alias /noindex/css/open-sans.css /usr/share/httpd/noindex/css/open-sans.css
+Alias /images/apache_pb.gif /usr/share/httpd/noindex/images/apache_pb.gif
+Alias /images/poweredby.png /usr/share/httpd/noindex/images/poweredby.png
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-base.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-base.conf
new file mode 100644
index 000000000..31d979f20
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-base.conf
@@ -0,0 +1,77 @@
+#
+# This file loads most of the modules included with the Apache HTTP
+# Server itself.
+#
+
+LoadModule access_compat_module modules/mod_access_compat.so
+LoadModule actions_module modules/mod_actions.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule allowmethods_module modules/mod_allowmethods.so
+LoadModule auth_basic_module modules/mod_auth_basic.so
+LoadModule auth_digest_module modules/mod_auth_digest.so
+LoadModule authn_anon_module modules/mod_authn_anon.so
+LoadModule authn_core_module modules/mod_authn_core.so
+LoadModule authn_dbd_module modules/mod_authn_dbd.so
+LoadModule authn_dbm_module modules/mod_authn_dbm.so
+LoadModule authn_file_module modules/mod_authn_file.so
+LoadModule authn_socache_module modules/mod_authn_socache.so
+LoadModule authz_core_module modules/mod_authz_core.so
+LoadModule authz_dbd_module modules/mod_authz_dbd.so
+LoadModule authz_dbm_module modules/mod_authz_dbm.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_owner_module modules/mod_authz_owner.so
+LoadModule authz_user_module modules/mod_authz_user.so
+LoadModule autoindex_module modules/mod_autoindex.so
+LoadModule cache_module modules/mod_cache.so
+LoadModule cache_disk_module modules/mod_cache_disk.so
+LoadModule data_module modules/mod_data.so
+LoadModule dbd_module modules/mod_dbd.so
+LoadModule deflate_module modules/mod_deflate.so
+LoadModule dir_module modules/mod_dir.so
+LoadModule dumpio_module modules/mod_dumpio.so
+LoadModule echo_module modules/mod_echo.so
+LoadModule env_module modules/mod_env.so
+LoadModule expires_module modules/mod_expires.so
+LoadModule ext_filter_module modules/mod_ext_filter.so
+LoadModule filter_module modules/mod_filter.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule include_module modules/mod_include.so
+LoadModule info_module modules/mod_info.so
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule logio_module modules/mod_logio.so
+LoadModule mime_magic_module modules/mod_mime_magic.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule remoteip_module modules/mod_remoteip.so
+LoadModule reqtimeout_module modules/mod_reqtimeout.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
+LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
+LoadModule socache_dbm_module modules/mod_socache_dbm.so
+LoadModule socache_memcache_module modules/mod_socache_memcache.so
+LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
+LoadModule status_module modules/mod_status.so
+LoadModule substitute_module modules/mod_substitute.so
+LoadModule suexec_module modules/mod_suexec.so
+LoadModule unique_id_module modules/mod_unique_id.so
+LoadModule unixd_module modules/mod_unixd.so
+LoadModule userdir_module modules/mod_userdir.so
+LoadModule version_module modules/mod_version.so
+LoadModule vhost_alias_module modules/mod_vhost_alias.so
+
+#LoadModule buffer_module modules/mod_buffer.so
+#LoadModule watchdog_module modules/mod_watchdog.so
+#LoadModule heartbeat_module modules/mod_heartbeat.so
+#LoadModule heartmonitor_module modules/mod_heartmonitor.so
+#LoadModule usertrack_module modules/mod_usertrack.so
+#LoadModule dialup_module modules/mod_dialup.so
+#LoadModule charset_lite_module modules/mod_charset_lite.so
+#LoadModule log_debug_module modules/mod_log_debug.so
+#LoadModule ratelimit_module modules/mod_ratelimit.so
+#LoadModule reflector_module modules/mod_reflector.so
+#LoadModule request_module modules/mod_request.so
+#LoadModule sed_module modules/mod_sed.so
+#LoadModule speling_module modules/mod_speling.so
+
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-dav.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-dav.conf
new file mode 100644
index 000000000..e6af8decd
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-dav.conf
@@ -0,0 +1,3 @@
+LoadModule dav_module modules/mod_dav.so
+LoadModule dav_fs_module modules/mod_dav_fs.so
+LoadModule dav_lock_module modules/mod_dav_lock.so
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-lua.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-lua.conf
new file mode 100644
index 000000000..9e0d0db6e
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-lua.conf
@@ -0,0 +1 @@
+LoadModule lua_module modules/mod_lua.so
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-mpm.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-mpm.conf
new file mode 100644
index 000000000..7bfd1d413
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-mpm.conf
@@ -0,0 +1,19 @@
+# Select the MPM module which should be used by uncommenting exactly
+# one of the following LoadModule lines:
+
+# prefork MPM: Implements a non-threaded, pre-forking web server
+# See: http://httpd.apache.org/docs/2.4/mod/prefork.html
+LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
+
+# worker MPM: Multi-Processing Module implementing a hybrid
+# multi-threaded multi-process web server
+# See: http://httpd.apache.org/docs/2.4/mod/worker.html
+#
+#LoadModule mpm_worker_module modules/mod_mpm_worker.so
+
+# event MPM: A variant of the worker MPM with the goal of consuming
+# threads only for connections with active processing
+# See: http://httpd.apache.org/docs/2.4/mod/event.html
+#
+#LoadModule mpm_event_module modules/mod_mpm_event.so
+
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-proxy.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-proxy.conf
new file mode 100644
index 000000000..cc0bca077
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-proxy.conf
@@ -0,0 +1,16 @@
+# This file configures all the proxy modules:
+LoadModule proxy_module modules/mod_proxy.so
+LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
+LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
+LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
+LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
+LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
+LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
+LoadModule proxy_connect_module modules/mod_proxy_connect.so
+LoadModule proxy_express_module modules/mod_proxy_express.so
+LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
+LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
+LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
+LoadModule proxy_http_module modules/mod_proxy_http.so
+LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
+LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-ssl.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-ssl.conf
new file mode 100644
index 000000000..53235cd76
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-ssl.conf
@@ -0,0 +1 @@
+LoadModule ssl_module modules/mod_ssl.so
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-systemd.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-systemd.conf
new file mode 100644
index 000000000..b208c972d
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/00-systemd.conf
@@ -0,0 +1,2 @@
+# This file configures systemd module:
+LoadModule systemd_module modules/mod_systemd.so
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/01-cgi.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/01-cgi.conf
new file mode 100644
index 000000000..5b8b9362e
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf.modules.d/01-cgi.conf
@@ -0,0 +1,14 @@
+# This configuration file loads a CGI module appropriate to the MPM
+# which has been configured in 00-mpm.conf. mod_cgid should be used
+# with a threaded MPM; mod_cgi with the prefork MPM.
+
+<IfModule mpm_worker_module>
+ LoadModule cgid_module modules/mod_cgid.so
+</IfModule>
+<IfModule mpm_event_module>
+ LoadModule cgid_module modules/mod_cgid.so
+</IfModule>
+<IfModule mpm_prefork_module>
+ LoadModule cgi_module modules/mod_cgi.so
+</IfModule>
+
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf/httpd.conf b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf/httpd.conf
new file mode 100644
index 000000000..a7af0dc1e
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf/httpd.conf
@@ -0,0 +1,353 @@
+#
+# This is the main Apache HTTP server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
+# In particular, see
+# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
+# for a discussion of each configuration directive.
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path. If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so 'log/access_log'
+# with ServerRoot set to '/www' will be interpreted by the
+# server as '/www/log/access_log', where as '/log/access_log' will be
+# interpreted as '/log/access_log'.
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# Do not add a slash at the end of the directory path. If you point
+# ServerRoot at a non-local disk, be sure to specify a local disk on the
+# Mutex directive, if file-based mutexes are used. If you wish to share the
+# same ServerRoot for multiple httpd daemons, you will need to change at
+# least PidFile.
+#
+ServerRoot "/etc/httpd"
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to
+# prevent Apache from glomming onto all bound IP addresses.
+#
+#Listen 12.34.56.78:80
+Listen 80
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+Include conf.modules.d/*.conf
+
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# It is usually good practice to create a dedicated user and group for
+# running httpd, as with most system services.
+#
+User apache
+Group apache
+
+# 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition. These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed. This address appears on some server-generated pages, such
+# as error documents. e.g. admin@your-domain.com
+#
+ServerAdmin root@localhost
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+#
+#ServerName www.example.com:80
+
+#
+# Deny access to the entirety of your server's filesystem. You must
+# explicitly permit access to web content directories in other
+# <Directory> blocks below.
+#
+<Directory />
+ AllowOverride none
+ Require all denied
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+DocumentRoot "/var/www/html"
+
+#
+# Relax access to content within /var/www.
+#
+<Directory "/var/www">
+ AllowOverride None
+ # Allow open access:
+ Require all granted
+</Directory>
+
+# Further relax access to the default document root:
+<Directory "/var/www/html">
+ #
+ # Possible values for the Options directive are "None", "All",
+ # or any combination of:
+ # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+ #
+ # Note that "MultiViews" must be named *explicitly* --- "Options All"
+ # doesn't give it to you.
+ #
+ # The Options directive is both complicated and important. Please see
+ # http://httpd.apache.org/docs/2.4/mod/core.html#options
+ # for more information.
+ #
+ Options Indexes FollowSymLinks
+
+ #
+ # AllowOverride controls what directives may be placed in .htaccess files.
+ # It can be "All", "None", or any combination of the keywords:
+ # Options FileInfo AuthConfig Limit
+ #
+ AllowOverride None
+
+ #
+ # Controls who can get stuff from this server.
+ #
+ Require all granted
+</Directory>
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+<IfModule dir_module>
+ DirectoryIndex index.html
+</IfModule>
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<Files ".ht*">
+ Require all denied
+</Files>
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog "logs/error_log"
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+<IfModule log_config_module>
+ #
+ # The following directives define some format nicknames for use with
+ # a CustomLog directive (see below).
+ #
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+ LogFormat "%h %l %u %t \"%r\" %>s %b" common
+
+ <IfModule logio_module>
+ # You need to enable mod_logio.c to use %I and %O
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+ </IfModule>
+
+ #
+ # The location and format of the access logfile (Common Logfile Format).
+ # If you do not define any access logfiles within a <VirtualHost>
+ # container, they will be logged here. Contrariwise, if you *do*
+ # define per-<VirtualHost> access logfiles, transactions will be
+ # logged therein and *not* in this file.
+ #
+ #CustomLog "logs/access_log" common
+
+ #
+ # If you prefer a logfile with access, agent, and referer information
+ # (Combined Logfile Format) you can use the following directive.
+ #
+ CustomLog "logs/access_log" combined
+</IfModule>
+
+<IfModule alias_module>
+ #
+ # Redirect: Allows you to tell clients about documents that used to
+ # exist in your server's namespace, but do not anymore. The client
+ # will make a new request for the document at its new location.
+ # Example:
+ # Redirect permanent /foo http://www.example.com/bar
+
+ #
+ # Alias: Maps web paths into filesystem paths and is used to
+ # access content that does not live under the DocumentRoot.
+ # Example:
+ # Alias /webpath /full/filesystem/path
+ #
+ # If you include a trailing / on /webpath then the server will
+ # require it to be present in the URL. You will also likely
+ # need to provide a <Directory> section to allow access to
+ # the filesystem path.
+
+ #
+ # ScriptAlias: This controls which directories contain server scripts.
+ # ScriptAliases are essentially the same as Aliases, except that
+ # documents in the target directory are treated as applications and
+ # run by the server when requested rather than as documents sent to the
+ # client. The same rules about trailing "/" apply to ScriptAlias
+ # directives as to Alias.
+ #
+ ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+
+</IfModule>
+
+#
+# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+#
+<Directory "/var/www/cgi-bin">
+ AllowOverride None
+ Options None
+ Require all granted
+</Directory>
+
+<IfModule mime_module>
+ #
+ # TypesConfig points to the file containing the list of mappings from
+ # filename extension to MIME-type.
+ #
+ TypesConfig /etc/mime.types
+
+ #
+ # AddType allows you to add to or override the MIME configuration
+ # file specified in TypesConfig for specific file types.
+ #
+ #AddType application/x-gzip .tgz
+ #
+ # AddEncoding allows you to have certain browsers uncompress
+ # information on the fly. Note: Not all browsers support this.
+ #
+ #AddEncoding x-compress .Z
+ #AddEncoding x-gzip .gz .tgz
+ #
+ # If the AddEncoding directives above are commented-out, then you
+ # probably should define those extensions to indicate media types:
+ #
+ AddType application/x-compress .Z
+ AddType application/x-gzip .gz .tgz
+
+ #
+ # AddHandler allows you to map certain file extensions to "handlers":
+ # actions unrelated to filetype. These can be either built into the server
+ # or added with the Action directive (see below)
+ #
+ # To use CGI scripts outside of ScriptAliased directories:
+ # (You will also need to add "ExecCGI" to the "Options" directive.)
+ #
+ #AddHandler cgi-script .cgi
+
+ # For type maps (negotiated resources):
+ #AddHandler type-map var
+
+ #
+ # Filters allow you to process content before it is sent to the client.
+ #
+ # To parse .shtml files for server-side includes (SSI):
+ # (You will also need to add "Includes" to the "Options" directive.)
+ #
+ AddType text/html .shtml
+ AddOutputFilter INCLUDES .shtml
+</IfModule>
+
+#
+# Specify a default charset for all content served; this enables
+# interpretation of all content as UTF-8 by default. To use the
+# default browser choice (ISO-8859-1), or to allow the META tags
+# in HTML content to override this choice, comment out this
+# directive:
+#
+AddDefaultCharset UTF-8
+
+<IfModule mime_magic_module>
+ #
+ # The mod_mime_magic module allows the server to use various hints from the
+ # contents of the file itself to determine its type. The MIMEMagicFile
+ # directive tells the module where the hint definitions are located.
+ #
+ MIMEMagicFile conf/magic
+</IfModule>
+
+#
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# EnableMMAP and EnableSendfile: On systems that support it,
+# memory-mapping or the sendfile syscall may be used to deliver
+# files. This usually improves server performance, but must
+# be turned off when serving from networked-mounted
+# filesystems or if support for these functions is otherwise
+# broken on your system.
+# Defaults if commented: EnableMMAP On, EnableSendfile Off
+#
+#EnableMMAP off
+EnableSendfile on
+
+# Supplemental configuration
+#
+# Load config files in the "/etc/httpd/conf.d" directory, if any.
+IncludeOptional conf.d/*.conf
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf/magic b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf/magic
new file mode 100644
index 000000000..7c56119e9
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/httpd/conf/magic
@@ -0,0 +1,385 @@
+# Magic data for mod_mime_magic Apache module (originally for file(1) command)
+# The module is described in /manual/mod/mod_mime_magic.html
+#
+# The format is 4-5 columns:
+# Column #1: byte number to begin checking from, ">" indicates continuation
+# Column #2: type of data to match
+# Column #3: contents of data to match
+# Column #4: MIME type of result
+# Column #5: MIME encoding of result (optional)
+
+#------------------------------------------------------------------------------
+# Localstuff: file(1) magic for locally observed files
+# Add any locally observed files here.
+
+#------------------------------------------------------------------------------
+# end local stuff
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# Java
+
+0 short 0xcafe
+>2 short 0xbabe application/java
+
+#------------------------------------------------------------------------------
+# audio: file(1) magic for sound formats
+#
+# from Jan Nicolai Langfeldt <janl@ifi.uio.no>,
+#
+
+# Sun/NeXT audio data
+0 string .snd
+>12 belong 1 audio/basic
+>12 belong 2 audio/basic
+>12 belong 3 audio/basic
+>12 belong 4 audio/basic
+>12 belong 5 audio/basic
+>12 belong 6 audio/basic
+>12 belong 7 audio/basic
+
+>12 belong 23 audio/x-adpcm
+
+# DEC systems (e.g. DECstation 5000) use a variant of the Sun/NeXT format
+# that uses little-endian encoding and has a different magic number
+# (0x0064732E in little-endian encoding).
+0 lelong 0x0064732E
+>12 lelong 1 audio/x-dec-basic
+>12 lelong 2 audio/x-dec-basic
+>12 lelong 3 audio/x-dec-basic
+>12 lelong 4 audio/x-dec-basic
+>12 lelong 5 audio/x-dec-basic
+>12 lelong 6 audio/x-dec-basic
+>12 lelong 7 audio/x-dec-basic
+# compressed (G.721 ADPCM)
+>12 lelong 23 audio/x-dec-adpcm
+
+# Bytes 0-3 of AIFF, AIFF-C, & 8SVX audio files are "FORM"
+# AIFF audio data
+8 string AIFF audio/x-aiff
+# AIFF-C audio data
+8 string AIFC audio/x-aiff
+# IFF/8SVX audio data
+8 string 8SVX audio/x-aiff
+
+# Creative Labs AUDIO stuff
+# Standard MIDI data
+0 string MThd audio/unknown
+#>9 byte >0 (format %d)
+#>11 byte >1 using %d channels
+# Creative Music (CMF) data
+0 string CTMF audio/unknown
+# SoundBlaster instrument data
+0 string SBI audio/unknown
+# Creative Labs voice data
+0 string Creative\ Voice\ File audio/unknown
+## is this next line right? it came this way...
+#>19 byte 0x1A
+#>23 byte >0 - version %d
+#>22 byte >0 \b.%d
+
+# [GRR 950115: is this also Creative Labs? Guessing that first line
+# should be string instead of unknown-endian long...]
+#0 long 0x4e54524b MultiTrack sound data
+#0 string NTRK MultiTrack sound data
+#>4 long x - version %ld
+
+# Microsoft WAVE format (*.wav)
+# [GRR 950115: probably all of the shorts and longs should be leshort/lelong]
+# Microsoft RIFF
+0 string RIFF audio/unknown
+# - WAVE format
+>8 string WAVE audio/x-wav
+# MPEG audio.
+0 beshort&0xfff0 0xfff0 audio/mpeg
+# C64 SID Music files, from Linus Walleij <triad@df.lth.se>
+0 string PSID audio/prs.sid
+
+#------------------------------------------------------------------------------
+# c-lang: file(1) magic for C programs or various scripts
+#
+
+# XPM icons (Greg Roelofs, newt@uchicago.edu)
+# ideally should go into "images", but entries below would tag XPM as C source
+0 string /*\ XPM image/x-xbm 7bit
+
+# this first will upset you if you're a PL/1 shop... (are there any left?)
+# in which case rm it; ascmagic will catch real C programs
+# C or REXX program text
+0 string /* text/plain
+# C++ program text
+0 string // text/plain
+
+#------------------------------------------------------------------------------
+# compress: file(1) magic for pure-compression formats (no archives)
+#
+# compress, gzip, pack, compact, huf, squeeze, crunch, freeze, yabba, whap, etc.
+#
+# Formats for various forms of compressed data
+# Formats for "compress" proper have been moved into "compress.c",
+# because it tries to uncompress it to figure out what's inside.
+
+# standard unix compress
+0 string \037\235 application/octet-stream x-compress
+
+# gzip (GNU zip, not to be confused with [Info-ZIP/PKWARE] zip archiver)
+0 string \037\213 application/octet-stream x-gzip
+
+# According to gzip.h, this is the correct byte order for packed data.
+0 string \037\036 application/octet-stream
+#
+# This magic number is byte-order-independent.
+#
+0 short 017437 application/octet-stream
+
+# XXX - why *two* entries for "compacted data", one of which is
+# byte-order independent, and one of which is byte-order dependent?
+#
+# compacted data
+0 short 0x1fff application/octet-stream
+0 string \377\037 application/octet-stream
+# huf output
+0 short 0145405 application/octet-stream
+
+# Squeeze and Crunch...
+# These numbers were gleaned from the Unix versions of the programs to
+# handle these formats. Note that I can only uncrunch, not crunch, and
+# I didn't have a crunched file handy, so the crunch number is untested.
+# Keith Waclena <keith@cerberus.uchicago.edu>
+#0 leshort 0x76FF squeezed data (CP/M, DOS)
+#0 leshort 0x76FE crunched data (CP/M, DOS)
+
+# Freeze
+#0 string \037\237 Frozen file 2.1
+#0 string \037\236 Frozen file 1.0 (or gzip 0.5)
+
+# lzh?
+#0 string \037\240 LZH compressed data
+
+#------------------------------------------------------------------------------
+# frame: file(1) magic for FrameMaker files
+#
+# This stuff came on a FrameMaker demo tape, most of which is
+# copyright, but this file is "published" as witness the following:
+#
+0 string \<MakerFile application/x-frame
+0 string \<MIFFile application/x-frame
+0 string \<MakerDictionary application/x-frame
+0 string \<MakerScreenFon application/x-frame
+0 string \<MML application/x-frame
+0 string \<Book application/x-frame
+0 string \<Maker application/x-frame
+
+#------------------------------------------------------------------------------
+# html: file(1) magic for HTML (HyperText Markup Language) docs
+#
+# from Daniel Quinlan <quinlan@yggdrasil.com>
+# and Anna Shergold <anna@inext.co.uk>
+#
+0 string \<!DOCTYPE\ HTML text/html
+0 string \<!doctype\ html text/html
+0 string \<HEAD text/html
+0 string \<head text/html
+0 string \<TITLE text/html
+0 string \<title text/html
+0 string \<html text/html
+0 string \<HTML text/html
+0 string \<!-- text/html
+0 string \<h1 text/html
+0 string \<H1 text/html
+
+# XML eXtensible Markup Language, from Linus Walleij <triad@df.lth.se>
+0 string \<?xml text/xml
+
+#------------------------------------------------------------------------------
+# images: file(1) magic for image formats (see also "c-lang" for XPM bitmaps)
+#
+# originally from jef@helios.ee.lbl.gov (Jef Poskanzer),
+# additions by janl@ifi.uio.no as well as others. Jan also suggested
+# merging several one- and two-line files into here.
+#
+# XXX - byte order for GIF and TIFF fields?
+# [GRR: TIFF allows both byte orders; GIF is probably little-endian]
+#
+
+# [GRR: what the hell is this doing in here?]
+#0 string xbtoa btoa'd file
+
+# PBMPLUS
+# PBM file
+0 string P1 image/x-portable-bitmap 7bit
+# PGM file
+0 string P2 image/x-portable-greymap 7bit
+# PPM file
+0 string P3 image/x-portable-pixmap 7bit
+# PBM "rawbits" file
+0 string P4 image/x-portable-bitmap
+# PGM "rawbits" file
+0 string P5 image/x-portable-greymap
+# PPM "rawbits" file
+0 string P6 image/x-portable-pixmap
+
+# NIFF (Navy Interchange File Format, a modification of TIFF)
+# [GRR: this *must* go before TIFF]
+0 string IIN1 image/x-niff
+
+# TIFF and friends
+# TIFF file, big-endian
+0 string MM image/tiff
+# TIFF file, little-endian
+0 string II image/tiff
+
+# possible GIF replacements; none yet released!
+# (Greg Roelofs, newt@uchicago.edu)
+#
+# GRR 950115: this was mine ("Zip GIF"):
+# ZIF image (GIF+deflate alpha)
+0 string GIF94z image/unknown
+#
+# GRR 950115: this is Jeremy Wohl's Free Graphics Format (better):
+# FGF image (GIF+deflate beta)
+0 string FGF95a image/unknown
+#
+# GRR 950115: this is Thomas Boutell's Portable Bitmap Format proposal
+# (best; not yet implemented):
+# PBF image (deflate compression)
+0 string PBF image/unknown
+
+# GIF
+0 string GIF image/gif
+
+# JPEG images
+0 beshort 0xffd8 image/jpeg
+
+# PC bitmaps (OS/2, Windoze BMP files) (Greg Roelofs, newt@uchicago.edu)
+0 string BM image/bmp
+#>14 byte 12 (OS/2 1.x format)
+#>14 byte 64 (OS/2 2.x format)
+#>14 byte 40 (Windows 3.x format)
+#0 string IC icon
+#0 string PI pointer
+#0 string CI color icon
+#0 string CP color pointer
+#0 string BA bitmap array
+
+0 string \x89PNG image/png
+0 string FWS application/x-shockwave-flash
+0 string CWS application/x-shockwave-flash
+
+#------------------------------------------------------------------------------
+# lisp: file(1) magic for lisp programs
+#
+# various lisp types, from Daniel Quinlan (quinlan@yggdrasil.com)
+0 string ;; text/plain 8bit
+# Emacs 18 - this is always correct, but not very magical.
+0 string \012( application/x-elc
+# Emacs 19
+0 string ;ELC\023\000\000\000 application/x-elc
+
+#------------------------------------------------------------------------------
+# mail.news: file(1) magic for mail and news
+#
+# There are tests to ascmagic.c to cope with mail and news.
+0 string Relay-Version: message/rfc822 7bit
+0 string #!\ rnews message/rfc822 7bit
+0 string N#!\ rnews message/rfc822 7bit
+0 string Forward\ to message/rfc822 7bit
+0 string Pipe\ to message/rfc822 7bit
+0 string Return-Path: message/rfc822 7bit
+0 string Path: message/news 8bit
+0 string Xref: message/news 8bit
+0 string From: message/rfc822 7bit
+0 string Article message/news 8bit
+#------------------------------------------------------------------------------
+# msword: file(1) magic for MS Word files
+#
+# Contributor claims:
+# Reversed-engineered MS Word magic numbers
+#
+
+0 string \376\067\0\043 application/msword
+0 string \333\245-\0\0\0 application/msword
+
+# disable this one because it applies also to other
+# Office/OLE documents for which msword is not correct. See PR#2608.
+#0 string \320\317\021\340\241\261 application/msword
+
+
+
+#------------------------------------------------------------------------------
+# printer: file(1) magic for printer-formatted files
+#
+
+# PostScript
+0 string %! application/postscript
+0 string \004%! application/postscript
+
+# Acrobat
+# (due to clamen@cs.cmu.edu)
+0 string %PDF- application/pdf
+
+#------------------------------------------------------------------------------
+# sc: file(1) magic for "sc" spreadsheet
+#
+38 string Spreadsheet application/x-sc
+
+#------------------------------------------------------------------------------
+# tex: file(1) magic for TeX files
+#
+# XXX - needs byte-endian stuff (big-endian and little-endian DVI?)
+#
+# From <conklin@talisman.kaleida.com>
+
+# Although we may know the offset of certain text fields in TeX DVI
+# and font files, we can't use them reliably because they are not
+# zero terminated. [but we do anyway, christos]
+0 string \367\002 application/x-dvi
+#0 string \367\203 TeX generic font data
+#0 string \367\131 TeX packed font data
+#0 string \367\312 TeX virtual font data
+#0 string This\ is\ TeX, TeX transcript text
+#0 string This\ is\ METAFONT, METAFONT transcript text
+
+# There is no way to detect TeX Font Metric (*.tfm) files without
+# breaking them apart and reading the data. The following patterns
+# match most *.tfm files generated by METAFONT or afm2tfm.
+#2 string \000\021 TeX font metric data
+#2 string \000\022 TeX font metric data
+#>34 string >\0 (%s)
+
+# Texinfo and GNU Info, from Daniel Quinlan (quinlan@yggdrasil.com)
+#0 string \\input\ texinfo Texinfo source text
+#0 string This\ is\ Info\ file GNU Info text
+
+# correct TeX magic for Linux (and maybe more)
+# from Peter Tobias (tobias@server.et-inf.fho-emden.de)
+#
+0 leshort 0x02f7 application/x-dvi
+
+# RTF - Rich Text Format
+0 string {\\rtf application/rtf
+
+#------------------------------------------------------------------------------
+# animation: file(1) magic for animation/movie formats
+#
+# animation formats, originally from vax@ccwf.cc.utexas.edu (VaX#n8)
+# MPEG file
+0 string \000\000\001\263 video/mpeg
+#
+# The contributor claims:
+# I couldn't find a real magic number for these, however, this
+# -appears- to work. Note that it might catch other files, too,
+# so BE CAREFUL!
+#
+# Note that title and author appear in the two 20-byte chunks
+# at decimal offsets 2 and 22, respectively, but they are XOR'ed with
+# 255 (hex FF)! DL format SUCKS BIG ROCKS.
+#
+# DL file version 1 , medium format (160x100, 4 images/screen)
+0 byte 1 video/unknown
+0 byte 2 video/unknown
+# Quicktime video, from Linus Walleij <triad@df.lth.se>
+# from Apple quicktime file format documentation.
+4 string moov video/quicktime
+4 string mdat video/quicktime
+
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/sites b/certbot-apache/tests/testdata/centos7_apache/apache/sites
new file mode 100644
index 000000000..6af1f63fa
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/sites
@@ -0,0 +1 @@
+conf.d/centos.example.com.conf, centos.example.com
diff --git a/certbot-apache/tests/testdata/centos7_apache/apache/sysconfig/httpd b/certbot-apache/tests/testdata/centos7_apache/apache/sysconfig/httpd
new file mode 100644
index 000000000..4bcb300c2
--- /dev/null
+++ b/certbot-apache/tests/testdata/centos7_apache/apache/sysconfig/httpd
@@ -0,0 +1,25 @@
+#
+# This file can be used to set additional environment variables for
+# the httpd process, or pass additional options to the httpd
+# executable.
+#
+# Note: With previous versions of httpd, the MPM could be changed by
+# editing an "HTTPD" variable here. With the current version, that
+# variable is now ignored. The MPM is a loadable module, and the
+# choice of MPM can be changed by editing the configuration file
+# /etc/httpd/conf.modules.d/00-mpm.conf.
+#
+
+#
+# To pass additional options (for instance, -D definitions) to the
+# httpd binary at startup, set OPTIONS here.
+#
+OPTIONS="-D mock_define -D mock_define_too -D mock_value=TRUE -DMOCK_NOSEP -DNOSEP_TWO=NOSEP_VAL"
+
+#
+# This setting ensures the httpd process is started in the "C" locale
+# by default. (Some modules will not behave correctly if
+# case-sensitive string comparisons are performed in a different
+# locale.)
+#
+LANG=C
diff --git a/certbot-apache/tests/testdata/complex_parsing/apache2.conf b/certbot-apache/tests/testdata/complex_parsing/apache2.conf
new file mode 100644
index 000000000..14cf95f9e
--- /dev/null
+++ b/certbot-apache/tests/testdata/complex_parsing/apache2.conf
@@ -0,0 +1,55 @@
+# Global configuration
+
+PidFile ${APACHE_PID_FILE}
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 300
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive On
+
+# These need to be set in /etc/apache2/envvars
+User ${APACHE_RUN_USER}
+Group ${APACHE_RUN_GROUP}
+
+ErrorLog ${APACHE_LOG_DIR}/error.log
+
+LogLevel warn
+
+# Include module configuration:
+IncludeOptional mods-enabled/*.load
+IncludeOptional mods-enabled/*.conf
+
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+ Require all denied
+</Directory>
+
+<Directory /var/www/>
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+</Directory>
+
+# Include generic snippets of statements
+IncludeOptional conf-enabled/
+
+# Include the virtual host configurations:
+IncludeOptional sites-enabled/*.conf
+
+Define COMPLEX
+
+Define tls_port 1234
+Define tls_port_str "1234"
+
+Define fnmatch_filename test_fnmatch.conf
+
+
+Include test_variables.conf
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/complex_parsing/conf-enabled/dummy.conf b/certbot-apache/tests/testdata/complex_parsing/conf-enabled/dummy.conf
new file mode 100644
index 000000000..1e5307780
--- /dev/null
+++ b/certbot-apache/tests/testdata/complex_parsing/conf-enabled/dummy.conf
@@ -0,0 +1,9 @@
+# 3 - one arg directives
+# 2 - two arg directives
+# 1 - three arg directives
+TestArgsDirective one_arg
+TestArgsDirective one_arg two_arg
+TestArgsDirective one_arg
+TestArgsDirective one_arg two_arg
+TestArgsDirective one_arg two_arg three_arg
+TestArgsDirective one_arg
diff --git a/certbot-apache/tests/testdata/complex_parsing/test_fnmatch.conf b/certbot-apache/tests/testdata/complex_parsing/test_fnmatch.conf
new file mode 100644
index 000000000..4e6b84edf
--- /dev/null
+++ b/certbot-apache/tests/testdata/complex_parsing/test_fnmatch.conf
@@ -0,0 +1 @@
+FNMATCH_DIRECTIVE Success
diff --git a/certbot-apache/tests/testdata/complex_parsing/test_variables.conf b/certbot-apache/tests/testdata/complex_parsing/test_variables.conf
new file mode 100644
index 000000000..1a9edff74
--- /dev/null
+++ b/certbot-apache/tests/testdata/complex_parsing/test_variables.conf
@@ -0,0 +1,66 @@
+TestVariablePort ${tls_port}
+TestVariablePortStr "${tls_port_str}"
+
+LoadModule status_module modules/mod_status.so
+
+# Basic IfDefine
+<IfDefine COMPLEX>
+ VAR_DIRECTIVE success
+ LoadModule ssl_module modules/mod_ssl.so
+</IfDefine>
+
+<IfDefine !COMPLEX>
+ INVALID_VAR_DIRECTIVE failure
+</IfDefine>
+
+<IfDefine NOT_COMPLEX>
+ INVALID_VAR_DIRECTIVE failure
+</IfDefine>
+
+<IfDefine !NOT_COMPLEX>
+ VAR_DIRECTIVE failure
+</IfDefine>
+
+
+# Basic IfModule
+<IfModule ssl_module>
+ MOD_DIRECTIVE Success
+</IfModule>
+
+<IfModule !ssl_module>
+ INVALID_MOD_DIRECTIVE failure
+</IfModule>
+
+<IfModule fake_module>
+ INVALID_MOD_DIRECTIVE failure
+</IfModule>
+
+<IfModule !fake_module>
+ MOD_DIRECTIVE Success
+</IfModule>
+
+# Nested Tests
+<IfModule status_module>
+ <IfDefine COMPLEX>
+ NESTED_DIRECTIVE success
+
+ <IfModule mod_ssl.c>
+ NESTED_DIRECTIVE success
+ </IfModule>
+
+ <IfModule !mod_ssl.c>
+ INVALID_NESTED_DIRECTIVE failure
+ </IfModule>
+ </IfDefine>
+
+ <IfDefine !COMPLEX>
+ INVALID_NESTED_DIRECTIVE failure
+
+ <IfModule ssl_module>
+ INVALID_NESTED_DIRECTIVE failure
+ </IfModule>
+ </IfDefine>
+
+ NESTED_DIRECTIVE success
+
+</IfModule>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/apache2.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/apache2.conf
new file mode 100644
index 000000000..2a5bb7be2
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/apache2.conf
@@ -0,0 +1,196 @@
+# This is the main Apache server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See http://httpd.apache.org/docs/2.4/ for detailed information about
+# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
+# hints.
+#
+#
+# Summary of how the Apache 2 configuration works in Debian:
+# The Apache 2 web server configuration in Debian is quite different to
+# upstream's suggested way to configure the web server. This is because Debian's
+# default Apache2 installation attempts to make adding and removing modules,
+# virtual hosts, and extra configuration directives as flexible as possible, in
+# order to make automating the changes and administering the server as easy as
+# possible.
+
+# It is split into several files forming the configuration hierarchy outlined
+# below, all located in the /etc/apache2/ directory:
+#
+# /etc/apache2/
+# |-- apache2.conf
+# | `-- ports.conf
+# |-- mods-enabled
+# | |-- *.load
+# | `-- *.conf
+# |-- conf-enabled
+# | `-- *.conf
+# `-- sites-enabled
+# `-- *.conf
+#
+#
+# * apache2.conf is the main configuration file (this file). It puts the pieces
+# together by including all remaining configuration files when starting up the
+# web server.
+#
+# * ports.conf is always included from the main configuration file. It is
+# supposed to determine listening ports for incoming connections which can be
+# customized anytime.
+#
+# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
+# directories contain particular configuration snippets which manage modules,
+# global configuration fragments, or virtual host configurations,
+# respectively.
+#
+# They are activated by symlinking available configuration files from their
+# respective *-available/ counterparts. These should be managed by using our
+# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
+# their respective man pages for detailed information.
+#
+# * The binary is called apache2. Due to the use of environment variables, in
+# the default configuration, apache2 needs to be started/stopped with
+# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
+# work with the default configuration.
+
+
+# Global configuration
+
+#
+# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
+#
+Mutex file:${APACHE_LOCK_DIR} default
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+# This needs to be set in /etc/apache2/envvars
+#
+PidFile ${APACHE_PID_FILE}
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 300
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive On
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 5
+
+
+# These need to be set in /etc/apache2/envvars
+User ${APACHE_RUN_USER}
+Group ${APACHE_RUN_GROUP}
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog ${APACHE_LOG_DIR}/error.log
+
+#
+# LogLevel: Control the severity of messages logged to the error_log.
+# Available values: trace8, ..., trace1, debug, info, notice, warn,
+# error, crit, alert, emerg.
+# It is also possible to configure the log level for particular modules, e.g.
+# "LogLevel info ssl:warn"
+#
+LogLevel warn
+
+# Include module configuration:
+IncludeOptional mods-enabled/*.load
+IncludeOptional mods-enabled/*.conf
+
+# Include list of ports to listen on
+Include ports.conf
+
+
+# Sets the default security model of the Apache2 HTTPD server. It does
+# not allow access to the root filesystem outside of /usr/share and /var/www.
+# The former is used by web applications packaged in Debian,
+# the latter may be used for local directories served by the web server. If
+# your system is serving content from a sub-directory in /srv you must allow
+# access here, or in any related virtual host.
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+ Require all denied
+</Directory>
+
+<Directory /usr/share>
+ AllowOverride None
+ Require all granted
+</Directory>
+
+<Directory /var/>
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+</Directory>
+
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives. See also the AllowOverride
+# directive.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<FilesMatch "^\.ht">
+ Require all denied
+</FilesMatch>
+
+# The following directives define some format nicknames for use with
+# a CustomLog directive.
+#
+# These deviate from the Common Log Format definitions in that they use %O
+# (the actual bytes sent including headers) instead of %b (the size of the
+# requested file), because the latter makes it impossible to detect partial
+# requests.
+#
+# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.
+# Use mod_remoteip instead.
+#
+LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
+LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %O" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+# Include of directories ignores editors' and dpkg's backup files,
+# see README.Debian for details.
+
+# Include generic snippets of statements
+IncludeOptional conf-enabled/*.conf
+
+# Include the virtual host configurations:
+IncludeOptional sites-enabled/*.conf
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/bad_conf_file.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/bad_conf_file.conf
new file mode 100644
index 000000000..8e9178803
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/bad_conf_file.conf
@@ -0,0 +1,3 @@
+<VirtualHost 1.1.1.1>
+
+ServerName invalid.net
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/other-vhosts-access-log.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/other-vhosts-access-log.conf
new file mode 100644
index 000000000..5e9f5e9e7
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/other-vhosts-access-log.conf
@@ -0,0 +1,4 @@
+# Define an access log for VirtualHosts that don't define their own logfile
+CustomLog ${APACHE_LOG_DIR}/other_vhosts_access.log vhost_combined
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/security.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/security.conf
new file mode 100644
index 000000000..eccfcb1fd
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/security.conf
@@ -0,0 +1,35 @@
+# Changing the following options will not really affect the security of the
+# server, but might make attacks slightly more difficult in some cases.
+
+#
+# ServerTokens
+# This directive configures what you return as the Server HTTP response
+# Header. The default is 'Full' which sends information about the OS-Type
+# and compiled in modules.
+# Set to one of: Full | OS | Minimal | Minor | Major | Prod
+# where Full conveys the most information, and Prod the least.
+#ServerTokens Minimal
+ServerTokens OS
+#ServerTokens Full
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#ServerSignature Off
+ServerSignature On
+
+#
+# Allow TRACE method
+#
+# Set to "extended" to also reflect the request body (only for testing and
+# diagnostic purposes).
+#
+# Set to one of: On | Off | extended
+TraceEnable Off
+#TraceEnable On
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/serve-cgi-bin.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/serve-cgi-bin.conf
new file mode 100644
index 000000000..b02782dab
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-available/serve-cgi-bin.conf
@@ -0,0 +1,20 @@
+<IfModule mod_alias.c>
+ <IfModule mod_cgi.c>
+ Define ENABLE_USR_LIB_CGI_BIN
+ </IfModule>
+
+ <IfModule mod_cgid.c>
+ Define ENABLE_USR_LIB_CGI_BIN
+ </IfModule>
+
+ <IfDefine ENABLE_USR_LIB_CGI_BIN>
+ ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+ <Directory "/usr/lib/cgi-bin">
+ AllowOverride None
+ Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
+ Require all granted
+ </Directory>
+ </IfDefine>
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/other-vhosts-access-log.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/other-vhosts-access-log.conf
new file mode 120000
index 000000000..8af91e530
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/other-vhosts-access-log.conf
@@ -0,0 +1 @@
+../conf-available/other-vhosts-access-log.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/security.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/security.conf
new file mode 120000
index 000000000..036c97fa7
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/security.conf
@@ -0,0 +1 @@
+../conf-available/security.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/serve-cgi-bin.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/serve-cgi-bin.conf
new file mode 120000
index 000000000..d917f688e
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/conf-enabled/serve-cgi-bin.conf
@@ -0,0 +1 @@
+../conf-available/serve-cgi-bin.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/envvars b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/envvars
new file mode 100644
index 000000000..a13d9a89e
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/envvars
@@ -0,0 +1,29 @@
+# envvars - default environment variables for apache2ctl
+
+# this won't be correct after changing uid
+unset HOME
+
+# for supporting multiple apache2 instances
+if [ "${APACHE_CONFDIR##/etc/apache2-}" != "${APACHE_CONFDIR}" ] ; then
+ SUFFIX="-${APACHE_CONFDIR##/etc/apache2-}"
+else
+ SUFFIX=
+fi
+
+# Since there is no sane way to get the parsed apache2 config in scripts, some
+# settings are defined via environment variables and then used in apache2ctl,
+# /etc/init.d/apache2, /etc/logrotate.d/apache2, etc.
+export APACHE_RUN_USER=www-data
+export APACHE_RUN_GROUP=www-data
+# temporary state file location. This might be changed to /run in Wheezy+1
+export APACHE_PID_FILE=/var/run/apache2/apache2$SUFFIX.pid
+export APACHE_RUN_DIR=/var/run/apache2$SUFFIX
+export APACHE_LOCK_DIR=/var/lock/apache2$SUFFIX
+# Only /var/log/apache2 is handled by /etc/logrotate.d/apache2.
+export APACHE_LOG_DIR=/var/log/apache2$SUFFIX
+
+## The locale used by some modules like mod_dav
+export LANG=C
+
+export LANG
+
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/authz_svn.load b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/authz_svn.load
new file mode 100644
index 000000000..c6df2733b
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/authz_svn.load
@@ -0,0 +1,5 @@
+# Depends: dav_svn
+<IfModule !mod_dav_svn.c>
+ Include mods-enabled/dav_svn.load
+</IfModule>
+LoadModule authz_svn_module /usr/lib/apache2/modules/mod_authz_svn.so
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav.load b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav.load
new file mode 100644
index 000000000..a5867fff3
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav.load
@@ -0,0 +1,3 @@
+<IfModule !mod_dav.c>
+ LoadModule dav_module /usr/lib/apache2/modules/mod_dav.so
+</IfModule>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav_svn.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav_svn.conf
new file mode 100644
index 000000000..801cbd6bd
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav_svn.conf
@@ -0,0 +1,56 @@
+# dav_svn.conf - Example Subversion/Apache configuration
+#
+# For details and further options see the Apache user manual and
+# the Subversion book.
+#
+# NOTE: for a setup with multiple vhosts, you will want to do this
+# configuration in /etc/apache2/sites-available/*, not here.
+
+# <Location URL> ... </Location>
+# URL controls how the repository appears to the outside world.
+# In this example clients access the repository as http://hostname/svn/
+# Note, a literal /svn should NOT exist in your document root.
+#<Location /svn>
+
+ # Uncomment this to enable the repository
+ #DAV svn
+
+ # Set this to the path to your repository
+ #SVNPath /var/lib/svn
+ # Alternatively, use SVNParentPath if you have multiple repositories under
+ # under a single directory (/var/lib/svn/repo1, /var/lib/svn/repo2, ...).
+ # You need either SVNPath and SVNParentPath, but not both.
+ #SVNParentPath /var/lib/svn
+
+ # Access control is done at 3 levels: (1) Apache authentication, via
+ # any of several methods. A "Basic Auth" section is commented out
+ # below. (2) Apache <Limit> and <LimitExcept>, also commented out
+ # below. (3) mod_authz_svn is a svn-specific authorization module
+ # which offers fine-grained read/write access control for paths
+ # within a repository. (The first two layers are coarse-grained; you
+ # can only enable/disable access to an entire repository.) Note that
+ # mod_authz_svn is noticeably slower than the other two layers, so if
+ # you don't need the fine-grained control, don't configure it.
+
+ # Basic Authentication is repository-wide. It is not secure unless
+ # you are using https. See the 'htpasswd' command to create and
+ # manage the password file - and the documentation for the
+ # 'auth_basic' and 'authn_file' modules, which you will need for this
+ # (enable them with 'a2enmod').
+ #AuthType Basic
+ #AuthName "Subversion Repository"
+ #AuthUserFile /etc/apache2/dav_svn.passwd
+
+ # To enable authorization via mod_authz_svn (enable that module separately):
+ #<IfModule mod_authz_svn.c>
+ #AuthzSVNAccessFile /etc/apache2/dav_svn.authz
+ #</IfModule>
+
+ # The following three lines allow anonymous read, but make
+ # committers authenticate themselves. It requires the 'authz_user'
+ # module (enable it with 'a2enmod').
+ #<LimitExcept GET PROPFIND OPTIONS REPORT>
+ #Require valid-user
+ #</LimitExcept>
+
+#</Location>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav_svn.load b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav_svn.load
new file mode 100644
index 000000000..e41e1581a
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/dav_svn.load
@@ -0,0 +1,7 @@
+# Depends: dav
+<IfModule !mod_dav_svn.c>
+ <IfModule !mod_dav.c>
+ Include mods-enabled/dav.load
+ </IfModule>
+ LoadModule dav_svn_module /usr/lib/apache2/modules/mod_dav_svn.so
+</IfModule>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/rewrite.load b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/rewrite.load
new file mode 100644
index 000000000..b32f16264
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/rewrite.load
@@ -0,0 +1 @@
+LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.conf
new file mode 100644
index 000000000..65baec874
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.conf
@@ -0,0 +1,89 @@
+<IfModule mod_ssl.c>
+
+ # Pseudo Random Number Generator (PRNG):
+ # Configure one or more sources to seed the PRNG of the SSL library.
+ # The seed data should be of good random quality.
+ # WARNING! On some platforms /dev/random blocks if not enough entropy
+ # is available. This means you then cannot use the /dev/random device
+ # because it would lead to very long connection times (as long as
+ # it requires to make more entropy available). But usually those
+ # platforms additionally provide a /dev/urandom device which doesn't
+ # block. So, if available, use this one instead. Read the mod_ssl User
+ # Manual for more details.
+ #
+ SSLRandomSeed startup builtin
+ SSLRandomSeed startup file:/dev/urandom 512
+ SSLRandomSeed connect builtin
+ SSLRandomSeed connect file:/dev/urandom 512
+
+ ##
+ ## SSL Global Context
+ ##
+ ## All SSL configuration in this context applies both to
+ ## the main server and all SSL-enabled virtual hosts.
+ ##
+
+ #
+ # Some MIME-types for downloading Certificates and CRLs
+ #
+ AddType application/x-x509-ca-cert .crt
+ AddType application/x-pkcs7-crl .crl
+
+ # Pass Phrase Dialog:
+ # Configure the pass phrase gathering process.
+ # The filtering dialog program (`builtin' is an internal
+ # terminal dialog) has to provide the pass phrase on stdout.
+ SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase
+
+ # Inter-Process Session Cache:
+ # Configure the SSL Session Cache: First the mechanism
+ # to use and second the expiring timeout (in seconds).
+ # (The mechanism dbm has known memory leaks and should not be used).
+ #SSLSessionCache dbm:${APACHE_RUN_DIR}/ssl_scache
+ SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
+ SSLSessionCacheTimeout 300
+
+ # Semaphore:
+ # Configure the path to the mutual exclusion semaphore the
+ # SSL engine uses internally for inter-process synchronization.
+ # (Disabled by default, the global Mutex directive consolidates by default
+ # this)
+ #Mutex file:${APACHE_LOCK_DIR}/ssl_mutex ssl-cache
+
+
+ # SSL Cipher Suite:
+ # List the ciphers that the client is permitted to negotiate. See the
+ # ciphers(1) man page from the openssl package for list of all available
+ # options.
+ # Enable only secure ciphers:
+ SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
+
+ # Speed-optimized SSL Cipher configuration:
+ # If speed is your main concern (on busy HTTPS servers e.g.),
+ # you might want to force clients to specific, performance
+ # optimized ciphers. In this case, prepend those ciphers
+ # to the SSLCipherSuite list, and enable SSLHonorCipherOrder.
+ # Caveat: by giving precedence to RC4-SHA and AES128-SHA
+ # (as in the example below), most connections will no longer
+ # have perfect forward secrecy - if the server's key is
+ # compromised, captures of past or future traffic must be
+ # considered compromised, too.
+ #SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5
+ #SSLHonorCipherOrder on
+
+ # The protocols to enable.
+ # Available values: all, SSLv3, TLSv1, TLSv1.1, TLSv1.2
+ # SSL v2 is no longer supported
+ SSLProtocol all
+
+ # Allow insecure renegotiation with clients which do not yet support the
+ # secure renegotiation protocol. Default: Off
+ #SSLInsecureRenegotiation on
+
+ # Whether to forbid non-SNI clients to access name based virtual hosts.
+ # Default: Off
+ #SSLStrictSNIVHostCheck On
+
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.load b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.load
new file mode 100644
index 000000000..3d2336ae0
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-available/ssl.load
@@ -0,0 +1,2 @@
+# Depends: setenvif mime socache_shmcb
+LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/authz_svn.load b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/authz_svn.load
new file mode 120000
index 000000000..7ac0725dd
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/authz_svn.load
@@ -0,0 +1 @@
+../mods-available/authz_svn.load \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav.load b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav.load
new file mode 120000
index 000000000..9dcfef6da
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav.load
@@ -0,0 +1 @@
+../mods-available/dav.load \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav_svn.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav_svn.conf
new file mode 120000
index 000000000..964c7bb0b
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav_svn.conf
@@ -0,0 +1 @@
+../mods-available/dav_svn.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav_svn.load b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav_svn.load
new file mode 120000
index 000000000..4094e4173
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/mods-enabled/dav_svn.load
@@ -0,0 +1 @@
+../mods-available/dav_svn.load \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/ports.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/ports.conf
new file mode 100644
index 000000000..5daec58c1
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/ports.conf
@@ -0,0 +1,15 @@
+# If you just change the port or add more ports here, you will likely also
+# have to change the VirtualHost statement in
+# /etc/apache2/sites-enabled/000-default.conf
+
+Listen 80
+
+<IfModule ssl_module>
+ Listen 443
+</IfModule>
+
+<IfModule mod_gnutls.c>
+ Listen 443
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/another_wildcard.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/another_wildcard.conf
new file mode 100644
index 000000000..1a5b7de47
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/another_wildcard.conf
@@ -0,0 +1,11 @@
+<VirtualHost *:80>
+ ServerName wildcard.tld
+ ServerAlias ?.wildcard.tld
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/old-and-default.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/old-and-default.conf
new file mode 100644
index 000000000..2bd4e1fe9
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/old-and-default.conf
@@ -0,0 +1,12 @@
+<VirtualHost *:80 [::]:80>
+
+ ServerName ip-172-30-0-17
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/wildcard.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/wildcard.conf
new file mode 100644
index 000000000..b8046e6c9
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-available/wildcard.conf
@@ -0,0 +1,11 @@
+<VirtualHost *:80>
+ ServerName example.net
+ ServerAlias ??.example.net *.other.example.net *another.example.net
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/another_wildcard.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/another_wildcard.conf
new file mode 120000
index 000000000..95f52f002
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/another_wildcard.conf
@@ -0,0 +1 @@
+../sites-available/another_wildcard.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/old-and-default.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/old-and-default.conf
new file mode 120000
index 000000000..f7fdf1bbe
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/old-and-default.conf
@@ -0,0 +1 @@
+../sites-available/old-and-default.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/wildcard.conf b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/wildcard.conf
new file mode 120000
index 000000000..a87af2c93
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/apache2/sites-enabled/wildcard.conf
@@ -0,0 +1 @@
+../sites-available/wildcard.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/sites b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/sites
new file mode 100644
index 000000000..ab518ee5b
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/augeas_vhosts/sites
@@ -0,0 +1,3 @@
+sites-available/certbot.conf, certbot.demo
+sites-available/encryption-example.conf, encryption-example.demo
+sites-available/ocsp-ssl.conf, ocspvhost.com
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/apache2.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/apache2.conf
new file mode 100644
index 000000000..4ed016e07
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/apache2.conf
@@ -0,0 +1,198 @@
+# This is the main Apache server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See http://httpd.apache.org/docs/2.4/ for detailed information about
+# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
+# hints.
+#
+#
+# Summary of how the Apache 2 configuration works in Debian:
+# The Apache 2 web server configuration in Debian is quite different to
+# upstream's suggested way to configure the web server. This is because Debian's
+# default Apache2 installation attempts to make adding and removing modules,
+# virtual hosts, and extra configuration directives as flexible as possible, in
+# order to make automating the changes and administering the server as easy as
+# possible.
+
+# It is split into several files forming the configuration hierarchy outlined
+# below, all located in the /etc/apache2/ directory:
+#
+# /etc/apache2/
+# |-- apache2.conf
+# | `-- ports.conf
+# |-- mods-enabled
+# | |-- *.load
+# | `-- *.conf
+# |-- conf-enabled
+# | `-- *.conf
+# `-- sites-enabled
+# `-- *.conf
+#
+#
+# * apache2.conf is the main configuration file (this file). It puts the pieces
+# together by including all remaining configuration files when starting up the
+# web server.
+#
+# * ports.conf is always included from the main configuration file. It is
+# supposed to determine listening ports for incoming connections which can be
+# customized anytime.
+#
+# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
+# directories contain particular configuration snippets which manage modules,
+# global configuration fragments, or virtual host configurations,
+# respectively.
+#
+# They are activated by symlinking available configuration files from their
+# respective *-available/ counterparts. These should be managed by using our
+# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
+# their respective man pages for detailed information.
+#
+# * The binary is called apache2. Due to the use of environment variables, in
+# the default configuration, apache2 needs to be started/stopped with
+# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
+# work with the default configuration.
+
+
+# Global configuration
+
+#
+# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
+#
+Mutex file:${APACHE_LOCK_DIR} default
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+# This needs to be set in /etc/apache2/envvars
+#
+PidFile ${APACHE_PID_FILE}
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 300
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive On
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 5
+
+
+# These need to be set in /etc/apache2/envvars
+User ${APACHE_RUN_USER}
+Group ${APACHE_RUN_GROUP}
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog ${APACHE_LOG_DIR}/error.log
+
+#
+# LogLevel: Control the severity of messages logged to the error_log.
+# Available values: trace8, ..., trace1, debug, info, notice, warn,
+# error, crit, alert, emerg.
+# It is also possible to configure the log level for particular modules, e.g.
+# "LogLevel info ssl:warn"
+#
+LogLevel warn
+
+# Include module configuration:
+IncludeOptional mods-enabled/*.load
+IncludeOptional mods-enabled/*.conf
+
+# Include list of ports to listen on
+Include ports.conf
+
+
+# Sets the default security model of the Apache2 HTTPD server. It does
+# not allow access to the root filesystem outside of /usr/share and /var/www.
+# The former is used by web applications packaged in Debian,
+# the latter may be used for local directories served by the web server. If
+# your system is serving content from a sub-directory in /srv you must allow
+# access here, or in any related virtual host.
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+ Require all denied
+</Directory>
+
+<Directory /usr/share>
+ AllowOverride None
+ Require all granted
+</Directory>
+
+<Directory /var/>
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+</Directory>
+
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives. See also the AllowOverride
+# directive.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<FilesMatch "^\.ht">
+ Require all denied
+</FilesMatch>
+
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive.
+#
+# These deviate from the Common Log Format definitions in that they use %O
+# (the actual bytes sent including headers) instead of %b (the size of the
+# requested file), because the latter makes it impossible to detect partial
+# requests.
+#
+# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.
+# Use mod_remoteip instead.
+#
+LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
+LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %O" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+# Include of directories ignores editors' and dpkg's backup files,
+# see README.Debian for details.
+
+# Include generic snippets of statements
+IncludeOptional conf-enabled/*.conf
+
+# Include the virtual host configurations:
+IncludeOptional sites-enabled/*.conf
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/other-vhosts-access-log.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/other-vhosts-access-log.conf
new file mode 100644
index 000000000..5e9f5e9e7
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/other-vhosts-access-log.conf
@@ -0,0 +1,4 @@
+# Define an access log for VirtualHosts that don't define their own logfile
+CustomLog ${APACHE_LOG_DIR}/other_vhosts_access.log vhost_combined
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/security.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/security.conf
new file mode 100644
index 000000000..1dfe33c60
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/security.conf
@@ -0,0 +1,31 @@
+# ServerTokens
+# This directive configures what you return as the Server HTTP response
+# Header. The default is 'Full' which sends information about the OS-Type
+# and compiled in modules.
+# Set to one of: Full | OS | Minimal | Minor | Major | Prod
+# where Full conveys the most information, and Prod the least.
+#ServerTokens Minimal
+ServerTokens OS
+#ServerTokens Full
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#ServerSignature Off
+ServerSignature On
+
+#
+# Allow TRACE method
+#
+# Set to "extended" to also reflect the request body (only for testing and
+# diagnostic purposes).
+#
+# Set to one of: On | Off | extended
+TraceEnable Off
+#TraceEnable On
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/serve-cgi-bin.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/serve-cgi-bin.conf
new file mode 100644
index 000000000..b02782dab
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-available/serve-cgi-bin.conf
@@ -0,0 +1,20 @@
+<IfModule mod_alias.c>
+ <IfModule mod_cgi.c>
+ Define ENABLE_USR_LIB_CGI_BIN
+ </IfModule>
+
+ <IfModule mod_cgid.c>
+ Define ENABLE_USR_LIB_CGI_BIN
+ </IfModule>
+
+ <IfDefine ENABLE_USR_LIB_CGI_BIN>
+ ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+ <Directory "/usr/lib/cgi-bin">
+ AllowOverride None
+ Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
+ Require all granted
+ </Directory>
+ </IfDefine>
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/other-vhosts-access-log.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/other-vhosts-access-log.conf
new file mode 120000
index 000000000..8af91e530
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/other-vhosts-access-log.conf
@@ -0,0 +1 @@
+../conf-available/other-vhosts-access-log.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/security.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/security.conf
new file mode 120000
index 000000000..036c97fa7
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/security.conf
@@ -0,0 +1 @@
+../conf-available/security.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/serve-cgi-bin.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/serve-cgi-bin.conf
new file mode 120000
index 000000000..d917f688e
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/conf-enabled/serve-cgi-bin.conf
@@ -0,0 +1 @@
+../conf-available/serve-cgi-bin.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/envvars b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/envvars
new file mode 100644
index 000000000..8051c4544
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/envvars
@@ -0,0 +1,28 @@
+# envvars - default environment variables for apache2ctl
+
+# this won't be correct after changing uid
+unset HOME
+
+# for supporting multiple apache2 instances
+if [ "${APACHE_CONFDIR##/etc/apache2-}" != "${APACHE_CONFDIR}" ] ; then
+ SUFFIX="-${APACHE_CONFDIR##/etc/apache2-}"
+else
+ SUFFIX=
+fi
+
+# Since there is no sane way to get the parsed apache2 config in scripts, some
+# settings are defined via environment variables and then used in apache2ctl,
+# /etc/init.d/apache2, /etc/logrotate.d/apache2, etc.
+export APACHE_RUN_USER=www-data
+export APACHE_RUN_GROUP=www-data
+# temporary state file location. This might be changed to /run in Wheezy+1
+export APACHE_PID_FILE=/var/run/apache2/apache2$SUFFIX.pid
+export APACHE_RUN_DIR=/var/run/apache2$SUFFIX
+export APACHE_LOCK_DIR=/var/lock/apache2$SUFFIX
+# Only /var/log/apache2 is handled by /etc/logrotate.d/apache2.
+export APACHE_LOG_DIR=/var/log/apache2$SUFFIX
+
+## The locale used by some modules like mod_dav
+export LANG=C
+
+export LANG
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.conf
new file mode 100644
index 000000000..65baec874
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.conf
@@ -0,0 +1,89 @@
+<IfModule mod_ssl.c>
+
+ # Pseudo Random Number Generator (PRNG):
+ # Configure one or more sources to seed the PRNG of the SSL library.
+ # The seed data should be of good random quality.
+ # WARNING! On some platforms /dev/random blocks if not enough entropy
+ # is available. This means you then cannot use the /dev/random device
+ # because it would lead to very long connection times (as long as
+ # it requires to make more entropy available). But usually those
+ # platforms additionally provide a /dev/urandom device which doesn't
+ # block. So, if available, use this one instead. Read the mod_ssl User
+ # Manual for more details.
+ #
+ SSLRandomSeed startup builtin
+ SSLRandomSeed startup file:/dev/urandom 512
+ SSLRandomSeed connect builtin
+ SSLRandomSeed connect file:/dev/urandom 512
+
+ ##
+ ## SSL Global Context
+ ##
+ ## All SSL configuration in this context applies both to
+ ## the main server and all SSL-enabled virtual hosts.
+ ##
+
+ #
+ # Some MIME-types for downloading Certificates and CRLs
+ #
+ AddType application/x-x509-ca-cert .crt
+ AddType application/x-pkcs7-crl .crl
+
+ # Pass Phrase Dialog:
+ # Configure the pass phrase gathering process.
+ # The filtering dialog program (`builtin' is an internal
+ # terminal dialog) has to provide the pass phrase on stdout.
+ SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase
+
+ # Inter-Process Session Cache:
+ # Configure the SSL Session Cache: First the mechanism
+ # to use and second the expiring timeout (in seconds).
+ # (The mechanism dbm has known memory leaks and should not be used).
+ #SSLSessionCache dbm:${APACHE_RUN_DIR}/ssl_scache
+ SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
+ SSLSessionCacheTimeout 300
+
+ # Semaphore:
+ # Configure the path to the mutual exclusion semaphore the
+ # SSL engine uses internally for inter-process synchronization.
+ # (Disabled by default, the global Mutex directive consolidates by default
+ # this)
+ #Mutex file:${APACHE_LOCK_DIR}/ssl_mutex ssl-cache
+
+
+ # SSL Cipher Suite:
+ # List the ciphers that the client is permitted to negotiate. See the
+ # ciphers(1) man page from the openssl package for list of all available
+ # options.
+ # Enable only secure ciphers:
+ SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
+
+ # Speed-optimized SSL Cipher configuration:
+ # If speed is your main concern (on busy HTTPS servers e.g.),
+ # you might want to force clients to specific, performance
+ # optimized ciphers. In this case, prepend those ciphers
+ # to the SSLCipherSuite list, and enable SSLHonorCipherOrder.
+ # Caveat: by giving precedence to RC4-SHA and AES128-SHA
+ # (as in the example below), most connections will no longer
+ # have perfect forward secrecy - if the server's key is
+ # compromised, captures of past or future traffic must be
+ # considered compromised, too.
+ #SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5
+ #SSLHonorCipherOrder on
+
+ # The protocols to enable.
+ # Available values: all, SSLv3, TLSv1, TLSv1.1, TLSv1.2
+ # SSL v2 is no longer supported
+ SSLProtocol all
+
+ # Allow insecure renegotiation with clients which do not yet support the
+ # secure renegotiation protocol. Default: Off
+ #SSLInsecureRenegotiation on
+
+ # Whether to forbid non-SNI clients to access name based virtual hosts.
+ # Default: Off
+ #SSLStrictSNIVHostCheck On
+
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.load b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.load
new file mode 100644
index 000000000..3d2336ae0
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/mods-available/ssl.load
@@ -0,0 +1,2 @@
+# Depends: setenvif mime socache_shmcb
+LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/ports.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/ports.conf
new file mode 100644
index 000000000..176b9d103
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/ports.conf
@@ -0,0 +1,20 @@
+# If you just change the port or add more ports here, you will likely also
+# have to change the VirtualHost statement in
+# /etc/apache2/sites-enabled/000-default.conf
+
+Listen 80
+
+NameVirtualHost *:80
+
+<IfModule ssl_module>
+ Listen 443
+</IfModule>
+
+<IfModule mod_gnutls.c>
+ Listen 443
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
+<IfModule mod_ssl.c>
+NameVirtualHost *:443
+</IfModule>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-available/000-default.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-available/000-default.conf
new file mode 100644
index 000000000..d81fe132d
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-available/000-default.conf
@@ -0,0 +1,11 @@
+<VirtualHost *:80>
+ # How well does Certbot work without a ServerName/Alias?
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-available/default-ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-available/default-ssl.conf
new file mode 100644
index 000000000..e659d4b07
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-available/default-ssl.conf
@@ -0,0 +1,38 @@
+<IfModule mod_ssl.c>
+ <VirtualHost _default_:443>
+ ServerAdmin webmaster@localhost
+
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ # SSL Engine Switch:
+ # Enable/Disable SSL for this virtual host.
+ SSLEngine on
+
+ # A self-signed (snakeoil) certificate can be created by installing
+ # the ssl-cert package. See
+ # /usr/share/doc/apache2/README.Debian.gz for more info.
+ # If both key and certificate are stored in the same file, only the
+ # SSLCertificateFile directive is needed.
+ SSLCertificateFile /etc/apache2/certs/certbot-cert_5.pem
+ SSLCertificateKeyFile /etc/apache2/ssl/key-certbot_15.pem
+
+ <FilesMatch "\.(cgi|shtml|phtml|php)$">
+ SSLOptions +StdEnvVars
+ </FilesMatch>
+ <Directory /usr/lib/cgi-bin>
+ SSLOptions +StdEnvVars
+ </Directory>
+
+ BrowserMatch "MSIE [2-6]" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+ # MSIE 7 and newer should be able to use keepalive
+ BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
+
+ </VirtualHost>
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-enabled/000-default.conf b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-enabled/000-default.conf
new file mode 120000
index 000000000..3c4632b73
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/apache2/sites-enabled/000-default.conf
@@ -0,0 +1 @@
+../sites-available/000-default.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/sites b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/sites
new file mode 100644
index 000000000..03d53dd61
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/default_vhost/sites
@@ -0,0 +1 @@
+sites-available/000-default.conf, default.com
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/apache2.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/apache2.conf
new file mode 100644
index 000000000..2a5bb7be2
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/apache2.conf
@@ -0,0 +1,196 @@
+# This is the main Apache server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See http://httpd.apache.org/docs/2.4/ for detailed information about
+# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
+# hints.
+#
+#
+# Summary of how the Apache 2 configuration works in Debian:
+# The Apache 2 web server configuration in Debian is quite different to
+# upstream's suggested way to configure the web server. This is because Debian's
+# default Apache2 installation attempts to make adding and removing modules,
+# virtual hosts, and extra configuration directives as flexible as possible, in
+# order to make automating the changes and administering the server as easy as
+# possible.
+
+# It is split into several files forming the configuration hierarchy outlined
+# below, all located in the /etc/apache2/ directory:
+#
+# /etc/apache2/
+# |-- apache2.conf
+# | `-- ports.conf
+# |-- mods-enabled
+# | |-- *.load
+# | `-- *.conf
+# |-- conf-enabled
+# | `-- *.conf
+# `-- sites-enabled
+# `-- *.conf
+#
+#
+# * apache2.conf is the main configuration file (this file). It puts the pieces
+# together by including all remaining configuration files when starting up the
+# web server.
+#
+# * ports.conf is always included from the main configuration file. It is
+# supposed to determine listening ports for incoming connections which can be
+# customized anytime.
+#
+# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
+# directories contain particular configuration snippets which manage modules,
+# global configuration fragments, or virtual host configurations,
+# respectively.
+#
+# They are activated by symlinking available configuration files from their
+# respective *-available/ counterparts. These should be managed by using our
+# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
+# their respective man pages for detailed information.
+#
+# * The binary is called apache2. Due to the use of environment variables, in
+# the default configuration, apache2 needs to be started/stopped with
+# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
+# work with the default configuration.
+
+
+# Global configuration
+
+#
+# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
+#
+Mutex file:${APACHE_LOCK_DIR} default
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+# This needs to be set in /etc/apache2/envvars
+#
+PidFile ${APACHE_PID_FILE}
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 300
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive On
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 5
+
+
+# These need to be set in /etc/apache2/envvars
+User ${APACHE_RUN_USER}
+Group ${APACHE_RUN_GROUP}
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog ${APACHE_LOG_DIR}/error.log
+
+#
+# LogLevel: Control the severity of messages logged to the error_log.
+# Available values: trace8, ..., trace1, debug, info, notice, warn,
+# error, crit, alert, emerg.
+# It is also possible to configure the log level for particular modules, e.g.
+# "LogLevel info ssl:warn"
+#
+LogLevel warn
+
+# Include module configuration:
+IncludeOptional mods-enabled/*.load
+IncludeOptional mods-enabled/*.conf
+
+# Include list of ports to listen on
+Include ports.conf
+
+
+# Sets the default security model of the Apache2 HTTPD server. It does
+# not allow access to the root filesystem outside of /usr/share and /var/www.
+# The former is used by web applications packaged in Debian,
+# the latter may be used for local directories served by the web server. If
+# your system is serving content from a sub-directory in /srv you must allow
+# access here, or in any related virtual host.
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+ Require all denied
+</Directory>
+
+<Directory /usr/share>
+ AllowOverride None
+ Require all granted
+</Directory>
+
+<Directory /var/>
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+</Directory>
+
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives. See also the AllowOverride
+# directive.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<FilesMatch "^\.ht">
+ Require all denied
+</FilesMatch>
+
+# The following directives define some format nicknames for use with
+# a CustomLog directive.
+#
+# These deviate from the Common Log Format definitions in that they use %O
+# (the actual bytes sent including headers) instead of %b (the size of the
+# requested file), because the latter makes it impossible to detect partial
+# requests.
+#
+# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.
+# Use mod_remoteip instead.
+#
+LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
+LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %O" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+# Include of directories ignores editors' and dpkg's backup files,
+# see README.Debian for details.
+
+# Include generic snippets of statements
+IncludeOptional conf-enabled/*.conf
+
+# Include the virtual host configurations:
+IncludeOptional sites-enabled/*.conf
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/envvars b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/envvars
new file mode 100644
index 000000000..a13d9a89e
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/envvars
@@ -0,0 +1,29 @@
+# envvars - default environment variables for apache2ctl
+
+# this won't be correct after changing uid
+unset HOME
+
+# for supporting multiple apache2 instances
+if [ "${APACHE_CONFDIR##/etc/apache2-}" != "${APACHE_CONFDIR}" ] ; then
+ SUFFIX="-${APACHE_CONFDIR##/etc/apache2-}"
+else
+ SUFFIX=
+fi
+
+# Since there is no sane way to get the parsed apache2 config in scripts, some
+# settings are defined via environment variables and then used in apache2ctl,
+# /etc/init.d/apache2, /etc/logrotate.d/apache2, etc.
+export APACHE_RUN_USER=www-data
+export APACHE_RUN_GROUP=www-data
+# temporary state file location. This might be changed to /run in Wheezy+1
+export APACHE_PID_FILE=/var/run/apache2/apache2$SUFFIX.pid
+export APACHE_RUN_DIR=/var/run/apache2$SUFFIX
+export APACHE_LOCK_DIR=/var/lock/apache2$SUFFIX
+# Only /var/log/apache2 is handled by /etc/logrotate.d/apache2.
+export APACHE_LOG_DIR=/var/log/apache2$SUFFIX
+
+## The locale used by some modules like mod_dav
+export LANG=C
+
+export LANG
+
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/ports.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/ports.conf
new file mode 100644
index 000000000..5daec58c1
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/ports.conf
@@ -0,0 +1,15 @@
+# If you just change the port or add more ports here, you will likely also
+# have to change the VirtualHost statement in
+# /etc/apache2/sites-enabled/000-default.conf
+
+Listen 80
+
+<IfModule ssl_module>
+ Listen 443
+</IfModule>
+
+<IfModule mod_gnutls.c>
+ Listen 443
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-available/default.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-available/default.conf
new file mode 100644
index 000000000..6ab206b2d
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-available/default.conf
@@ -0,0 +1,22 @@
+<VirtualHost *:80>
+
+ ServerName banana.vomit.net
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+</VirtualHost>
+
+<VirtualHost *:80>
+
+ ServerName banana.vomit.com
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+</VirtualHost>
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-available/multi-vhost.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-available/multi-vhost.conf
new file mode 100644
index 000000000..5f2b727bf
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-available/multi-vhost.conf
@@ -0,0 +1,38 @@
+<VirtualHost *:80>
+ ServerName 1.multi.vhost.tld
+ ServerAlias first.multi.vhost.tld
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
+
+<IfModule mod_ssl.c>
+ <VirtualHost *:80>
+ ServerName 2.multi.vhost.tld
+ ServerAlias second.multi.vhost.tld
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+RewriteEngine on
+RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
+RewriteRule ^(.*)$ b://u%{REQUEST_URI} [P,NE,L]
+RewriteCond %{HTTPS} !=on
+RewriteCond %{HTTPS} !^$
+RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [L,NE,R=permanent]
+ </VirtualHost>
+</IfModule>
+
+<VirtualHost *:80>
+ ServerName 3.multi.vhost.tld
+ ServerAlias third.multi.vhost.tld
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+RewriteEngine on
+RewriteRule "^/secrets/(.+)" "https://new.example.com/docs/$1" [R,L]
+RewriteRule "^/docs/(.+)" "http://new.example.com/docs/$1" [R,L]
+</VirtualHost>
+
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-enabled/default.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-enabled/default.conf
new file mode 120000
index 000000000..032e6bcf0
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-enabled/default.conf
@@ -0,0 +1 @@
+../sites-available/default.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-enabled/multi-vhost.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-enabled/multi-vhost.conf
new file mode 120000
index 000000000..7f0910ff4
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multi_vhosts/apache2/sites-enabled/multi-vhost.conf
@@ -0,0 +1 @@
+../sites-available/multi-vhost.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/apache2.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/apache2.conf
new file mode 100644
index 000000000..819a6bcb4
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/apache2.conf
@@ -0,0 +1,207 @@
+# This is the main Apache server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See http://httpd.apache.org/docs/2.4/ for detailed information about
+# the directives and /usr/share/doc/apache2/README.Debian about Debian specific
+# hints.
+#
+#
+# Summary of how the Apache 2 configuration works in Debian:
+# The Apache 2 web server configuration in Debian is quite different to
+# upstream's suggested way to configure the web server. This is because Debian's
+# default Apache2 installation attempts to make adding and removing modules,
+# virtual hosts, and extra configuration directives as flexible as possible, in
+# order to make automating the changes and administering the server as easy as
+# possible.
+
+# It is split into several files forming the configuration hierarchy outlined
+# below, all located in the /etc/apache2/ directory:
+#
+# /etc/apache2/
+# |-- apache2.conf
+# | `-- ports.conf
+# |-- mods-enabled
+# | |-- *.load
+# | `-- *.conf
+# |-- conf-enabled
+# | `-- *.conf
+# `-- sites-enabled
+# `-- *.conf
+#
+#
+# * apache2.conf is the main configuration file (this file). It puts the pieces
+# together by including all remaining configuration files when starting up the
+# web server.
+#
+# * ports.conf is always included from the main configuration file. It is
+# supposed to determine listening ports for incoming connections which can be
+# customized anytime.
+#
+# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/
+# directories contain particular configuration snippets which manage modules,
+# global configuration fragments, or virtual host configurations,
+# respectively.
+#
+# They are activated by symlinking available configuration files from their
+# respective *-available/ counterparts. These should be managed by using our
+# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See
+# their respective man pages for detailed information.
+#
+# * The binary is called apache2. Due to the use of environment variables, in
+# the default configuration, apache2 needs to be started/stopped with
+# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not
+# work with the default configuration.
+
+
+# Global configuration
+
+#
+# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
+#
+Mutex file:${APACHE_LOCK_DIR} default
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+# This needs to be set in /etc/apache2/envvars
+#
+PidFile ${APACHE_PID_FILE}
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 300
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive On
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 5
+
+
+# These need to be set in /etc/apache2/envvars
+User ${APACHE_RUN_USER}
+Group ${APACHE_RUN_GROUP}
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog ${APACHE_LOG_DIR}/error.log
+
+#
+# LogLevel: Control the severity of messages logged to the error_log.
+# Available values: trace8, ..., trace1, debug, info, notice, warn,
+# error, crit, alert, emerg.
+# It is also possible to configure the log level for particular modules, e.g.
+# "LogLevel info ssl:warn"
+#
+LogLevel warn
+
+# Include module configuration:
+IncludeOptional mods-enabled/*.load
+IncludeOptional mods-enabled/*.conf
+
+# Include list of ports to listen on
+Include ports.conf
+
+
+# Sets the default security model of the Apache2 HTTPD server. It does
+# not allow access to the root filesystem outside of /usr/share and /var/www.
+# The former is used by web applications packaged in Debian,
+# the latter may be used for local directories served by the web server. If
+# your system is serving content from a sub-directory in /srv you must allow
+# access here, or in any related virtual host.
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+ Require all denied
+</Directory>
+
+<Directory /usr/share>
+ AllowOverride None
+ Require all granted
+</Directory>
+
+<Directory /var/>
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+</Directory>
+
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives. See also the AllowOverride
+# directive.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<FilesMatch "^\.ht">
+ Require all denied
+</FilesMatch>
+
+# The following directives define some format nicknames for use with
+# a CustomLog directive.
+#
+# These deviate from the Common Log Format definitions in that they use %O
+# (the actual bytes sent including headers) instead of %b (the size of the
+# requested file), because the latter makes it impossible to detect partial
+# requests.
+#
+# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended.
+# Use mod_remoteip instead.
+#
+LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
+LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %O" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+# Include of directories ignores editors' and dpkg's backup files,
+# see README.Debian for details.
+
+# Include generic snippets of statements
+IncludeOptional conf-enabled/*.conf
+
+# Include the virtual host configurations:
+IncludeOptional sites-enabled/*.conf
+
+<VirtualHost *:80>
+
+ ServerName vhost.in.rootconf
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/bad_conf_file.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/bad_conf_file.conf
new file mode 100644
index 000000000..8e9178803
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/bad_conf_file.conf
@@ -0,0 +1,3 @@
+<VirtualHost 1.1.1.1>
+
+ServerName invalid.net
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/other-vhosts-access-log.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/other-vhosts-access-log.conf
new file mode 100644
index 000000000..5e9f5e9e7
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/other-vhosts-access-log.conf
@@ -0,0 +1,4 @@
+# Define an access log for VirtualHosts that don't define their own logfile
+CustomLog ${APACHE_LOG_DIR}/other_vhosts_access.log vhost_combined
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/security.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/security.conf
new file mode 100644
index 000000000..eccfcb1fd
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/security.conf
@@ -0,0 +1,35 @@
+# Changing the following options will not really affect the security of the
+# server, but might make attacks slightly more difficult in some cases.
+
+#
+# ServerTokens
+# This directive configures what you return as the Server HTTP response
+# Header. The default is 'Full' which sends information about the OS-Type
+# and compiled in modules.
+# Set to one of: Full | OS | Minimal | Minor | Major | Prod
+# where Full conveys the most information, and Prod the least.
+#ServerTokens Minimal
+ServerTokens OS
+#ServerTokens Full
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#ServerSignature Off
+ServerSignature On
+
+#
+# Allow TRACE method
+#
+# Set to "extended" to also reflect the request body (only for testing and
+# diagnostic purposes).
+#
+# Set to one of: On | Off | extended
+TraceEnable Off
+#TraceEnable On
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/serve-cgi-bin.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/serve-cgi-bin.conf
new file mode 100644
index 000000000..b02782dab
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-available/serve-cgi-bin.conf
@@ -0,0 +1,20 @@
+<IfModule mod_alias.c>
+ <IfModule mod_cgi.c>
+ Define ENABLE_USR_LIB_CGI_BIN
+ </IfModule>
+
+ <IfModule mod_cgid.c>
+ Define ENABLE_USR_LIB_CGI_BIN
+ </IfModule>
+
+ <IfDefine ENABLE_USR_LIB_CGI_BIN>
+ ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+ <Directory "/usr/lib/cgi-bin">
+ AllowOverride None
+ Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
+ Require all granted
+ </Directory>
+ </IfDefine>
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/other-vhosts-access-log.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/other-vhosts-access-log.conf
new file mode 120000
index 000000000..8af91e530
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/other-vhosts-access-log.conf
@@ -0,0 +1 @@
+../conf-available/other-vhosts-access-log.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/security.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/security.conf
new file mode 120000
index 000000000..036c97fa7
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/security.conf
@@ -0,0 +1 @@
+../conf-available/security.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/serve-cgi-bin.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/serve-cgi-bin.conf
new file mode 120000
index 000000000..d917f688e
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/conf-enabled/serve-cgi-bin.conf
@@ -0,0 +1 @@
+../conf-available/serve-cgi-bin.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/envvars b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/envvars
new file mode 100644
index 000000000..a13d9a89e
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/envvars
@@ -0,0 +1,29 @@
+# envvars - default environment variables for apache2ctl
+
+# this won't be correct after changing uid
+unset HOME
+
+# for supporting multiple apache2 instances
+if [ "${APACHE_CONFDIR##/etc/apache2-}" != "${APACHE_CONFDIR}" ] ; then
+ SUFFIX="-${APACHE_CONFDIR##/etc/apache2-}"
+else
+ SUFFIX=
+fi
+
+# Since there is no sane way to get the parsed apache2 config in scripts, some
+# settings are defined via environment variables and then used in apache2ctl,
+# /etc/init.d/apache2, /etc/logrotate.d/apache2, etc.
+export APACHE_RUN_USER=www-data
+export APACHE_RUN_GROUP=www-data
+# temporary state file location. This might be changed to /run in Wheezy+1
+export APACHE_PID_FILE=/var/run/apache2/apache2$SUFFIX.pid
+export APACHE_RUN_DIR=/var/run/apache2$SUFFIX
+export APACHE_LOCK_DIR=/var/lock/apache2$SUFFIX
+# Only /var/log/apache2 is handled by /etc/logrotate.d/apache2.
+export APACHE_LOG_DIR=/var/log/apache2$SUFFIX
+
+## The locale used by some modules like mod_dav
+export LANG=C
+
+export LANG
+
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/authz_svn.load b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/authz_svn.load
new file mode 100644
index 000000000..c6df2733b
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/authz_svn.load
@@ -0,0 +1,5 @@
+# Depends: dav_svn
+<IfModule !mod_dav_svn.c>
+ Include mods-enabled/dav_svn.load
+</IfModule>
+LoadModule authz_svn_module /usr/lib/apache2/modules/mod_authz_svn.so
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav.load b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav.load
new file mode 100644
index 000000000..a5867fff3
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav.load
@@ -0,0 +1,3 @@
+<IfModule !mod_dav.c>
+ LoadModule dav_module /usr/lib/apache2/modules/mod_dav.so
+</IfModule>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav_svn.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav_svn.conf
new file mode 100644
index 000000000..801cbd6bd
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav_svn.conf
@@ -0,0 +1,56 @@
+# dav_svn.conf - Example Subversion/Apache configuration
+#
+# For details and further options see the Apache user manual and
+# the Subversion book.
+#
+# NOTE: for a setup with multiple vhosts, you will want to do this
+# configuration in /etc/apache2/sites-available/*, not here.
+
+# <Location URL> ... </Location>
+# URL controls how the repository appears to the outside world.
+# In this example clients access the repository as http://hostname/svn/
+# Note, a literal /svn should NOT exist in your document root.
+#<Location /svn>
+
+ # Uncomment this to enable the repository
+ #DAV svn
+
+ # Set this to the path to your repository
+ #SVNPath /var/lib/svn
+ # Alternatively, use SVNParentPath if you have multiple repositories under
+ # under a single directory (/var/lib/svn/repo1, /var/lib/svn/repo2, ...).
+ # You need either SVNPath and SVNParentPath, but not both.
+ #SVNParentPath /var/lib/svn
+
+ # Access control is done at 3 levels: (1) Apache authentication, via
+ # any of several methods. A "Basic Auth" section is commented out
+ # below. (2) Apache <Limit> and <LimitExcept>, also commented out
+ # below. (3) mod_authz_svn is a svn-specific authorization module
+ # which offers fine-grained read/write access control for paths
+ # within a repository. (The first two layers are coarse-grained; you
+ # can only enable/disable access to an entire repository.) Note that
+ # mod_authz_svn is noticeably slower than the other two layers, so if
+ # you don't need the fine-grained control, don't configure it.
+
+ # Basic Authentication is repository-wide. It is not secure unless
+ # you are using https. See the 'htpasswd' command to create and
+ # manage the password file - and the documentation for the
+ # 'auth_basic' and 'authn_file' modules, which you will need for this
+ # (enable them with 'a2enmod').
+ #AuthType Basic
+ #AuthName "Subversion Repository"
+ #AuthUserFile /etc/apache2/dav_svn.passwd
+
+ # To enable authorization via mod_authz_svn (enable that module separately):
+ #<IfModule mod_authz_svn.c>
+ #AuthzSVNAccessFile /etc/apache2/dav_svn.authz
+ #</IfModule>
+
+ # The following three lines allow anonymous read, but make
+ # committers authenticate themselves. It requires the 'authz_user'
+ # module (enable it with 'a2enmod').
+ #<LimitExcept GET PROPFIND OPTIONS REPORT>
+ #Require valid-user
+ #</LimitExcept>
+
+#</Location>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav_svn.load b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav_svn.load
new file mode 100644
index 000000000..e41e1581a
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/dav_svn.load
@@ -0,0 +1,7 @@
+# Depends: dav
+<IfModule !mod_dav_svn.c>
+ <IfModule !mod_dav.c>
+ Include mods-enabled/dav.load
+ </IfModule>
+ LoadModule dav_svn_module /usr/lib/apache2/modules/mod_dav_svn.so
+</IfModule>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/rewrite.load b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/rewrite.load
new file mode 100644
index 000000000..b32f16264
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/rewrite.load
@@ -0,0 +1 @@
+LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.conf
new file mode 100644
index 000000000..65baec874
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.conf
@@ -0,0 +1,89 @@
+<IfModule mod_ssl.c>
+
+ # Pseudo Random Number Generator (PRNG):
+ # Configure one or more sources to seed the PRNG of the SSL library.
+ # The seed data should be of good random quality.
+ # WARNING! On some platforms /dev/random blocks if not enough entropy
+ # is available. This means you then cannot use the /dev/random device
+ # because it would lead to very long connection times (as long as
+ # it requires to make more entropy available). But usually those
+ # platforms additionally provide a /dev/urandom device which doesn't
+ # block. So, if available, use this one instead. Read the mod_ssl User
+ # Manual for more details.
+ #
+ SSLRandomSeed startup builtin
+ SSLRandomSeed startup file:/dev/urandom 512
+ SSLRandomSeed connect builtin
+ SSLRandomSeed connect file:/dev/urandom 512
+
+ ##
+ ## SSL Global Context
+ ##
+ ## All SSL configuration in this context applies both to
+ ## the main server and all SSL-enabled virtual hosts.
+ ##
+
+ #
+ # Some MIME-types for downloading Certificates and CRLs
+ #
+ AddType application/x-x509-ca-cert .crt
+ AddType application/x-pkcs7-crl .crl
+
+ # Pass Phrase Dialog:
+ # Configure the pass phrase gathering process.
+ # The filtering dialog program (`builtin' is an internal
+ # terminal dialog) has to provide the pass phrase on stdout.
+ SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase
+
+ # Inter-Process Session Cache:
+ # Configure the SSL Session Cache: First the mechanism
+ # to use and second the expiring timeout (in seconds).
+ # (The mechanism dbm has known memory leaks and should not be used).
+ #SSLSessionCache dbm:${APACHE_RUN_DIR}/ssl_scache
+ SSLSessionCache shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
+ SSLSessionCacheTimeout 300
+
+ # Semaphore:
+ # Configure the path to the mutual exclusion semaphore the
+ # SSL engine uses internally for inter-process synchronization.
+ # (Disabled by default, the global Mutex directive consolidates by default
+ # this)
+ #Mutex file:${APACHE_LOCK_DIR}/ssl_mutex ssl-cache
+
+
+ # SSL Cipher Suite:
+ # List the ciphers that the client is permitted to negotiate. See the
+ # ciphers(1) man page from the openssl package for list of all available
+ # options.
+ # Enable only secure ciphers:
+ SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
+
+ # Speed-optimized SSL Cipher configuration:
+ # If speed is your main concern (on busy HTTPS servers e.g.),
+ # you might want to force clients to specific, performance
+ # optimized ciphers. In this case, prepend those ciphers
+ # to the SSLCipherSuite list, and enable SSLHonorCipherOrder.
+ # Caveat: by giving precedence to RC4-SHA and AES128-SHA
+ # (as in the example below), most connections will no longer
+ # have perfect forward secrecy - if the server's key is
+ # compromised, captures of past or future traffic must be
+ # considered compromised, too.
+ #SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5
+ #SSLHonorCipherOrder on
+
+ # The protocols to enable.
+ # Available values: all, SSLv3, TLSv1, TLSv1.1, TLSv1.2
+ # SSL v2 is no longer supported
+ SSLProtocol all
+
+ # Allow insecure renegotiation with clients which do not yet support the
+ # secure renegotiation protocol. Default: Off
+ #SSLInsecureRenegotiation on
+
+ # Whether to forbid non-SNI clients to access name based virtual hosts.
+ # Default: Off
+ #SSLStrictSNIVHostCheck On
+
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.load b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.load
new file mode 100644
index 000000000..3d2336ae0
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-available/ssl.load
@@ -0,0 +1,2 @@
+# Depends: setenvif mime socache_shmcb
+LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/authz_svn.load b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/authz_svn.load
new file mode 120000
index 000000000..7ac0725dd
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/authz_svn.load
@@ -0,0 +1 @@
+../mods-available/authz_svn.load \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav.load b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav.load
new file mode 120000
index 000000000..9dcfef6da
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav.load
@@ -0,0 +1 @@
+../mods-available/dav.load \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav_svn.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav_svn.conf
new file mode 120000
index 000000000..964c7bb0b
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav_svn.conf
@@ -0,0 +1 @@
+../mods-available/dav_svn.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav_svn.load b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav_svn.load
new file mode 120000
index 000000000..4094e4173
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/mods-enabled/dav_svn.load
@@ -0,0 +1 @@
+../mods-available/dav_svn.load \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/ports.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/ports.conf
new file mode 100644
index 000000000..5daec58c1
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/ports.conf
@@ -0,0 +1,15 @@
+# If you just change the port or add more ports here, you will likely also
+# have to change the VirtualHost statement in
+# /etc/apache2/sites-enabled/000-default.conf
+
+Listen 80
+
+<IfModule ssl_module>
+ Listen 443
+</IfModule>
+
+<IfModule mod_gnutls.c>
+ Listen 443
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/000-default.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/000-default.conf
new file mode 100644
index 000000000..2bd4e1fe9
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/000-default.conf
@@ -0,0 +1,12 @@
+<VirtualHost *:80 [::]:80>
+
+ ServerName ip-172-30-0-17
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/certbot.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/certbot.conf
new file mode 100644
index 000000000..965ca2222
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/certbot.conf
@@ -0,0 +1,43 @@
+<VirtualHost *:80>
+ServerName certbot.demo
+ServerAlias www.certbot.demo
+ServerAdmin webmaster@localhost
+
+DocumentRoot /var/www-certbot-reworld/static/
+<Directory />
+Options FollowSymLinks
+AllowOverride None
+</Directory>
+<Directory /var/www/>
+Options Indexes FollowSymLinks MultiViews
+AllowOverride None
+Order allow,deny
+allow from all
+</Directory>
+
+ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+<Directory "/usr/lib/cgi-bin">
+AllowOverride None
+Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
+Order allow,deny
+Allow from all
+</Directory>
+
+ErrorLog ${APACHE_LOG_DIR}/error.log
+
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+LogLevel warn
+
+CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+Alias /doc/ "/usr/share/doc/"
+<Directory "/usr/share/doc/">
+Options Indexes MultiViews FollowSymLinks
+AllowOverride None
+Order deny,allow
+Deny from all
+Allow from 127.0.0.0/255.0.0.0 ::1/128
+</Directory>
+
+</VirtualHost>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/default-ssl-port-only.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/default-ssl-port-only.conf
new file mode 100644
index 000000000..849b42e9f
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/default-ssl-port-only.conf
@@ -0,0 +1,36 @@
+<IfModule mod_ssl.c>
+ <VirtualHost _default_:443>
+ ServerAdmin webmaster@localhost
+
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ # A self-signed (snakeoil) certificate can be created by installing
+ # the ssl-cert package. See
+ # /usr/share/doc/apache2/README.Debian.gz for more info.
+ # If both key and certificate are stored in the same file, only the
+ # SSLCertificateFile directive is needed.
+ SSLCertificateFile /etc/apache2/certs/certbot-cert_5.pem
+ SSLCertificateKeyFile /etc/apache2/ssl/key-certbot_15.pem
+
+
+ #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
+ <FilesMatch "\.(cgi|shtml|phtml|php)$">
+ SSLOptions +StdEnvVars
+ </FilesMatch>
+ <Directory /usr/lib/cgi-bin>
+ SSLOptions +StdEnvVars
+ </Directory>
+
+ BrowserMatch "MSIE [2-6]" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+ # MSIE 7 and newer should be able to use keepalive
+ BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
+
+ </VirtualHost>
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/default-ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/default-ssl.conf
new file mode 100644
index 000000000..a3025ae8a
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/default-ssl.conf
@@ -0,0 +1,40 @@
+<IfModule mod_ssl.c>
+ <VirtualHost _default_:443>
+ ServerAdmin webmaster@localhost
+
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ # SSL Engine Switch:
+ # Enable/Disable SSL for this virtual host.
+ SSLEngine on
+
+ # A self-signed (snakeoil) certificate can be created by installing
+ # the ssl-cert package. See
+ # /usr/share/doc/apache2/README.Debian.gz for more info.
+ # If both key and certificate are stored in the same file, only the
+ # SSLCertificateFile directive is needed.
+ SSLCertificateFile /etc/apache2/certs/certbot-cert_5.pem
+ SSLCertificateKeyFile /etc/apache2/ssl/key-certbot_15.pem
+
+
+ #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
+ <FilesMatch "\.(cgi|shtml|phtml|php)$">
+ SSLOptions +StdEnvVars
+ </FilesMatch>
+ <Directory /usr/lib/cgi-bin>
+ SSLOptions +StdEnvVars
+ </Directory>
+
+ BrowserMatch "MSIE [2-6]" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+ # MSIE 7 and newer should be able to use keepalive
+ BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
+
+ </VirtualHost>
+</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/duplicatehttp.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/duplicatehttp.conf
new file mode 100644
index 000000000..5684651fb
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/duplicatehttp.conf
@@ -0,0 +1,9 @@
+<VirtualHost 10.2.3.4:80>
+ ServerName duplicate.example.com
+
+ ServerAdmin webmaster@certbot.demo
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/duplicatehttps.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/duplicatehttps.conf
new file mode 100644
index 000000000..e3ac21fac
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/duplicatehttps.conf
@@ -0,0 +1,14 @@
+<IfModule mod_ssl.c>
+<VirtualHost 10.2.3.4:443>
+ ServerName duplicate.example.com
+
+ ServerAdmin webmaster@certbot.demo
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+SSLCertificateFile /etc/apache2/certs/certbot-cert_5.pem
+SSLCertificateKeyFile /etc/apache2/ssl/key-certbot_15.pem
+</VirtualHost>
+</IfModule>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/encryption-example.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/encryption-example.conf
new file mode 100644
index 000000000..862040fc1
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/encryption-example.conf
@@ -0,0 +1,42 @@
+<Virtualhost *:80>
+ ServerName encryption-example.demo
+ ServerAdmin webmaster@localhost
+
+ DocumentRoot /var/www-encryption-example/static/
+ <Directory />
+ Options FollowSymLinks
+ AllowOverride None
+ </Directory>
+ <Directory /var/www/>
+ Options Indexes FollowSymLinks MultiViews
+ AllowOverride None
+ Order allow,deny
+ allow from all
+ </Directory>
+
+ ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
+ <Directory "/usr/lib/cgi-bin">
+ AllowOverride None
+ Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+
+ # Possible values include: debug, info, notice, warn, error, crit,
+ # alert, emerg.
+ LogLevel warn
+
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ Alias /doc/ "/usr/share/doc/"
+ <Directory "/usr/share/doc/">
+ Options Indexes MultiViews FollowSymLinks
+ AllowOverride None
+ Order deny,allow
+ Deny from all
+ Allow from 127.0.0.0/255.0.0.0 ::1/128
+ </Directory>
+
+</Virtualhost>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/mod_macro-example.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/mod_macro-example.conf
new file mode 100644
index 000000000..6a6579007
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/mod_macro-example.conf
@@ -0,0 +1,15 @@
+<Macro VHost $name $domain>
+<VirtualHost *:80>
+ ServerName $domain
+ ServerAlias www.$domain
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
+</Macro>
+Use VHost macro1 test.com
+Use VHost macro2 hostname.org
+Use VHost macro3 apache.org
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/ocsp-ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/ocsp-ssl.conf
new file mode 100644
index 000000000..631cf16c8
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/ocsp-ssl.conf
@@ -0,0 +1,36 @@
+<IfModule mod_ssl.c>
+SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)
+<VirtualHost 10.2.3.4:443>
+ # The ServerName directive sets the request scheme, hostname and port that
+ # the server uses to identify itself. This is used when creating
+ # redirection URLs. In the context of virtual hosts, the ServerName
+ # specifies what hostname must appear in the request's Host: header to
+ # match this virtual host. For the default virtual host (this file) this
+ # value is not decisive as it is used as a last resort host regardless.
+ # However, you must set it for any further virtual host explicitly.
+ ServerName ocspvhost.com
+
+ ServerAdmin webmaster@dumpbits.com
+ DocumentRoot /var/www/html
+
+ # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
+ # error, crit, alert, emerg.
+ # It is also possible to configure the loglevel for particular
+ # modules, e.g.
+ #LogLevel info ssl:warn
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ # For most configuration files from conf-available/, which are
+ # enabled or disabled at a global level, it is possible to
+ # include a line for only one particular virtual host. For example the
+ # following line enables the CGI configuration for this host only
+ # after it has been globally disabled with "a2disconf".
+ #Include conf-available/serve-cgi-bin.conf
+SSLCertificateFile /etc/apache2/certs/certbot-cert_5.pem
+SSLCertificateKeyFile /etc/apache2/ssl/key-certbot_15.pem
+SSLUseStapling on
+</VirtualHost>
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
+</IfModule>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/wildcard.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/wildcard.conf
new file mode 100644
index 000000000..33e30a63b
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-available/wildcard.conf
@@ -0,0 +1,13 @@
+<VirtualHost *:80>
+
+ ServerName ip-172-30-0-17
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+ ServerAlias *.blue.purple.com
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+</VirtualHost>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/000-default.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/000-default.conf
new file mode 120000
index 000000000..3c4632b73
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/000-default.conf
@@ -0,0 +1 @@
+../sites-available/000-default.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/certbot.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/certbot.conf
new file mode 120000
index 000000000..4d08c763f
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/certbot.conf
@@ -0,0 +1 @@
+../sites-available/certbot.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/default-ssl-port-only.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/default-ssl-port-only.conf
new file mode 120000
index 000000000..103c1b68d
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/default-ssl-port-only.conf
@@ -0,0 +1 @@
+../sites-available/default-ssl-port-only.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/default-ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/default-ssl.conf
new file mode 120000
index 000000000..d02890bbd
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/default-ssl.conf
@@ -0,0 +1 @@
+../sites-available/default-ssl.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/duplicatehttp.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/duplicatehttp.conf
new file mode 120000
index 000000000..a69ee3c1d
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/duplicatehttp.conf
@@ -0,0 +1 @@
+../sites-available/duplicatehttp.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/duplicatehttps.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/duplicatehttps.conf
new file mode 120000
index 000000000..a52ee1ccb
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/duplicatehttps.conf
@@ -0,0 +1 @@
+../sites-available/duplicatehttps.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/encryption-example.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/encryption-example.conf
new file mode 120000
index 000000000..417818069
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/encryption-example.conf
@@ -0,0 +1 @@
+../sites-available/encryption-example.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/mod_macro-example.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/mod_macro-example.conf
new file mode 120000
index 000000000..44f254304
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/mod_macro-example.conf
@@ -0,0 +1 @@
+../sites-available/mod_macro-example.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/non-symlink.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/non-symlink.conf
new file mode 100644
index 000000000..31cb6093c
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/non-symlink.conf
@@ -0,0 +1,9 @@
+<VirtualHost *:80>
+ServerName nonsym.link
+ServerAdmin webmaster@localhost
+
+DocumentRoot /var/www-certbot-reworld/static/
+
+ErrorLog ${APACHE_LOG_DIR}/error.log
+CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/ocsp-ssl.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/ocsp-ssl.conf
new file mode 120000
index 000000000..b25ee0482
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/ocsp-ssl.conf
@@ -0,0 +1 @@
+../sites-available/ocsp-ssl.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/wildcard.conf b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/wildcard.conf
new file mode 120000
index 000000000..a87af2c93
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/apache2/sites-enabled/wildcard.conf
@@ -0,0 +1 @@
+../sites-available/wildcard.conf \ No newline at end of file
diff --git a/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/sites b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/sites
new file mode 100644
index 000000000..ab518ee5b
--- /dev/null
+++ b/certbot-apache/tests/testdata/debian_apache_2_4/multiple_vhosts/sites
@@ -0,0 +1,3 @@
+sites-available/certbot.conf, certbot.demo
+sites-available/encryption-example.conf, encryption-example.demo
+sites-available/ocsp-ssl.conf, ocspvhost.com
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/httpd.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/httpd.conf
new file mode 100644
index 000000000..e5693ffff
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/httpd.conf
@@ -0,0 +1,157 @@
+# This is a modification of the default Apache 2.4 configuration file
+# for Gentoo Linux.
+#
+# Support:
+# http://www.gentoo.org/main/en/lists.xml [mailing lists]
+# http://forums.gentoo.org/ [web forums]
+# irc://irc.freenode.net#gentoo-apache [irc chat]
+#
+# Bug Reports:
+# http://bugs.gentoo.org [gentoo related bugs]
+# http://httpd.apache.org/bug_report.html [apache httpd related bugs]
+#
+#
+# This is the main Apache HTTP server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/2.4> for detailed information.
+# In particular, see
+# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
+# for a discussion of each configuration directive.
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path. If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "var/log/apache2/foo_log"
+# with ServerRoot set to "/usr" will be interpreted by the
+# server as "/usr/var/log/apache2/foo.log".
+
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# Do not add a slash at the end of the directory path. If you point
+# ServerRoot at a non-local disk, be sure to point the LockFile directive
+# at a local disk. If you wish to share the same ServerRoot for multiple
+# httpd daemons, you will need to change at least LockFile and PidFile.
+# Comment: The LockFile directive has been replaced by the Mutex directive
+ServerRoot "/usr/lib64/apache2"
+
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+# GENTOO: Automatically defined based on APACHE2_MODULES USE_EXPAND variable.
+# Do not change manually, it will be overwritten on upgrade.
+#
+# The following modules are considered as the default configuration.
+# If you wish to disable one of them, you may have to alter other
+# configuration directives.
+#
+# Change these at your own risk!
+
+LoadModule actions_module modules/mod_actions.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule auth_basic_module modules/mod_auth_basic.so
+LoadModule authn_anon_module modules/mod_authn_anon.so
+LoadModule authn_core_module modules/mod_authn_core.so
+LoadModule authn_dbm_module modules/mod_authn_dbm.so
+LoadModule authn_file_module modules/mod_authn_file.so
+LoadModule authz_core_module modules/mod_authz_core.so
+LoadModule authz_dbm_module modules/mod_authz_dbm.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_owner_module modules/mod_authz_owner.so
+LoadModule authz_user_module modules/mod_authz_user.so
+LoadModule autoindex_module modules/mod_autoindex.so
+<IfDefine CACHE>
+LoadModule cache_module modules/mod_cache.so
+</IfDefine>
+LoadModule cgi_module modules/mod_cgi.so
+LoadModule cgid_module modules/mod_cgid.so
+<IfDefine DAV>
+LoadModule dav_module modules/mod_dav.so
+</IfDefine>
+<IfDefine DAV>
+LoadModule dav_fs_module modules/mod_dav_fs.so
+</IfDefine>
+<IfDefine DAV>
+LoadModule dav_lock_module modules/mod_dav_lock.so
+</IfDefine>
+LoadModule deflate_module modules/mod_deflate.so
+LoadModule dir_module modules/mod_dir.so
+LoadModule env_module modules/mod_env.so
+LoadModule expires_module modules/mod_expires.so
+LoadModule ext_filter_module modules/mod_ext_filter.so
+<IfDefine CACHE>
+LoadModule file_cache_module modules/mod_file_cache.so
+</IfDefine>
+LoadModule filter_module modules/mod_filter.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule include_module modules/mod_include.so
+<IfDefine INFO>
+LoadModule info_module modules/mod_info.so
+</IfDefine>
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule logio_module modules/mod_logio.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule mime_magic_module modules/mod_mime_magic.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule setenvif_module modules/mod_setenvif.so
+<IfDefine SSL>
+LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
+</IfDefine>
+LoadModule speling_module modules/mod_speling.so
+<IfDefine SSL>
+LoadModule ssl_module modules/mod_ssl.so
+</IfDefine>
+<IfDefine STATUS>
+LoadModule status_module modules/mod_status.so
+</IfDefine>
+LoadModule unique_id_module modules/mod_unique_id.so
+LoadModule unixd_module modules/mod_unixd.so
+<IfDefine USERDIR>
+LoadModule userdir_module modules/mod_userdir.so
+</IfDefine>
+LoadModule usertrack_module modules/mod_usertrack.so
+LoadModule vhost_alias_module modules/mod_vhost_alias.so
+
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# It is usually good practice to create a dedicated user and group for
+# running httpd, as with most system services.
+User apache
+Group apache
+
+# Supplemental configuration
+#
+# Most of the configuration files in the /etc/apache2/modules.d/ directory can
+# be turned on using APACHE2_OPTS in /etc/conf.d/apache2 to add extra features
+# or to modify the default configuration of the server.
+#
+# To know which flag to add to APACHE2_OPTS, look at the first line of the
+# the file, which will usually be an <IfDefine OPTION> where OPTION is the
+# flag to use.
+
+Include modules.d/*.conf
+
+# Virtual-host support
+#
+# Gentoo has made using virtual-hosts easy. In /etc/apache2/vhosts.d/ we
+# include a default vhost (enabled by adding -D DEFAULT_VHOST to
+# APACHE2_OPTS in /etc/conf.d/apache2).
+Include vhosts.d/*.conf
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/magic b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/magic
new file mode 100644
index 000000000..7c56119e9
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/magic
@@ -0,0 +1,385 @@
+# Magic data for mod_mime_magic Apache module (originally for file(1) command)
+# The module is described in /manual/mod/mod_mime_magic.html
+#
+# The format is 4-5 columns:
+# Column #1: byte number to begin checking from, ">" indicates continuation
+# Column #2: type of data to match
+# Column #3: contents of data to match
+# Column #4: MIME type of result
+# Column #5: MIME encoding of result (optional)
+
+#------------------------------------------------------------------------------
+# Localstuff: file(1) magic for locally observed files
+# Add any locally observed files here.
+
+#------------------------------------------------------------------------------
+# end local stuff
+#------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------
+# Java
+
+0 short 0xcafe
+>2 short 0xbabe application/java
+
+#------------------------------------------------------------------------------
+# audio: file(1) magic for sound formats
+#
+# from Jan Nicolai Langfeldt <janl@ifi.uio.no>,
+#
+
+# Sun/NeXT audio data
+0 string .snd
+>12 belong 1 audio/basic
+>12 belong 2 audio/basic
+>12 belong 3 audio/basic
+>12 belong 4 audio/basic
+>12 belong 5 audio/basic
+>12 belong 6 audio/basic
+>12 belong 7 audio/basic
+
+>12 belong 23 audio/x-adpcm
+
+# DEC systems (e.g. DECstation 5000) use a variant of the Sun/NeXT format
+# that uses little-endian encoding and has a different magic number
+# (0x0064732E in little-endian encoding).
+0 lelong 0x0064732E
+>12 lelong 1 audio/x-dec-basic
+>12 lelong 2 audio/x-dec-basic
+>12 lelong 3 audio/x-dec-basic
+>12 lelong 4 audio/x-dec-basic
+>12 lelong 5 audio/x-dec-basic
+>12 lelong 6 audio/x-dec-basic
+>12 lelong 7 audio/x-dec-basic
+# compressed (G.721 ADPCM)
+>12 lelong 23 audio/x-dec-adpcm
+
+# Bytes 0-3 of AIFF, AIFF-C, & 8SVX audio files are "FORM"
+# AIFF audio data
+8 string AIFF audio/x-aiff
+# AIFF-C audio data
+8 string AIFC audio/x-aiff
+# IFF/8SVX audio data
+8 string 8SVX audio/x-aiff
+
+# Creative Labs AUDIO stuff
+# Standard MIDI data
+0 string MThd audio/unknown
+#>9 byte >0 (format %d)
+#>11 byte >1 using %d channels
+# Creative Music (CMF) data
+0 string CTMF audio/unknown
+# SoundBlaster instrument data
+0 string SBI audio/unknown
+# Creative Labs voice data
+0 string Creative\ Voice\ File audio/unknown
+## is this next line right? it came this way...
+#>19 byte 0x1A
+#>23 byte >0 - version %d
+#>22 byte >0 \b.%d
+
+# [GRR 950115: is this also Creative Labs? Guessing that first line
+# should be string instead of unknown-endian long...]
+#0 long 0x4e54524b MultiTrack sound data
+#0 string NTRK MultiTrack sound data
+#>4 long x - version %ld
+
+# Microsoft WAVE format (*.wav)
+# [GRR 950115: probably all of the shorts and longs should be leshort/lelong]
+# Microsoft RIFF
+0 string RIFF audio/unknown
+# - WAVE format
+>8 string WAVE audio/x-wav
+# MPEG audio.
+0 beshort&0xfff0 0xfff0 audio/mpeg
+# C64 SID Music files, from Linus Walleij <triad@df.lth.se>
+0 string PSID audio/prs.sid
+
+#------------------------------------------------------------------------------
+# c-lang: file(1) magic for C programs or various scripts
+#
+
+# XPM icons (Greg Roelofs, newt@uchicago.edu)
+# ideally should go into "images", but entries below would tag XPM as C source
+0 string /*\ XPM image/x-xbm 7bit
+
+# this first will upset you if you're a PL/1 shop... (are there any left?)
+# in which case rm it; ascmagic will catch real C programs
+# C or REXX program text
+0 string /* text/plain
+# C++ program text
+0 string // text/plain
+
+#------------------------------------------------------------------------------
+# compress: file(1) magic for pure-compression formats (no archives)
+#
+# compress, gzip, pack, compact, huf, squeeze, crunch, freeze, yabba, whap, etc.
+#
+# Formats for various forms of compressed data
+# Formats for "compress" proper have been moved into "compress.c",
+# because it tries to uncompress it to figure out what's inside.
+
+# standard unix compress
+0 string \037\235 application/octet-stream x-compress
+
+# gzip (GNU zip, not to be confused with [Info-ZIP/PKWARE] zip archiver)
+0 string \037\213 application/octet-stream x-gzip
+
+# According to gzip.h, this is the correct byte order for packed data.
+0 string \037\036 application/octet-stream
+#
+# This magic number is byte-order-independent.
+#
+0 short 017437 application/octet-stream
+
+# XXX - why *two* entries for "compacted data", one of which is
+# byte-order independent, and one of which is byte-order dependent?
+#
+# compacted data
+0 short 0x1fff application/octet-stream
+0 string \377\037 application/octet-stream
+# huf output
+0 short 0145405 application/octet-stream
+
+# Squeeze and Crunch...
+# These numbers were gleaned from the Unix versions of the programs to
+# handle these formats. Note that I can only uncrunch, not crunch, and
+# I didn't have a crunched file handy, so the crunch number is untested.
+# Keith Waclena <keith@cerberus.uchicago.edu>
+#0 leshort 0x76FF squeezed data (CP/M, DOS)
+#0 leshort 0x76FE crunched data (CP/M, DOS)
+
+# Freeze
+#0 string \037\237 Frozen file 2.1
+#0 string \037\236 Frozen file 1.0 (or gzip 0.5)
+
+# lzh?
+#0 string \037\240 LZH compressed data
+
+#------------------------------------------------------------------------------
+# frame: file(1) magic for FrameMaker files
+#
+# This stuff came on a FrameMaker demo tape, most of which is
+# copyright, but this file is "published" as witness the following:
+#
+0 string \<MakerFile application/x-frame
+0 string \<MIFFile application/x-frame
+0 string \<MakerDictionary application/x-frame
+0 string \<MakerScreenFon application/x-frame
+0 string \<MML application/x-frame
+0 string \<Book application/x-frame
+0 string \<Maker application/x-frame
+
+#------------------------------------------------------------------------------
+# html: file(1) magic for HTML (HyperText Markup Language) docs
+#
+# from Daniel Quinlan <quinlan@yggdrasil.com>
+# and Anna Shergold <anna@inext.co.uk>
+#
+0 string \<!DOCTYPE\ HTML text/html
+0 string \<!doctype\ html text/html
+0 string \<HEAD text/html
+0 string \<head text/html
+0 string \<TITLE text/html
+0 string \<title text/html
+0 string \<html text/html
+0 string \<HTML text/html
+0 string \<!-- text/html
+0 string \<h1 text/html
+0 string \<H1 text/html
+
+# XML eXtensible Markup Language, from Linus Walleij <triad@df.lth.se>
+0 string \<?xml text/xml
+
+#------------------------------------------------------------------------------
+# images: file(1) magic for image formats (see also "c-lang" for XPM bitmaps)
+#
+# originally from jef@helios.ee.lbl.gov (Jef Poskanzer),
+# additions by janl@ifi.uio.no as well as others. Jan also suggested
+# merging several one- and two-line files into here.
+#
+# XXX - byte order for GIF and TIFF fields?
+# [GRR: TIFF allows both byte orders; GIF is probably little-endian]
+#
+
+# [GRR: what the hell is this doing in here?]
+#0 string xbtoa btoa'd file
+
+# PBMPLUS
+# PBM file
+0 string P1 image/x-portable-bitmap 7bit
+# PGM file
+0 string P2 image/x-portable-greymap 7bit
+# PPM file
+0 string P3 image/x-portable-pixmap 7bit
+# PBM "rawbits" file
+0 string P4 image/x-portable-bitmap
+# PGM "rawbits" file
+0 string P5 image/x-portable-greymap
+# PPM "rawbits" file
+0 string P6 image/x-portable-pixmap
+
+# NIFF (Navy Interchange File Format, a modification of TIFF)
+# [GRR: this *must* go before TIFF]
+0 string IIN1 image/x-niff
+
+# TIFF and friends
+# TIFF file, big-endian
+0 string MM image/tiff
+# TIFF file, little-endian
+0 string II image/tiff
+
+# possible GIF replacements; none yet released!
+# (Greg Roelofs, newt@uchicago.edu)
+#
+# GRR 950115: this was mine ("Zip GIF"):
+# ZIF image (GIF+deflate alpha)
+0 string GIF94z image/unknown
+#
+# GRR 950115: this is Jeremy Wohl's Free Graphics Format (better):
+# FGF image (GIF+deflate beta)
+0 string FGF95a image/unknown
+#
+# GRR 950115: this is Thomas Boutell's Portable Bitmap Format proposal
+# (best; not yet implemented):
+# PBF image (deflate compression)
+0 string PBF image/unknown
+
+# GIF
+0 string GIF image/gif
+
+# JPEG images
+0 beshort 0xffd8 image/jpeg
+
+# PC bitmaps (OS/2, Windoze BMP files) (Greg Roelofs, newt@uchicago.edu)
+0 string BM image/bmp
+#>14 byte 12 (OS/2 1.x format)
+#>14 byte 64 (OS/2 2.x format)
+#>14 byte 40 (Windows 3.x format)
+#0 string IC icon
+#0 string PI pointer
+#0 string CI color icon
+#0 string CP color pointer
+#0 string BA bitmap array
+
+0 string \x89PNG image/png
+0 string FWS application/x-shockwave-flash
+0 string CWS application/x-shockwave-flash
+
+#------------------------------------------------------------------------------
+# lisp: file(1) magic for lisp programs
+#
+# various lisp types, from Daniel Quinlan (quinlan@yggdrasil.com)
+0 string ;; text/plain 8bit
+# Emacs 18 - this is always correct, but not very magical.
+0 string \012( application/x-elc
+# Emacs 19
+0 string ;ELC\023\000\000\000 application/x-elc
+
+#------------------------------------------------------------------------------
+# mail.news: file(1) magic for mail and news
+#
+# There are tests to ascmagic.c to cope with mail and news.
+0 string Relay-Version: message/rfc822 7bit
+0 string #!\ rnews message/rfc822 7bit
+0 string N#!\ rnews message/rfc822 7bit
+0 string Forward\ to message/rfc822 7bit
+0 string Pipe\ to message/rfc822 7bit
+0 string Return-Path: message/rfc822 7bit
+0 string Path: message/news 8bit
+0 string Xref: message/news 8bit
+0 string From: message/rfc822 7bit
+0 string Article message/news 8bit
+#------------------------------------------------------------------------------
+# msword: file(1) magic for MS Word files
+#
+# Contributor claims:
+# Reversed-engineered MS Word magic numbers
+#
+
+0 string \376\067\0\043 application/msword
+0 string \333\245-\0\0\0 application/msword
+
+# disable this one because it applies also to other
+# Office/OLE documents for which msword is not correct. See PR#2608.
+#0 string \320\317\021\340\241\261 application/msword
+
+
+
+#------------------------------------------------------------------------------
+# printer: file(1) magic for printer-formatted files
+#
+
+# PostScript
+0 string %! application/postscript
+0 string \004%! application/postscript
+
+# Acrobat
+# (due to clamen@cs.cmu.edu)
+0 string %PDF- application/pdf
+
+#------------------------------------------------------------------------------
+# sc: file(1) magic for "sc" spreadsheet
+#
+38 string Spreadsheet application/x-sc
+
+#------------------------------------------------------------------------------
+# tex: file(1) magic for TeX files
+#
+# XXX - needs byte-endian stuff (big-endian and little-endian DVI?)
+#
+# From <conklin@talisman.kaleida.com>
+
+# Although we may know the offset of certain text fields in TeX DVI
+# and font files, we can't use them reliably because they are not
+# zero terminated. [but we do anyway, christos]
+0 string \367\002 application/x-dvi
+#0 string \367\203 TeX generic font data
+#0 string \367\131 TeX packed font data
+#0 string \367\312 TeX virtual font data
+#0 string This\ is\ TeX, TeX transcript text
+#0 string This\ is\ METAFONT, METAFONT transcript text
+
+# There is no way to detect TeX Font Metric (*.tfm) files without
+# breaking them apart and reading the data. The following patterns
+# match most *.tfm files generated by METAFONT or afm2tfm.
+#2 string \000\021 TeX font metric data
+#2 string \000\022 TeX font metric data
+#>34 string >\0 (%s)
+
+# Texinfo and GNU Info, from Daniel Quinlan (quinlan@yggdrasil.com)
+#0 string \\input\ texinfo Texinfo source text
+#0 string This\ is\ Info\ file GNU Info text
+
+# correct TeX magic for Linux (and maybe more)
+# from Peter Tobias (tobias@server.et-inf.fho-emden.de)
+#
+0 leshort 0x02f7 application/x-dvi
+
+# RTF - Rich Text Format
+0 string {\\rtf application/rtf
+
+#------------------------------------------------------------------------------
+# animation: file(1) magic for animation/movie formats
+#
+# animation formats, originally from vax@ccwf.cc.utexas.edu (VaX#n8)
+# MPEG file
+0 string \000\000\001\263 video/mpeg
+#
+# The contributor claims:
+# I couldn't find a real magic number for these, however, this
+# -appears- to work. Note that it might catch other files, too,
+# so BE CAREFUL!
+#
+# Note that title and author appear in the two 20-byte chunks
+# at decimal offsets 2 and 22, respectively, but they are XOR'ed with
+# 255 (hex FF)! DL format SUCKS BIG ROCKS.
+#
+# DL file version 1 , medium format (160x100, 4 images/screen)
+0 byte 1 video/unknown
+0 byte 2 video/unknown
+# Quicktime video, from Linus Walleij <triad@df.lth.se>
+# from Apple quicktime file format documentation.
+4 string moov video/quicktime
+4 string mdat video/quicktime
+
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_default_settings.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_default_settings.conf
new file mode 100644
index 000000000..38635aa9d
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_default_settings.conf
@@ -0,0 +1,131 @@
+# This configuration file reflects default settings for Apache HTTP Server.
+# You may change these, but chances are that you may not need to.
+
+# Timeout: The number of seconds before receives and sends time out.
+Timeout 300
+
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+KeepAlive On
+
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+MaxKeepAliveRequests 100
+
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+KeepAliveTimeout 15
+
+# UseCanonicalName: Determines how Apache constructs self-referencing
+# URLs and the SERVER_NAME and SERVER_PORT variables.
+# When set "Off", Apache will use the Hostname and Port supplied
+# by the client. When set "On", Apache will use the value of the
+# ServerName directive.
+UseCanonicalName Off
+
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives. See also the AllowOverride
+# directive.
+AccessFileName .htaccess
+
+# ServerTokens
+# This directive configures what you return as the Server HTTP response
+# Header. The default is 'Full' which sends information about the OS-Type
+# and compiled in modules.
+# Set to one of: Full | OS | Minor | Minimal | Major | Prod
+# where Full conveys the most information, and Prod the least.
+ServerTokens Prod
+
+# TraceEnable
+# This directive overrides the behavior of TRACE for both the core server and
+# mod_proxy. The default TraceEnable on permits TRACE requests per RFC 2616,
+# which disallows any request body to accompany the request. TraceEnable off
+# causes the core server and mod_proxy to return a 405 (Method not allowed)
+# error to the client.
+# For security reasons this is turned off by default. (bug #240680)
+TraceEnable off
+
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+ServerSignature On
+
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+HostnameLookups Off
+
+# EnableMMAP and EnableSendfile: On systems that support it,
+# memory-mapping or the sendfile syscall is used to deliver
+# files. This usually improves server performance, but must
+# be turned off when serving from networked-mounted
+# filesystems or if support for these functions is otherwise
+# broken on your system.
+EnableMMAP On
+EnableSendfile Off
+
+# FileETag: Configures the file attributes that are used to create
+# the ETag (entity tag) response header field when the document is
+# based on a static file. (The ETag value is used in cache management
+# to save network bandwidth.)
+FileETag MTime Size
+
+# ContentDigest: This directive enables the generation of Content-MD5
+# headers as defined in RFC1864 respectively RFC2616.
+# The Content-MD5 header provides an end-to-end message integrity
+# check (MIC) of the entity-body. A proxy or client may check this
+# header for detecting accidental modification of the entity-body
+# in transit.
+# Note that this can cause performance problems on your server since
+# the message digest is computed on every request (the values are
+# not cached).
+# Content-MD5 is only sent for documents served by the core, and not
+# by any module. For example, SSI documents, output from CGI scripts,
+# and byte range responses do not have this header.
+ContentDigest Off
+
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+ErrorLog /var/log/apache2/error_log
+
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+LogLevel warn
+
+# We configure the "default" to be a very restrictive set of features.
+<Directory />
+ Options FollowSymLinks
+ AllowOverride None
+ Require all denied
+</Directory>
+
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+# The index.html.var file (a type-map) is used to deliver content-
+# negotiated documents. The MultiViews Options can be used for the
+# same purpose, but it is much slower.
+#
+# Do not change this entry unless you know what you are doing.
+<IfModule dir_module>
+ DirectoryIndex index.html index.html.var
+</IfModule>
+
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+<FilesMatch "^\.ht">
+ Require all denied
+</FilesMatch>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_error_documents.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_error_documents.conf
new file mode 100644
index 000000000..61479fa53
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_error_documents.conf
@@ -0,0 +1,57 @@
+# The configuration below implements multi-language error documents through
+# content-negotiation.
+
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+
+# Required modules: mod_alias, mod_include, mod_negotiation
+# We use Alias to redirect any /error/HTTP_<error>.html.var response to
+# our collection of by-error message multi-language collections. We use
+# includes to substitute the appropriate text.
+# You can modify the messages' appearance without changing any of the
+# default HTTP_<error>.html.var files by adding the line:
+# Alias /error/include/ "/your/include/path/"
+# which allows you to create your own set of files by starting with the
+# /var/www/localhost/error/include/ files and copying them to /your/include/path/,
+# even on a per-VirtualHost basis. The default include files will display
+# your Apache version number and your ServerAdmin email address regardless
+# of the setting of ServerSignature.
+
+<IfDefine ERRORDOCS>
+Alias /error/ "/usr/share/apache2/error/"
+
+<Directory "/usr/share/apache2/error">
+ AllowOverride None
+ Options IncludesNoExec
+ AddOutputFilter Includes html
+ AddHandler type-map var
+ Require all granted
+ LanguagePriority en cs de es fr it ja ko nl pl pt-br ro sv tr
+ ForceLanguagePriority Prefer Fallback
+</Directory>
+
+ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
+ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
+ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
+ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
+ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
+ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
+ErrorDocument 410 /error/HTTP_GONE.html.var
+ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
+ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
+ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
+ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
+ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
+ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
+ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
+ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
+ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
+ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_languages.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_languages.conf
new file mode 100644
index 000000000..10cf3fb54
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_languages.conf
@@ -0,0 +1,133 @@
+# Settings for hosting different languages.
+<IfDefine LANGUAGE>
+# DefaultLanguage and AddLanguage allows you to specify the language of
+# a document. You can then use content negotiation to give a browser a
+# file in a language the user can understand.
+#
+# Specify a default language. This means that all data
+# going out without a specific language tag (see below) will
+# be marked with this one. You probably do NOT want to set
+# this unless you are sure it is correct for all cases.
+#
+# It is generally better to not mark a page as
+# being a certain language than marking it with the wrong
+# language!
+#
+# DefaultLanguage nl
+#
+# Note 1: The suffix does not have to be the same as the language
+# keyword --- those with documents in Polish (whose net-standard
+# language code is pl) may wish to use "AddLanguage pl .po" to
+# avoid the ambiguity with the common suffix for perl scripts.
+#
+# Note 2: The example entries below illustrate that in some cases
+# the two character 'Language' abbreviation is not identical to
+# the two character 'Country' code for its country,
+# E.g. 'Danmark/dk' versus 'Danish/da'.
+#
+# Note 3: In the case of 'ltz' we violate the RFC by using a three char
+# specifier. There is 'work in progress' to fix this and get
+# the reference data for rfc1766 cleaned up.
+#
+# Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl)
+# English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de)
+# Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja)
+# Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn)
+# Norwegian (no) - Polish (pl) - Portuguese (pt)
+# Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv)
+# Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW)
+AddLanguage ca .ca
+AddLanguage cs .cz .cs
+AddLanguage da .dk
+AddLanguage de .de
+AddLanguage el .el
+AddLanguage en .en
+AddLanguage eo .eo
+AddLanguage es .es
+AddLanguage et .et
+AddLanguage fr .fr
+AddLanguage he .he
+AddLanguage hr .hr
+AddLanguage it .it
+AddLanguage ja .ja
+AddLanguage ko .ko
+AddLanguage ltz .ltz
+AddLanguage nl .nl
+AddLanguage nn .nn
+AddLanguage no .no
+AddLanguage pl .po
+AddLanguage pt .pt
+AddLanguage pt-BR .pt-br
+AddLanguage ru .ru
+AddLanguage sv .sv
+AddLanguage zh-CN .zh-cn
+AddLanguage zh-TW .zh-tw
+
+# LanguagePriority allows you to give precedence to some languages
+# in case of a tie during content negotiation.
+#
+# Just list the languages in decreasing order of preference. We have
+# more or less alphabetized them here. You probably want to change this.
+LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
+
+# ForceLanguagePriority allows you to serve a result page rather than
+# MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback)
+# [in case no accepted languages matched the available variants]
+ForceLanguagePriority Prefer Fallback
+
+# Commonly used filename extensions to character sets. You probably
+# want to avoid clashes with the language extensions, unless you
+# are good at carefully testing your setup after each change.
+# See http://www.iana.org/assignments/character-sets for the
+# official list of charset names and their respective RFCs.
+AddCharset us-ascii.ascii .us-ascii
+AddCharset ISO-8859-1 .iso8859-1 .latin1
+AddCharset ISO-8859-2 .iso8859-2 .latin2 .cen
+AddCharset ISO-8859-3 .iso8859-3 .latin3
+AddCharset ISO-8859-4 .iso8859-4 .latin4
+AddCharset ISO-8859-5 .iso8859-5 .cyr .iso-ru
+AddCharset ISO-8859-6 .iso8859-6 .arb .arabic
+AddCharset ISO-8859-7 .iso8859-7 .grk .greek
+AddCharset ISO-8859-8 .iso8859-8 .heb .hebrew
+AddCharset ISO-8859-9 .iso8859-9 .latin5 .trk
+AddCharset ISO-8859-10 .iso8859-10 .latin6
+AddCharset ISO-8859-13 .iso8859-13
+AddCharset ISO-8859-14 .iso8859-14 .latin8
+AddCharset ISO-8859-15 .iso8859-15 .latin9
+AddCharset ISO-8859-16 .iso8859-16 .latin10
+AddCharset ISO-2022-JP .iso2022-jp .jis
+AddCharset ISO-2022-KR .iso2022-kr .kis
+AddCharset ISO-2022-CN .iso2022-cn .cis
+AddCharset Big5.Big5 .big5 .b5
+AddCharset cn-Big5 .cn-big5
+# For russian, more than one charset is used (depends on client, mostly):
+AddCharset WINDOWS-1251 .cp-1251 .win-1251
+AddCharset CP866 .cp866
+AddCharset KOI8 .koi8
+AddCharset KOI8-E .koi8-e
+AddCharset KOI8-r .koi8-r .koi8-ru
+AddCharset KOI8-U .koi8-u
+AddCharset KOI8-ru .koi8-uk .ua
+AddCharset ISO-10646-UCS-2 .ucs2
+AddCharset ISO-10646-UCS-4 .ucs4
+AddCharset UTF-7 .utf7
+AddCharset UTF-8 .utf8
+AddCharset UTF-16 .utf16
+AddCharset UTF-16BE .utf16be
+AddCharset UTF-16LE .utf16le
+AddCharset UTF-32 .utf32
+AddCharset UTF-32BE .utf32be
+AddCharset UTF-32LE .utf32le
+AddCharset euc-cn .euc-cn
+AddCharset euc-gb .euc-gb
+AddCharset euc-jp .euc-jp
+AddCharset euc-kr .euc-kr
+# Not sure how euc-tw got in - IANA doesn't list it???
+AddCharset EUC-TW .euc-tw
+AddCharset gb2312 .gb2312 .gb
+AddCharset iso-10646-ucs-2 .ucs-2 .iso-10646-ucs-2
+AddCharset iso-10646-ucs-4 .ucs-4 .iso-10646-ucs-4
+AddCharset shift_jis .shift_jis .sjis
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_autoindex.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_autoindex.conf
new file mode 100644
index 000000000..10bf48317
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_autoindex.conf
@@ -0,0 +1,85 @@
+<IfModule autoindex_module>
+<IfDefine !NO_AUTOINDEX_CONF>
+
+<IfModule alias_module>
+# We include the /icons/ alias for FancyIndexed directory listings. If
+# you do not use FancyIndexing, you may comment this out.
+Alias /icons/ "/usr/share/apache2/icons/"
+
+<Directory "/usr/share/apache2/icons">
+ Options Indexes MultiViews
+ AllowOverride None
+ Require all granted
+</Directory>
+</IfModule>
+
+# Directives controlling the display of server-generated directory listings.
+#
+# To see the listing of a directory, the Options directive for the
+# directory must include "Indexes", and the directory must not contain
+# a file matching those listed in the DirectoryIndex directive.
+
+# IndexOptions: Controls the appearance of server-generated directory
+# listings.
+IndexOptions FancyIndexing VersionSort
+
+# AddIcon* directives tell the server which icon to show for different
+# files or filename extensions. These are only displayed for
+# FancyIndexed directories.
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+AddIcon /icons/bomb.gif core
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+# DefaultIcon is which icon to show for files which do not have an icon
+# explicitly set.
+DefaultIcon /icons/unknown.gif
+
+# AddDescription allows you to place a short description after a file in
+# server-generated indexes. These are only displayed for FancyIndexed
+# directories.
+# Format: AddDescription "description" filename
+
+#AddDescription "GZIP compressed document" .gz
+#AddDescription "tar archive" .tar
+#AddDescription "GZIP compressed tar archive" .tgz
+
+# ReadmeName is the name of the README file the server will look for by
+# default, and append to directory listings.
+
+# HeaderName is the name of a file which should be prepended to
+# directory indexes.
+ReadmeName README.html
+HeaderName HEADER.html
+
+# IndexIgnore is a set of filenames which directory indexing should ignore
+# and not include in the listing. Shell-style wildcarding is permitted.
+IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
+</IfDefine>
+</IfModule>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_info.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_info.conf
new file mode 100644
index 000000000..2cd32c477
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_info.conf
@@ -0,0 +1,10 @@
+<IfDefine INFO>
+# Allow remote server configuration reports, with the URL of
+# http://servername/server-info
+<Location /server-info>
+ SetHandler server-info
+ Require local
+</Location>
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_log_config.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_log_config.conf
new file mode 100644
index 000000000..ce0238eee
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_log_config.conf
@@ -0,0 +1,35 @@
+<IfModule log_config_module>
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-Agent}i" agent
+LogFormat "%v %h %l %u %t \"%r\" %>s %b %T" script
+LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" VLOG=%{VLOG}e" vhost
+
+<IfModule logio_module>
+# You need to enable mod_logio.c to use %I and %O
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" vhostio
+</IfModule>
+
+# The location and format of the access logfile (Common Logfile Format).
+# If you do not define any access logfiles within a <VirtualHost>
+# container, they will be logged here. Contrariwise, if you *do*
+# define per-<VirtualHost> access logfiles, transactions will be
+# logged therein and *not* in this file.
+CustomLog /var/log/apache2/access_log common
+
+# If you would like to have agent and referer logfiles,
+# uncomment the following directives.
+#CustomLog /var/log/apache2/referer_log referer
+#CustomLog /var/log/apache2/agent_logs agent
+
+# If you prefer a logfile with access, agent, and referer information
+# (Combined Logfile Format) you can use the following directive.
+#CustomLog /var/log/apache2/access_log combined
+</IfModule>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_mime.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_mime.conf
new file mode 100644
index 000000000..fb8a9a5d5
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_mime.conf
@@ -0,0 +1,46 @@
+<IfModule mime_module>
+# TypesConfig points to the file containing the list of mappings from
+# filename extension to MIME-type.
+TypesConfig /etc/mime.types
+
+# AddType allows you to add to or override the MIME configuration
+# file specified in TypesConfig for specific file types.
+#AddType application/x-gzip .tgz
+
+# AddEncoding allows you to have certain browsers uncompress
+# information on the fly. Note: Not all browsers support this.
+#AddEncoding x-compress .Z
+#AddEncoding x-gzip .gz .tgz
+
+# If the AddEncoding directives above are commented-out, then you
+# probably should define those extensions to indicate media types:
+AddType application/x-compress .Z
+AddType application/x-gzip .gz .tgz
+
+# AddHandler allows you to map certain file extensions to "handlers":
+# actions unrelated to filetype. These can be either built into the server
+# or added with the Action directive (see below)
+
+# To use CGI scripts outside of ScriptAliased directories:
+# (You will also need to add "ExecCGI" to the "Options" directive.)
+#AddHandler cgi-script .cgi
+
+# For type maps (negotiated resources):
+#AddHandler type-map var
+
+# Filters allow you to process content before it is sent to the client.
+#
+# To parse .shtml files for server-side includes (SSI):
+# (You will also need to add "Includes" to the "Options" directive.)
+#AddType text/html .shtml
+#AddOutputFilter INCLUDES .shtml
+</IfModule>
+
+<IfModule mime_magic_module>
+# The mod_mime_magic module allows the server to use various hints from the
+# contents of the file itself to determine its type. The MIMEMagicFile
+# directive tells the module where the hint definitions are located.
+MIMEMagicFile /etc/apache2/magic
+</IfModule>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_status.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_status.conf
new file mode 100644
index 000000000..ed8b3c7cb
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_status.conf
@@ -0,0 +1,15 @@
+<IfDefine STATUS>
+# Allow server status reports generated by mod_status,
+# with the URL of http://servername/server-status
+<Location /server-status>
+ SetHandler server-status
+ Require local
+</Location>
+
+# ExtendedStatus controls whether Apache will generate "full" status
+# information (ExtendedStatus On) or just basic information (ExtendedStatus
+# Off) when the "server-status" handler is called.
+ExtendedStatus On
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_userdir.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_userdir.conf
new file mode 100644
index 000000000..0087126c4
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mod_userdir.conf
@@ -0,0 +1,32 @@
+# Settings for user home directories
+<IfDefine USERDIR>
+# UserDir: The name of the directory that is appended onto a user's home
+# directory if a ~user request is received. Note that you must also set
+# the default access control for these directories, as in the example below.
+UserDir public_html
+
+# Control access to UserDir directories. The following is an example
+# for a site where these directories are restricted to read-only.
+<Directory /home/*/public_html>
+ AllowOverride FileInfo AuthConfig Limit Indexes
+ Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+ <Limit GET POST OPTIONS>
+ Require all granted
+ </Limit>
+ <LimitExcept GET POST OPTIONS>
+ Require all denied
+ </LimitExcept>
+</Directory>
+
+# Suexec isn't really required to run cgi-scripts, but it's a really good
+# idea if you have multiple users serving websites...
+<IfDefine SUEXEC>
+<Directory /home/*/public_html/cgi-bin>
+ Options ExecCGI
+ SetHandler cgi-script
+</Directory>
+</IfDefine>
+
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mpm.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mpm.conf
new file mode 100644
index 000000000..bcb9b6b47
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/00_mpm.conf
@@ -0,0 +1,99 @@
+# Server-Pool Management (MPM specific)
+
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+#
+# DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING
+PidFile /run/apache2.pid
+
+# The accept serialization lock file MUST BE STORED ON A LOCAL DISK.
+# Mutex file:/run/apache_mpm_mutex
+
+# Only one of the below sections will be relevant on your
+# installed httpd. Use "/usr/sbin/apache2 -l" to find out the
+# active mpm.
+
+# common MPM configuration
+# These configuration directives apply to all MPMs
+#
+# StartServers: Number of child server processes created at startup
+# MaxRequestWorkers: Maximum number of child processes to serve requests
+# MaxConnectionsPerChild: Limit on the number of connections that an individual
+# child server will handle during its life
+
+
+# prefork MPM
+# This is the default MPM if USE=-threads
+#
+# MinSpareServers: Minimum number of idle child server processes
+# MaxSpareServers: Maximum number of idle child server processes
+<IfModule mpm_prefork_module>
+ StartServers 5
+ MinSpareServers 5
+ MaxSpareServers 10
+ MaxRequestWorkers 150
+ MaxConnectionsPerChild 10000
+</IfModule>
+
+# worker MPM
+# This is the default MPM if USE=threads
+#
+# MinSpareThreads: Minimum number of idle threads available to handle request spikes
+# MaxSpareThreads: Maximum number of idle threads
+# ThreadsPerChild: Number of threads created by each child process
+<IfModule mpm_worker_module>
+ StartServers 2
+ MinSpareThreads 25
+ MaxSpareThreads 75
+ ThreadsPerChild 25
+ MaxRequestWorkers 150
+ MaxConnectionsPerChild 10000
+</IfModule>
+
+# event MPM
+#
+# MinSpareThreads: Minimum number of idle threads available to handle request spikes
+# MaxSpareThreads: Maximum number of idle threads
+# ThreadsPerChild: Number of threads created by each child process
+<IfModule mpm_event_module>
+ StartServers 2
+ MinSpareThreads 25
+ MaxSpareThreads 75
+ ThreadsPerChild 25
+ MaxRequestWorkers 150
+ MaxConnectionsPerChild 10000
+</IfModule>
+
+# peruser MPM
+#
+# MinSpareProcessors: Minimum number of idle child server processes
+# MinProcessors: Minimum number of processors per virtual host
+# MaxProcessors: Maximum number of processors per virtual host
+# ExpireTimeout: Maximum idle time before a child is killed, 0 to disable
+# Multiplexer: Specify a Multiplexer child configuration.
+# Processor: Specify a user and group for a specific child process
+<IfModule mpm_peruser_module>
+ MinSpareProcessors 2
+ MinProcessors 2
+ MaxProcessors 10
+ MaxRequestWorkers 150
+ MaxConnectionsPerChild 1000
+ ExpireTimeout 1800
+
+ Multiplexer nobody nobody
+ Processor apache apache
+</IfModule>
+
+# itk MPM
+#
+# MinSpareServers: Minimum number of idle child server processes
+# MaxSpareServers: Maximum number of idle child server processes
+<IfModule mpm_itk_module>
+ StartServers 5
+ MinSpareServers 5
+ MaxSpareServers 10
+ MaxRequestWorkers 150
+ MaxConnectionsPerChild 10000
+</IfModule>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/10_mod_mem_cache.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/10_mod_mem_cache.conf
new file mode 100644
index 000000000..520d9fd82
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/10_mod_mem_cache.conf
@@ -0,0 +1,10 @@
+<IfDefine MEM_CACHE>
+# 128MB cache for objects < 2MB
+CacheEnable mem /
+MCacheSize 131072
+MCacheMaxObjectCount 1000
+MCacheMinObjectSize 1
+MCacheMaxObjectSize 2097152
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/40_mod_ssl.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/40_mod_ssl.conf
new file mode 100644
index 000000000..7f3cef423
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/40_mod_ssl.conf
@@ -0,0 +1,67 @@
+# Note: The following must must be present to support
+# starting without SSL on platforms with no /dev/random equivalent
+# but a statically compiled-in mod_ssl.
+<IfModule ssl_module>
+SSLRandomSeed startup builtin
+SSLRandomSeed connect builtin
+</IfModule>
+
+<IfDefine SSL>
+# This is the Apache server configuration file providing SSL support.
+# It contains the configuration directives to instruct the server how to
+# serve pages over an https connection. For detailing information about these
+# directives see <URL:http://httpd.apache.org/docs/2.4/mod/mod_ssl.html>
+
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+
+## Pseudo Random Number Generator (PRNG):
+# Configure one or more sources to seed the PRNG of the SSL library.
+# The seed data should be of good random quality.
+# WARNING! On some platforms /dev/random blocks if not enough entropy
+# is available. This means you then cannot use the /dev/random device
+# because it would lead to very long connection times (as long as
+# it requires to make more entropy available). But usually those
+# platforms additionally provide a /dev/urandom device which doesn't
+# block. So, if available, use this one instead. Read the mod_ssl User
+# Manual for more details.
+#SSLRandomSeed startup file:/dev/random 512
+#SSLRandomSeed startup file:/dev/urandom 512
+#SSLRandomSeed connect file:/dev/random 512
+#SSLRandomSeed connect file:/dev/urandom 512
+
+## SSL Global Context:
+# All SSL configuration in this context applies both to the main server and
+# all SSL-enabled virtual hosts.
+
+# Some MIME-types for downloading Certificates and CRLs
+<IfModule mime_module>
+ AddType application/x-x509-ca-cert .crt
+ AddType application/x-pkcs7-crl .crl
+</IfModule>
+
+## Pass Phrase Dialog:
+# Configure the pass phrase gathering process. The filtering dialog program
+# (`builtin' is an internal terminal dialog) has to provide the pass phrase on
+# stdout.
+SSLPassPhraseDialog builtin
+
+## Inter-Process Session Cache:
+# Configure the SSL Session Cache: First the mechanism to use and second the
+# expiring timeout (in seconds).
+#SSLSessionCache dbm:/run/ssl_scache
+SSLSessionCache shmcb:/run/ssl_scache(512000)
+SSLSessionCacheTimeout 300
+
+## Semaphore:
+# Configure the path to the mutual exclusion semaphore the SSL engine uses
+# internally for inter-process synchronization.
+Mutex file:/run/apache_ssl_mutex ssl-cache
+
+## SSL Compression:
+# Known to be vulnerable thus disabled by default (bug #507324).
+SSLCompression off
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/41_mod_http2.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/41_mod_http2.conf
new file mode 100644
index 000000000..e4c9454e0
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/41_mod_http2.conf
@@ -0,0 +1,9 @@
+<IfDefine SSL>
+ <IfModule http2_module>
+ # enable debugging for this module
+ #LogLevel http2:info
+
+ #Enable HTTP/2 support
+ Protocols h2 h2c http/1.1
+ </IfModule>
+</IfDefine>
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/45_mod_dav.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/45_mod_dav.conf
new file mode 100644
index 000000000..36f6b9cca
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/45_mod_dav.conf
@@ -0,0 +1,19 @@
+<IfDefine DAV>
+DavLockDB "/var/lib/dav/lockdb"
+
+# The following directives disable redirects on non-GET requests for
+# a directory that does not include the trailing slash. This fixes a
+# problem with several clients that do not appropriately handle
+# redirects for folders with DAV methods.
+<IfModule setenvif_module>
+BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
+BrowserMatch "MS FrontPage" redirect-carefully
+BrowserMatch "^WebDrive" redirect-carefully
+BrowserMatch "^WebDAVFS/1.[012345678]" redirect-carefully
+BrowserMatch "^gnome-vfs/1.0" redirect-carefully
+BrowserMatch "^XML Spy" redirect-carefully
+BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
+</IfModule>
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/46_mod_ldap.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/46_mod_ldap.conf
new file mode 100644
index 000000000..883061fee
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/modules.d/46_mod_ldap.conf
@@ -0,0 +1,18 @@
+# Examples below are taken from the online documentation
+# Refer to:
+# http://localhost/manual/mod/mod_ldap.html
+# http://localhost/manual/mod/mod_auth_ldap.html
+<IfDefine LDAP>
+LDAPSharedCacheSize 200000
+LDAPCacheEntries 1024
+LDAPCacheTTL 600
+LDAPOpCacheEntries 1024
+LDAPOpCacheTTL 600
+
+<Location /ldap-status>
+ SetHandler ldap-status
+ Require local
+</Location>
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_ssl_vhost.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_ssl_vhost.conf
new file mode 100644
index 000000000..bb395473c
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_ssl_vhost.conf
@@ -0,0 +1,191 @@
+<IfDefine SSL>
+<IfDefine SSL_DEFAULT_VHOST>
+<IfModule ssl_module>
+# see bug #178966 why this is in here
+
+# When we also provide SSL we have to listen to the HTTPS port
+# Note: Configurations that use IPv6 but not IPv4-mapped addresses need two
+# Listen directives: "Listen [::]:443" and "Listen 0.0.0.0:443"
+Listen 443
+
+<VirtualHost _default_:443>
+ ServerName localhost
+ Include /etc/apache2/vhosts.d/default_vhost.include
+ ErrorLog /var/log/apache2/ssl_error_log
+
+ <IfModule log_config_module>
+ TransferLog /var/log/apache2/ssl_access_log
+ </IfModule>
+
+ ## SSL Engine Switch:
+ # Enable/Disable SSL for this virtual host.
+ SSLEngine on
+
+ ## SSLProtocol:
+ # Don't use SSLv2 anymore as it's considered to be broken security-wise.
+ # Also disable SSLv3 as most modern browsers are capable of TLS.
+ SSLProtocol ALL -SSLv2 -SSLv3
+
+ ## SSL Cipher Suite:
+ # List the ciphers that the client is permitted to negotiate.
+ # See the mod_ssl documentation for a complete list.
+ # This list of ciphers is recommended by mozilla and was stripped off
+ # its RC4 ciphers. (bug #506924)
+ SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:HIGH:!RC4:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK
+
+ ## SSLHonorCipherOrder:
+ # Prefer the server's cipher preference order as the client may have a
+ # weak default order.
+ SSLHonorCipherOrder On
+
+ ## Server Certificate:
+ # Point SSLCertificateFile at a PEM encoded certificate. If the certificate
+ # is encrypted, then you will be prompted for a pass phrase. Note that a
+ # kill -HUP will prompt again. Keep in mind that if you have both an RSA
+ # and a DSA certificate you can configure both in parallel (to also allow
+ # the use of DSA ciphers, etc.)
+ SSLCertificateFile /etc/ssl/apache2/server.crt
+
+ ## Server Private Key:
+ # If the key is not combined with the certificate, use this directive to
+ # point at the key file. Keep in mind that if you've both a RSA and a DSA
+ # private key you can configure both in parallel (to also allow the use of
+ # DSA ciphers, etc.)
+ SSLCertificateKeyFile /etc/ssl/apache2/server.key
+
+ ## Server Certificate Chain:
+ # Point SSLCertificateChainFile at a file containing the concatenation of
+ # PEM encoded CA certificates which form the certificate chain for the
+ # server certificate. Alternatively the referenced file can be the same as
+ # SSLCertificateFile when the CA certificates are directly appended to the
+ # server certificate for convinience.
+ #SSLCertificateChainFile /etc/ssl/apache2/ca.crt
+
+ ## Certificate Authority (CA):
+ # Set the CA certificate verification path where to find CA certificates
+ # for client authentication or alternatively one huge file containing all
+ # of them (file must be PEM encoded).
+ # Note: Inside SSLCACertificatePath you need hash symlinks to point to the
+ # certificate files. Use the provided Makefile to update the hash symlinks
+ # after changes.
+ #SSLCACertificatePath /etc/ssl/apache2/ssl.crt
+ #SSLCACertificateFile /etc/ssl/apache2/ca-bundle.crt
+
+ ## Certificate Revocation Lists (CRL):
+ # Set the CA revocation path where to find CA CRLs for client authentication
+ # or alternatively one huge file containing all of them (file must be PEM
+ # encoded).
+ # Note: Inside SSLCARevocationPath you need hash symlinks to point to the
+ # certificate files. Use the provided Makefile to update the hash symlinks
+ # after changes.
+ #SSLCARevocationPath /etc/ssl/apache2/ssl.crl
+ #SSLCARevocationFile /etc/ssl/apache2/ca-bundle.crl
+
+ ## Client Authentication (Type):
+ # Client certificate verification type and depth. Types are none, optional,
+ # require and optional_no_ca. Depth is a number which specifies how deeply
+ # to verify the certificate issuer chain before deciding the certificate is
+ # not valid.
+ #SSLVerifyClient require
+ #SSLVerifyDepth 10
+
+ ## Access Control:
+ # With SSLRequire you can do per-directory access control based on arbitrary
+ # complex boolean expressions containing server variable checks and other
+ # lookup directives. The syntax is a mixture between C and Perl. See the
+ # mod_ssl documentation for more details.
+ #<Location />
+ # #SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
+ # and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
+ # and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
+ # and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
+ # and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
+ # or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
+ #</Location>
+
+ ## SSL Engine Options:
+ # Set various options for the SSL engine.
+
+ ## FakeBasicAuth:
+ # Translate the client X.509 into a Basic Authorisation. This means that the
+ # standard Auth/DBMAuth methods can be used for access control. The user
+ # name is the `one line' version of the client's X.509 certificate.
+ # Note that no password is obtained from the user. Every entry in the user
+ # file needs this password: `xxj31ZMTZzkVA'.
+
+ ## ExportCertData:
+ # This exports two additional environment variables: SSL_CLIENT_CERT and
+ # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the server
+ # (always existing) and the client (only existing when client
+ # authentication is used). This can be used to import the certificates into
+ # CGI scripts.
+
+ ## StdEnvVars:
+ # This exports the standard SSL/TLS related `SSL_*' environment variables.
+ # Per default this exportation is switched off for performance reasons,
+ # because the extraction step is an expensive operation and is usually
+ # useless for serving static content. So one usually enables the exportation
+ # for CGI and SSI requests only.
+
+ ## StrictRequire:
+ # This denies access when "SSLRequireSSL" or "SSLRequire" applied even under
+ # a "Satisfy any" situation, i.e. when it applies access is denied and no
+ # other module can change it.
+
+ ## OptRenegotiate:
+ # This enables optimized SSL connection renegotiation handling when SSL
+ # directives are used in per-directory context.
+ #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
+ <FilesMatch "\.(cgi|shtml|phtml|php)$">
+ SSLOptions +StdEnvVars
+ </FilesMatch>
+
+ <Directory "/var/www/localhost/cgi-bin">
+ SSLOptions +StdEnvVars
+ </Directory>
+
+ ## SSL Protocol Adjustments:
+ # The safe and default but still SSL/TLS standard compliant shutdown
+ # approach is that mod_ssl sends the close notify alert but doesn't wait
+ # for the close notify alert from client. When you need a different
+ # shutdown approach you can use one of the following variables:
+
+ ## ssl-unclean-shutdown:
+ # This forces an unclean shutdown when the connection is closed, i.e. no
+ # SSL close notify alert is send or allowed to received. This violates the
+ # SSL/TLS standard but is needed for some brain-dead browsers. Use this when
+ # you receive I/O errors because of the standard approach where mod_ssl
+ # sends the close notify alert.
+
+ ## ssl-accurate-shutdown:
+ # This forces an accurate shutdown when the connection is closed, i.e. a
+ # SSL close notify alert is send and mod_ssl waits for the close notify
+ # alert of the client. This is 100% SSL/TLS standard compliant, but in
+ # practice often causes hanging connections with brain-dead browsers. Use
+ # this only for browsers where you know that their SSL implementation works
+ # correctly.
+ # Notice: Most problems of broken clients are also related to the HTTP
+ # keep-alive facility, so you usually additionally want to disable
+ # keep-alive for those clients, too. Use variable "nokeepalive" for this.
+ # Similarly, one has to force some clients to use HTTP/1.0 to workaround
+ # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
+ # "force-response-1.0" for this.
+ <IfModule setenvif_module>
+ BrowserMatch ".*MSIE.*" \
+ nokeepalive ssl-unclean-shutdown \
+ downgrade-1.0 force-response-1.0
+ </IfModule>
+
+ ## Per-Server Logging:
+ # The home of a custom SSL log file. Use this when you want a compact
+ # non-error SSL logfile on a virtual host basis.
+ <IfModule log_config_module>
+ CustomLog /var/log/apache2/ssl_request_log \
+ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
+ </IfModule>
+</VirtualHost>
+</IfModule>
+</IfDefine>
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_vhost.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_vhost.conf
new file mode 100644
index 000000000..b9766b5f1
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/00_default_vhost.conf
@@ -0,0 +1,45 @@
+# Virtual Hosts
+#
+# If you want to maintain multiple domains/hostnames on your
+# machine you can setup VirtualHost containers for them. Most configurations
+# use only name-based virtual hosts so the server doesn't need to worry about
+# IP addresses. This is indicated by the asterisks in the directives below.
+#
+# Please see the documentation at
+# <URL:http://httpd.apache.org/docs/2.4/vhosts/>
+# for further details before you try to setup virtual hosts.
+#
+# You may use the command line option '-S' to verify your virtual host
+# configuration.
+
+<IfDefine DEFAULT_VHOST>
+# see bug #178966 why this is in here
+
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to
+# prevent Apache from glomming onto all bound IP addresses.
+#
+#Listen 12.34.56.78:80
+Listen 80
+
+# When virtual hosts are enabled, the main host defined in the default
+# httpd.conf configuration will go away. We redefine it here so that it is
+# still available.
+#
+# If you disable this vhost by removing -D DEFAULT_VHOST from
+# /etc/conf.d/apache2, the first defined virtual host elsewhere will be
+# the default.
+<VirtualHost *:80>
+ ServerName localhost
+ Include /etc/apache2/vhosts.d/default_vhost.include
+
+ <IfModule mpm_peruser_module>
+ ServerEnvironment apache apache
+ </IfModule>
+</VirtualHost>
+</IfDefine>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/default_vhost.include b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/default_vhost.include
new file mode 100644
index 000000000..af6ece85b
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/default_vhost.include
@@ -0,0 +1,71 @@
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed. This address appears on some server-generated pages, such
+# as error documents. e.g. admin@your-domain.com
+ServerAdmin root@localhost
+
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+# If you change this to something that isn't under /var/www then suexec
+# will no longer work.
+DocumentRoot "/var/www/localhost/htdocs"
+
+# This should be changed to whatever you set DocumentRoot to.
+<Directory "/var/www/localhost/htdocs">
+ # Possible values for the Options directive are "None", "All",
+ # or any combination of:
+ # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+ #
+ # Note that "MultiViews" must be named *explicitly* --- "Options All"
+ # doesn't give it to you.
+ #
+ # The Options directive is both complicated and important. Please see
+ # http://httpd.apache.org/docs/2.4/mod/core.html#options
+ # for more information.
+ Options Indexes FollowSymLinks
+
+ # AllowOverride controls what directives may be placed in .htaccess files.
+ # It can be "All", "None", or any combination of the keywords:
+ # Options FileInfo AuthConfig Limit
+ AllowOverride All
+
+ # Controls who can get stuff from this server.
+ Require all granted
+</Directory>
+
+<IfModule alias_module>
+ # Redirect: Allows you to tell clients about documents that used to
+ # exist in your server's namespace, but do not anymore. The client
+ # will make a new request for the document at its new location.
+ # Example:
+ # Redirect permanent /foo http://www.example.com/bar
+
+ # Alias: Maps web paths into filesystem paths and is used to
+ # access content that does not live under the DocumentRoot.
+ # Example:
+ # Alias /webpath /full/filesystem/path
+ #
+ # If you include a trailing / on /webpath then the server will
+ # require it to be present in the URL. You will also likely
+ # need to provide a <Directory> section to allow access to
+ # the filesystem path.
+
+ # ScriptAlias: This controls which directories contain server scripts.
+ # ScriptAliases are essentially the same as Aliases, except that
+ # documents in the target directory are treated as applications and
+ # run by the server when requested rather than as documents sent to the
+ # client. The same rules about trailing "/" apply to ScriptAlias
+ # directives as to Alias.
+ ScriptAlias /cgi-bin/ "/var/www/localhost/cgi-bin/"
+</IfModule>
+
+# "/var/www/localhost/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+<Directory "/var/www/localhost/cgi-bin">
+ AllowOverride None
+ Options None
+ Require all granted
+</Directory>
+
+# vim: ts=4 filetype=apache
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/gentoo.example.com.conf b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/gentoo.example.com.conf
new file mode 100644
index 000000000..41de4d236
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/apache2/vhosts.d/gentoo.example.com.conf
@@ -0,0 +1,7 @@
+<VirtualHost *:80>
+ ServerName gentoo.example.com
+ ServerAdmin webmaster@localhost
+ DocumentRoot /var/www/html
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+</VirtualHost>
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/conf.d/apache2 b/certbot-apache/tests/testdata/gentoo_apache/apache/conf.d/apache2
new file mode 100644
index 000000000..b7ecb4f2a
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/conf.d/apache2
@@ -0,0 +1,74 @@
+# /etc/conf.d/apache2: config file for /etc/init.d/apache2
+
+# When you install a module it is easy to activate or deactivate the modules
+# and other features of apache using the APACHE2_OPTS line. Every module should
+# install a configuration in /etc/apache2/modules.d. In that file will have an
+# <IfDefine NNN> directive where NNN is the option to enable that module.
+#
+# Here are the options available in the default configuration:
+#
+# AUTH_DIGEST Enables mod_auth_digest
+# AUTHNZ_LDAP Enables authentication through mod_ldap (available if USE=ldap)
+# CACHE Enables mod_cache
+# DAV Enables mod_dav
+# ERRORDOCS Enables default error documents for many languages.
+# INFO Enables mod_info, a useful module for debugging
+# LANGUAGE Enables content-negotiation based on language and charset.
+# LDAP Enables mod_ldap (available if USE=ldap)
+# MANUAL Enables /manual/ to be the apache manual (available if USE=docs)
+# MEM_CACHE Enables default configuration mod_mem_cache
+# PROXY Enables mod_proxy
+# SSL Enables SSL (available if USE=ssl)
+# STATUS Enabled mod_status, a useful module for statistics
+# SUEXEC Enables running CGI scripts (in USERDIR) through suexec.
+# USERDIR Enables /~username mapping to /home/username/public_html
+#
+#
+# The following two options provide the default virtual host for the HTTP and
+# HTTPS protocol. YOU NEED TO ENABLE AT LEAST ONE OF THEM, otherwise apache
+# will not listen for incomming connections on the approriate port.
+#
+# DEFAULT_VHOST Enables name-based virtual hosts, with the default
+# virtual host being in /var/www/localhost/htdocs
+# SSL_DEFAULT_VHOST Enables default vhost for SSL (you should enable this
+# when you enable SSL)
+#
+APACHE2_OPTS="-D DEFAULT_VHOST -D INFO -D SSL -D SSL_DEFAULT_VHOST -D LANGUAGE"
+
+# Extended options for advanced uses of Apache ONLY
+# You don't need to edit these unless you are doing crazy Apache stuff
+# As not having them set correctly, or feeding in an incorrect configuration
+# via them will result in Apache failing to start
+# YOU HAVE BEEN WARNED.
+
+# PID file
+#PIDFILE=/var/run/apache2.pid
+
+# timeout for startup/shutdown checks
+#TIMEOUT=10
+
+# ServerRoot setting
+#SERVERROOT=/usr/lib64/apache2
+
+# Configuration file location
+# - If this does NOT start with a '/', then it is treated relative to
+# $SERVERROOT by Apache
+#CONFIGFILE=/etc/apache2/httpd.conf
+
+# Location to log startup errors to
+# They are normally dumped to your terminal.
+#STARTUPERRORLOG="/var/log/apache2/startuperror.log"
+
+# A command that outputs a formatted text version of the HTML at the URL
+# of the command line. Designed for lynx, however other programs may work.
+#LYNX="lynx -dump"
+
+# The URL to your server's mod_status status page.
+# Required for status and fullstatus
+#STATUSURL="http://localhost/server-status"
+
+# Method to use when reloading the server
+# Valid options are 'restart' and 'graceful'
+# See http://httpd.apache.org/docs/2.2/stopping.html for information on
+# what they do and how they differ.
+#RELOAD_TYPE="graceful"
diff --git a/certbot-apache/tests/testdata/gentoo_apache/apache/sites b/certbot-apache/tests/testdata/gentoo_apache/apache/sites
new file mode 100644
index 000000000..7f0b3a8b3
--- /dev/null
+++ b/certbot-apache/tests/testdata/gentoo_apache/apache/sites
@@ -0,0 +1,3 @@
+vhosts.d/gentoo.example.com.conf, gentoo.example.com
+vhosts.d/00_default_vhost.conf, localhost
+vhosts.d/00_default_ssl_vhost.conf, localhost
diff --git a/certbot-apache/tests/util.py b/certbot-apache/tests/util.py
new file mode 100644
index 000000000..57b20dc9d
--- /dev/null
+++ b/certbot-apache/tests/util.py
@@ -0,0 +1,238 @@
+"""Common utilities for certbot_apache."""
+import shutil
+import sys
+import unittest
+
+import augeas
+import josepy as jose
+import mock
+import zope.component
+
+from certbot.compat import os
+from certbot.display import util as display_util
+from certbot.plugins import common
+from certbot.tests import util as test_util
+from certbot_apache._internal import configurator
+from certbot_apache._internal import entrypoint
+from certbot_apache._internal import obj
+
+
+class ApacheTest(unittest.TestCase):
+
+ def setUp(self, test_dir="debian_apache_2_4/multiple_vhosts",
+ config_root="debian_apache_2_4/multiple_vhosts/apache2",
+ vhost_root="debian_apache_2_4/multiple_vhosts/apache2/sites-available"):
+ # pylint: disable=arguments-differ
+ super(ApacheTest, self).setUp()
+
+ self.temp_dir, self.config_dir, self.work_dir = common.dir_setup(
+ test_dir=test_dir,
+ pkg=__name__)
+
+ self.config_path = os.path.join(self.temp_dir, config_root)
+ self.vhost_path = os.path.join(self.temp_dir, vhost_root)
+
+ self.rsa512jwk = jose.JWKRSA.load(test_util.load_vector(
+ "rsa512_key.pem"))
+
+ self.config = get_apache_configurator(self.config_path, vhost_root,
+ self.config_dir, self.work_dir)
+
+ # Make sure all vhosts in sites-enabled are symlinks (Python packaging
+ # does not preserve symlinks)
+ sites_enabled = os.path.join(self.config_path, "sites-enabled")
+ if not os.path.exists(sites_enabled):
+ return
+
+ for vhost_basename in os.listdir(sites_enabled):
+ # Keep the one non-symlink test vhost in place
+ if vhost_basename == "non-symlink.conf":
+ continue
+ vhost = os.path.join(sites_enabled, vhost_basename)
+ if not os.path.islink(vhost): # pragma: no cover
+ os.remove(vhost)
+ target = os.path.join(
+ os.path.pardir, "sites-available", vhost_basename)
+ os.symlink(target, vhost)
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+ shutil.rmtree(self.config_dir)
+ shutil.rmtree(self.work_dir)
+
+
+class ParserTest(ApacheTest):
+
+ def setUp(self, test_dir="debian_apache_2_4/multiple_vhosts",
+ config_root="debian_apache_2_4/multiple_vhosts/apache2",
+ vhost_root="debian_apache_2_4/multiple_vhosts/apache2/sites-available"):
+ super(ParserTest, self).setUp(test_dir, config_root, vhost_root)
+
+ zope.component.provideUtility(display_util.FileDisplay(sys.stdout,
+ False))
+
+ from certbot_apache._internal.parser import ApacheParser
+ self.aug = augeas.Augeas(
+ flags=augeas.Augeas.NONE | augeas.Augeas.NO_MODL_AUTOLOAD)
+ with mock.patch("certbot_apache._internal.parser.ApacheParser."
+ "update_runtime_variables"):
+ self.parser = ApacheParser(
+ self.config_path, self.vhost_path, configurator=self.config)
+
+
+def get_apache_configurator(
+ config_path, vhost_path,
+ config_dir, work_dir, version=(2, 4, 7),
+ os_info="generic",
+ conf_vhost_path=None):
+ """Create an Apache Configurator with the specified options.
+
+ :param conf: Function that returns binary paths. self.conf in Configurator
+
+ """
+ backups = os.path.join(work_dir, "backups")
+ mock_le_config = mock.MagicMock(
+ apache_server_root=config_path,
+ apache_vhost_root=None,
+ apache_le_vhost_ext="-le-ssl.conf",
+ apache_challenge_location=config_path,
+ apache_enmod=None,
+ backup_dir=backups,
+ config_dir=config_dir,
+ http01_port=80,
+ temp_checkpoint_dir=os.path.join(work_dir, "temp_checkpoints"),
+ in_progress_dir=os.path.join(backups, "IN_PROGRESS"),
+ work_dir=work_dir)
+
+ with mock.patch("certbot_apache._internal.configurator.util.run_script"):
+ with mock.patch("certbot_apache._internal.configurator.util."
+ "exe_exists") as mock_exe_exists:
+ mock_exe_exists.return_value = True
+ with mock.patch("certbot_apache._internal.parser.ApacheParser."
+ "update_runtime_variables"):
+ try:
+ config_class = entrypoint.OVERRIDE_CLASSES[os_info]
+ except KeyError:
+ config_class = configurator.ApacheConfigurator
+ config = config_class(config=mock_le_config, name="apache",
+ version=version)
+ if not conf_vhost_path:
+ config_class.OS_DEFAULTS["vhost_root"] = vhost_path
+ else:
+ # Custom virtualhost path was requested
+ config.config.apache_vhost_root = conf_vhost_path
+ config.config.apache_ctl = config_class.OS_DEFAULTS["ctl"]
+ config.prepare()
+ return config
+
+
+def get_vh_truth(temp_dir, config_name):
+ """Return the ground truth for the specified directory."""
+ if config_name == "debian_apache_2_4/multiple_vhosts":
+ prefix = os.path.join(
+ temp_dir, config_name, "apache2/sites-enabled")
+
+ aug_pre = "/files" + prefix
+ vh_truth = [
+ obj.VirtualHost(
+ os.path.join(prefix, "encryption-example.conf"),
+ os.path.join(aug_pre, "encryption-example.conf/Virtualhost"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "encryption-example.demo"),
+ obj.VirtualHost(
+ os.path.join(prefix, "default-ssl.conf"),
+ os.path.join(aug_pre,
+ "default-ssl.conf/IfModule/VirtualHost"),
+ set([obj.Addr.fromstring("_default_:443")]), True, True),
+ obj.VirtualHost(
+ os.path.join(prefix, "000-default.conf"),
+ os.path.join(aug_pre, "000-default.conf/VirtualHost"),
+ set([obj.Addr.fromstring("*:80"),
+ obj.Addr.fromstring("[::]:80")]),
+ False, True, "ip-172-30-0-17"),
+ obj.VirtualHost(
+ os.path.join(prefix, "certbot.conf"),
+ os.path.join(aug_pre, "certbot.conf/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]), False, True,
+ "certbot.demo", aliases=["www.certbot.demo"]),
+ obj.VirtualHost(
+ os.path.join(prefix, "mod_macro-example.conf"),
+ os.path.join(aug_pre,
+ "mod_macro-example.conf/Macro/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]), False, True,
+ modmacro=True),
+ obj.VirtualHost(
+ os.path.join(prefix, "default-ssl-port-only.conf"),
+ os.path.join(aug_pre, ("default-ssl-port-only.conf/"
+ "IfModule/VirtualHost")),
+ set([obj.Addr.fromstring("_default_:443")]), True, True),
+ obj.VirtualHost(
+ os.path.join(prefix, "wildcard.conf"),
+ os.path.join(aug_pre, "wildcard.conf/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]), False, True,
+ "ip-172-30-0-17", aliases=["*.blue.purple.com"]),
+ obj.VirtualHost(
+ os.path.join(prefix, "ocsp-ssl.conf"),
+ os.path.join(aug_pre, "ocsp-ssl.conf/IfModule/VirtualHost"),
+ set([obj.Addr.fromstring("10.2.3.4:443")]), True, True,
+ "ocspvhost.com"),
+ obj.VirtualHost(
+ os.path.join(prefix, "non-symlink.conf"),
+ os.path.join(aug_pre, "non-symlink.conf/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]), False, True,
+ "nonsym.link"),
+ obj.VirtualHost(
+ os.path.join(prefix, "default-ssl-port-only.conf"),
+ os.path.join(aug_pre,
+ "default-ssl-port-only.conf/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]), True, True, ""),
+ obj.VirtualHost(
+ os.path.join(temp_dir, config_name,
+ "apache2/apache2.conf"),
+ "/files" + os.path.join(temp_dir, config_name,
+ "apache2/apache2.conf/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]), False, True,
+ "vhost.in.rootconf"),
+ obj.VirtualHost(
+ os.path.join(prefix, "duplicatehttp.conf"),
+ os.path.join(aug_pre, "duplicatehttp.conf/VirtualHost"),
+ set([obj.Addr.fromstring("10.2.3.4:80")]), False, True,
+ "duplicate.example.com"),
+ obj.VirtualHost(
+ os.path.join(prefix, "duplicatehttps.conf"),
+ os.path.join(aug_pre, "duplicatehttps.conf/IfModule/VirtualHost"),
+ set([obj.Addr.fromstring("10.2.3.4:443")]), True, True,
+ "duplicate.example.com")]
+ return vh_truth
+ if config_name == "debian_apache_2_4/multi_vhosts":
+ prefix = os.path.join(
+ temp_dir, config_name, "apache2/sites-available")
+ aug_pre = "/files" + prefix
+ vh_truth = [
+ obj.VirtualHost(
+ os.path.join(prefix, "default.conf"),
+ os.path.join(aug_pre, "default.conf/VirtualHost[1]"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "ip-172-30-0-17"),
+ obj.VirtualHost(
+ os.path.join(prefix, "default.conf"),
+ os.path.join(aug_pre, "default.conf/VirtualHost[2]"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "banana.vomit.com"),
+ obj.VirtualHost(
+ os.path.join(prefix, "multi-vhost.conf"),
+ os.path.join(aug_pre, "multi-vhost.conf/VirtualHost[1]"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "1.multi.vhost.tld"),
+ obj.VirtualHost(
+ os.path.join(prefix, "multi-vhost.conf"),
+ os.path.join(aug_pre, "multi-vhost.conf/IfModule/VirtualHost"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "2.multi.vhost.tld"),
+ obj.VirtualHost(
+ os.path.join(prefix, "multi-vhost.conf"),
+ os.path.join(aug_pre, "multi-vhost.conf/VirtualHost[2]"),
+ set([obj.Addr.fromstring("*:80")]),
+ False, True, "3.multi.vhost.tld")]
+ return vh_truth
+ return None # pragma: no cover