From 5abc051901e5b490b767035b008e7f5486f9e13f Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Mon, 23 Sep 2019 12:11:15 +0200 Subject: [PATCH] Add `wo secure --ssh` --- CHANGELOG.md | 6 ++ config/bash_completion.d/wo_auto.rc | 2 +- wo/cli/plugins/secure.py | 33 +++++++++- wo/cli/plugins/stack.py | 98 ++++++++++++++++++----------- 4 files changed, 97 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84590ce..7d700c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### v3.9.x - [Unreleased] +#### Added + +- [STACK] UFW as a STACK available with `--ufw` + #### Changed - [APP] WordOps dashboard updated to v1.2, shipped as a html file, it can be used without PHP stack - [STACK] Refactor Let's Encrypt with acme.sh - [STACK] Log error improved with acme.sh depending on the acme challenge (DNS API or Webroot) +- [INSTALL] Removed UFW setup from install script +- [APP] phpMyAdmin updated to v4.9.1 #### Fixed diff --git a/config/bash_completion.d/wo_auto.rc b/config/bash_completion.d/wo_auto.rc index f9bd70b..b6abc9e 100644 --- a/config/bash_completion.d/wo_auto.rc +++ b/config/bash_completion.d/wo_auto.rc @@ -74,7 +74,7 @@ _wo_complete() # HANDLE EVERYTHING AFTER THE THIRD LEVEL NAMESPACE "install" | "purge" | "remove" ) COMPREPLY=( $(compgen \ - -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 --force" \ + -W "--web --admin --security --nginx --php --php73 --mysql --wpcli --phpmyadmin --adminer --utils --redis --phpredisadmin --composer --netdata --fail2ban --dashboard --proftpd --clamav --mysqlclient --mysqltuner --extplorer --all --force" \ -- $cur) ) ;; "upgrade" ) diff --git a/wo/cli/plugins/secure.py b/wo/cli/plugins/secure.py index 8977707..b8bf8b8 100644 --- a/wo/cli/plugins/secure.py +++ b/wo/cli/plugins/secure.py @@ -1,4 +1,5 @@ import getpass +import os from cement.core import handler, hook from cement.core.controller import CementBaseController, expose @@ -8,7 +9,9 @@ from wo.core.logging import Log from wo.core.random import RANDOM from wo.core.services import WOService from wo.core.shellexec import WOShellExec +from wo.core.template import WOTemplate from wo.core.variables import WOVariables +from wo.core.services import WOService def wo_secure_hook(app): @@ -31,10 +34,10 @@ class WOSecureController(CementBaseController): dict(help='set backend port', action='store_true')), (['--ip'], dict(help='set backend whitelisted ip', action='store_true')), - (['--ssh-port'], dict( + (['--sshport'], dict( help='set custom ssh port', action='store_true')), - (['--ssh-strict'], dict(help='harden ssh security', - action='store_true')), + (['--ssh'], dict( + help='harden ssh security', action='store_true')), (['--ufw'], dict(help='setup and configure ufw firewall', action='store_true')), @@ -53,6 +56,10 @@ class WOSecureController(CementBaseController): self.secure_port() if pargs.ip: self.secure_ip() + if pargs.sshport: + self.secure_ssh_port() + if pargs.ssh: + self.secure_ssh() @expose(hide=True) def secure_auth(self): @@ -139,6 +146,26 @@ class WOSecureController(CementBaseController): Log.info(self, "Successfully added IP address in acl.conf file") + @expose(hide=True) + def secure_ssh(self): + """Harden ssh security""" + pargs = self.app.pargs + if pargs.user_input: + current_ssh_port = pargs.user_input + else: + if os.path.isfile('/etc/ssh/sshd_config'): + for line in open('/etc/ssh/sshd_config', encoding='utf-8'): + if 'Port' in line: + ssh_line = line.strip() + break + port = (ssh_line).split(' ') + current_ssh_port = port[1] + else: + Log.error(self, "SSH config file not found") + data = dict(sshport=current_ssh_port, allowpass='no') + WOTemplate.render(self, '/etc/ssh/sshd_config', 'sshd.mustache', data) + WOService.restart_service(self, 'ssh') + def load(app): handler.register(WOSecureController) diff --git a/wo/cli/plugins/stack.py b/wo/cli/plugins/stack.py index 843e227..c5072a1 100644 --- a/wo/cli/plugins/stack.py +++ b/wo/cli/plugins/stack.py @@ -122,7 +122,6 @@ class WOStackController(CementBaseController): pargs.web = True pargs.admin = True pargs.fail2ban = True - pargs.ufw = True if pargs.all: pargs.web = True @@ -262,8 +261,10 @@ class WOStackController(CementBaseController): # UFW if pargs.ufw: - Log.debug(self, "Setting apt_packages variable for UFW") - apt_packages = apt_packages + ["ufw"] + if not WOFileUtils.grep( + self, '/etc/ufw/ufw.conf', 'ENABLED=yes'): + Log.debug(self, "Setting apt_packages variable for UFW") + apt_packages = apt_packages + ["ufw"] # sendmail if pargs.sendmail: @@ -579,14 +580,17 @@ class WOStackController(CementBaseController): # REDIS if pargs.redis: - Log.debug(self, "Remove apt_packages variable of Redis") - apt_packages = apt_packages + ["redis-server"] + if WOAptGet.is_installed(self, 'redis-server'): + Log.debug(self, "Remove apt_packages variable of Redis") + apt_packages = apt_packages + ["redis-server"] # MariaDB if pargs.mysql: - Log.debug(self, "Removing apt_packages variable of MySQL") - apt_packages = apt_packages + ['mariadb-server', 'mysql-common', - 'mariadb-client'] + if WOAptGet.is_installed(self, 'mariadb-server'): + Log.debug(self, "Removing apt_packages variable of MySQL") + apt_packages = apt_packages + ['mariadb-server', + 'mysql-common', + 'mariadb-client'] # mysqlclient if pargs.mysqlclient: @@ -621,8 +625,9 @@ class WOStackController(CementBaseController): # UFW if pargs.ufw: - Log.debug(self, "Remove apt_packages variable for UFW") - apt_packages = apt_packages + ["ufw"] + if WOAptGet.is_installed(self, 'ufw'): + Log.debug(self, "Remove apt_packages variable for UFW") + apt_packages = apt_packages + ["ufw"] # WPCLI if pargs.wpcli: @@ -632,18 +637,22 @@ class WOStackController(CementBaseController): # PHPMYADMIN if pargs.phpmyadmin: - Log.debug(self, "Removing package of phpMyAdmin ") - packages = packages + ['{0}22222/htdocs/db/pma' - .format(WOVariables.wo_webroot)] + if os.path.isdir('{0}22222/htdocs/db/pma' + .format(WOVariables.wo_webroot)): + Log.debug(self, "Removing package of phpMyAdmin ") + packages = packages + ['{0}22222/htdocs/db/pma' + .format(WOVariables.wo_webroot)] # Composer if pargs.composer: Log.debug(self, "Removing package of Composer ") if os.path.isfile('/usr/local/bin/composer'): packages = packages + ['/usr/local/bin/composer'] + # MySQLTuner if pargs.mysqltuner: - Log.debug(self, "Removing packages for MySQLTuner ") - packages = packages + ['/usr/bin/mysqltuner'] + if os.path.isfile(/usr/bin/mysqltuner): + Log.debug(self, "Removing packages for MySQLTuner ") + packages = packages + ['/usr/bin/mysqltuner'] # PHPREDISADMIN if pargs.phpredisadmin: @@ -655,9 +664,11 @@ class WOStackController(CementBaseController): .format(WOVariables.wo_webroot)] # ADMINER if pargs.adminer: - Log.debug(self, "Removing package variable of Adminer ") - packages = packages + ['{0}22222/htdocs/db/adminer' - .format(WOVariables.wo_webroot)] + if os.path.isdir('{0}22222/htdocs/db/adminer' + .format(WOVariables.wo_webroot)): + Log.debug(self, "Removing package variable of Adminer ") + packages = packages + ['{0}22222/htdocs/db/adminer' + .format(WOVariables.wo_webroot)] if pargs.utils: Log.debug(self, "Removing package variable of utils ") packages = packages + ['{0}22222/htdocs/php/webgrind/' @@ -677,11 +688,17 @@ class WOStackController(CementBaseController): packages = packages + ['/var/lib/wo/tmp/kickstart.sh'] if pargs.dashboard: - Log.debug(self, "Removing Wo-Dashboard") - packages = packages + ['{0}22222/htdocs/assets' - .format(WOVariables.wo_webroot), - '{0}22222/htdocs/index.php' - .format(WOVariables.wo_webroot)] + if (os.path.isfile('{0}22222/htdocs/index.php' + .format(WOVariables.wo_webroot)) or + os.path.isfile('{0}22222/htdocs/index.html' + .format(WOVariables.wo_webroot))): + Log.debug(self, "Removing Wo-Dashboard") + packages = packages + ['{0}22222/htdocs/assets' + .format(WOVariables.wo_webroot), + '{0}22222/htdocs/index.php' + .format(WOVariables.wo_webroot), + '{0}22222/htdocs/index.html' + .format(WOVariables.wo_webroot)] if (packages) or (apt_packages): if (not pargs.force): @@ -693,10 +710,10 @@ class WOStackController(CementBaseController): if start_remove != "Y" and start_remove != "y": Log.error(self, "Not starting stack removal") - if (set(["nginx-custom"]).issubset(set(apt_packages))): + if 'nginx-custom' in apt_packages: WOService.stop_service(self, 'nginx') - if (set(["mariadb-server"]).issubset(set(apt_packages))): + if 'mariadb-server' in apt_packages: WOMysql.backupAll(self) WOService.stop_service(self, 'mysql') @@ -814,7 +831,6 @@ class WOStackController(CementBaseController): else: Log.info(self, "Redis is not installed") - # MariaDB if pargs.mysql: if WOAptGet.is_installed(self, 'mariadb-server'): @@ -840,8 +856,8 @@ class WOStackController(CementBaseController): # ClamAV if pargs.clamav: - Log.debug(self, "Add ClamAV to apt_packages list") if WOAptGet.is_installed(self, 'clamav'): + Log.debug(self, "Add ClamAV to apt_packages list") apt_packages = apt_packages + WOVariables.wo_clamav # UFW @@ -864,25 +880,29 @@ class WOStackController(CementBaseController): # WP-CLI if pargs.wpcli: - Log.debug(self, "Purge package variable WPCLI") if os.path.isfile('/usr/local/bin/wp'): + Log.debug(self, "Purge package variable WPCLI") packages = packages + ['/usr/local/bin/wp'] # PHPMYADMIN if pargs.phpmyadmin: - packages = packages + ['{0}22222/htdocs/db/pma'. - format(WOVariables.wo_webroot)] - Log.debug(self, "Purge package variable phpMyAdmin") + if os.path.isdir('{0}22222/htdocs/db/pma' + .format(WOVariables.wo_webroot)): + Log.debug(self, "Removing package of phpMyAdmin ") + packages = packages + ['{0}22222/htdocs/db/pma' + .format(WOVariables.wo_webroot)] # Composer if pargs.composer: - Log.debug(self, "Removing package variable of Composer ") if os.path.isfile('/usr/local/bin/composer'): + Log.debug(self, "Removing package variable of Composer ") packages = packages + ['/usr/local/bin/composer'] + # MySQLTuner if pargs.mysqltuner: - Log.debug(self, "Removing packages for MySQLTuner ") - packages = packages + ['/usr/bin/mysqltuner'] + if os.path.isfile(/usr/bin/mysqltuner): + Log.debug(self, "Removing packages for MySQLTuner ") + packages = packages + ['/usr/bin/mysqltuner'] # PHPREDISADMIN if pargs.phpredisadmin: @@ -892,11 +912,13 @@ class WOStackController(CementBaseController): packages = packages + ['{0}22222/htdocs/' 'cache/redis' .format(WOVariables.wo_webroot)] - # Adminer + # ADMINER if pargs.adminer: - Log.debug(self, "Purge package variable Adminer") - packages = packages + ['{0}22222/htdocs/db/adminer' - .format(WOVariables.wo_webroot)] + if os.path.isdir('{0}22222/htdocs/db/adminer' + .format(WOVariables.wo_webroot)): + Log.debug(self, "Removing package variable of Adminer ") + packages = packages + ['{0}22222/htdocs/db/adminer' + .format(WOVariables.wo_webroot)] # utils if pargs.utils: Log.debug(self, "Purge package variable utils")