diff --git a/CHANGELOG.md b/CHANGELOG.md index ad83701..3777422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### v3.9.x - [Unreleased] +### v3.9.8.11 - 2019-09-06 + +#### Changed + +- Improved general logs display +- UFW configuration is only applied during initial installation if UFW is disabled + +#### Fixed + +- Redis-server configuration and start +- Nginx upgrade with `wo stack upgrade` + ### v3.9.8.10 - 2019-09-04 #### Changed diff --git a/install b/install index 97d8544..926c222 100755 --- a/install +++ b/install @@ -390,7 +390,7 @@ wo_update_wp_cli() { wo_install_acme_sh() { # check if acme.sh is already installed - if [ ! -x /etc/letsencrypt/acme.sh ]; then + if [ ! -x /etc/letsencrypt/acme.sh ] && [ ! -d /etc/letsencrypt/archive ]; then { # clone the git repository if [ -d /opt/acme.sh/.git ]; then @@ -539,6 +539,8 @@ wo_upgrade_nginx() { sed -i "s/locations-php71.conf/locations-wo.conf/" /etc/nginx/sites-available/* sed -i "s/locations-php72.conf/locations-wo.conf/" /etc/nginx/sites-available/* sed -i "s/locations-php73.conf/locations-wo.conf/" /etc/nginx/sites-available/* + sed -i "s/php.conf/php72.conf/" /etc/nginx/sites-available/* + sed -i "s/php7.conf/php72.conf/" /etc/nginx/sites-available/* sed -i 's/ssl on;/#ssl on;/' /var/www/*/conf/nginx/ssl.conf # update redis.conf headers @@ -731,75 +733,71 @@ wo_uninstall() { } wo_ufw_setup() { - - # get custom ssh port - if [ -f /etc/ssh/sshd_config ]; then - CURRENT_SSH_PORT=$(grep "Port" /etc/ssh/sshd_config | awk -F " " '{print $2}') - fi - # define firewall rules - if ! grep -q "LOGLEVEL=low" /etc/ufw/ufw.conf; then - ufw logging low - fi - if ! grep -q 'DEFAULT_OUTPUT_POLICY="ACCEPT"' /etc/default/ufw; then - ufw default allow outgoing - fi - if ! grep -q 'DEFAULT_INPUT_POLICY="DROP"' /etc/default/ufw; then - ufw default deny incoming - fi - if ! grep -q "\-\-dport 22 -j" /etc/ufw/user.rules; then - # default ssh port - ufw limit 22 - fi - - # custom ssh port - if [ "$CURRENT_SSH_PORT" != "22" ]; then - if ! grep -q "\-\-dport $CURRENT_SSH_PORT -j" /etc/ufw/user.rules; then - ufw limit "$CURRENT_SSH_PORT" + if ! grep -q "ENABLED=yes" /etc/ufw/ufw.conf; then + # get custom ssh port + if [ -f /etc/ssh/sshd_config ]; then + CURRENT_SSH_PORT=$(grep "Port" /etc/ssh/sshd_config | awk -F " " '{print $2}') + fi + # define firewall rules + if ! grep -q "LOGLEVEL=low" /etc/ufw/ufw.conf; then + ufw logging low + fi + if ! grep -q 'DEFAULT_OUTPUT_POLICY="ACCEPT"' /etc/default/ufw; then + ufw default allow outgoing + fi + if ! grep -q 'DEFAULT_INPUT_POLICY="DROP"' /etc/default/ufw; then + ufw default deny incoming + fi + if ! grep -q "\-\-dport 22 -j" /etc/ufw/user.rules; then + # default ssh port + ufw limit 22 fi - fi - # nginx - if ! grep -q "\-\-dport 80 -j" /etc/ufw/user.rules; then - # http - ufw allow http - fi - if ! grep -q "\-\-dport 443 -j" /etc/ufw/user.rules; then - # https - ufw allow https - fi + # custom ssh port + if [ "$CURRENT_SSH_PORT" != "22" ]; then + if ! grep -q "\-\-dport $CURRENT_SSH_PORT -j" /etc/ufw/user.rules; then + ufw limit "$CURRENT_SSH_PORT" + fi + fi - # ntp - if ! grep -q "\-\-dport 123 -j" /etc/ufw/user.rules; then - ufw allow 123 - fi + # nginx + if ! grep -q "\-\-dport 80 -j" /etc/ufw/user.rules; then + # http + ufw allow http + fi + if ! grep -q "\-\-dport 443 -j" /etc/ufw/user.rules; then + # https + ufw allow https + fi - if ! grep -q "\-\-dport 22222 -j" /etc/ufw/user.rules; then - # wordops backend - ufw limit 22222 - fi - # enable ufw - if [ -n "$CURRENT_SSH_PORT" ]; then - if ! grep -q "ENABLED=yes" /etc/ufw/ufw.conf; then + # ntp + if ! grep -q "\-\-dport 123 -j" /etc/ufw/user.rules; then + ufw allow 123 + fi + + if ! grep -q "\-\-dport 22222 -j" /etc/ufw/user.rules; then + # wordops backend + ufw limit 22222 + fi + # enable ufw + if [ -n "$CURRENT_SSH_PORT" ]; then ufw --force enable - else - ufw reload + fi + + # remove ufw from syslog + if [ -f /etc/rsyslog.d/20-ufw.conf ]; then + sed -i 's/\#\& stop/\& stop/' /etc/rsyslog.d/20-ufw.conf + service rsyslog restart fi fi - - # remove ufw from syslog - if [ -f /etc/rsyslog.d/20-ufw.conf ]; then - sed -i 's/\#\& stop/\& stop/' /etc/rsyslog.d/20-ufw.conf - service rsyslog restart - fi - } \ >> $wo_install_log wo_cheat_install() { curl -sL https://cht.sh/:cht.sh > /usr/local/bin/cht.sh chmod +x /usr/local/bin/cht.sh - [ ! -h /usr/local/bin/cheat ] && { - ln -s /usr/local/bin/cht.sh /usr/local/bin/cheat + [ ! -h /usr/local/bin/cheat ] && { + ln -s /usr/local/bin/cht.sh /usr/local/bin/cheat } curl -sL https://cheat.sh/:bash_completion > /etc/bash_completion.d/cht.sh } diff --git a/tests/travis.sh b/tests/travis.sh index 747379a..2542b61 100644 --- a/tests/travis.sh +++ b/tests/travis.sh @@ -10,7 +10,7 @@ CGREEN="${CSI}1;32m" CEND="${CSI}0m" exit_script() { - curl --progress-bar --upload-file /var/log/wo/wordops.log https://transfer.vtbox.net/"$(basename wordops.log)" && echo "" | sudo tee -a $HOME/.transfer.log && echo "" + curl --progress-bar --upload-file /var/log/wo/wordops.log https://transfer.vtbox.net/"$(basename wordops.log)" && echo "" exit 1 } diff --git a/wo/cli/main.py b/wo/cli/main.py index 4579177..d0c009e 100644 --- a/wo/cli/main.py +++ b/wo/cli/main.py @@ -1,12 +1,14 @@ """WordOps main application entry point.""" -import sys import os +import sys + from cement.core import foundation -from cement.utils.misc import init_defaults -from cement.core.exc import FrameworkError, CaughtSignal +from cement.core.exc import CaughtSignal, FrameworkError from cement.ext.ext_argparse import ArgParseArgumentHandler -from wo.core import exc +from cement.utils.misc import init_defaults + from wo.cli.ext.wo_outputhandler import WOOutputHandler +from wo.core import exc # this has to happen after you import sys, but before you import anything # from Cement "source: https://github.com/datafolklabs/cement/issues/290" diff --git a/wo/cli/plugins/secure.py b/wo/cli/plugins/secure.py index e8ca67e..38f8190 100644 --- a/wo/cli/plugins/secure.py +++ b/wo/cli/plugins/secure.py @@ -86,12 +86,12 @@ class WOSecureController(CementBaseController): while not pargs.user_input.isdigit(): Log.info(self, "Please enter a valid port number ") pargs.user_input = input("WordOps " - "admin port [22222]:") + "admin port [22222]:") if not pargs.user_input: port = input("WordOps admin port [22222]:") if port == "": pargs.user_input = 22222 - while not port.isdigit() and port != "": + while (not port.isdigit()) and (port != "") and (not port < 65556): Log.info(self, "Please Enter valid port number :") port = input("WordOps admin port [22222]:") pargs.user_input = port diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 2050fad..4e19cfc 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -7,6 +7,7 @@ from subprocess import Popen from cement.core import handler, hook from cement.core.controller import CementBaseController, expose + from wo.cli.plugins.site_functions import * from wo.cli.plugins.sitedb import (addNewSite, deleteSiteInfo, getAllsites, getSiteInfo, updateSiteInfo) diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 80bbb1a..b6a1355 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -35,15 +35,18 @@ class SiteError(Exception): def pre_run_checks(self): # Check nginx configuration - Log.info(self, "Running pre-update checks, please wait...") + Log.wait(self, "Running pre-update checks") try: Log.debug(self, "checking NGINX configuration ...") FNULL = open('/dev/null', 'w') subprocess.check_call(["/usr/sbin/nginx", "-t"], stdout=FNULL, stderr=subprocess.STDOUT) except CalledProcessError as e: + Log.failed(self, "Running pre-update checks") Log.debug(self, "{0}".format(str(e))) raise SiteError("nginx configuration check failed.") + else: + Log.valide(self, "Running pre-update checks") def check_domain_exists(self, domain): @@ -643,7 +646,7 @@ def setupwordpressnetwork(self, data): def installwp_plugin(self, plugin_name, data): wo_site_webroot = data['webroot'] - Log.info(self, "Installing plugin {0}, please wait..." + Log.wait(self, "Installing plugin {0}" .format(plugin_name)) WOFileUtils.chdir(self, '{0}/htdocs/'.format(wo_site_webroot)) try: @@ -665,9 +668,13 @@ def installwp_plugin(self, plugin_name, data): else '' )) except CommandExecutionError as e: + Log.failed(self, "Installing plugin {0}" + .format(plugin_name)) Log.debug(self, "{0}".format(e)) raise SiteError("plugin activation failed") - + else: + Log.valide(self, "Installing plugin {0}" + .format(plugin_name)) return 1 @@ -676,7 +683,7 @@ def uninstallwp_plugin(self, plugin_name, data): Log.debug(self, "Uninstalling plugin {0}, please wait..." .format(plugin_name)) WOFileUtils.chdir(self, '{0}/htdocs/'.format(wo_site_webroot)) - Log.info(self, "Uninstalling plugin {0}, please wait..." + Log.wait(self, "Uninstalling plugin {0}" .format(plugin_name)) try: WOShellExec.cmd_exec(self, "{0} plugin " @@ -689,13 +696,18 @@ def uninstallwp_plugin(self, plugin_name, data): "--allow-root uninstall " "{0}".format(plugin_name)) except CommandExecutionError as e: + Log.failed(self, "Uninstalling plugin {0}" + .format(plugin_name)) Log.debug(self, "{0}".format(e)) raise SiteError("plugin uninstall failed") + else: + Log.valide(self, "Uninstalling plugin {0}" + .format(plugin_name)) def setupwp_plugin(self, plugin_name, plugin_option, plugin_data, data): wo_site_webroot = data['webroot'] - Log.info(self, "Setting plugin {0}, please wait..." + Log.wait(self, "Setting plugin {0}" .format(plugin_name)) WOFileUtils.chdir(self, '{0}/htdocs/'.format(wo_site_webroot)) @@ -707,8 +719,13 @@ def setupwp_plugin(self, plugin_name, plugin_option, plugin_data, data): "{0} \'{1}\' --format=json" .format(plugin_option, plugin_data)) except CommandExecutionError as e: + Log.failed(self, "Setting plugin {0}" + .format(plugin_name)) Log.debug(self, "{0}".format(e)) raise SiteError("plugin setup failed") + else: + Log.valide(self, "Setting plugin {0}" + .format(plugin_name)) else: try: WOShellExec.cmd_exec(self, "{0} " @@ -718,8 +735,13 @@ def setupwp_plugin(self, plugin_name, plugin_option, plugin_data, data): .format(plugin_option, plugin_data )) except CommandExecutionError as e: + Log.failed(self, "Setting plugin {0}" + .format(plugin_name)) Log.debug(self, "{0}".format(e)) raise SiteError("plugin setup failed") + else: + Log.valide(self, "Setting plugin {0}" + .format(plugin_name)) def setwebrootpermissions(self, webroot): @@ -1354,7 +1376,7 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False, if subdomain: Log.info(self, "Certificate type: Subdomain") Log.info(self, "Validation mode : {0}".format(validation_mode)) - Log.wait(self, "Issuing SSL certificate with acme.sh") + Log.wait(self, "Issuing SSL cert with acme.sh") ssl = WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) + "--issue " "-d {0} {1} " @@ -1365,7 +1387,7 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False, elif wildcard: Log.info(self, "Certificate type: Wildcard") Log.info(self, "Validation mode : {0}".format(validation_mode)) - Log.wait(self, "Issuing SSL certificate with acme.sh") + Log.wait(self, "Issuing SSL cert with acme.sh") ssl = WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) + "--issue " "-d {0} -d '*.{0}' --dns {1} " @@ -1376,7 +1398,7 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False, else: Log.info(self, "Certificate type: Domain + www") Log.info(self, "Validation mode : {0}".format(validation_mode)) - Log.wait(self, "Issuing SSL certificate with acme.sh") + Log.wait(self, "Issuing SSL cert with acme.sh") ssl = WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) + "--issue " "-d {0} -d www.{0} {1} " @@ -1384,8 +1406,8 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False, .format(wo_domain_name, acme_mode, keylenght)) if ssl: - Log.valide(self, "Issuing SSL certificate with acme.sh") - Log.wait(self, "Deploying SSL cert with acme.sh") + Log.valide(self, "Issuing SSL cert with acme.sh") + Log.wait(self, "Deploying SSL cert") Log.debug(self, "Cert deployment for domain: {0}" .format(wo_domain_name)) try: @@ -1405,7 +1427,7 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False, "service nginx restart\" " .format(WOVariables.wo_ssl_live, wo_domain_name)) - Log.valide(self, "Deploying SSL cert with acme.sh") + Log.valide(self, "Deploying SSL cert") if os.path.isdir('/var/www/{0}/conf/nginx' .format(wo_domain_name)): @@ -1553,6 +1575,7 @@ def httpsRedirect(self, wo_domain_name, redirect=True, wildcard=False): "/etc/nginx/conf.d/force-ssl-{0}.conf" .format(wo_domain_name)) else: + Log.wait(self, "Adding HTTPS redirection") if wildcard: try: sslconf = open("/etc/nginx/conf.d/force-ssl-{0}.conf" @@ -1582,18 +1605,18 @@ def httpsRedirect(self, wo_domain_name, redirect=True, wildcard=False): "\tlisten [::]:80;\n" + "\tserver_name www.{0} {0};\n" .format(wo_domain_name) + - "\treturn 301 https://{0}" - .format(wo_domain_name)+"$request_uri;\n}") + "\treturn 301 https://$host" + "$request_uri;\n}") sslconf.close() except IOError as e: + Log.failed(self, "Adding HTTPS redirection") Log.debug(self, str(e)) Log.debug(self, "Error occured while generating " "/etc/nginx/conf.d/force-ssl-{0}.conf" .format(wo_domain_name)) - - Log.info(self, "Added HTTPS Force Redirection for Site " - " http://{0}".format(wo_domain_name)) + else: + Log.valide(self, "Adding HTTPS redirection") # Nginx Configation into GIT WOGit.add(self, ["/etc/nginx"], msg="Adding /etc/nginx/conf.d/" @@ -1715,3 +1738,16 @@ def archivedCertificateHandle(self, domain): .format(domain)) return ssl + + +def setuprocketchat(self): + if ((not WOVariables.wo_platform_codename == 'bionic') and + (not WOVariables.wo_platform_codename == 'xenial')): + Log.info(self, "Rocket.chat is only available on Ubuntu 16.04 " + "& 18.04 LTS") + return False + else: + if not WOAptGet.is_installed(self, 'snapd'): + WOAptGet.install(self, ["snapd"]) + if WOShellExec.cmd_exec(self, "snap install rocketchat-server"): + return True diff --git a/wo/cli/plugins/stack.py b/wo/cli/plugins/stack.py index 72f6c79..5f0b022 100644 --- a/wo/cli/plugins/stack.py +++ b/wo/cli/plugins/stack.py @@ -9,11 +9,12 @@ import re import shutil import string +import psutil import requests -import psutil from cement.core import handler, hook from cement.core.controller import CementBaseController, expose + from wo.cli.plugins.site_functions import * from wo.cli.plugins.sitedb import * from wo.cli.plugins.stack_migrate import WOStackMigrateController @@ -189,9 +190,8 @@ class WOStackController(CementBaseController): # Redis if pargs.redis: - pargs.php = True if not WOAptGet.is_installed(self, 'redis-server'): - apt_packages = apt_packages + ["redis-server"] + apt_packages = apt_packages + WOVariables.wo_redis else: Log.info(self, "Redis already installed") @@ -200,11 +200,8 @@ class WOStackController(CementBaseController): if pargs.php: Log.debug(self, "Setting apt_packages variable for PHP 7.2") if not (WOAptGet.is_installed(self, 'php7.2-fpm')): - if not (WOAptGet.is_installed(self, 'php7.3-fpm')): - apt_packages = (apt_packages + WOVariables.wo_php + - WOVariables.wo_php_extra) - else: - apt_packages = apt_packages + WOVariables.wo_php + apt_packages = (apt_packages + WOVariables.wo_php + + WOVariables.wo_php_extra) else: Log.debug(self, "PHP 7.2 already installed") Log.info(self, "PHP 7.2 already installed") @@ -213,12 +210,9 @@ class WOStackController(CementBaseController): if pargs.php73: Log.debug(self, "Setting apt_packages variable for PHP 7.3") if not WOAptGet.is_installed(self, 'php7.3-fpm'): - if not (WOAptGet.is_installed(self, 'php7.2-fpm')): - apt_packages = (apt_packages + WOVariables.wo_php + - WOVariables.wo_php73 + - WOVariables.wo_php_extra) - else: - apt_packages = apt_packages + WOVariables.wo_php73 + apt_packages = (apt_packages + WOVariables.wo_php + + WOVariables.wo_php73 + + WOVariables.wo_php_extra) else: Log.debug(self, "PHP 7.3 already installed") Log.info(self, "PHP 7.3 already installed") @@ -228,17 +222,7 @@ class WOStackController(CementBaseController): pargs.mysqltuner = True Log.debug(self, "Setting apt_packages variable for MySQL") if not WOShellExec.cmd_exec(self, "mysqladmin ping"): - if not WOVariables.wo_distro == 'raspbian': - if (not WOVariables.wo_platform_codename == 'jessie'): - wo_mysql = ["mariadb-server", "percona-toolkit", - "python3-mysqldb", "mariadb-backup"] - else: - wo_mysql = ["mariadb-server", "percona-toolkit", - "python3-mysql.connector"] - else: - wo_mysql = ["mariadb-server", "percona-toolkit", - "python3-mysqldb"] - apt_packages = apt_packages + wo_mysql + apt_packages = apt_packages + WOVariables.wo_mysql else: Log.debug(self, "MySQL already installed and alive") Log.info(self, "MySQL already installed and alive") @@ -502,13 +486,13 @@ class WOStackController(CementBaseController): WOAptGet.install(self, apt_packages) Log.valide(self, "Installing APT packages ") Log.wait(self, "Configuring APT packages ") - post_pref(self, apt_packages, empty_packages) + post_pref(self, apt_packages, []) Log.valide(self, "Configuring APT packages ") if (packages): Log.debug(self, "Downloading following: {0}".format(packages)) WODownload.download(self, packages) Log.debug(self, "Calling post_pref") - post_pref(self, empty_packages, packages) + post_pref(self, [], packages) if disp_msg: if (self.msg): @@ -548,6 +532,7 @@ class WOStackController(CementBaseController): pargs.proftpd = True pargs.utils = True pargs.redis = True + pargs.security = True packages = packages + ['/var/www/22222/htdocs'] if pargs.web: @@ -823,6 +808,7 @@ class WOStackController(CementBaseController): Log.debug(self, "Removing apt_packages variable of MySQL") apt_packages = apt_packages + ['mariadb-server', 'mysql-common', 'mariadb-client'] + packages = packages + ['/etc/mysql', '/var/lib/mysql'] # mysqlclient if pargs.mysqlclient: diff --git a/wo/cli/plugins/stack_migrate.py b/wo/cli/plugins/stack_migrate.py index 5c47906..7b64b37 100644 --- a/wo/cli/plugins/stack_migrate.py +++ b/wo/cli/plugins/stack_migrate.py @@ -3,6 +3,7 @@ import os from cement.core import handler, hook from cement.core.controller import CementBaseController, expose + from wo.core.apt_repo import WORepo from wo.core.aptget import WOAptGet from wo.core.logging import Log @@ -28,6 +29,17 @@ class WOStackMigrateController(CementBaseController): # Backup all database WOMysql.backupAll(self) + if not WOVariables.wo_distro == 'raspbian': + if (not WOVariables.wo_platform_codename == 'jessie'): + wo_mysql = ["mariadb-server", "percona-toolkit", + "python3-mysqldb", "mariadb-backup"] + else: + wo_mysql = ["mariadb-server", "percona-toolkit", + "python3-mysql.connector"] + else: + wo_mysql = ["mariadb-server", "percona-toolkit", + "python3-mysqldb"] + # Add MariaDB repo Log.info(self, "Adding repository for MariaDB, please wait...") @@ -78,7 +90,7 @@ class WOStackMigrateController(CementBaseController): log=False) # Install MariaDB - apt_packages = ["mariadb-server"] + apt_packages = wo_mysql Log.info(self, "Updating apt-cache, hang on...") WOAptGet.update(self) diff --git a/wo/cli/plugins/stack_pref.py b/wo/cli/plugins/stack_pref.py index b131c13..7488f70 100644 --- a/wo/cli/plugins/stack_pref.py +++ b/wo/cli/plugins/stack_pref.py @@ -23,14 +23,13 @@ from wo.core.services import WOService from wo.core.shellexec import CommandExecutionError, WOShellExec from wo.core.template import WOTemplate from wo.core.variables import WOVariables +from wo.core.sslutils import SSL def pre_pref(self, apt_packages): """Pre settings to do before installation packages""" - if (set(["mariadb-server"]).issubset(set(apt_packages)) or - set(["mariadb-client"]).issubset(set(apt_packages)) or - set(["mariadb-backup"]).issubset((set(apt_packages)))): + if ("mariadb-server" in apt_packages or "mariadb-client" in apt_packages): # add mariadb repository excepted on raspbian and ubuntu 19.04 if (not WOVariables.wo_distro == 'raspbian'): Log.info(self, "Adding repository for MySQL, please wait...") @@ -41,13 +40,11 @@ def pre_pref(self, apt_packages): 'MariaDB.pref', 'w') as mysql_pref_file: mysql_pref_file.write(mysql_pref) WORepo.add(self, repo_url=WOVariables.wo_mysql_repo) - Log.debug(self, 'Adding key for {0}' - .format(WOVariables.wo_mysql_repo)) WORepo.add_key(self, '0xcbcb082a1bb943db', - keyserver="keyserver.ubuntu.com") + keyserver='keys.gnupg.net') WORepo.add_key(self, '0xF1656F24C74CD1D8', - keyserver="keyserver.ubuntu.com") - if set(["mariadb-server"]).issubset(set(apt_packages)): + keyserver='hkp://keys.gnupg.net') + if "mariadb-server" in apt_packages: # generate random 24 characters root password chars = ''.join(random.sample(string.ascii_letters, 24)) @@ -139,7 +136,7 @@ def pre_pref(self, apt_packages): Log.debug(self, 'Adding deb.sury GPG key') WORepo.add_key(self, WOVariables.wo_php_key) # add redis repository - if set(['redis-server']).issubset(set(apt_packages)): + if set(WOVariables.wo_redis).issubset(set(apt_packages)): Log.info(self, "Adding repository for Redis, please wait...") if WOVariables.wo_distro == 'ubuntu': Log.debug(self, 'Adding ppa for redis') @@ -367,7 +364,7 @@ def post_pref(self, apt_packages, packages, upgrade=False): WOTemplate.render( self, '/etc/nginx/sites-available/22222', - '22222.mustache', data, overwrite=False) + '22222.mustache', data, overwrite=True) passwd = ''.join([random.choice (string.ascii_letters + string.digits) for n in range(24)]) @@ -392,98 +389,60 @@ def post_pref(self, apt_packages, packages, upgrade=False): '/etc/nginx/' 'sites-enabled/' '22222']) - # Create log and cert folder and softlinks - if not os.path.exists('{0}22222/logs' - .format(ngxroot)): - Log.debug(self, "Creating directory " - "{0}22222/logs " - .format(ngxroot)) - os.makedirs('{0}22222/logs' - .format(ngxroot)) - - if not os.path.exists('{0}22222/cert' - .format(ngxroot)): - Log.debug(self, "Creating directory " - "{0}22222/cert" - .format(ngxroot)) - os.makedirs('{0}22222/cert' - .format(ngxroot)) - - if not os.path.isdir('{0}22222/conf/nginx' - .format(ngxroot)): - Log.debug(self, "Creating directory " - "{0}22222/conf/nginx" - .format(ngxroot)) - os.makedirs('{0}22222/conf/nginx' - .format(ngxroot)) - - WOFileUtils.create_symlink( - self, - ['/var/log/nginx/' - '22222.access.log', - '{0}22222/' - 'logs/access.log' - .format(ngxroot)] - ) - - WOFileUtils.create_symlink( - self, - ['/var/log/nginx/' - '22222.error.log', - '{0}22222/' - 'logs/error.log' - .format(ngxroot)] - ) - - try: - WOShellExec.cmd_exec( - self, "openssl genrsa -out " - "{0}22222/cert/22222.key 2048" - .format(ngxroot)) - WOShellExec.cmd_exec( - self, "openssl req -new -batch " - "-subj /commonName=localhost/ " - "-key {0}22222/cert/22222.key " - "-out {0}22222/cert/" - "22222.csr" + # Create log and cert folder and softlinks + if not os.path.exists('{0}22222/logs' + .format(ngxroot)): + Log.debug(self, "Creating directory " + "{0}22222/logs " + .format(ngxroot)) + os.makedirs('{0}22222/logs' .format(ngxroot)) - WOFileUtils.mvfile( - self, "{0}22222/cert/22222.key" - .format(ngxroot), - "{0}22222/cert/" - "22222.key.org" + if not os.path.exists('{0}22222/cert' + .format(ngxroot)): + Log.debug(self, "Creating directory " + "{0}22222/cert" + .format(ngxroot)) + os.makedirs('{0}22222/cert' .format(ngxroot)) - WOShellExec.cmd_exec( - self, "openssl rsa -in " - "{0}22222/cert/" - "22222.key.org -out " - "{0}22222/cert/22222.key" + if not os.path.isdir('{0}22222/conf/nginx' + .format(ngxroot)): + Log.debug(self, "Creating directory " + "{0}22222/conf/nginx" + .format(ngxroot)) + os.makedirs('{0}22222/conf/nginx' .format(ngxroot)) - WOShellExec.cmd_exec( - self, "openssl x509 -req -days " - "3652 -in {0}22222/cert/" - "22222.csr -signkey {0}" - "22222/cert/22222.key -out " - "{0}22222/cert/22222.crt" - .format(ngxroot)) + WOFileUtils.create_symlink( + self, + ['/var/log/nginx/' + '22222.access.log', + '{0}22222/' + 'logs/access.log' + .format(ngxroot)] + ) - except CommandExecutionError as e: - Log.debug(self, "{0}".format(e)) - Log.error( - self, "Failed to generate HTTPS " - "certificate for 22222", False) + WOFileUtils.create_symlink( + self, + ['/var/log/nginx/' + '22222.error.log', + '{0}22222/' + 'logs/error.log' + .format(ngxroot)] + ) + if (not os.path.isfile('{0}22222/cert/22222.key' + .format(ngxroot))): + SSL.selfsignedcert(self, proftpd=False, backend=True) - if not os.path.isfile('{0}22222/conf/nginx/ssl.conf' - .format(ngxroot)): - with open("/var/www/22222/conf/nginx/" - "ssl.conf", "w") as php_file: - php_file.write("ssl_certificate " - "/var/www/22222/cert/22222.crt;\n" - "ssl_certificate_key " - "/var/www/22222/cert/22222.key;\n") + if not os.path.isfile('{0}22222/conf/nginx/ssl.conf' + .format(ngxroot)): + with open("/var/www/22222/conf/nginx/" + "ssl.conf", "w") as php_file: + php_file.write("ssl_certificate " + "/var/www/22222/cert/22222.crt;\n" + "ssl_certificate_key " + "/var/www/22222/cert/22222.key;\n") server_ip = requests.get('http://v4.wordops.eu') @@ -876,7 +835,7 @@ def post_pref(self, apt_packages, packages, upgrade=False): WOService.restart_service(self, 'php7.3-fpm') # create mysql config if it doesn't exist - if set(["mariadb-server"]).issubset(set(apt_packages)): + if "mariadb-server" in apt_packages: if not os.path.isfile("/etc/mysql/my.cnf"): config = ("[mysqld]\nwait_timeout = 30\n" "interactive_timeout=60\nperformance_schema = 0" @@ -953,7 +912,7 @@ def post_pref(self, apt_packages, packages, upgrade=False): WOService.reload_service(self, 'fail2ban') # Proftpd configuration - if set(["proftpd-basic"]).issubset(set(apt_packages)): + if "proftpd-basic" in apt_packages: if os.path.isfile("/etc/proftpd/proftpd.conf"): Log.info(self, "Configuring ProFTPd") Log.debug(self, "Setting up Proftpd configuration") @@ -976,28 +935,7 @@ def post_pref(self, apt_packages, packages, upgrade=False): # proftpd TLS configuration if not os.path.isdir("/etc/proftpd/ssl"): WOFileUtils.mkdir(self, "/etc/proftpd/ssl") - - try: - WOShellExec.cmd_exec(self, "openssl genrsa -out " - "/etc/proftpd/ssl/proftpd.key 2048") - WOShellExec.cmd_exec(self, "openssl req -new -batch " - "-subj /commonName=localhost/ " - "-key /etc/proftpd/ssl/proftpd.key " - "-out /etc/proftpd/ssl/proftpd.csr") - WOFileUtils.mvfile(self, "/etc/proftpd/ssl/proftpd.key", - "/etc/proftpd/ssl/proftpd.key.org") - WOShellExec.cmd_exec(self, "openssl rsa -in " - "/etc/proftpd/ssl/proftpd.key.org " - "-out /etc/proftpd/ssl/proftpd.key") - WOShellExec.cmd_exec(self, "openssl x509 -req -days " - "3652 -in /etc/proftpd/ssl/proftpd.csr " - "-signkey /etc/proftpd/ssl/proftpd.key " - " -out /etc/proftpd/ssl/proftpd.crt") - except CommandExecutionError as e: - Log.debug(self, "{0}".format(e)) - Log.error( - self, "Failed to generate SSL " - "certificate for Proftpd") + SSL.selfsignedcert(self, proftpd=True, backend=False) WOFileUtils.chmod(self, "/etc/proftpd/ssl/proftpd.key", 0o700) WOFileUtils.chmod(self, "/etc/proftpd/ssl/proftpd.crt", 0o700) data = dict() @@ -1041,7 +979,7 @@ def post_pref(self, apt_packages, packages, upgrade=False): WOService.reload_service(self, 'proftpd') # Redis configuration - if set(['redus-server']).issubset(set(apt_packages)): + if "redis-server" in apt_packages: if os.path.isfile("/etc/nginx/conf.d/upstream.conf"): if not WOFileUtils.grep(self, "/etc/nginx/conf.d/" "upstream.conf", @@ -1072,7 +1010,7 @@ def post_pref(self, apt_packages, packages, upgrade=False): if (os.path.isfile("/etc/redis/redis.conf") and (not WOFileUtils.grep(self, "/etc/redis/redis.conf", "WordOps"))): - Log.info(self, "Tuning Redis configuration") + Log.wait(self, "Tuning Redis configuration") with open("/etc/redis/redis.conf", "a") as redis_file: redis_file.write("\n# WordOps v3.9.8\n") @@ -1116,6 +1054,7 @@ def post_pref(self, apt_packages, packages, upgrade=False): WOFileUtils.chown(self, '/etc/redis/redis.conf', 'redis', 'redis', recursive=False) WOService.restart_service(self, 'redis-server') + Log.valide(self, "Tuning Redis configuration") # ClamAV configuration if set(WOVariables.wo_clamav).issubset(set(apt_packages)): diff --git a/wo/cli/plugins/stack_upgrade.py b/wo/cli/plugins/stack_upgrade.py index 1f6e2b2..694a198 100644 --- a/wo/cli/plugins/stack_upgrade.py +++ b/wo/cli/plugins/stack_upgrade.py @@ -62,7 +62,6 @@ class WOStackUpgradeController(CementBaseController): # All package update apt_packages = [] packages = [] - nginx_packages = [] self.msg = [] pargs = self.app.pargs @@ -94,7 +93,7 @@ class WOStackUpgradeController(CementBaseController): if pargs.nginx: if WOAptGet.is_installed(self, 'nginx-custom'): - nginx_packages = nginx_packages + WOVariables.wo_nginx + apt_packages = apt_packages + WOVariables.wo_nginx else: Log.info(self, "Nginx Stable is not already installed") @@ -178,41 +177,56 @@ class WOStackUpgradeController(CementBaseController): "Composer"]] else: Log.error(self, "Composer isn't installed") - if len(apt_packages) or len(packages): - if len(apt_packages): - Log.info(self, "Your site may be down for few seconds if " - "you are upgrading Nginx, PHP-FPM, MariaDB or Redis") + + if ((not (apt_packages)) and (not(packages))): + self.app.args.print_help() + else: + if (apt_packages): + if not (set(["php7.2-fpm"]).issubset(set(apt_packages)) and + set(["php7.3-fpm"]).issubset(set(apt_packages)) and + set(["nginx-custom", + "nginx-wo"]).issubset(set(apt_packages)) and + set(['mariadb-server']).issubset(set(apt_packages))): + pass + else: + Log.info( + self, "Your site may be down for few seconds if " + "you are upgrading Nginx, PHP-FPM, MariaDB or Redis") # Check prompt if ((not pargs.no_prompt) and (not pargs.force)): start_upgrade = input("Do you want to continue:[y/N]") if start_upgrade != "Y" and start_upgrade != "y": Log.error(self, "Not starting package update") - Log.info(self, "Updating APT packages, please wait...") - - pre_pref(self, nginx_packages) + Log.wait(self, "Updating APT packages") # apt-get update WOAptGet.update(self) - if set(WOVariables.wo_php).issubset(set(apt_packages)): + Log.valide(self, "Updating APT packages") + Log.wait(self, "Upgrading APT Packages") + + # additional pre_pref + if ["nginx-custom"] in apt_packages: + pre_pref(self, WOVariables.wo_nginx) + if ["php7.2-fpm"] in apt_packages: WOAptGet.remove(self, ['php7.2-fpm'], auto=False, purge=True) - if set(WOVariables.wo_php73).issubset(set(apt_packages)): + if ["php7.3-fpm"] in apt_packages: WOAptGet.remove(self, ['php7.3-fpm'], auto=False, purge=True) - # Update packages - if not os.path.isfile( - '/etc/apt/preferences.d/nginx-block'): - WOAptGet.install(self, nginx_packages) - Log.wait(self, "Upgrading APT Packages ") + # check if nginx upgrade is blocked + if os.path.isfile( + '/etc/apt/preferences.d/nginx-block'): + apt_packages.remove(WOVariables.wo_nginx) + post_pref(self, WOVariables.wo_nginx, [], True) + # upgrade packages WOAptGet.install(self, apt_packages) - Log.valide(self, "Upgrading APT Packages ") - Log.wait(self, "Configuring APT Packages ") - post_pref(self, nginx_packages, [], True) - Log.valide(self, "Configuring APT Packages ") + Log.valide(self, "Upgrading APT Packages") + Log.wait(self, "Configuring APT Packages") post_pref(self, apt_packages, [], True) + Log.valide(self, "Configuring APT Packages") # Post Actions after package updates - if len(packages): + if (packages): if pargs.wpcli: WOFileUtils.rm(self, '/usr/local/bin/wp') @@ -229,7 +243,7 @@ class WOStackUpgradeController(CementBaseController): WOFileUtils.chmod(self, "/usr/local/bin/wp", 0o775) if pargs.netdata: - Log.wait(self, "Upgrading Netdata ") + Log.wait(self, "Upgrading Netdata") if os.path.isdir('/opt/netdata'): WOShellExec.cmd_exec( self, "bash /opt/netdata/usr/" @@ -240,7 +254,7 @@ class WOStackUpgradeController(CementBaseController): self, "bash /usr/" "libexec/netdata/netdata-" "updater.sh") - Log.valide(self, "Upgrading Netdata ") + Log.valide(self, "Upgrading Netdata") if pargs.dashboard: Log.debug(self, "Extracting wo-dashboard.tar.gz " @@ -252,21 +266,22 @@ class WOStackUpgradeController(CementBaseController): .format(WOVariables.wo_webroot)) WOFileUtils.chown(self, "{0}22222/htdocs" .format(WOVariables.wo_webroot), - WOVariables.wo_php_user, - WOVariables.wo_php_user, recursive=True) + 'www-data', + 'www-data', recursive=True) if pargs.composer: - Log.wait(self, "Upgrading Composer ") - WOShellExec.cmd_exec(self, "php -q /var/lib/wo" - "/tmp/composer-install " - "--install-dir=/var/lib/wo/tmp/") + Log.wait(self, "Upgrading Composer ") + WOShellExec.cmd_exec( + self, "php -q /var/lib/wo" + "/tmp/composer-install " + "--install-dir=/var/lib/wo/tmp/") shutil.copyfile('/var/lib/wo/tmp/composer.phar', '/usr/local/bin/composer') WOFileUtils.chmod(self, "/usr/local/bin/composer", 0o775) - Log.valide(self, "Upgrading Composer ") + Log.valide(self, "Upgrading Composer ") if pargs.phpmyadmin: - Log.wait(self, "Upgrading phpMyAdmin ") + Log.wait(self, "Upgrading phpMyAdmin ") WOExtract.extract(self, '/var/lib/wo/tmp/pma.tar.gz', '/var/lib/wo/tmp/') shutil.copyfile(('{0}22222/htdocs/db/pma' @@ -285,10 +300,8 @@ class WOStackUpgradeController(CementBaseController): .format(WOVariables.wo_webroot)) WOFileUtils.chown(self, "{0}22222/htdocs" .format(WOVariables.wo_webroot), - WOVariables.wo_php_user, - WOVariables.wo_php_user, recursive=True) - Log.valide(self, "Upgrading phpMyAdmin ") + 'www-data', + 'www-data', recursive=True) + Log.valide(self, "Upgrading phpMyAdmin ") Log.info(self, "Successfully updated packages") - else: - self.app.args.print_help() diff --git a/wo/cli/templates/nextcloud.mustache b/wo/cli/templates/nextcloud.mustache new file mode 100644 index 0000000..f907de7 --- /dev/null +++ b/wo/cli/templates/nextcloud.mustache @@ -0,0 +1,82 @@ +# WordOps nextcloud configuration + add_header X-Robots-Tag none; + add_header X-Permitted-Cross-Domain-Policies none; + add_header Referrer-Policy no-referrer; + + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + + # Enable gzip but do not remove ETag headers + gzip on; + gzip_vary on; + gzip_comp_level 4; + gzip_min_length 256; + gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; + gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; + + location / { + rewrite ^ /index.php$request_uri; + } + + location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ { + deny all; + } + location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) { + deny all; + } + + location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) { + fastcgi_split_path_info ^(.+?\.php)(\/.*|)$; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param HTTPS on; + # Avoid sending the security headers twice + fastcgi_param modHeadersAvailable true; + # Enable pretty urls + fastcgi_param front_controller_active true; + fastcgi_pass {{upstream}}; + fastcgi_intercept_errors on; + fastcgi_request_buffering off; + } + + location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) { + try_files $uri/ =404; + index index.php; + } + + # Adding the cache control header for js, css and map files + # Make sure it is BELOW the PHP block + location ~ \.(?:css|js|woff2?|svg|gif|map)$ { + try_files $uri /index.php$request_uri; + add_header Cache-Control "public, max-age=15778463"; + # Add headers to serve security related headers (It is intended to + # have those duplicated to the ones above) + # Before enabling Strict-Transport-Security headers please read into + # this topic first. + #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;"; + # + # WARNING: Only add the preload option once you read about + # the consequences in https://hstspreload.org/. This option + # will add the domain to a hardcoded list that is shipped + # in all major browsers and getting removed from this list + # could take several months. + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Robots-Tag none; + add_header X-Download-Options noopen; + add_header X-Permitted-Cross-Domain-Policies none; + add_header Referrer-Policy no-referrer; + + # Optional: Don't log access to assets + access_log off; + } + + location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ { + try_files $uri /index.php$request_uri; + # Optional: Don't log access to other assets + access_log off; + } diff --git a/wo/core/apt_repo.py b/wo/core/apt_repo.py index 1715639..1684b6e 100644 --- a/wo/core/apt_repo.py +++ b/wo/core/apt_repo.py @@ -48,8 +48,9 @@ class WORepo(): Log.debug(self, "{0}".format(e)) Log.error(self, "Unable to add repo") if ppa is not None: - WOShellExec.cmd_exec(self, "LC_ALL=C.UTF-8 add-apt-repository -yu '{ppa_name}'" - .format(ppa_name=ppa)) + WOShellExec.cmd_exec( + self, "LC_ALL=C.UTF-8 add-apt-repository -yu '{ppa_name}'" + .format(ppa_name=ppa)) def remove(self, ppa=None, repo_url=None): """ @@ -77,13 +78,35 @@ class WORepo(): Log.debug(self, "{0}".format(e)) Log.error(self, "Unable to remove repo") - def add_key(self, keyids, keyserver=None): + def add_key(self, keyid, keyserver=None): """ This function adds imports repository keys from keyserver. default keyserver is hkp://keyserver.ubuntu.com user can provide other keyserver with keyserver="hkp://xyz" """ - WOShellExec.cmd_exec(self, "apt-key adv --keyserver {serv}" - .format(serv=(keyserver or - "hkp://keyserver.ubuntu.com")) + - " --recv-keys {key}".format(key=keyids)) + try: + WOShellExec.cmd_exec( + self, "apt-key adv --keyserver {serv}" + .format(serv=(keyserver or + "hkp://keyserver.ubuntu.com")) + + " --recv-keys {key}".format(key=keyid)) + except Exception as e: + Log.debug(self, "{0}".format(e)) + Log.error(self, "Unable to import repo key") + + def add_keys(self, keyids, keyserver=None): + """ + This function adds imports repository keys from keyserver. + default keyserver is hkp://keyserver.ubuntu.com + user can provide other keyserver with keyserver="hkp://xyz" + """ + all_keys = ' '.join(keyids) + try: + WOShellExec.cmd_exec( + self, "apt-key adv --keyserver {serv}" + .format(serv=(keyserver or + "hkp://keyserver.ubuntu.com")) + + " --recv-keys {keys}".format(keys=all_keys)) + except Exception as e: + Log.debug(self, "{0}".format(e)) + Log.error(self, "Unable to import repo keys") diff --git a/wo/core/aptget.py b/wo/core/aptget.py index 3bff57e..e41a4f6 100644 --- a/wo/core/aptget.py +++ b/wo/core/aptget.py @@ -54,7 +54,7 @@ class WOAptGet(): "`tail /var/log/wo/wordops.log` " "and please try again...") - except Exception as e: + except Exception: Log.error(self, "apt-get update exited with error") def check_upgrade(self): diff --git a/wo/core/logging.py b/wo/core/logging.py index 3078f59..bb6cbda 100644 --- a/wo/core/logging.py +++ b/wo/core/logging.py @@ -50,9 +50,12 @@ class Log: """ Logs info messages with validation step """ + space_to_add = int(31 - len(msg[0:31])) + space = " " print( - Log.OKBLUE + msg + - " [" + Log.ENDC + ".." + Log.OKBLUE + "]" + Log.ENDC, end=end) + Log.OKBLUE + "{0}".format(msg[0:31]) + + "{0}".format(space[0:space_to_add]) + + " [" + Log.ENDC + ".." + Log.OKBLUE + "]" + Log.ENDC, end=end) if log: self.app.log.info(Log.OKBLUE + msg + Log.ENDC) @@ -60,9 +63,12 @@ class Log: """ Logs info messages after validation step """ + space_to_add = int(31 - len(msg[0:31])) + space = " " print( - Log.OKBLUE + msg + - " [" + Log.ENDC + Log.OKGREEN + "OK" + + Log.OKBLUE + "{0}".format(msg[0:31]) + + "{0}".format(space[0:space_to_add]) + + " [" + Log.ENDC + Log.OKGREEN + "OK" + Log.ENDC + Log.OKBLUE + "]" + Log.ENDC, end=end) if log: self.app.log.info(Log.OKGREEN + msg + Log.ENDC) @@ -71,9 +77,12 @@ class Log: """ Logs info messages after validation step """ + space_to_add = int(31 - len(msg[0:31])) + space = " " print( - Log.OKBLUE + msg + - " [" + Log.ENDC + Log.FAIL + "OK" + + Log.OKBLUE + "{0}".format(msg[0:31]) + + "{0}".format(space[0:space_to_add]) + + " [" + Log.ENDC + Log.FAIL + "KO" + Log.ENDC + Log.OKBLUE + "]" + Log.ENDC, end=end) if log: self.app.log.info(Log.FAIL + msg + Log.ENDC) diff --git a/wo/core/services.py b/wo/core/services.py index 5d4a1bd..dc874b2 100644 --- a/wo/core/services.py +++ b/wo/core/services.py @@ -38,7 +38,8 @@ class WOService(): Log.info(self, "Start : {0:10}" .format(service_name), end='') retcode = subprocess.getstatusoutput(service_cmd) if retcode[0] == 0: - Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]") + Log.info(self, "[" + Log.ENDC + Log.OKGREEN + + "OK" + Log.ENDC + Log.OKBLUE + "]") return True else: Log.debug(self, "{0}".format(retcode[1])) @@ -55,11 +56,12 @@ class WOService(): Similar to `service xyz stop` """ try: - Log.info(self, "Stop : {0:10}" .format(service_name), end='') + Log.info(self, "Stop : {0:10}" .format(service_name), end='') retcode = subprocess.getstatusoutput('service {0} stop' .format(service_name)) if retcode[0] == 0: - Log.info(self, "[" + Log.ENDC + "OK" + Log.OKBLUE + "]") + Log.info(self, "[" + Log.ENDC + Log.OKGREEN + "OK" + + Log.ENDC + Log.OKBLUE + "]") return True else: Log.debug(self, "{0}".format(retcode[1])) diff --git a/wo/core/sslutils.py b/wo/core/sslutils.py index d380557..b04745f 100644 --- a/wo/core/sslutils.py +++ b/wo/core/sslutils.py @@ -39,6 +39,9 @@ class SSL: def getexpirationdate(self, domain): # check if exist + if os.path.islink('/var/www/{0}/conf/nginx/ssl.conf'): + split_domain = domain.split('.') + domain = ('.').join(split_domain[1:]) if not os.path.isfile('/etc/letsencrypt/live/{0}/cert.pem' .format(domain)): Log.error(self, 'File Not Found: /etc/letsencrypt/' @@ -68,22 +71,26 @@ class SSL: "--allow-root --quiet")) test_url = re.split(":", wo_siteurl) if not (test_url[0] == 'https'): - WOShellExec.cmd_exec( - self, "{0} option update siteurl " - "\'https://{1}\' --allow-root".format( - WOVariables.wo_wpcli_path, domain)) - WOShellExec.cmd_exec( - self, "{0} option update home " - "\'https://{1}\' --allow-root".format( - WOVariables.wo_wpcli_path, domain)) - WOShellExec.cmd_exec( - self, "{0} search-replace \'http://{0}\'" - "\'https://{0}\' --skip-columns=guid " - "--skip-tables=wp_users" - .format(domain)) - Log.info( - self, "Site address updated " - "successfully to https://{0}".format(domain)) + Log.wait(self, "Updating site url with https") + try: + WOShellExec.cmd_exec( + self, "{0} option update siteurl " + "\'https://{1}\' --allow-root".format( + WOVariables.wo_wpcli_path, domain)) + WOShellExec.cmd_exec( + self, "{0} option update home " + "\'https://{1}\' --allow-root".format( + WOVariables.wo_wpcli_path, domain)) + WOShellExec.cmd_exec( + self, "{0} search-replace \'http://{0}\'" + "\'https://{0}\' --skip-columns=guid " + "--skip-tables=wp_users" + .format(domain)) + except Exception as e: + Log.debug(self, str(e)) + Log.failed(self, "Updating site url with https") + else: + Log.valide(self, "Updating site url with https") # check if a wildcard exist to secure a new subdomain @@ -111,3 +118,81 @@ class SSL: certfile.close() return iswildcard + + def setupHsts(self, wo_domain_name): + Log.info( + self, "Adding /var/www/{0}/conf/nginx/hsts.conf" + .format(wo_domain_name)) + + hstsconf = open("/var/www/{0}/conf/nginx/hsts.conf" + .format(wo_domain_name), + encoding='utf-8', mode='w') + hstsconf.write("more_set_headers " + "\"Strict-Transport-Security: " + "max-age=31536000; " + "includeSubDomains; " + "preload\";") + hstsconf.close() + return 0 + + def selfsignedcert(self, proftpd=False, backend=False): + """issue a self-signed certificate""" + + selfs_tmp = '/var/lib/wo/tmp/selfssl' + # create self-signed tmp directory + if not os.path.isdir(selfs_tmp): + WOFileUtils.mkdir(self, selfs_tmp) + try: + WOShellExec.cmd_exec( + self, "openssl genrsa -out " + "{0}/ssl.key 2048" + .format(selfs_tmp)) + WOShellExec.cmd_exec( + self, "openssl req -new -batch " + "-subj /commonName=localhost/ " + "-key {0}/ssl.key -out {0}/ssl.csr" + .format(selfs_tmp)) + + WOFileUtils.mvfile( + self, "{0}/ssl.key" + .format(selfs_tmp), + "{0}/ssl.key.org" + .format(selfs_tmp)) + + WOShellExec.cmd_exec( + self, "openssl rsa -in " + "{0}/ssl.key.org -out " + "{0}/ssl.key" + .format(selfs_tmp)) + + WOShellExec.cmd_exec( + self, "openssl x509 -req -days " + "3652 -in {0}/ssl.csr -signkey {0}" + "/ssl.key -out {0}/ssl.crt" + .format(selfs_tmp)) + + except Exception as e: + Log.debug(self, "{0}".format(e)) + Log.error( + self, "Failed to generate HTTPS " + "certificate for 22222", False) + if backend: + WOFileUtils.mvfile( + self, "{0}/ssl.key" + .format(selfs_tmp), + "/var/www/22222/cert/22222.key") + WOFileUtils.mvfile( + self, "{0}/ssl.crt" + .format(selfs_tmp), + "/var/www/22222/cert/22222.crt") + if proftpd: + WOFileUtils.mvfile( + self, "{0}/ssl.key" + .format(selfs_tmp), + "/etc/proftpd/ssl/proftpd.key") + WOFileUtils.mvfile( + self, "{0}/ssl.crt" + .format(selfs_tmp), + "/etc/proftpd/ssl/proftpd.crt") + # remove self-signed tmp directory + WOFileUtils.rm(self, selfs_tmp) diff --git a/wo/core/variables.py b/wo/core/variables.py index 10349b5..5e9b19b 100644 --- a/wo/core/variables.py +++ b/wo/core/variables.py @@ -145,13 +145,22 @@ class WOVariables(): "10.3/debian {codename} main" .format(codename=wo_platform_codename)) + if not wo_distro == 'raspbian': + if (not wo_platform_codename == 'jessie'): + wo_mysql = ["mariadb-server", "percona-toolkit", + "python3-mysqldb", "mariadb-backup"] + else: + wo_mysql = ["mariadb-server", "percona-toolkit", + "python3-mysql.connector"] + else: + wo_mysql = ["mariadb-server", "percona-toolkit", + "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"] wo_clamav = ["clamav", "clamav-freshclam"]