Mini Shell
"""
cPanel upload hook manager plugin.
It enables/disables cPanel upload hook on an imunify360 config change.
"""
import logging
from functools import lru_cache
from defence360agent.contracts.config import Malware as Config
from defence360agent.contracts.config import SystemConfig
from defence360agent.contracts.messages import MessageType
from defence360agent.contracts.plugins import MessageSink, expect
from defence360agent.utils import CheckRunError, await_for, check_run, retry_on
from im360.subsys.panels.cpanel import cPanel
from im360.subsys.panels.hosting_panel import HostingPanel
logger = logging.getLogger(__name__)
MANAGE_HOOKS_CMD = "/usr/local/cpanel/bin/manage_hooks"
HOOK_PATH = "/usr/libexec/imunify360/cpanel_fileman_hook"
class CpanelUploadHookManager(MessageSink):
def __init__(self):
self._current_cpanel_scan_status = None
async def create_sink(self, loop):
"""MessageSink method"""
@lru_cache(maxsize=1)
def is_supported(self) -> bool:
return HostingPanel().NAME == cPanel.NAME
async def is_installed(self) -> bool:
hooks = (await check_run([MANAGE_HOOKS_CMD, "list"])).decode()
return HOOK_PATH in hooks
@retry_on(CheckRunError, max_tries=2, on_error=await_for(seconds=2))
async def _reset_hook(self, enabled):
action = "add" if enabled else "del"
await check_run([MANAGE_HOOKS_CMD, action, "script", HOOK_PATH])
@expect(MessageType.ConfigUpdate)
async def update_hook(self, message):
# expect to get ConfigUpdate every time on start up (at least)
# see ConfigWatcher plugin for details
if isinstance(message["conf"], SystemConfig) and self.is_supported():
enabled = Config.CPANEL_SCAN_ENABLED
if self._current_cpanel_scan_status != enabled:
installed = await self.is_installed()
if installed != enabled: # need to update
try:
await self._reset_hook(enabled)
except CheckRunError as exc:
logger.error(
"Error occured during update cpanel hook: %s", exc
)
else:
self._current_cpanel_scan_status = enabled
logger.info(
"cPanel uploader hook %sinstalled successfully",
"" if enabled else "un",
)
else: # already installed/removed
self._current_cpanel_scan_status = enabled
logger.info(
"cPanel uploader hook %sinstalled already",
"" if enabled else "un",
)