2019-09-04 20:36:15 +02:00
|
|
|
import getpass
|
2019-09-23 12:11:15 +02:00
|
|
|
import os
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
import shutil
|
2019-09-04 20:36:15 +02:00
|
|
|
|
|
|
|
|
from cement.core.controller import CementBaseController, expose
|
2019-10-16 13:31:30 +02:00
|
|
|
|
2019-09-24 12:09:43 +02:00
|
|
|
from wo.core.fileutils import WOFileUtils
|
2018-11-13 21:55:59 +01:00
|
|
|
from wo.core.git import WOGit
|
2019-09-04 20:36:15 +02:00
|
|
|
from wo.core.logging import Log
|
2019-09-22 17:00:35 +02:00
|
|
|
from wo.core.random import RANDOM
|
2018-11-13 21:55:59 +01:00
|
|
|
from wo.core.services import WOService
|
2019-09-04 20:36:15 +02:00
|
|
|
from wo.core.shellexec import WOShellExec
|
2019-09-23 12:11:15 +02:00
|
|
|
from wo.core.template import WOTemplate
|
2019-10-02 13:13:32 +02:00
|
|
|
from wo.core.variables import WOVar
|
2018-11-13 21:55:59 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def wo_secure_hook(app):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WOSecureController(CementBaseController):
|
|
|
|
|
class Meta:
|
|
|
|
|
label = 'secure'
|
|
|
|
|
stacked_on = 'base'
|
|
|
|
|
stacked_type = 'nested'
|
2019-09-19 14:07:34 +02:00
|
|
|
description = (
|
2021-04-10 20:19:40 +10:00
|
|
|
'Secure command provide the ability to '
|
2019-09-19 14:07:34 +02:00
|
|
|
'adjust settings for backend and to harden server security.')
|
2018-11-13 21:55:59 +01:00
|
|
|
arguments = [
|
|
|
|
|
(['--auth'],
|
2019-09-19 14:07:34 +02:00
|
|
|
dict(help='secure backend authentification',
|
|
|
|
|
action='store_true')),
|
2018-11-13 21:55:59 +01:00
|
|
|
(['--port'],
|
2019-09-19 14:07:34 +02:00
|
|
|
dict(help='set backend port', action='store_true')),
|
2018-11-13 21:55:59 +01:00
|
|
|
(['--ip'],
|
2019-09-19 14:07:34 +02:00
|
|
|
dict(help='set backend whitelisted ip', action='store_true')),
|
2019-09-23 12:11:15 +02:00
|
|
|
(['--sshport'], dict(
|
2019-09-21 19:12:46 +02:00
|
|
|
help='set custom ssh port', action='store_true')),
|
2019-09-23 12:11:15 +02:00
|
|
|
(['--ssh'], dict(
|
|
|
|
|
help='harden ssh security', action='store_true')),
|
2019-09-26 15:45:38 +02:00
|
|
|
(['--allowpassword'], dict(
|
|
|
|
|
help='allow password authentification '
|
|
|
|
|
'when hardening ssh security', action='store_true')),
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
(['--lockdown'], dict(
|
|
|
|
|
help='enable WP Fort Knox lockdown on a site',
|
|
|
|
|
action='store_true')),
|
|
|
|
|
(['--unlock'], dict(
|
|
|
|
|
help='disable WP Fort Knox lockdown on a site',
|
|
|
|
|
action='store_true')),
|
2019-09-24 02:44:33 +02:00
|
|
|
(['--force'],
|
|
|
|
|
dict(help='force execution without being prompt',
|
2019-09-21 19:12:46 +02:00
|
|
|
action='store_true')),
|
2018-11-13 21:55:59 +01:00
|
|
|
(['user_input'],
|
|
|
|
|
dict(help='user input', nargs='?', default=None)),
|
|
|
|
|
(['user_pass'],
|
|
|
|
|
dict(help='user pass', nargs='?', default=None))]
|
|
|
|
|
usage = "wo secure [options]"
|
|
|
|
|
|
|
|
|
|
@expose(hide=True)
|
|
|
|
|
def default(self):
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs = self.app.pargs
|
|
|
|
|
if pargs.auth:
|
2019-03-19 16:58:35 +01:00
|
|
|
self.secure_auth()
|
2019-08-07 02:45:26 +02:00
|
|
|
if pargs.port:
|
2019-03-19 16:58:35 +01:00
|
|
|
self.secure_port()
|
2019-08-07 02:45:26 +02:00
|
|
|
if pargs.ip:
|
2019-03-19 16:58:35 +01:00
|
|
|
self.secure_ip()
|
2019-09-23 12:11:15 +02:00
|
|
|
if pargs.sshport:
|
|
|
|
|
self.secure_ssh_port()
|
|
|
|
|
if pargs.ssh:
|
|
|
|
|
self.secure_ssh()
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
if pargs.lockdown:
|
|
|
|
|
self.secure_lockdown()
|
|
|
|
|
if pargs.unlock:
|
|
|
|
|
self.secure_unlock()
|
2018-11-13 21:55:59 +01:00
|
|
|
|
|
|
|
|
@expose(hide=True)
|
|
|
|
|
def secure_auth(self):
|
|
|
|
|
"""This function secures authentication"""
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
WOGit.add(self, [WOVar.wo_ols_conf_dir],
|
|
|
|
|
msg="Add OLS config to Git")
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs = self.app.pargs
|
2019-10-08 11:17:07 +02:00
|
|
|
passwd = RANDOM.long(self)
|
2019-08-07 02:45:26 +02:00
|
|
|
if not pargs.user_input:
|
2018-11-13 21:55:59 +01:00
|
|
|
username = input("Provide HTTP authentication user "
|
2019-10-02 13:13:32 +02:00
|
|
|
"name [{0}] :".format(WOVar.wo_user))
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs.user_input = username
|
2018-11-13 21:55:59 +01:00
|
|
|
if username == "":
|
2019-10-02 13:13:32 +02:00
|
|
|
pargs.user_input = WOVar.wo_user
|
2019-08-07 02:45:26 +02:00
|
|
|
if not pargs.user_pass:
|
2018-11-13 21:55:59 +01:00
|
|
|
password = getpass.getpass("Provide HTTP authentication "
|
|
|
|
|
"password [{0}] :".format(passwd))
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs.user_pass = password
|
2018-11-13 21:55:59 +01:00
|
|
|
if password == "":
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs.user_pass = passwd
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
# Set OLS admin password using admpass.sh
|
|
|
|
|
WOShellExec.cmd_exec(
|
|
|
|
|
self, "/usr/local/lsws/admin/misc/admpass.sh "
|
|
|
|
|
"{username} {password}"
|
|
|
|
|
.format(username=pargs.user_input,
|
|
|
|
|
password=pargs.user_pass),
|
|
|
|
|
log=False)
|
|
|
|
|
WOGit.add(self, [WOVar.wo_ols_conf_dir],
|
2018-11-13 21:55:59 +01:00
|
|
|
msg="Adding changed secure auth into Git")
|
|
|
|
|
|
|
|
|
|
@expose(hide=True)
|
|
|
|
|
def secure_port(self):
|
|
|
|
|
"""This function Secures port"""
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
WOGit.add(self, [WOVar.wo_ols_conf_dir],
|
|
|
|
|
msg="Add OLS config to Git")
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs = self.app.pargs
|
|
|
|
|
if pargs.user_input:
|
2019-09-23 13:09:15 +02:00
|
|
|
while ((not pargs.user_input.isdigit()) and
|
2019-09-23 14:24:16 +02:00
|
|
|
(not pargs.user_input < 65536)):
|
2018-11-13 21:55:59 +01:00
|
|
|
Log.info(self, "Please enter a valid port number ")
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs.user_input = input("WordOps "
|
2019-09-05 11:47:04 +02:00
|
|
|
"admin port [22222]:")
|
2019-10-07 13:11:38 +02:00
|
|
|
else:
|
2018-11-13 21:55:59 +01:00
|
|
|
port = input("WordOps admin port [22222]:")
|
|
|
|
|
if port == "":
|
2019-09-23 13:09:15 +02:00
|
|
|
port = 22222
|
2019-10-07 13:11:38 +02:00
|
|
|
while ((not port.isdigit()) and (not port != "") and
|
|
|
|
|
(not port < 65536)):
|
2018-11-13 21:55:59 +01:00
|
|
|
Log.info(self, "Please Enter valid port number :")
|
|
|
|
|
port = input("WordOps admin port [22222]:")
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs.user_input = port
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
# Update OLS backend listener port
|
|
|
|
|
httpd_conf = '{0}/httpd_config.conf'.format(WOVar.wo_ols_conf_dir)
|
|
|
|
|
if os.path.isfile(httpd_conf):
|
|
|
|
|
WOFileUtils.searchreplace(
|
|
|
|
|
self, httpd_conf,
|
|
|
|
|
'address *:22222',
|
|
|
|
|
'address *:{0}'.format(pargs.user_input))
|
|
|
|
|
WOGit.add(self, [WOVar.wo_ols_conf_dir],
|
2018-11-13 21:55:59 +01:00
|
|
|
msg="Adding changed secure port into Git")
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
if not WOService.reload_service(self, 'lsws'):
|
|
|
|
|
Log.error(self, "service lsws reload failed. "
|
|
|
|
|
"check issues with `{0} -t` command"
|
|
|
|
|
.format(WOVar.wo_ols_bin))
|
2018-11-13 21:55:59 +01:00
|
|
|
Log.info(self, "Successfully port changed {port}"
|
2019-08-07 02:45:26 +02:00
|
|
|
.format(port=pargs.user_input))
|
2018-11-13 21:55:59 +01:00
|
|
|
|
|
|
|
|
@expose(hide=True)
|
|
|
|
|
def secure_ip(self):
|
|
|
|
|
"""IP whitelisting"""
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
WOGit.add(self, [WOVar.wo_ols_conf_dir],
|
|
|
|
|
msg="Add OLS config to Git")
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs = self.app.pargs
|
|
|
|
|
if not pargs.user_input:
|
2018-11-13 21:55:59 +01:00
|
|
|
ip = input("Enter the comma separated IP addresses "
|
|
|
|
|
"to white list [127.0.0.1]:")
|
2019-08-07 02:45:26 +02:00
|
|
|
pargs.user_input = ip
|
2018-11-13 21:55:59 +01:00
|
|
|
try:
|
2020-04-22 17:50:01 +02:00
|
|
|
user_ip = pargs.user_input.strip().split(',')
|
2018-11-13 21:55:59 +01:00
|
|
|
except Exception as e:
|
2019-07-29 15:08:49 +02:00
|
|
|
Log.debug(self, "{0}".format(e))
|
2018-11-13 21:55:59 +01:00
|
|
|
user_ip = ['127.0.0.1']
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
# Update OLS ACL configuration
|
|
|
|
|
acl_conf = '{0}/22222/vhconf.conf'.format(WOVar.wo_ols_vhost_dir)
|
|
|
|
|
if os.path.isfile(acl_conf):
|
|
|
|
|
for ip_addr in user_ip:
|
|
|
|
|
ip_addr = ip_addr.strip()
|
|
|
|
|
if not WOFileUtils.grepcheck(self, acl_conf, ip_addr):
|
|
|
|
|
WOFileUtils.searchreplace(
|
|
|
|
|
self, acl_conf,
|
|
|
|
|
'allowList',
|
|
|
|
|
'allowList\n {0}'.format(ip_addr))
|
|
|
|
|
WOGit.add(self, [WOVar.wo_ols_conf_dir],
|
2018-11-13 21:55:59 +01:00
|
|
|
msg="Adding changed secure ip into Git")
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
Log.info(self, "Successfully added IP address in access control")
|
2018-11-13 21:55:59 +01:00
|
|
|
|
feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:
- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script
Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:55:16 +01:00
|
|
|
@expose(hide=True)
|
|
|
|
|
def secure_lockdown(self):
|
|
|
|
|
"""Enable WP Fort Knox lockdown on a WordPress site"""
|
|
|
|
|
pargs = self.app.pargs
|
|
|
|
|
if not pargs.user_input:
|
|
|
|
|
site_name = input("Enter the site name to lockdown: ")
|
|
|
|
|
pargs.user_input = site_name
|
|
|
|
|
|
|
|
|
|
site_name = pargs.user_input
|
|
|
|
|
webroot = '{0}{1}'.format(WOVar.wo_webroot, site_name)
|
|
|
|
|
mu_plugins_dir = '{0}/htdocs/wp-content/mu-plugins'.format(webroot)
|
|
|
|
|
fort_knox_src = '/var/lib/wo/wp-fort-knox.php'
|
|
|
|
|
|
|
|
|
|
if not os.path.isdir(webroot):
|
|
|
|
|
Log.error(self, "Site {0} not found".format(site_name))
|
|
|
|
|
|
|
|
|
|
# Check if it's a WordPress site
|
|
|
|
|
if not os.path.isfile(
|
|
|
|
|
'{0}/htdocs/wp-config.php'.format(webroot)):
|
|
|
|
|
Log.error(self, "Site {0} is not a WordPress site"
|
|
|
|
|
.format(site_name))
|
|
|
|
|
|
|
|
|
|
# Check if Fort Knox source exists
|
|
|
|
|
if not os.path.isfile(fort_knox_src):
|
|
|
|
|
Log.error(self, "WP Fort Knox plugin not found at {0}. "
|
|
|
|
|
"Please reinstall WordOps.".format(fort_knox_src))
|
|
|
|
|
|
|
|
|
|
# Create mu-plugins directory if it doesn't exist
|
|
|
|
|
if not os.path.isdir(mu_plugins_dir):
|
|
|
|
|
WOFileUtils.mkdir(self, mu_plugins_dir)
|
|
|
|
|
|
|
|
|
|
fort_knox_dest = '{0}/wp-fort-knox.php'.format(mu_plugins_dir)
|
|
|
|
|
|
|
|
|
|
if os.path.isfile(fort_knox_dest):
|
|
|
|
|
Log.info(self, "WP Fort Knox is already enabled for {0}"
|
|
|
|
|
.format(site_name))
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
Log.wait(self, "Enabling WP Fort Knox lockdown")
|
|
|
|
|
shutil.copy2(fort_knox_src, fort_knox_dest)
|
|
|
|
|
WOFileUtils.chown(
|
|
|
|
|
self, fort_knox_dest,
|
|
|
|
|
WOVar.wo_php_user, WOVar.wo_php_user)
|
|
|
|
|
Log.valide(self, "Enabling WP Fort Knox lockdown")
|
|
|
|
|
Log.info(self, "WP Fort Knox enabled for {0}\n"
|
|
|
|
|
" File modifications and plugin management "
|
|
|
|
|
"are now disabled in wp-admin.\n"
|
|
|
|
|
" Use WP-CLI for all administrative tasks.\n"
|
|
|
|
|
" To disable: wo secure --unlock {0}"
|
|
|
|
|
.format(site_name))
|
|
|
|
|
|
|
|
|
|
@expose(hide=True)
|
|
|
|
|
def secure_unlock(self):
|
|
|
|
|
"""Disable WP Fort Knox lockdown on a WordPress site"""
|
|
|
|
|
pargs = self.app.pargs
|
|
|
|
|
if not pargs.user_input:
|
|
|
|
|
site_name = input("Enter the site name to unlock: ")
|
|
|
|
|
pargs.user_input = site_name
|
|
|
|
|
|
|
|
|
|
site_name = pargs.user_input
|
|
|
|
|
webroot = '{0}{1}'.format(WOVar.wo_webroot, site_name)
|
|
|
|
|
fort_knox_path = ('{0}/htdocs/wp-content/mu-plugins/'
|
|
|
|
|
'wp-fort-knox.php'.format(webroot))
|
|
|
|
|
|
|
|
|
|
if not os.path.isdir(webroot):
|
|
|
|
|
Log.error(self, "Site {0} not found".format(site_name))
|
|
|
|
|
|
|
|
|
|
if not os.path.isfile(fort_knox_path):
|
|
|
|
|
Log.info(self, "WP Fort Knox is not enabled for {0}"
|
|
|
|
|
.format(site_name))
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
Log.wait(self, "Disabling WP Fort Knox lockdown")
|
|
|
|
|
WOFileUtils.rm(self, fort_knox_path)
|
|
|
|
|
Log.valide(self, "Disabling WP Fort Knox lockdown")
|
|
|
|
|
Log.info(self, "WP Fort Knox disabled for {0}\n"
|
|
|
|
|
" Plugin management is now available in wp-admin."
|
|
|
|
|
.format(site_name))
|
2018-11-13 21:55:59 +01:00
|
|
|
|
2019-09-23 12:11:15 +02:00
|
|
|
@expose(hide=True)
|
|
|
|
|
def secure_ssh(self):
|
|
|
|
|
"""Harden ssh security"""
|
2019-09-24 02:44:33 +02:00
|
|
|
pargs = self.app.pargs
|
2019-09-26 15:45:38 +02:00
|
|
|
if not pargs.force and not pargs.allowpassword:
|
2019-09-24 02:44:33 +02:00
|
|
|
start_secure = input('Are you sure you to want to'
|
|
|
|
|
' harden SSH security ?'
|
|
|
|
|
'\nSSH login with password will not '
|
|
|
|
|
'be possible anymore. Please make sure '
|
|
|
|
|
'you are already using SSH Keys.\n'
|
|
|
|
|
'Harden SSH security [y/N]')
|
|
|
|
|
if start_secure != "Y" and start_secure != "y":
|
|
|
|
|
Log.error(self, "Not hardening SSH security")
|
2020-04-22 17:50:01 +02:00
|
|
|
if os.path.exists('/etc/ssh'):
|
|
|
|
|
WOGit.add(self, ["/etc/ssh"],
|
|
|
|
|
msg="Adding SSH into Git")
|
2019-09-23 12:38:16 +02:00
|
|
|
Log.debug(self, "check if /etc/ssh/sshd_config exist")
|
2019-09-23 12:35:11 +02:00
|
|
|
if os.path.isfile('/etc/ssh/sshd_config'):
|
2019-09-23 12:38:16 +02:00
|
|
|
Log.debug(self, "looking for the current ssh port")
|
2019-09-23 12:35:11 +02:00
|
|
|
for line in open('/etc/ssh/sshd_config', encoding='utf-8'):
|
|
|
|
|
if 'Port' in line:
|
|
|
|
|
ssh_line = line.strip()
|
2019-09-23 12:11:15 +02:00
|
|
|
break
|
2019-09-23 12:42:58 +02:00
|
|
|
port = (ssh_line).split(' ')
|
|
|
|
|
current_ssh_port = (port[1]).strip()
|
2019-09-23 13:46:31 +02:00
|
|
|
if os.getenv('SUDO_USER'):
|
2019-09-23 15:43:23 +02:00
|
|
|
sudo_user = os.getenv('SUDO_USER')
|
2019-09-23 13:46:31 +02:00
|
|
|
else:
|
|
|
|
|
sudo_user = ''
|
2019-09-26 15:45:38 +02:00
|
|
|
if pargs.allowpassword:
|
|
|
|
|
wo_allowpassword = 'yes'
|
|
|
|
|
else:
|
|
|
|
|
wo_allowpassword = 'no'
|
|
|
|
|
data = dict(sshport=current_ssh_port, allowpass=wo_allowpassword,
|
2019-09-23 13:46:31 +02:00
|
|
|
user=sudo_user)
|
2019-09-23 16:35:20 +02:00
|
|
|
WOTemplate.deploy(self, '/etc/ssh/sshd_config',
|
2019-09-23 12:42:58 +02:00
|
|
|
'sshd.mustache', data)
|
2019-09-23 13:09:15 +02:00
|
|
|
WOGit.add(self, ["/etc/ssh"],
|
|
|
|
|
msg="Adding changed SSH port into Git")
|
|
|
|
|
if not WOService.restart_service(self, 'ssh'):
|
|
|
|
|
Log.error(self, "service SSH restart failed.")
|
|
|
|
|
Log.info(self, "Successfully harden SSH security")
|
2019-09-23 12:35:11 +02:00
|
|
|
else:
|
|
|
|
|
Log.error(self, "SSH config file not found")
|
2019-09-23 12:11:15 +02:00
|
|
|
|
2019-09-23 13:09:15 +02:00
|
|
|
@expose(hide=True)
|
|
|
|
|
def secure_ssh_port(self):
|
|
|
|
|
"""Change SSH port"""
|
|
|
|
|
WOGit.add(self, ["/etc/ssh"],
|
|
|
|
|
msg="Adding changed SSH port into Git")
|
|
|
|
|
pargs = self.app.pargs
|
|
|
|
|
if pargs.user_input:
|
|
|
|
|
while ((not pargs.user_input.isdigit()) and
|
2019-09-23 14:24:16 +02:00
|
|
|
(not pargs.user_input < 65536)):
|
2019-09-23 13:09:15 +02:00
|
|
|
Log.info(self, "Please enter a valid port number ")
|
|
|
|
|
pargs.user_input = input("Server "
|
|
|
|
|
"SSH port [22]:")
|
|
|
|
|
if not pargs.user_input:
|
|
|
|
|
port = input("Server SSH port [22]:")
|
|
|
|
|
if port == "":
|
|
|
|
|
port = 22
|
2019-09-23 14:24:16 +02:00
|
|
|
while (not port.isdigit()) and (port != "") and (not port < 65536):
|
2019-09-23 13:09:15 +02:00
|
|
|
Log.info(self, "Please Enter valid port number :")
|
|
|
|
|
port = input("Server SSH port [22]:")
|
|
|
|
|
pargs.user_input = port
|
2019-10-08 11:17:07 +02:00
|
|
|
if WOFileUtils.grepcheck(self, '/etc/ssh/sshd_config', '#Port'):
|
|
|
|
|
WOShellExec.cmd_exec(self, "sed -i \"s/#Port.*/Port "
|
|
|
|
|
"{port}/\" /etc/ssh/sshd_config"
|
|
|
|
|
.format(port=pargs.user_input))
|
|
|
|
|
else:
|
|
|
|
|
WOShellExec.cmd_exec(self, "sed -i \"s/Port.*/Port "
|
|
|
|
|
"{port}/\" /etc/ssh/sshd_config"
|
|
|
|
|
.format(port=pargs.user_input))
|
2019-09-24 12:09:43 +02:00
|
|
|
# allow new ssh port if ufw is enabled
|
|
|
|
|
if os.path.isfile('/etc/ufw/ufw.conf'):
|
|
|
|
|
# add rule for proftpd with UFW
|
|
|
|
|
if WOFileUtils.grepcheck(
|
|
|
|
|
self, '/etc/ufw/ufw.conf', 'ENABLED=yes'):
|
|
|
|
|
try:
|
|
|
|
|
WOShellExec.cmd_exec(
|
|
|
|
|
self, 'ufw limit {0}'.format(pargs.user_input))
|
|
|
|
|
WOShellExec.cmd_exec(
|
|
|
|
|
self, 'ufw reload')
|
|
|
|
|
except Exception as e:
|
|
|
|
|
Log.debug(self, "{0}".format(e))
|
|
|
|
|
Log.error(self, "Unable to add UFW rule")
|
|
|
|
|
# add ssh into git
|
2019-09-23 13:09:15 +02:00
|
|
|
WOGit.add(self, ["/etc/ssh"],
|
|
|
|
|
msg="Adding changed SSH port into Git")
|
2019-09-24 12:09:43 +02:00
|
|
|
# restart ssh service
|
2019-09-23 13:09:15 +02:00
|
|
|
if not WOService.restart_service(self, 'ssh'):
|
|
|
|
|
Log.error(self, "service SSH restart failed.")
|
|
|
|
|
Log.info(self, "Successfully changed SSH port to {port}"
|
|
|
|
|
.format(port=pargs.user_input))
|
|
|
|
|
|
2018-11-13 21:55:59 +01:00
|
|
|
|
|
|
|
|
def load(app):
|
2019-09-24 00:01:20 +02:00
|
|
|
app.handler.register(WOSecureController)
|
2019-09-24 00:04:32 +02:00
|
|
|
app.hook.register('post_argument_parsing', wo_secure_hook)
|