%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /proc/self/root/opt/imunify360/venv/lib64/python3.11/site-packages/imav/patchman/rpc/
Upload File :
Create Path :
Current File : //proc/self/root/opt/imunify360/venv/lib64/python3.11/site-packages/imav/patchman/rpc/endpoints.py

"""
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.


This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU General Public License for more details.


You should have received a copy of the GNU General Public License
 along with this program.  If not, see <https://www.gnu.org/licenses/>.

Copyright © 2019 Cloud Linux Software Inc.

This software is also available under ImunifyAV commercial license,
see <https://www.imunify360.com/legal/eula>
"""
import logging
import pathlib
from enum import IntEnum

from imav.patchman.constants import PATCHMAN_PACKAGE, PATCHMAN_SERVICE_NAME
from imav.patchman.custom_integration import PatchmanCustomIntegration
from imav.patchman.exceptions import PatchmanError
from imav.patchman.model import Domain, Path, User, patchman_db
from imav.patchman.license import License
from imav.patchman.state import is_installed
from imav.subsys.realtime_av import REALTIME_PACKAGE, REALTIME_SERVICE_NAME

from defence360agent.contracts.config import Core, ANTIVIRUS_MODE
from defence360agent.contracts.messages import MessageType
from defence360agent.rpc_tools.lookup import RootEndpoints, bind
from defence360agent.subsys.panels import hosting_panel
from defence360agent.utils import check_run, OsReleaseInfo
from imav.subsys import realtime_av

logger = logging.getLogger(__name__)

OLD_PATCHMAN_PACKAGE = "patchman-client"
OLD_PATCHMAN_BIN = "/usr/local/patchman/patchmand"


class Status(IntEnum):
    not_installed = 0
    installed = 1


def is_debian() -> bool:
    return OsReleaseInfo.id_like() & OsReleaseInfo.DEBIAN


class PatchmanEndpoints(RootEndpoints):
    KEYFILE = "/etc/patchman/license/key"

    @bind("patchman", "users")
    async def users(
        self,
        custom_integration=False,
        integration_type=None,
        metadata_path=None,
    ):
        """Writes the users and their domains to database.

        Patchman go agent executes this endpoint to fill the database. In case
        of custom integration it retrieves the user-defined parameters from
        Patchman Portal and passes it here.

        :param custom_integration: true if custom integration, false by default
        :param integration_type: only for custom integration, file or script
        :param metadata_path: only for custom integration, path to file or
        script that represent metadata (File type 1 or Script 1 from
        https://docs.imunify360.com/Patchman_custom_integration.pdf)
        """
        if custom_integration:
            hp = PatchmanCustomIntegration(integration_type, metadata_path)
        else:
            hp = hosting_panel.HostingPanel()

        patchman_users = await hp.patchman_users()

        with patchman_db(
            [User, Domain, Path], target_dir=Core.TMPDIR, prefix="users"
        ) as db:
            for user_data in patchman_users:
                user_name = user_data["username"]
                email = user_data["email"] or ""
                language = user_data["language"]
                parent = user_data["parent"]
                level = user_data["level"]
                suspended = user_data["suspended"]

                user = User.create(
                    name=user_name,
                    email=email,
                    language=language,
                    parent=parent,
                    level=level,
                    suspended=suspended,
                )

                domains = user_data["domains"]
                for domain_data in domains:
                    domain_name = domain_data["domain"]
                    domain = Domain.create(name=domain_name, user=user)

                    paths = domain_data["paths"]
                    for path_name in paths:
                        Path.create(name=path_name, domain=domain)

            return {"path": db.database}

    @bind("patchman", "register")
    async def register(self, regkey=None):
        """
        Writes a key to Patchman's key file.
        Patchman automatically checks for registration every 5 seconds.
        """
        keyfile_path = pathlib.Path(self.KEYFILE)
        keyfile_path.parent.mkdir(parents=True, exist_ok=True)
        with keyfile_path.open("w") as f:
            f.write(regkey)

    @property
    def package_manager(self):
        return "apt-get" if is_debian() else "yum"

    def _get_install_command(self, package: str) -> list:
        return [self.package_manager, "-y", "install", package]

    async def _install(self, package):
        cmd = self._get_install_command(package)
        await check_run(cmd)

    async def _uninstall(self, package):
        cmd = [self.package_manager, "-y", "remove", package]
        await check_run(cmd)

    async def _install_patchman(self, migrate=False) -> bool:
        if is_installed():
            logger.info("%s package already installed", PATCHMAN_PACKAGE)
            return False
        cmd = self._get_install_command(PATCHMAN_PACKAGE)
        if migrate and not is_debian():
            # use swap to replace old patchman package(s)
            cmd = [
                self.package_manager,
                "--allowerasing",
                "-y",
                "swap",
                OLD_PATCHMAN_PACKAGE,
                PATCHMAN_PACKAGE,
            ]
        await check_run(cmd)
        await self._sink.process_message(
            MessageType.EnsureServiceState(service=PATCHMAN_SERVICE_NAME)
        )

    @bind("patchman", "install")
    async def install(self):
        """Install imunify-patchman package"""
        raise NotImplementedError(
            "Installation from scratch is not supported now, migrate instead."
        )

    @bind("patchman", "migrate")
    async def migrate(self):
        """Migrate old patchman agent to imunify-patchman"""
        if not pathlib.Path(OLD_PATCHMAN_BIN).exists():
            logger.info("There is nothing to migrate")
            return
        if not License.has_clean_mode():
            logger.warning("Unsupported license type to migrate")
            return
        await self._install_patchman(migrate=True)

    @bind("patchman", "uninstall")
    async def uninstall(self):
        """Uninstall imunify-patchman package"""
        await self._uninstall(PATCHMAN_PACKAGE)

    @bind("patchman", "status")
    async def get_status(self):
        """Get patchman status"""
        return {
            "status": Status(is_installed()).name,
            "realtime": Status(realtime_av.is_installed()).name,
        }

    @bind("patchman", "install", "realtime")
    async def install_realtime(self):
        """Install imunify-realtime-av package"""
        if realtime_av.is_installed():
            logger.info("%s package already installed", REALTIME_PACKAGE)
            return
        if not is_installed():
            # don't install realtime package without patchman package
            raise PatchmanError(
                "Can't install realtime package, install patchman first"
            )
        if not License.has_realtime_enabled():
            raise PatchmanError(
                "Realtime is not enabled for the current Patchman license"
            )
        await self._install(REALTIME_PACKAGE)
        await self._sink.process_message(
            MessageType.EnsureServiceState(service=REALTIME_SERVICE_NAME)
        )

    @bind("patchman", "uninstall", "realtime")
    async def uninstall_realtime(self):
        """Uninstall imunify-realtime-av package"""
        if not ANTIVIRUS_MODE:
            logger.warning(
                "Can't uninstall imunify-realtime-av "
                "since it's part of imunify360"
            )
            return
        if realtime_av.is_installed():
            await self._uninstall(REALTIME_PACKAGE)

Zerion Mini Shell 1.0