From edb81f38638ef000d1fbf67f847ddeb3637d6a12 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 03:05:58 +0200 Subject: [PATCH 01/34] Add wo_version variable for installation --- install | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/install b/install index 2085b53..8a2ed15 100755 --- a/install +++ b/install @@ -80,6 +80,10 @@ while [ "$#" -gt 0 ]; do -w | --wufw | --without-ufw) ufw="n" ;; + -v | --version) + wo_version="$2" + shift + ;; *) # positional args ;; esac @@ -438,8 +442,13 @@ wo_install() { { rm -f /etc/bash_completion.d/wo_auto.rc rm -rf /var/lib/wo/tmp/WordOps-* - curl -sL https://github.com/WordOps/WordOps/archive/${wo_branch}.tar.gz | tar -I pigz -xf - -C /var/lib/wo/tmp - cd /var/lib/wo/tmp/WordOps-${wo_branch} || exit 1 + if [ -z "$wo_version" ]; then + curl -sL https://github.com/WordOps/WordOps/archive/${wo_branch}.tar.gz | tar -I pigz -xf - -C /var/lib/wo/tmp + cd "/var/lib/wo/tmp/WordOps-$wo_branch" || exit 1 + else + curl -sL https://github.com/WordOps/WordOps/archive/v${wo_version}.tar.gz | tar -I pigz -xf - -C /var/lib/wo/tmp + cd "/var/lib/wo/tmp/WordOps-$wo_version" || exit 1 + fi } \ >> "$wo_install_log" 2>&1 From 3a28a419fbae3aaafe463cbb10c46296e424a7f9 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 03:51:25 +0200 Subject: [PATCH 02/34] Fix `wo site update site.tld --wpce` not installing plugin --- wo/cli/plugins/site.py | 206 ++++++++++++++----------------- wo/cli/plugins/site_functions.py | 32 +++-- 2 files changed, 116 insertions(+), 122 deletions(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index a5259f1..5df3201 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -626,84 +626,56 @@ class WOSiteCreateController(CementBaseController): "and please try again") # Setup WordPress if Wordpress site - if (data['wp'] and (not pargs.vhostonly)): - try: - wo_wp_creds = setupwordpress(self, data) - # Add database information for site into database - updateSiteInfo(self, wo_domain, - db_name=data['wo_db_name'], - db_user=data['wo_db_user'], - db_password=data['wo_db_pass'], - db_host=data['wo_db_host']) - except SiteError as e: - # call cleanup actions on failure - Log.debug(self, str(e)) - Log.info(self, Log.FAIL + - "There was a serious error encountered...") - Log.info(self, Log.FAIL + "Cleaning up afterwards...") - doCleanupAction(self, domain=wo_domain, - webroot=data['webroot'], - dbname=data['wo_db_name'], - dbuser=data['wo_db_user'], - dbhost=data['wo_mysql_grant_host']) - deleteSiteInfo(self, wo_domain) - Log.error(self, "Check the log for details: " - "`tail /var/log/wo/wordops.log` " - "and please try again") - - if (data['wp'] and (pargs.vhostonly)): - try: - wo_wp_creds = setupwordpress(self, data) - # Add database information for site into database - updateSiteInfo(self, wo_domain, db_name=data['wo_db_name'], - db_user=data['wo_db_user'], - db_password=data['wo_db_pass'], - db_host=data['wo_db_host']) - except SiteError as e: - # call cleanup actions on failure - Log.debug(self, str(e)) - Log.info(self, Log.FAIL + - "There was a serious error encountered...") - Log.info(self, Log.FAIL + "Cleaning up afterwards...") - doCleanupAction(self, domain=wo_domain, - webroot=data['webroot'], - dbname=data['wo_db_name'], - dbuser=data['wo_db_user'], - dbhost=data['wo_db_host']) - deleteSiteInfo(self, wo_domain) - Log.error(self, "Check the log for details: " - "`tail /var/log/wo/wordops.log` " - "and please try again") - try: - wodbconfig = open("{0}/wo-config.php" - .format(wo_site_webroot), - encoding='utf-8', mode='w') - wodbconfig.write("" - .format(data['wo_db_name'], - data['wo_db_user'], - data['wo_db_pass'], - data['wo_db_host'])) - wodbconfig.close() - - except IOError as e: - Log.debug(self, str(e)) - Log.debug(self, "Error occured while generating " - "wo-config.php") - Log.info(self, Log.FAIL + - "There was a serious error encountered...") - Log.info(self, Log.FAIL + "Cleaning up afterwards...") - doCleanupAction(self, domain=wo_domain, - webroot=data['webroot'], - dbname=data['wo_db_name'], - dbuser=data['wo_db_user'], - dbhost=data['wo_db_host']) - deleteSiteInfo(self, wo_domain) - Log.error(self, "Check the log for details: " - "`tail /var/log/wo/wordops.log` " - "and please try again") + if data['wp']: + if not pargs.vhostonly: + try: + wo_wp_creds = setupwordpress(self, data) + # Add database information for site into database + updateSiteInfo(self, wo_domain, + db_name=data['wo_db_name'], + db_user=data['wo_db_user'], + db_password=data['wo_db_pass'], + db_host=data['wo_db_host']) + except SiteError as e: + # call cleanup actions on failure + Log.debug(self, str(e)) + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot'], + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_mysql_grant_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + else: + try: + wo_wp_creds = setupwordpress( + self, data, vhostonly=True) + # Add database information for site into database + updateSiteInfo(self, wo_domain, + db_name=data['wo_db_name'], + db_user=data['wo_db_user'], + db_password=data['wo_db_pass'], + db_host=data['wo_db_host']) + except SiteError as e: + # call cleanup actions on failure + Log.debug(self, str(e)) + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot'], + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_mysql_grant_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") # Service Nginx Reload call cleanup if failed to reload nginx if not WOService.reload_service(self, 'nginx'): @@ -1557,7 +1529,8 @@ class WOSiteUpdateController(CementBaseController): "and please try again") return 1 - if ((oldcachetype in ['wpsc', 'basic', 'wpredis', 'wprocket', 'wpce'] and + if ((oldcachetype in ['wpsc', 'basic', 'wpredis', 'wprocket', + 'wpce'] and (data['wpfc'])) or (oldsitetype == 'wp' and data['multisite'] and data['wpfc'])): try: @@ -1584,9 +1557,9 @@ class WOSiteUpdateController(CementBaseController): "redis_port": "6379", "redis_prefix": "nginx-cache:"} plugin_data = json.dumps(plugin_data_object) - setupwp_plugin( - self, 'nginx-helper', - 'rt_wp_nginx_helper_options', plugin_data, data) + setupwp_plugin(self, 'nginx-helper', + 'rt_wp_nginx_helper_options', + plugin_data, data) except SiteError as e: Log.debug(self, str(e)) Log.info(self, Log.FAIL + "Update nginx-helper " @@ -1596,7 +1569,8 @@ class WOSiteUpdateController(CementBaseController): "and please try again") return 1 - elif ((oldcachetype in ['wpsc', 'basic', 'wpfc', 'wprocket', 'wpce'] and + elif ((oldcachetype in ['wpsc', 'basic', 'wpfc', + 'wprocket', 'wpce'] and (data['wpredis'])) or (oldsitetype == 'wp' and data['multisite'] and data['wpredis'])): @@ -1624,9 +1598,9 @@ class WOSiteUpdateController(CementBaseController): "redis_port": "6379", "redis_prefix": "nginx-cache:"} plugin_data = json.dumps(plugin_data_object) - setupwp_plugin( - self, 'nginx-helper', - 'rt_wp_nginx_helper_options', plugin_data, data) + setupwp_plugin(self, 'nginx-helper', + 'rt_wp_nginx_helper_options', + plugin_data, data) except SiteError as e: Log.debug(self, str(e)) Log.info(self, Log.FAIL + "Update nginx-helper " @@ -1635,37 +1609,9 @@ class WOSiteUpdateController(CementBaseController): " `tail /var/log/wo/wordops.log` " "and please try again") return 1 - - elif ((oldcachetype in ['wpsc', 'basic', 'wpfc', 'wprocket', 'wpredis'] and - (data['wpce'])) or (oldsitetype == 'wp' and - data['multisite'] and - data['wpce'])): - try: - plugin_data_object = {"expires": 24, - "new_post": 1, - "new_comment": 0, - "webp": 0, - "clear_on_upgrade": 1, - "compress": 0, - "excl_ids": "", - "excl_regexp": "", - "excl_cookies": "", - "incl_attributes": "", - "minify_html": 1} - plugin_data = json.dumps(plugin_data_object) - setupwp_plugin( - self, 'cache-enabler', - 'cache-enabler', plugin_data, data) - except SiteError as e: - Log.debug(self, str(e)) - Log.info(self, Log.FAIL + "Update cache-enabler " - "settings failed. " - "Check the log for details:" - " `tail /var/log/wo/wordops.log` " - "and please try again") - return 1 else: try: + # disable nginx-helper plugin_data_object = {"log_level": "INFO", "log_filesize": 5, "enable_purge": 0, @@ -1701,6 +1647,36 @@ class WOSiteUpdateController(CementBaseController): "and please try again") return 1 + if ((oldcachetype in ['wpsc', 'basic', 'wpfc', 'wprocket', 'wpredis'] and + (data['wpce'])) or (oldsitetype == 'wp' and + data['multisite'] and + data['wpce'])): + try: + installwp_plugin(self, 'cache-enabler', data) + # setup cache-enabler + plugin_data_object = {"expires": 24, + "new_post": 1, + "new_comment": 0, + "webp": 0, + "clear_on_upgrade": 1, + "compress": 0, + "excl_ids": "", + "excl_regexp": "", + "excl_cookies": "", + "incl_attributes": "", + "minify_html": 1} + plugin_data = json.dumps(plugin_data_object) + setupwp_plugin(self, 'cache-enabler', + 'cache-enabler', plugin_data, data) + except SiteError as e: + Log.debug(self, str(e)) + Log.info(self, Log.FAIL + "Update cache-enabler " + "settings failed. " + "Check the log for details:" + " `tail /var/log/wo/wordops.log` " + "and please try again") + return 1 + if oldcachetype == 'wpsc' and not data['wpsc']: try: uninstallwp_plugin(self, 'wp-super-cache', data) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index c0b9b17..0c333dd 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -229,7 +229,7 @@ def setupdatabase(self, data): return(data) -def setupwordpress(self, data): +def setupwordpress(self, data, vhostonly=False): wo_domain_name = data['site_name'] wo_site_webroot = data['webroot'] prompt_wpprefix = self.app.config.get('wordpress', 'prefix') @@ -531,13 +531,13 @@ def setupwordpress(self, data): "enable_purge": 1, "enable_map": "0", "enable_log": 0, - "enable_stamp": 0, + "enable_stamp": 1, "purge_homepage_on_new": 1, "purge_homepage_on_edit": 1, "purge_homepage_on_del": 1, "purge_archive_on_new": 1, - "purge_archive_on_edit": 0, - "purge_archive_on_del": 0, + "purge_archive_on_edit": 1, + "purge_archive_on_del": 1, "purge_archive_on_new_comment": 0, "purge_archive_on_deleted_comment": 0, "purge_page_on_mod": 1, @@ -557,13 +557,13 @@ def setupwordpress(self, data): "enable_purge": 1, "enable_map": "0", "enable_log": 0, - "enable_stamp": 0, + "enable_stamp": 1, "purge_homepage_on_new": 1, "purge_homepage_on_edit": 1, "purge_homepage_on_del": 1, "purge_archive_on_new": 1, - "purge_archive_on_edit": 0, - "purge_archive_on_del": 0, + "purge_archive_on_edit": 1, + "purge_archive_on_del": 1, "purge_archive_on_new_comment": 0, "purge_archive_on_deleted_comment": 0, "purge_page_on_mod": 1, @@ -588,6 +588,7 @@ def setupwordpress(self, data): """Install Cache-Enabler""" if data['wpce']: + installwp_plugin(self, 'cache-enabler', data) plugin_data_object = {"expires": 24, "new_post": 1, "new_comment": 0, @@ -603,6 +604,13 @@ def setupwordpress(self, data): setupwp_plugin(self, 'cache-enabler', 'cache-enabler', plugin_data, data) + if vhostonly: + try: + WOShellExec.cmd_exec(self, "/bin/bash -c \"{0} --allow-root " + .format(WOVariables.wo_wpcli_path) + + "db clean --yes\"") + WOFileUtils.rm(self, "{0}/htdocs/*".format(wo_site_webroot)) + wp_creds = dict(wp_user=wo_wp_user, wp_pass=wo_wp_pass, wp_email=wo_wp_email) @@ -988,6 +996,16 @@ def display_cache_settings(self, data): "\thttp://{0}/wp-admin/options-general.php?" "page=nginx".format(data['site_name'])) + if data['wpce']: + if data['multisite']: + Log.info(self, "Nginx-Helper configuration :" + "\thttp://{0}/wp-admin/network/settings.php?" + "page=cache-enabler".format(data['site_name'])) + else: + Log.info(self, "Nginx-Helper configuration :" + "\thttp://{0}/wp-admin/options-general.php?" + "page=cache-enabler".format(data['site_name'])) + def logwatch(self, logfiles): import zlib From 743aec2caa4f3ecc13be6435cd82ce5793a12a8e Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 03:54:25 +0200 Subject: [PATCH 03/34] Fix missing except --- setup.py | 2 +- wo/cli/plugins/site_functions.py | 2 ++ wo/core/variables.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index ff19262..5f3cbd1 100644 --- a/setup.py +++ b/setup.py @@ -57,7 +57,7 @@ if not os.path.isfile('/root/.gitconfig'): shutil.copy2(os.path.expanduser("~")+'/.gitconfig', '/root/.gitconfig') setup(name='wo', - version='3.9.8.5', + version='3.9.8.6', description=long_description, long_description=long_description, classifiers=[], diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 0c333dd..219dd81 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -610,6 +610,8 @@ def setupwordpress(self, data, vhostonly=False): .format(WOVariables.wo_wpcli_path) + "db clean --yes\"") WOFileUtils.rm(self, "{0}/htdocs/*".format(wo_site_webroot)) + except CommandExecutionError: + raise SiteError("Cleaning WordPress install failed") wp_creds = dict(wp_user=wo_wp_user, wp_pass=wo_wp_pass, wp_email=wo_wp_email) diff --git a/wo/core/variables.py b/wo/core/variables.py index 61a06eb..6fb7f9f 100644 --- a/wo/core/variables.py +++ b/wo/core/variables.py @@ -10,7 +10,7 @@ class WOVariables(): """Intialization of core variables""" # WordOps version - wo_version = "3.9.8.5" + wo_version = "3.9.8.6" # WordOps packages versions wo_wp_cli = "2.2.0" wo_adminer = "4.7.2" From 51b698988e02a99508f62f404c82064504226c70 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 04:27:54 +0200 Subject: [PATCH 04/34] Parse acme.sh csv cert list to detect if a wildcard is available --- CHANGELOG.md | 8 ++++++++ wo/cli/plugins/site.py | 4 ++-- wo/cli/plugins/site_functions.py | 33 ++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bda29eb..60fc841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### v3.9.x - [Unreleased] +#### Changed + +- Date format in backup name : /backup/30Aug2019035932 -> /backup/30Aug2019-03-59-32 + +#### Fixed + +- cache-enabler plugin not installed and configured with `wo site update site.tld --wpce` + ### v3.9.8.5 - 2019-08-30 #### Changed diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 5df3201..fd991f3 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -1539,7 +1539,7 @@ class WOSiteUpdateController(CementBaseController): "enable_purge": 1, "enable_map": "0", "enable_log": 0, - "enable_stamp": 0, + "enable_stamp": 1, "purge_homepage_on_new": 1, "purge_homepage_on_edit": 1, "purge_homepage_on_del": 1, @@ -1580,7 +1580,7 @@ class WOSiteUpdateController(CementBaseController): "enable_purge": 1, "enable_map": "0", "enable_log": 0, - "enable_stamp": 0, + "enable_stamp": 1, "purge_homepage_on_new": 1, "purge_homepage_on_edit": 1, "purge_homepage_on_del": 1, diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 219dd81..095479d 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -6,6 +6,7 @@ import json import re import string import subprocess +import csv from subprocess import CalledProcessError from wo.cli.plugins.sitedb import getSiteInfo @@ -1455,6 +1456,38 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False, "you are running Let\'s Encrypt Client " "\n to allow it to verify the site automatically.") +# check if a wildcard exist to secure a new subdomain + + +def checkWildcardExist(self, wo_domain_name): + + wo_acme_exec = ("/etc/letsencrypt/acme.sh --config-home " + "'/etc/letsencrypt/config'") + try: + # export certificates list from acme.sh + WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) + + "--list --list-raw > /var/lib/wo/cert.csv") + except CommandExecutionError as e: + Log.debug(self, "{0}".format(e)) + Log.error(self, "Failed to export cert list") + + # define new csv dialect + csv.register_dialect('acmeconf', delimiter='|') + # open file + with open('/var/lib/wo/cert.csv', 'rt') as wo_cert: + reader = csv.reader(wo_cert, 'acmeconf') + wo_wildcard = "*.{0}".format(wo_domain_name) + try: + for row in reader: + if wo_wildcard in row[2]: + break + return True + else: + return False + except csv.Error as e: + Log.debug(self, "{0}".format(e)) + Log.error(self, "Failed to read cert list") + # letsencrypt cert renewal From 79469e90ad3d8b6bea135b1b6158c106975bd44f Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 06:08:54 +0200 Subject: [PATCH 05/34] Copy the certificate from wildcard if available --- wo/cli/plugins/site.py | 16 +++++++++++++--- wo/cli/plugins/site_functions.py | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index fd991f3..92dffc8 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -760,9 +760,19 @@ class WOSiteCreateController(CementBaseController): if ((wo_domain_type == 'subdomain') and (not pargs.letsencrypt == 'wildcard')): wo_subdomain = True - - setupLetsEncrypt(self, wo_domain, wo_subdomain, wo_wildcard, - wo_dns, wo_acme_dns) + # check if a wildcard cert for the root domain exist + if wo_subdomain is True: + wo_exist_wildcard = checkWildcardExist(self, + wo_root_domain) + # copy the cert from the root domain + if wo_exist_wildcard is True: + copyWildcardCert(self, wo_domain, wo_root_domain) + else: + setupLetsEncrypt(self, wo_domain, wo_subdomain, + wo_wildcard, wo_dns, wo_acme_dns) + else: + setupLetsEncrypt(self, wo_domain, wo_subdomain, + wo_wildcard, wo_dns, wo_acme_dns) httpsRedirect(self, wo_domain, True, wo_wildcard) if pargs.hsts: diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 095479d..9483b6e 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1488,6 +1488,27 @@ def checkWildcardExist(self, wo_domain_name): Log.debug(self, "{0}".format(e)) Log.error(self, "Failed to read cert list") +# copy wildcard certificate to a subdomain + + +def copyWildcardCert(self, wo_domain_name, wo_root_domain): + + if os.path.isfile("/var/www/{0}/conf/nginx/ssl.conf" + .format(wo_root_domain)): + try: + WOFileUtils.copyfile(self, "/var/www/{0}/conf/nginx/ssl.conf" + .format(wo_root_domain), + "/var/www/{0}/conf/nginx/ssl.conf" + .format(wo_domain_name)) + cert_link = open('/var/lib/wo/linked.csv', encoding='utf-8', + mode='a') + cert_link.write('{0}|{1}\n'.format(wo_root_domain, + wo_domain_name)) + cert_link.close() + except IOError as e: + Log.debug(self, str(e)) + Log.debug(self, "Error occured while copying ssl cert") + # letsencrypt cert renewal From a68b85e0bae3591e5c5d4193b193ac0311bc2ade Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 07:24:08 +0200 Subject: [PATCH 06/34] Use symlinks instead of copying file --- wo/cli/plugins/site_functions.py | 49 ++++++++++++++++++-------------- wo/core/fileutils.py | 30 +++++++++++++++++++ 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 9483b6e..a0be834 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1235,6 +1235,10 @@ def removeNginxConf(self, domain): def removeAcmeConf(self, domain): + sslconf = ("/var/www/{0}/conf/nginx/ssl.conf" + .format(domain)) + sslforce = ("/etc/nginx/conf.d/force-ssl-{0}.conf" + .format(domain)) if os.path.isdir('/etc/letsencrypt/renewal/{0}_ecc' .format(domain)): Log.info(self, "Removing Acme configuration") @@ -1250,18 +1254,23 @@ def removeAcmeConf(self, domain): Log.debug(self, "{0}".format(e)) Log.error(self, "Cert removal failed") - WOFileUtils.rm(self, '/etc/letsencrypt/renewal/{0}_ecc' - .format(domain)) - WOFileUtils.rm(self, '/etc/letsencrypt/live/{0}' - .format(domain)) - WOFileUtils.rm(self, '/var/www/{0}/conf/nginx/ssl.conf' - .format(domain)) - WOFileUtils.rm(self, '/var/www/{0}/conf/nginx/ssl.conf.disabled' - .format(domain)) - WOFileUtils.rm(self, '/etc/nginx/conf.d/force-ssl-{0}.conf' - .format(domain)) - WOFileUtils.rm(self, '/etc/nginx/conf.d/force-ssl-{0}.conf.disabled' - .format(domain)) + WOFileUtils.rm(self, '{0}/{1}_ecc' + .format(WOVariables.wo_ssl_archive, domain)) + WOFileUtils.rm(self, '{0}/{1}' + .format(WOVariables.wo_ssl_live, domain)) + WOFileUtils.rm(self, '{0}'.format(sslconf)) + WOFileUtils.rm(self, '{0}.disabled'.format(sslconf)) + WOFileUtils.rm(self, '{0}'.format(sslforce)) + WOFileUtils.rm(self, '{0}.disabled' + .format(sslforce)) + + # find all broken symlinks + symlinks = WOFileUtils.findBrokenSymlink(self, "/var/www") + for symlink in symlinks: + if os.path.islink('{0}'.format(sslconf)): + # remove broken symlinks + WOFileUtils.remove_symlink(self, symlink) + if WOFileUtils.grepcheck(self, '/var/www/22222/conf/nginx/ssl.conf', '{0}'.format(domain)): Log.info(self, "Setting back default certificate for WordOps backend") @@ -1496,18 +1505,14 @@ def copyWildcardCert(self, wo_domain_name, wo_root_domain): if os.path.isfile("/var/www/{0}/conf/nginx/ssl.conf" .format(wo_root_domain)): try: - WOFileUtils.copyfile(self, "/var/www/{0}/conf/nginx/ssl.conf" - .format(wo_root_domain), - "/var/www/{0}/conf/nginx/ssl.conf" - .format(wo_domain_name)) - cert_link = open('/var/lib/wo/linked.csv', encoding='utf-8', - mode='a') - cert_link.write('{0}|{1}\n'.format(wo_root_domain, - wo_domain_name)) - cert_link.close() + WOFileUtils.create_symlink(self, "/var/www/{0}/conf/nginx/ssl.conf" + .format(wo_root_domain), + "/var/www/{0}/conf/nginx/ssl.conf" + .format(wo_domain_name)) except IOError as e: Log.debug(self, str(e)) - Log.debug(self, "Error occured while copying ssl cert") + Log.debug(self, "Error occured while " + "creating symlink for ssl cert") # letsencrypt cert renewal diff --git a/wo/core/fileutils.py b/wo/core/fileutils.py index 85654e2..7450b61 100644 --- a/wo/core/fileutils.py +++ b/wo/core/fileutils.py @@ -279,3 +279,33 @@ class WOFileUtils(): Log.debug(self, "{0}".format(e)) Log.error(self, "Unable to remove file : {0} " .format(path)) + + def findBrokenSymlink(self, sympath): + """ + Find symlinks + """ + links = [] + broken = [] + + for root, dirs, files in os.walk(sympath): + if root.startswith('./.git'): + # Ignore the .git directory. + continue + for filename in files: + path = os.path.join(root, filename) + if os.path.islink(path): + target_path = os.readlink(path) + # Resolve relative symlinks + if not os.path.isabs(target_path): + target_path = os.path.join(os.path.dirname(path), + target_path) + if not os.path.exists(target_path): + links.append(path) + broken.append(path) + else: + links.append(path) + else: + # If it's not a symlink we're not interested. + continue + + return broken From 8b2395d0f9587b83be24e72c732cf2107af137d2 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 07:30:42 +0200 Subject: [PATCH 07/34] Add quote for acme.sh --- wo/cli/plugins/site_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index a0be834..41c2c0b 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1369,7 +1369,7 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False, self, "Validation : DNS mode with {0}".format(wo_acme_dns)) else: acme_mode = "-w /var/www/html" - validation_mode = "Webroot challenge" + validation_mode = "Subdomain Webroot challenge" Log.debug(self, "Validation : Webroot mode") if subdomain: Log.info(self, "Issuing subdomain SSL cert with acme.sh") @@ -1386,7 +1386,7 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False, Log.info(self, "Validation mode : {0}".format(validation_mode)) ssl = WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) + "--issue " - "-d {0} -d *.{0} --dns {1} " + "-d {0} -d '*.{0}' --dns {1} " "-k {2} -f" .format(wo_domain_name, wo_acme_dns, From 2ba68a4db9d23bb45d38955f5dca5727c367675b Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 07:34:48 +0200 Subject: [PATCH 08/34] Fix typo --- CHANGELOG.md | 1 + wo/cli/plugins/site_functions.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60fc841..5f0eb19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), #### Fixed - cache-enabler plugin not installed and configured with `wo site update site.tld --wpce` +- possible issue with domain variable in `--letsencrypt=wildcard` ### v3.9.8.5 - 2019-08-30 diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 41c2c0b..99adab5 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1475,7 +1475,7 @@ def checkWildcardExist(self, wo_domain_name): try: # export certificates list from acme.sh WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) + - "--list --list-raw > /var/lib/wo/cert.csv") + "--list --listraw > /var/lib/wo/cert.csv") except CommandExecutionError as e: Log.debug(self, "{0}".format(e)) Log.error(self, "Failed to export cert list") From d8c391ff54582b7e69015b4dfe697e0f6ed2111c Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 07:43:58 +0200 Subject: [PATCH 09/34] Fix acme.sh output --- wo/cli/plugins/site_functions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 99adab5..3a7fa1b 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1475,7 +1475,8 @@ def checkWildcardExist(self, wo_domain_name): try: # export certificates list from acme.sh WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) + - "--list --listraw > /var/lib/wo/cert.csv") + "--list --listraw > /var/lib/wo/cert.csv;" + " echo 'OK'") except CommandExecutionError as e: Log.debug(self, "{0}".format(e)) Log.error(self, "Failed to export cert list") From 4e95fd9fba8dad066cf7399b3cee6c9b2fa3a224 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 07:46:53 +0200 Subject: [PATCH 10/34] Fix acme.sh listing --- wo/cli/plugins/site_functions.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 3a7fa1b..1aac6c5 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1472,14 +1472,9 @@ def checkWildcardExist(self, wo_domain_name): wo_acme_exec = ("/etc/letsencrypt/acme.sh --config-home " "'/etc/letsencrypt/config'") - try: - # export certificates list from acme.sh - WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) + - "--list --listraw > /var/lib/wo/cert.csv;" - " echo 'OK'") - except CommandExecutionError as e: - Log.debug(self, "{0}".format(e)) - Log.error(self, "Failed to export cert list") + # export certificates list from acme.sh + WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) + + "--list --listraw > /var/lib/wo/cert.csv") # define new csv dialect csv.register_dialect('acmeconf', delimiter='|') @@ -1497,6 +1492,8 @@ def checkWildcardExist(self, wo_domain_name): except csv.Error as e: Log.debug(self, "{0}".format(e)) Log.error(self, "Failed to read cert list") + finally: + wo_cert.close() # copy wildcard certificate to a subdomain From bb418c23fc9e490fc7ca9ddfd0e477bd07769a8d Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 07:50:35 +0200 Subject: [PATCH 11/34] Fix csv reading --- wo/cli/plugins/site_functions.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 1aac6c5..389616d 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1482,18 +1482,17 @@ def checkWildcardExist(self, wo_domain_name): with open('/var/lib/wo/cert.csv', 'rt') as wo_cert: reader = csv.reader(wo_cert, 'acmeconf') wo_wildcard = "*.{0}".format(wo_domain_name) - try: - for row in reader: - if wo_wildcard in row[2]: - break - return True - else: - return False - except csv.Error as e: - Log.debug(self, "{0}".format(e)) - Log.error(self, "Failed to read cert list") - finally: - wo_cert.close() + try: + for row in reader: + if wo_wildcard in row[2]: + break + return True + else: + return False + except csv.Error as e: + Log.debug(self, "{0}".format(e)) + Log.error(self, "Failed to read cert list") + # copy wildcard certificate to a subdomain From 2d1c17648e4751e07ba5dfe94ceaf8ee9b6547bd Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 07:53:49 +0200 Subject: [PATCH 12/34] Set return true properly --- wo/cli/plugins/site_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 389616d..8da23e0 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1485,8 +1485,8 @@ def checkWildcardExist(self, wo_domain_name): try: for row in reader: if wo_wildcard in row[2]: - break return True + break else: return False except csv.Error as e: From 6c70ba782457da77c3c52bcc3cfce23b0ed08e6e Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 07:58:00 +0200 Subject: [PATCH 13/34] simplify cert --- wo/cli/plugins/site.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 92dffc8..5b03141 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -424,7 +424,7 @@ class WOSiteCreateController(CementBaseController): pargs.site_name = pargs.site_name.strip() (wo_domain, wo_www_domain) = ValidateDomain(pargs.site_name) - wo_domain_type, wo_root_domain = GetDomainlevel(wo_domain) + (wo_domain_type, wo_root_domain) = GetDomainlevel(wo_domain) if not wo_domain.strip(): Log.error("Invalid domain name, " "Provide valid domain name") @@ -760,12 +760,9 @@ class WOSiteCreateController(CementBaseController): if ((wo_domain_type == 'subdomain') and (not pargs.letsencrypt == 'wildcard')): wo_subdomain = True - # check if a wildcard cert for the root domain exist - if wo_subdomain is True: - wo_exist_wildcard = checkWildcardExist(self, - wo_root_domain) - # copy the cert from the root domain - if wo_exist_wildcard is True: + # check if a wildcard cert for the root domain exist + if checkWildcardExist(self, wo_root_domain): + # copy the cert from the root domain copyWildcardCert(self, wo_domain, wo_root_domain) else: setupLetsEncrypt(self, wo_domain, wo_subdomain, From ebea1e5e7df6b8355cec2b84a5d4c424bf14ec18 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 07:59:44 +0200 Subject: [PATCH 14/34] Small adjustement for variable --- wo/cli/plugins/site_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 8da23e0..91eff6e 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1481,10 +1481,10 @@ def checkWildcardExist(self, wo_domain_name): # open file with open('/var/lib/wo/cert.csv', 'rt') as wo_cert: reader = csv.reader(wo_cert, 'acmeconf') - wo_wildcard = "*.{0}".format(wo_domain_name) + wo_wildcard_domain = ("*.{0}".format(wo_domain_name)) try: for row in reader: - if wo_wildcard in row[2]: + if wo_wildcard_domain in row[2]: return True break else: From 01c1c3909c9aaaa14ca9a490764bbf9e0445751b Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:09:27 +0200 Subject: [PATCH 15/34] Refactor function --- wo/cli/plugins/site.py | 3 ++- wo/cli/plugins/site_functions.py | 25 ++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 5b03141..6099ce2 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -761,7 +761,8 @@ class WOSiteCreateController(CementBaseController): (not pargs.letsencrypt == 'wildcard')): wo_subdomain = True # check if a wildcard cert for the root domain exist - if checkWildcardExist(self, wo_root_domain): + isWildcard = checkWildcardExist(self, wo_root_domain) + if isWildcard is True: # copy the cert from the root domain copyWildcardCert(self, wo_domain, wo_root_domain) else: diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 91eff6e..f2abb29 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1479,19 +1479,18 @@ def checkWildcardExist(self, wo_domain_name): # define new csv dialect csv.register_dialect('acmeconf', delimiter='|') # open file - with open('/var/lib/wo/cert.csv', 'rt') as wo_cert: - reader = csv.reader(wo_cert, 'acmeconf') - wo_wildcard_domain = ("*.{0}".format(wo_domain_name)) - try: - for row in reader: - if wo_wildcard_domain in row[2]: - return True - break - else: - return False - except csv.Error as e: - Log.debug(self, "{0}".format(e)) - Log.error(self, "Failed to read cert list") + certfile = open('/var/lib/wo/cert.csv', 'rt') + reader = csv.reader(certfile, 'acmeconf') + wo_wildcard_domain = ("*.{0}".format(wo_domain_name)) + for row in reader: + if wo_wildcard_domain in row[2]: + isWildcard = True + break + else: + isWildcard = False + certfile.close() + + return isWildcard # copy wildcard certificate to a subdomain From 10b29e3ad558f26bd16c8eef6cf7bf3a0b87926d Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:17:18 +0200 Subject: [PATCH 16/34] Add debug.log --- wo/cli/plugins/site.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 6099ce2..09c2c04 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -757,15 +757,25 @@ class WOSiteCreateController(CementBaseController): else: wo_wildcard = False wo_subdomain = False + Log.debug(self, "Domain type = {0}" + .format(wo_domain_type)) if ((wo_domain_type == 'subdomain') and (not pargs.letsencrypt == 'wildcard')): wo_subdomain = True # check if a wildcard cert for the root domain exist + Log.debug(self, "checkWildcardExist on *.{0}" + .format(wo_root_domain)) isWildcard = checkWildcardExist(self, wo_root_domain) - if isWildcard is True: + Log.debug(self, "isWildcard = {0}".format(isWildcard)) + if isWildcard: + Log.debug(self, "symlink wildcard " + "cert between {0} & {1}" + .format(wo_domain, wo_root_domain)) # copy the cert from the root domain copyWildcardCert(self, wo_domain, wo_root_domain) else: + Log.debug(self, "Setup Cert with acme.sh for {0}" + .format(wo_domain)) setupLetsEncrypt(self, wo_domain, wo_subdomain, wo_wildcard, wo_dns, wo_acme_dns) else: From 0e67eeba43cc12db40a4a7aace12614520a834f7 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:19:35 +0200 Subject: [PATCH 17/34] Fix root domain --- wo/core/domainvalidate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wo/core/domainvalidate.py b/wo/core/domainvalidate.py index 9008f82..574f6bc 100644 --- a/wo/core/domainvalidate.py +++ b/wo/core/domainvalidate.py @@ -40,11 +40,11 @@ def GetDomainlevel(domain): for domain_suffix in Suffix_file: if (str(domain_suffix).strip()) == ('.'.join(domain_name[1:])): domain_type = 'domain' - root_domain = domain_name[0:] + root_domain = ('.'.join(domain_name[0:])) break elif (str(domain_suffix).strip()) == ('.'.join(domain_name[2:])): domain_type = 'subdomain' - root_domain = domain_name[1:] + root_domain = ('.'.join(domain_name[1:])) break else: domain_type = 'other' From 257ead3230c43761268200c23d5163713a013a72 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:24:02 +0200 Subject: [PATCH 18/34] Fix symlink creation --- wo/cli/plugins/site_functions.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index f2abb29..948a6e1 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1501,10 +1501,12 @@ def copyWildcardCert(self, wo_domain_name, wo_root_domain): if os.path.isfile("/var/www/{0}/conf/nginx/ssl.conf" .format(wo_root_domain)): try: - WOFileUtils.create_symlink(self, "/var/www/{0}/conf/nginx/ssl.conf" - .format(wo_root_domain), - "/var/www/{0}/conf/nginx/ssl.conf" - .format(wo_domain_name)) + WOFileUtils.create_symlink(self, ["/var/www/{0}/conf/nginx/" + "ssl.conf" + .format(wo_root_domain), + '/var/www/{0}/conf/nginx/' + 'ssl.conf' + .format(wo_domain_name)]) except IOError as e: Log.debug(self, str(e)) Log.debug(self, "Error occured while " From e8d0517dc0366f66b74682bcce2a0a561e3bffe1 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:28:10 +0200 Subject: [PATCH 19/34] Add wildcard detection to wo site update --- wo/cli/plugins/site.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 09c2c04..a2f2f6f 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -1372,9 +1372,27 @@ class WOSiteUpdateController(CementBaseController): wo_acme_dns = '' wo_dns = False if not os.path.isfile("{0}/conf/nginx/ssl.conf.disabled"): - setupLetsEncrypt(self, wo_domain, wo_subdomain, - wo_wildcard, - wo_dns, wo_acme_dns) + if wo_subdomain: + # check if a wildcard cert for the root domain exist + Log.debug(self, "checkWildcardExist on *.{0}" + .format(wo_root_domain)) + isWildcard = checkWildcardExist(self, wo_root_domain) + Log.debug(self, "isWildcard = {0}".format(isWildcard)) + if isWildcard: + Log.debug(self, "symlink wildcard " + "cert between {0} & {1}" + .format(wo_domain, wo_root_domain)) + # copy the cert from the root domain + copyWildcardCert(self, wo_domain, wo_root_domain) + else: + Log.debug(self, "Setup Cert with acme.sh for {0}" + .format(wo_domain)) + setupLetsEncrypt(self, wo_domain, wo_subdomain, + wo_wildcard, wo_dns, wo_acme_dns) + else: + setupLetsEncrypt(self, wo_domain, wo_subdomain, + wo_wildcard, wo_dns, wo_acme_dns) + httpsRedirect(self, wo_domain, True, wo_wildcard) site_url_https(self, wo_domain) else: From d3ba3ae9fcb829b1c26f5ccac96a1258b61ba2af Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:31:33 +0200 Subject: [PATCH 20/34] Add Log.info --- wo/cli/plugins/site.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index a2f2f6f..5a91221 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -1376,9 +1376,14 @@ class WOSiteUpdateController(CementBaseController): # check if a wildcard cert for the root domain exist Log.debug(self, "checkWildcardExist on *.{0}" .format(wo_root_domain)) + Log.info(self, "Checking if there is a wildcard " + "certificate available from the root domain") isWildcard = checkWildcardExist(self, wo_root_domain) Log.debug(self, "isWildcard = {0}".format(isWildcard)) if isWildcard: + Log.info(self, "Using existing Wildcard SSL" + "certificate from {0} to secure {1}" + .format(wo_root_domain, wo_domain)) Log.debug(self, "symlink wildcard " "cert between {0} & {1}" .format(wo_domain, wo_root_domain)) From 8e9af7c3123a1dcd7cad48e68281394529adc5d8 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:35:06 +0200 Subject: [PATCH 21/34] Fix SSL check on wildcard --- wo/cli/plugins/site.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 5a91221..3226d56 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -1420,15 +1420,24 @@ class WOSiteUpdateController(CementBaseController): Log.info(self, "Congratulations! Successfully " "Configured SSl for Site " " https://{0}".format(wo_domain)) - - if (SSL.getExpirationDays(self, wo_domain) > 0): - Log.info(self, "Your cert will expire within " + - str(SSL.getExpirationDays(self, wo_domain)) + - " days.") + if wo_subdomain: + if (SSL.getExpirationDays(self, wo_root_domain) > 0): + Log.info(self, "Your cert will expire within " + + str(SSL.getExpirationDays(self, wo_domain)) + + " days.") + else: + Log.warn( + self, "Your cert already EXPIRED ! " + ".PLEASE renew soon . ") else: - Log.warn( - self, "Your cert already EXPIRED ! " - ".PLEASE renew soon . ") + if (SSL.getExpirationDays(self, wo_domain) > 0): + Log.info(self, "Your cert will expire within " + + str(SSL.getExpirationDays(self, wo_domain)) + + " days.") + else: + Log.warn( + self, "Your cert already EXPIRED ! " + ".PLEASE renew soon . ") elif data['letsencrypt'] is False: if pargs.letsencrypt == "off": From eabfa5a7ff68f28d186abc0ead5bf3f89b4ce1b0 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:40:35 +0200 Subject: [PATCH 22/34] Add config removal --- wo/cli/plugins/site.py | 7 ++++++- wo/cli/plugins/site_functions.py | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 3226d56..112a009 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -1441,8 +1441,13 @@ class WOSiteUpdateController(CementBaseController): elif data['letsencrypt'] is False: if pargs.letsencrypt == "off": - if os.path.isfile("{0}/conf/nginx/ssl.conf" + if os.path.islink("{0}/conf/nginx/ssl.conf" .format(wo_site_webroot)): + WOFileUtils.remove_symlink(self, + "{0}/conf/nginx/ssl.conf" + .format(wo_site_webroot)) + elif os.path.isfile("{0}/conf/nginx/ssl.conf" + .format(wo_site_webroot)): Log.info(self, 'Setting Nginx configuration') WOFileUtils.mvfile(self, "{0}/conf/nginx/ssl.conf" .format(wo_site_webroot), diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 948a6e1..ca8269e 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1270,6 +1270,10 @@ def removeAcmeConf(self, domain): if os.path.islink('{0}'.format(sslconf)): # remove broken symlinks WOFileUtils.remove_symlink(self, symlink) + else: + if os.path.islink("{0}".format(sslconf)): + WOFileUtils.remove_symlink(self, "{0}".format(sslconf)) + WOFileUtils.rm(self, '{0}'.format(sslforce)) if WOFileUtils.grepcheck(self, '/var/www/22222/conf/nginx/ssl.conf', '{0}'.format(domain)): From 56bc72489a2cd53b3ded074f92831ea9e9d99559 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:42:56 +0200 Subject: [PATCH 23/34] Fix wrong variable --- wo/cli/plugins/site.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 112a009..06c614b 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -1423,7 +1423,7 @@ class WOSiteUpdateController(CementBaseController): if wo_subdomain: if (SSL.getExpirationDays(self, wo_root_domain) > 0): Log.info(self, "Your cert will expire within " + - str(SSL.getExpirationDays(self, wo_domain)) + + str(SSL.getExpirationDays(self, wo_root_domain)) + " days.") else: Log.warn( From 7f0463602d2a09cc03050ca37544ba395a5f07b1 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:51:43 +0200 Subject: [PATCH 24/34] Fix wo site info --- wo/cli/plugins/site.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 06c614b..129f6e4 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -137,7 +137,7 @@ class WOSiteController(CementBaseController): Log.error(self, 'could not input site name') pargs.site_name = pargs.site_name.strip() (wo_domain, wo_www_domain) = ValidateDomain(pargs.site_name) - wo_domain_type, wo_root_domain = GetDomainlevel(wo_domain) + (wo_domain_type, wo_root_domain) = GetDomainlevel(wo_domain) wo_db_name = '' wo_db_user = '' wo_db_pass = '' @@ -162,7 +162,12 @@ class WOSiteController(CementBaseController): ssl = ("enabled" if siteinfo.is_ssl else "disabled") if (ssl == "enabled"): sslprovider = "Lets Encrypt" - sslexpiry = str(SSL.getExpirationDate(self, wo_domain)) + if os.path.islink("{0}/conf/nginx/ssl.conf" + .format(wo_site_webroot)): + sslexpiry = str( + SSL.getExpirationDate(self, wo_root_domain)) + else: + sslexpiry = str(SSL.getExpirationDate(self, wo_domain)) else: sslprovider = '' sslexpiry = '' @@ -1271,14 +1276,15 @@ class WOSiteUpdateController(CementBaseController): wo_subdomain = False wo_wildcard = False - if letsencrypt is check_ssl: - if letsencrypt is False: - Log.error(self, "SSl is not configured for given " - "site") - elif letsencrypt is True: - Log.error(self, "SSl is already configured for given " - "site") - pargs.letsencrypt = False + if not wo_subdomain: + if letsencrypt is check_ssl: + if letsencrypt is False: + Log.error(self, "SSl is not configured for given " + "site") + elif letsencrypt is True: + Log.error(self, "SSl is already configured for given " + "site") + pargs.letsencrypt = False if data and (not pargs.php73): if old_php73 is True: From 137318d562765b26e90dee1656c59a15b29f17d5 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 08:55:23 +0200 Subject: [PATCH 25/34] Reduce Log.info amount for SSL --- wo/cli/plugins/site.py | 9 +++++---- wo/cli/plugins/site_functions.py | 7 ------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 129f6e4..f3e2dd6 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -773,6 +773,9 @@ class WOSiteCreateController(CementBaseController): isWildcard = checkWildcardExist(self, wo_root_domain) Log.debug(self, "isWildcard = {0}".format(isWildcard)) if isWildcard: + Log.info(self, "Using existing Wildcard SSL " + "certificate from {0} to secure {1}" + .format(wo_root_domain, wo_domain)) Log.debug(self, "symlink wildcard " "cert between {0} & {1}" .format(wo_domain, wo_root_domain)) @@ -1382,12 +1385,10 @@ class WOSiteUpdateController(CementBaseController): # check if a wildcard cert for the root domain exist Log.debug(self, "checkWildcardExist on *.{0}" .format(wo_root_domain)) - Log.info(self, "Checking if there is a wildcard " - "certificate available from the root domain") isWildcard = checkWildcardExist(self, wo_root_domain) Log.debug(self, "isWildcard = {0}".format(isWildcard)) if isWildcard: - Log.info(self, "Using existing Wildcard SSL" + Log.info(self, "Using existing Wildcard SSL " "certificate from {0} to secure {1}" .format(wo_root_domain, wo_domain)) Log.debug(self, "symlink wildcard " @@ -1424,7 +1425,7 @@ class WOSiteUpdateController(CementBaseController): Log.error(self, "service nginx reload failed. " "check issues with `nginx -t` command") Log.info(self, "Congratulations! Successfully " - "Configured SSl for Site " + "Configured SSL for Site " " https://{0}".format(wo_domain)) if wo_subdomain: if (SSL.getExpirationDays(self, wo_root_domain) > 0): diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index ca8269e..1f70093 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1595,9 +1595,6 @@ def httpsRedirect(self, wo_domain_name, redirect=True, wildcard=False): else: if wildcard: try: - Log.info( - self, "Adding /etc/nginx/conf.d/force-ssl-{0}.conf" - .format(wo_domain_name)) sslconf = open("/etc/nginx/conf.d/force-ssl-{0}.conf" .format(wo_domain_name), encoding='utf-8', mode='w') @@ -1617,10 +1614,6 @@ def httpsRedirect(self, wo_domain_name, redirect=True, wildcard=False): else: try: - Log.info( - self, "Adding /etc/nginx/conf.d/force-ssl-{0}.conf" - .format(wo_domain_name)) - sslconf = open("/etc/nginx/conf.d/force-ssl-{0}.conf" .format(wo_domain_name), encoding='utf-8', mode='w') From 8275236bf7f33f5f96fe68ddb2b88d98847691cf Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 10:05:48 +0200 Subject: [PATCH 26/34] Fix symlink removal --- wo/cli/plugins/site_functions.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 1f70093..18dd3f0 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1265,9 +1265,12 @@ def removeAcmeConf(self, domain): .format(sslforce)) # find all broken symlinks - symlinks = WOFileUtils.findBrokenSymlink(self, "/var/www") + sympath = "/var/www" + symlinks = WOFileUtils.findBrokenSymlink(self, sympath) + for symlink in symlinks: - if os.path.islink('{0}'.format(sslconf)): + wo_symlink = os.readlink('{0}'.format(symlink)) + if wo_symlink == sslconf: # remove broken symlinks WOFileUtils.remove_symlink(self, symlink) else: From be0b0a832e3357a63923622d67be643fcdf6c1bb Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 10:10:39 +0200 Subject: [PATCH 27/34] Add remove symlink for wo update -le=off --- wo/cli/plugins/site.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index f3e2dd6..b37f366 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -1468,6 +1468,17 @@ class WOSiteUpdateController(CementBaseController): '{0}/conf/nginx/' 'hsts.conf.disabled' .format(wo_site_webroot)) + # find all broken symlinks + sympath = "/var/www" + sslconf = ("{0}/conf/nginx/ssl.conf" + .format(wo_site_webroot)) + symlinks = WOFileUtils.findBrokenSymlink(self, sympath) + + for symlink in symlinks: + wo_symlink = os.readlink('{0}'.format(symlink)) + if wo_symlink == sslconf: + # remove broken symlinks + WOFileUtils.remove_symlink(self, symlink) elif (pargs.letsencrypt == "clean" or pargs.letsencrypt == "purge"): removeAcmeConf(self, wo_domain) From 27aa48ae7bd65426c9a40518e2f0d9fdd2358ecf Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 10:17:31 +0200 Subject: [PATCH 28/34] Remove symlink directly --- wo/cli/plugins/site.py | 9 +-------- wo/cli/plugins/site_functions.py | 7 +------ wo/core/fileutils.py | 4 ++-- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index b37f366..1530857 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -1470,15 +1470,8 @@ class WOSiteUpdateController(CementBaseController): .format(wo_site_webroot)) # find all broken symlinks sympath = "/var/www" - sslconf = ("{0}/conf/nginx/ssl.conf" - .format(wo_site_webroot)) - symlinks = WOFileUtils.findBrokenSymlink(self, sympath) + WOFileUtils.findBrokenSymlink(self, sympath) - for symlink in symlinks: - wo_symlink = os.readlink('{0}'.format(symlink)) - if wo_symlink == sslconf: - # remove broken symlinks - WOFileUtils.remove_symlink(self, symlink) elif (pargs.letsencrypt == "clean" or pargs.letsencrypt == "purge"): removeAcmeConf(self, wo_domain) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 18dd3f0..9b4d1eb 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1266,13 +1266,8 @@ def removeAcmeConf(self, domain): # find all broken symlinks sympath = "/var/www" - symlinks = WOFileUtils.findBrokenSymlink(self, sympath) + WOFileUtils.findBrokenSymlink(self, sympath) - for symlink in symlinks: - wo_symlink = os.readlink('{0}'.format(symlink)) - if wo_symlink == sslconf: - # remove broken symlinks - WOFileUtils.remove_symlink(self, symlink) else: if os.path.islink("{0}".format(sslconf)): WOFileUtils.remove_symlink(self, "{0}".format(sslconf)) diff --git a/wo/core/fileutils.py b/wo/core/fileutils.py index 7450b61..cc6678f 100644 --- a/wo/core/fileutils.py +++ b/wo/core/fileutils.py @@ -302,10 +302,10 @@ class WOFileUtils(): if not os.path.exists(target_path): links.append(path) broken.append(path) + os.remove(path) else: links.append(path) else: # If it's not a symlink we're not interested. continue - - return broken + return True From f7ee487901969cb2267692517f3728547064f849 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 10:49:55 +0200 Subject: [PATCH 29/34] Copy file before creating a symlink --- wo/cli/plugins/site_functions.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 9b4d1eb..febe665 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1263,6 +1263,8 @@ def removeAcmeConf(self, domain): WOFileUtils.rm(self, '{0}'.format(sslforce)) WOFileUtils.rm(self, '{0}.disabled' .format(sslforce)) + WOFileUtils.rm(self, '/etc/letsencrypt/shared/{0}.conf' + .format(domain)) # find all broken symlinks sympath = "/var/www" @@ -1503,8 +1505,16 @@ def copyWildcardCert(self, wo_domain_name, wo_root_domain): if os.path.isfile("/var/www/{0}/conf/nginx/ssl.conf" .format(wo_root_domain)): try: - WOFileUtils.create_symlink(self, ["/var/www/{0}/conf/nginx/" - "ssl.conf" + if not os.path.isdir("/etc/letsencrypt/shared"): + WOFileUtils.mkdir(self, "/etc/letsencrypt/shared") + if not os.path.isfile("/etc/letsencrypt/shared/{0}.conf" + .format(wo_root_domain)): + WOFileUtils.copyfile("/var/www/{0}/conf/nginx/ssl.conf" + .format(wo_root_domain), + "/etc/letsencrypt/shared/{0}.conf" + .format(wo_root_domain)) + WOFileUtils.create_symlink(self, ["/etc/letsencrypt/shared/" + "{0}.conf" .format(wo_root_domain), '/var/www/{0}/conf/nginx/' 'ssl.conf' From 528aedea0c2ddecd5dca941ca4969d94cb95f3af Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 10:51:00 +0200 Subject: [PATCH 30/34] Fix missing argument --- wo/cli/plugins/site_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index febe665..1ecec76 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1509,7 +1509,7 @@ def copyWildcardCert(self, wo_domain_name, wo_root_domain): WOFileUtils.mkdir(self, "/etc/letsencrypt/shared") if not os.path.isfile("/etc/letsencrypt/shared/{0}.conf" .format(wo_root_domain)): - WOFileUtils.copyfile("/var/www/{0}/conf/nginx/ssl.conf" + WOFileUtils.copyfile(self, "/var/www/{0}/conf/nginx/ssl.conf" .format(wo_root_domain), "/etc/letsencrypt/shared/{0}.conf" .format(wo_root_domain)) From f6f412a2906a65fa5281f46954fc07507bda35b5 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 20:33:33 +0200 Subject: [PATCH 31/34] Prepare for release --- CHANGELOG.md | 12 ++++++++++++ config/bash_completion.d/wo_auto.rc | 29 ++++++++++++----------------- wo/cli/plugins/site.py | 10 +++------- wo/cli/plugins/stack.py | 1 - wo/core/variables.py | 9 ++++++++- 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f0eb19..3eb70f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,14 +8,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### v3.9.x - [Unreleased] +### v3.9.8.6 - 2019-08-30 + +#### Added + +- Subdomains are automatically secured with an existant Wildcard LetsEncrypt SSL certificate. +(If a wildcard certificate exist, WordOps will use this certificate for subdomains instead of issuing new certificates) +- MySQL & Redis stack to `wo stack remove/purge` +- Dump MySQL databases before purging MySQL Stack + #### Changed - Date format in backup name : /backup/30Aug2019035932 -> /backup/30Aug2019-03-59-32 +- Cleanup and update bash_completion #### Fixed - cache-enabler plugin not installed and configured with `wo site update site.tld --wpce` - possible issue with domain variable in `--letsencrypt=wildcard` +- python3-mysqldb not available on Debian 8 (Jessie) +- Fix mysql variable skip-name-resolved ### v3.9.8.5 - 2019-08-30 diff --git a/config/bash_completion.d/wo_auto.rc b/config/bash_completion.d/wo_auto.rc index d7e3cc9..56ec872 100644 --- a/config/bash_completion.d/wo_auto.rc +++ b/config/bash_completion.d/wo_auto.rc @@ -35,7 +35,7 @@ _wo_complete() "stack") COMPREPLY=( $(compgen \ - -W "upgrade install purge reload remove restart start status stop migrate" \ + -W "upgrade install purge reload remove restart start status stop" \ -- $cur) ) ;; @@ -74,12 +74,12 @@ _wo_complete() # HANDLE EVERYTHING AFTER THE THIRD LEVEL NAMESPACE "install" | "purge" | "remove" ) COMPREPLY=( $(compgen \ - -W "--web --admin --nginx --php --php73 --mysql --wpcli --phpmyadmin --adminer --utils --all --redis --phpredisadmin --composer --netdata --fail2ban --dashboard --proftpd" \ + -W "--recommended --web --admin --security --nginx --php --php73 --mysql --wpcli --phpmyadmin --adminer --utils --redis --phpredisadmin --composer --netdata --fail2ban --dashboard --proftpd --clamav --mysqlclient --mysqltuner --extplorer --all" \ -- $cur) ) ;; "upgrade" ) COMPREPLY=( $(compgen \ - -W "--web --nginx --php --php73 --mysql --all --netdata --composer --phpmyadmin --dashboard --no-prompt --wpcli" \ + -W "--web --admin --utils --nginx --php --php73 --mysql --all --netdata --composer --phpmyadmin --dashboard --no-prompt --mysqtuner --wpcli" \ -- $cur) ) ;; "start" | "stop" | "reload" | "restart" | "status") @@ -87,11 +87,6 @@ _wo_complete() -W "--nginx --php --php73 --mysql --redis --fail2ban --netdata -proftpd" \ -- $cur) ) ;; - "migrate") - COMPREPLY=( $(compgen \ - -W "--mariadb" \ - -- $cur) ) - ;; "list") COMPREPLY=( $(compgen \ -W "--enabled --disabled" \ @@ -159,13 +154,13 @@ _wo_complete() "create") COMPREPLY=( $(compgen \ - -W "--user --pass --email --html --php --php73 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --proxy= --wpredis --wprocket --wpce -le --letsencrypt --letsencrypt=wildcard -le=wildcard --dns --dns=dns_cf --dns=dns_do" \ + -W "--user --pass --email --html --php --php73 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --proxy= --wpredis --wprocket --wpce -le --letsencrypt --letsencrypt=wildcard -le=wildcard --dns --dns=dns_cf --dns=dns_do" \ -- $cur) ) ;; "update") COMPREPLY=( $(compgen \ - -W "--password --php --php73 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le --letsencrypt --letsencrypt=off --letsencrypt=clean -le=wildcard --dns --dns=dns_cf --dns=dns_do" \ + -W "--password --php --php73 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le -le=off --letsencrypt --letsencrypt=off --letsencrypt=clean -le=wildcard -le=clean --dns --dns=dns_cf --dns=dns_do" \ -- $cur) ) ;; "delete") @@ -230,9 +225,9 @@ _wo_complete() "--wpsubdir" | "--wpsubdomain") if [ ${COMP_WORDS[1]} != "debug" ]; then if [ ${COMP_WORDS[2]} == "create" ]; then - retlist="--wpsc --wpfc --user --email --pass --wpredis --wprocket --wpce --letsencrypt --letsencrypt=wildcard -le --php73 --dns --dns=dns_cf --dns=dns_do" + retlist="--wpsc --wpfc --user --email --pass --wpredis --wprocket --wpce -le -le=wildcard --letsencrypt --letsencrypt=wildcard --php73 --dns --dns=dns_cf --dns=dns_do" elif [ ${COMP_WORDS[2]} == "update" ]; then - retlist="--wpfc --wpsc --php73 --php73=off --wpredis --wprocket --wpce -le --letsencrypt --letsencrypt=wildcard --letsencrypt=off --letsencrypt=clean --dns --dns=dns_cf --dns=dns_do" + retlist="--wpfc --wpsc --php73 --php73=off --wpredis --wprocket --wpce -le -le=off -le=wildcard --letsencrypt --letsencrypt=wildcard --letsencrypt=off --letsencrypt=clean --dns --dns=dns_cf --dns=dns_do" else retlist="" fi @@ -248,7 +243,7 @@ _wo_complete() "--wpredis --wprocket --wpce" | "--wpfc" | "--wpsc" | "--wpsubdir" | "--wpsubdomain" | "--user" | "--pass" | "--email" | "--wp") if [ ${COMP_WORDS[2]} == "create" ]; then - retlist="--user --pass --email --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce --php73 -le --letsencrypt --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_do" + retlist="--user --pass --email --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce --php73 -le -le=off -le=wildcard --letsencrypt --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_do" else retlist="" fi @@ -261,7 +256,7 @@ _wo_complete() "--wpredis --wprocket --wpce" | "--wpfc") if [ ${COMP_WORDS[2]} == "update" ]; then - retlist="--password --php --php73 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le --letsencrypt --letsencrypt=off --letsencrypt=clean --dns --dns=dns_cf --dns=dns_do" + retlist="--password --php --php73 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le -le=off --letsencrypt --letsencrypt=off --letsencrypt=clean --dns --dns=dns_cf --dns=dns_do" else retlist="" fi @@ -274,7 +269,7 @@ _wo_complete() "--web" | "--admin" | "--nginx" | "--php" | "--php73" | "--mysql" | "--wpcli" | "--phpmyadmin" | "--adminer" | "--utils" | "--fail2ban" | "--redis | --phpredisadmin | --netdata") if [[ ${COMP_WORDS[2]} == "install" || ${COMP_WORDS[2]} == "purge" || ${COMP_WORDS[2]} == "remove" ]]; then - retlist="--web --admin --nginx --php --php73 --mysql --wpcli --phpmyadmin --adminer --utils --redis --fail2ban --phpredisadmin --netdata" + retlist="--web --admin --security --nginx --php --php73 --mysql --wpcli --phpmyadmin --adminer --utils --redis --fail2ban --phpredisadmin --netdata -f --force" elif [[ ${COMP_WORDS[2]} == "start" || ${COMP_WORDS[2]} == "reload" || ${COMP_WORDS[2]} == "restart" || ${COMP_WORDS[2]} == "stop" ]]; then retlist="--nginx --php --php73 --mysql --redis --netdata" elif [[ ${COMP_WORDS[1]} == "debug" ]]; then @@ -314,7 +309,7 @@ _wo_complete() elif [ ${COMP_WORDS[2]} == "delete" ]; then retlist="--db --files --force" elif [ ${COMP_WORDS[2]} == "update" ]; then - retlist="--password --php --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce --letsencrypt --letsencrypt=off " + retlist="--password --php --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le -le=off -le=wildcard --letsencrypt --letsencrypt=off " else retlist="" fi @@ -363,7 +358,7 @@ _wo_complete() case "$mprev" in "--user" | "--email" | "--pass") if [ ${COMP_WORDS[2]} == "create" ]; then - retlist="--user --pass --email --html --php --php73 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce --letsencrypt --letsencrypt=wildcard -le --dns --dns=dns_cf --dns=dns_do" + retlist="--user --pass --email --html --php --php73 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le -le=wildcard --letsencrypt --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_do" fi ret="${retlist[@]/$prev}" COMPREPLY=( $(compgen \ diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 1530857..9096a94 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -853,7 +853,8 @@ class WOSiteUpdateController(CementBaseController): (['--wprocket'], dict(help="update to WP-Rocket cache", action='store_true')), (['--wpce'], - dict(help="update to Cache-Enabler cache", action='store_true')), + dict(help="update to Cache-Enabler cache", + action='store_true')), (['--wpredis'], dict(help="update to redis cache", action='store_true')), (['-le', '--letsencrypt'], @@ -1238,12 +1239,6 @@ class WOSiteUpdateController(CementBaseController): return 0 if pargs.letsencrypt: - if ((wo_domain_type == 'subdomain') and - (not pargs.letsencrypt == 'wildcard') and - (not pargs.letsencrypt == 'off') and - (not pargs.letsencrypt == 'clean') and - (not pargs.letsencrypt == 'purge')): - pargs.letsencrypt == 'subdomain' if pargs.letsencrypt == 'on': data['letsencrypt'] = True letsencrypt = True @@ -1874,6 +1869,7 @@ class WOSiteDeleteController(CementBaseController): pargs.site_name = (input('Enter site name : ') .strip()) except IOError as e: + Log.debug(self, str(e)) Log.error(self, 'could not input site name') pargs.site_name = pargs.site_name.strip() diff --git a/wo/cli/plugins/stack.py b/wo/cli/plugins/stack.py index 33b6f01..39b6d2f 100644 --- a/wo/cli/plugins/stack.py +++ b/wo/cli/plugins/stack.py @@ -45,7 +45,6 @@ class WOStackController(CementBaseController): label = 'stack' stacked_on = 'base' stacked_type = 'nested' - exit_on_close = True description = 'Stack command manages stack operations' arguments = [ (['--all'], diff --git a/wo/core/variables.py b/wo/core/variables.py index 6fb7f9f..d31594e 100644 --- a/wo/core/variables.py +++ b/wo/core/variables.py @@ -147,11 +147,18 @@ class WOVariables(): if wo_distro == 'raspbian': wo_mysql = ["mariadb-server", "percona-toolkit", "python3-mysqldb"] + elif wo_distro == 'debian': + if wo_platform_codename == 'jessie': + wo_mysql = ["mariadb-server", "percona-toolkit", + "python3-mysql.connector"] else: wo_mysql = ["mariadb-server", "percona-toolkit", "python3-mysqldb", "mariadb-backup"] - wo_mysql_client = ["mariadb-client", "python3-mysqldb"] + if wo_platform_codename == 'jessie': + wo_mysql_client = ["mariadb-client", "python3-mysqldb"] + else: + wo_mysql_client = ["mariadb-client", "python3-mysql.connector"] wo_fail2ban = ["fail2ban"] From 73fb3b9495b28c58e1f46f6d1a5daa3e69a7b2a9 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 20:59:42 +0200 Subject: [PATCH 32/34] Ready for release --- CHANGELOG.md | 2 +- wo/cli/plugins/stack_pref.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3eb70f7..9c6a518 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Subdomains are automatically secured with an existant Wildcard LetsEncrypt SSL certificate. (If a wildcard certificate exist, WordOps will use this certificate for subdomains instead of issuing new certificates) - MySQL & Redis stack to `wo stack remove/purge` -- Dump MySQL databases before purging MySQL Stack #### Changed @@ -28,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - possible issue with domain variable in `--letsencrypt=wildcard` - python3-mysqldb not available on Debian 8 (Jessie) - Fix mysql variable skip-name-resolved +- Fix typo in redis tuning directives ### v3.9.8.5 - 2019-08-30 diff --git a/wo/cli/plugins/stack_pref.py b/wo/cli/plugins/stack_pref.py index bf1e816..5400b47 100644 --- a/wo/cli/plugins/stack_pref.py +++ b/wo/cli/plugins/stack_pref.py @@ -907,7 +907,8 @@ def post_pref(self, apt_packages, packages, upgrade=False): "wait_timeout " "= 600", "wait_timeout " - "= 120") + "= 120\n" + "skip-name-resolve = 1\n") # disabling mariadb binlog WOFileUtils.searchreplace(self, "/etc/mysql/my.cnf", @@ -957,8 +958,7 @@ def post_pref(self, apt_packages, packages, upgrade=False): "table_open_cache = 16000") WOFileUtils.searchreplace(self, "/etc/mysql/my.cnf", "max_allowed_packet = 16M", - "max_allowed_packet = 64M\n" - "skip-name-resolve=1\n") + "max_allowed_packet = 64M\n") WOService.stop_service(self, 'mysql') WOFileUtils.mvfile(self, '/var/lib/mysql/ib_logfile0', @@ -1114,7 +1114,8 @@ def post_pref(self, apt_packages, packages, upgrade=False): Log.debug(self, "Enabling redis systemd service") WOShellExec.cmd_exec(self, "systemctl enable redis-server") if (os.path.isfile("/etc/redis/redis.conf") and - not WOFileUtils.grep(self, "/etc/mysql/my.cnf", "WordOps")): + not WOFileUtils.grep(self, "/etc/redis/redis.conf", + "WordOps")): Log.info(self, "Tuning Redis configuration") with open("/etc/redis/redis.conf", "a") as redis_file: From 3136671525581f4497f1396bc8da0415726cf291 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 21:09:10 +0200 Subject: [PATCH 33/34] Add cheat.sh --- install | 20 +++++++++++--------- wo/cli/plugins/stack.py | 24 +++--------------------- wo/cli/plugins/stack_pref.py | 5 ----- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/install b/install index 8a2ed15..f34f842 100755 --- a/install +++ b/install @@ -725,12 +725,6 @@ wo_uninstall() { rm -rf /usr/local/lib/python3.*/dist-packages/{pystache-*,cement-2.*,wo-*} /usr/local/bin/wo /etc/bash_completion.d/wo_auto.rc /var/lib/wo /etc/wo /usr/lib/wo/templates >> /var/log/wo/install.log 2>&1 } -wo_cheat_alias() { - if ! grep -q "cheat" "$HOME/.bashrc"; then - echo "alias cheat='/usr/local/bin/cht.sh'" >> "$HOME/.bashrc" - fi -} - wo_ufw_setup() { # get custom ssh port @@ -796,6 +790,14 @@ wo_ufw_setup() { } \ >> $wo_install_log +wo_cheat_install() { + curl -sL https://cht.sh/:cht.sh > /usr/local/bin/cht.sh + curl -sL https://cheat.sh/:bash_completion > /etc/bash_completion.d/cht.sh + if ! grep -q "cheat" $HOME/.bashrc; then + echo "alias cheat='/usr/local/bin/cht.sh'" >> "$HOME/.bashrc" + fi +} + ### # 4 - WO MAIN SETUP ### @@ -849,7 +851,7 @@ else if [ -d /etc/systemd/system/mariadb.service.d ]; then wo_mariadb_tweak | tee -ai $wo_install_log fi - wo_cheat_alias | tee -ai $wo_install_log + wo_cheat_install | tee -ai $wo_install_log wo_domain_suffix | tee -ai $wo_install_log wo_lib_echo "Running post-install steps " | tee -ai $wo_install_log wo_update_wp_cli | tee -ai $wo_install_log @@ -902,7 +904,7 @@ else wo_lib_echo "Running post-install steps " | tee -ai $wo_install_log wo_git_init | tee -ai $wo_install_log wo_update_wp_cli | tee -ai $wo_install_log - wo_cheat_alias | tee -ai $wo_install_log + wo_cheat_install | tee -ai $wo_install_log wo_lib_echo "Cleaning-up EE previous install" | tee -ai $wo_install_log wo_clean_ee | tee -ai $wo_install_log else @@ -937,7 +939,7 @@ else wo_install_acme_sh | tee -ai $wo_install_log wo_lib_echo "Running post-install steps " | tee -ai $wo_install_log secure_wo_db | tee -ai $wo_install_log - wo_cheat_alias | tee -ai $wo_install_log + wo_cheat_install | tee -ai $wo_install_log wo_domain_suffix | tee -ai $wo_install_log wo_git_init | tee -ai $wo_install_log wo_update_wp_cli | tee -ai $wo_install_log diff --git a/wo/cli/plugins/stack.py b/wo/cli/plugins/stack.py index 39b6d2f..c829708 100644 --- a/wo/cli/plugins/stack.py +++ b/wo/cli/plugins/stack.py @@ -90,8 +90,6 @@ class WOStackController(CementBaseController): dict(help='Install ClamAV stack', action='store_true')), (['--utils'], dict(help='Install Utils stack', action='store_true')), - (['--cheat'], - dict(help='Install cheat.sh stack', action='store_true')), (['--redis'], dict(help='Install Redis', action='store_true')), (['--phpredisadmin'], @@ -127,8 +125,7 @@ class WOStackController(CementBaseController): (not pargs.mysqlclient) and (not pargs.mysqltuner) and (not pargs.adminer) and (not pargs.utils) and (not pargs.redis) and (not pargs.proftpd) and - (not pargs.extplorer) and - (not pargs.cheat) and (not pargs.clamav) and + (not pargs.extplorer) and (not pargs.clamav) and (not pargs.phpredisadmin) and (not pargs.php73)): pargs.web = True @@ -158,7 +155,6 @@ class WOStackController(CementBaseController): pargs.dashboard = True pargs.phpredisadmin = True pargs.extplorer = True - pargs.cheat = True if pargs.security: pargs.fail2ban = True @@ -417,17 +413,6 @@ class WOStackController(CementBaseController): Log.debug(self, "eXtplorer is already installed") Log.info(self, "eXtplorer is already installed") - # cheat.sh - if pargs.cheat: - if not os.path.isfile('/usr/local/bin/cht.sh'): - Log.debug(self, "Setting packages variable for cht.sh") - packages = packages + [["https://cht.sh/:cht.sh", - "/usr/local/bin/cht.sh", - "cheat.sh"]] - else: - Log.debug(self, "cheat.sh is already installed") - Log.info(self, "cheat.sh is already installed") - # UTILS if pargs.utils: Log.debug(self, "Setting packages variable for utils") @@ -516,8 +501,7 @@ class WOStackController(CementBaseController): (not pargs.mysqlclient) and (not pargs.mysqltuner) and (not pargs.adminer) and (not pargs.utils) and (not pargs.redis) and (not pargs.proftpd) and - (not pargs.extplorer) and - (not pargs.cheat) and (not pargs.clamav) and + (not pargs.extplorer) and (not pargs.clamav) and (not pargs.phpredisadmin) and (not pargs.php73)): pargs.web = True @@ -723,8 +707,7 @@ class WOStackController(CementBaseController): (not pargs.mysqlclient) and (not pargs.mysqltuner) and (not pargs.adminer) and (not pargs.utils) and (not pargs.redis) and (not pargs.proftpd) and - (not pargs.extplorer) and - (not pargs.cheat) and (not pargs.clamav) and + (not pargs.extplorer) and (not pargs.clamav) and (not pargs.phpredisadmin) and (not pargs.php73)): pargs.web = True @@ -752,7 +735,6 @@ class WOStackController(CementBaseController): pargs.composer = True pargs.netdata = True pargs.mysqltuner = True - pargs.cheat = True if pargs.security: pargs.fail2ban = True diff --git a/wo/cli/plugins/stack_pref.py b/wo/cli/plugins/stack_pref.py index 5400b47..2be7ad9 100644 --- a/wo/cli/plugins/stack_pref.py +++ b/wo/cli/plugins/stack_pref.py @@ -1482,11 +1482,6 @@ def post_pref(self, apt_packages, packages, upgrade=False): for x in packages): WOFileUtils.chmod(self, "/usr/bin/pt-query-advisor", 0o775) - # cht.sh - if any('/usr/local/bin/cht.sh' == x[1] - for x in packages): - WOFileUtils.chmod(self, "/usr/local/bin/cht.sh", 0o775) - # phpredisadmin if any('/var/lib/wo/tmp/pra.tar.gz' == x[1] for x in packages): From 87fbef74abb6ae16b6bd61bd887e713c4ef919cc Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Fri, 30 Aug 2019 21:13:27 +0200 Subject: [PATCH 34/34] [skip travis] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c6a518..12876bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Date format in backup name : /backup/30Aug2019035932 -> /backup/30Aug2019-03-59-32 - Cleanup and update bash_completion +- cheat.sh is installed with WordOps install script, not as a stack because it wasn't downloaded at all by WordOps (unknown reason yet) #### Fixed