AnonSec Shell
Server IP : 92.204.138.22  /  Your IP : 18.223.209.243
Web Server : Apache
System : Linux ns1009439.ip-92-204-138.us 4.18.0-553.8.1.el8_10.x86_64 #1 SMP Tue Jul 2 07:26:33 EDT 2024 x86_64
User : internationaljou ( 1019)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /usr/lib/panopta-agent/library/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     

Current File : /usr/lib/panopta-agent/library/plugin_manager.py
from agent_util import Plugin
import logging
import os
import sys
import traceback
import tempfile
import tarfile
import zipfile
try:
    from hashlib import sha1
except:
    from sha import sha as sha1
try:
    # Python 2.x
    import urllib2
except:
    import urllib.request as urllib2
# In case of python 3
try:
    import ConfigParser as configparser
except:
    import configparser

def execfile3(filepath, globals=None, locals=None):
    if globals is None:
        globals = {}
    globals.update({
        "__file__": filepath,
        "__name__": "__main__",
    })
    f = open(filepath, 'rb')
    exec(compile(f.read(), filepath, 'exec'), globals, locals)
    f.close()


class PluginManager(object):
    def __init__(self, db, config_file, *directories):
        self.log = logging.getLogger(self.__class__.__name__)
        self.db = db
        self.config_file = config_file
        self.directories = directories
        self.plugins = self._load_plugins(directories)

        # Internal container for metadata so we can avoid repeatedly regenerating it
        self._metadata = None
        self._hashed_metadata = None

        # now we load all the plugin-specific configs and map them to
        # self.config
        self.config = {}
        if os.path.exists(self.config_file):
            config_file = configparser.ConfigParser()
            config_file.read(self.config_file)
            for textkey in config_file.sections():
                try: debug = config_file.get('agent', 'debug')
                except: debug = False
                self.config[textkey] = {'debug': debug}
                for k, v in config_file.items(textkey):
                    self.config[textkey][k] = v

    def install_remote_plugins(self, url):
        """
        Grab the remote url and extract the contents, putting them in the
        appropiate plugin folder.
        """
        base_custom_plugin_dir = self.directories[-1]
        f = tempfile.NamedTemporaryFile(delete=False)
        num_installed = 0
        ext = url.split(".")[-1]
        fname = url.split("/")[-1]
        try:
            r = urllib2.urlopen(url)
            if "content-disposition" in r.info():
                ext = r.info().getheader("content-disposition").split(".")[-1]
            f.write(r.read())
            f.close()
        except Exception:
            self.log.error("Unable to download URL: %s" % traceback.format_exc())
            return

        if ext in ("tar", "tgz"):
            try:
                t = tarfile.open(f.name)
                for file in t.getnames():
                    if file.endswith(".py"):
                        self.log.info("  Installing plugin %s" % file)
                        t.extract(file, base_custom_plugin_dir)
                        num_installed += 1
            except Exception:
                self.log.error("Unable to extract tar contents: %s" % traceback.format_exc())
        elif ext == "zip":
            try:
                z = zipfile.ZipFile(f.name)
                for file in z.namelist():
                    if file.endswith(".py"):
                        self.log.info("  Installing plugin %s" % file)
                        z.extract(file, base_custom_plugin_dir)
                        num_installed += 1
            except Exception:
                self.log.error("Unable to extract zip contents: %s" % traceback.format_exc())
        elif ext == "py":
            self.log.info("  Installing plugin %s" % fname)
            os.system("cp %s %s" % (f.name, os.path.join(base_custom_plugin_dir, fname)))
            num_installed += 1
        else:
            self.log.error("Unable to install Agent Plugin, unknown extension: %s" % ext)

        if num_installed:
            self.log.info("\nInstalled %s Agent plugins" % num_installed)

        os.system("rm -f %s" % f.name)

    # run a specific plugin
    def check(self, schedule):
        try:
            self_key = self.config.get('agent', {}).get('server_key')
            container = None
            if getattr(schedule, 'server_key', None) and schedule.server_key != self_key:
                container_id = schedule.server_key.split(":")[-1]
                try:
                    container = self.db["docker_containers"][container_id]
                except:
                    if schedule.plugin_textkey == "docker" \
                            and schedule.resource_textkey == "status.running":
                        # Special handling of "container is running" metrics.
                        # Pass in a phony value to treat it as gone.
                        container = {"State": "deleted"}
                    else:
                        self.log.error("Could not find container with id %s", container_id)
                        return None

            plugin = self.plugins[schedule.plugin_textkey](schedule)
            config = self.config.get(schedule.plugin_textkey, {})

            scale = config.get('scale', 1.0)

            if container:
                value = plugin.check_docker(container, schedule.resource_textkey, schedule.option, config)
            else:
                value = plugin.check(schedule.resource_textkey, schedule.option, config)

            if value is not None: value *= scale

        except Exception:
            self.log.exception('failed: %s' % traceback.format_exc())
            return None

        return value

    def _load_plugins(self, directories):
        plugins = {}
        plugin_blacklist = ''

        if os.path.exists(self.config_file):
            config_file = configparser.ConfigParser()
            config_file.read(self.config_file)

            try:
                plugin_blacklist = config_file.get('agent', 'plugin_blacklist')
            except:
                plugin_blacklist = ''

            if plugin_blacklist:
                plugin_blacklist = list(map(str.strip, plugin_blacklist.split(',')))

        def plugin_file_checker():
            for plugin_dir in directories:
                self.log.info('Looking in directory %r', plugin_dir)
                for name in os.listdir(plugin_dir):
                    try:
                        if name[-3:] != '.py' or name == '__init__.py':
                            continue

                        plugin_file = os.path.join(plugin_dir, name)

                        # We've registed sys.modules['agent'] to equal THIS
                        # module, so this exec has the effect of 'importing' the
                        # plugin, and resolving 'import agent' to import this
                        # module. This is so we never have to change the plugins
                        # in order to whitelabel.
                        f_globals = {}
                        f_locals = {}
                        if sys.version_info[0] == 3:
                            execfile3(plugin_file, f_globals, f_globals)
                        else:
                            execfile(plugin_file, f_globals, f_globals)

                        for obj in list(f_globals.values()):
                            yield obj
                        self.log.debug('Loaded %r', plugin_file)

                    except Exception:
                        t, e = sys.exc_info()[:2]
                        self.log.info('Error importing plugin %s, skipping',
                                           name)
                        self.log.debug(e)
                        continue
                self.log.info('Loaded %d plugins', len(plugins))

        for obj in plugin_file_checker():
            if isinstance(obj, type):
                if issubclass(obj, Plugin) and hasattr(obj, 'textkey') and obj.textkey not in plugin_blacklist:
                    if obj.textkey != "TEMPLATE_PLUGIN":
                        plugins[obj.textkey] = obj

        return plugins

    # returns all the values needed to describe the plugins and their resources
    # in a json-serializable way.  Uses local cache of values to avoid recomputing.
    @property
    def metadata(self):
        if self._metadata == None:
            # We haven't previously built the metadata - go do that and cache for later
            metadata = {}
            for plugin in list(self.plugins.values()):
                # get the config and push it up with the metadata
                config = self.config.get(plugin.textkey, {})
                try:
                    meta = format_metadata(plugin.get_metadata(config))
                except:
                    self.log.exception('error getting metadata from %r', plugin.textkey)
                    continue
                self.log.info('got %d textkeys for %r', len(list(meta.keys())), plugin.textkey)
                label = getattr(plugin, 'label', plugin.textkey)
                metadata[plugin.textkey] = (label, meta)

            self._metadata = metadata

        return self._metadata

    # returns the metadata hash, used for comparing whether or not our metadata
    # has changed since we last pushed.  Uses local cache of values to avoid recomputing.
    def hashed_metadata(self):
        if self._hashed_metadata == None:
            flat_data = []

            for textkey, (label, plugin_metadata) in list(self.metadata.items()):
                plugin_options = []
                for resource_name, resource_metadata in list(plugin_metadata.items()):
                    resource_meta = sorted(repr(resource_metadata))
                    plugin_options.append(repr((resource_name, resource_metadata)))

                plugin_options.sort()
                flat_data.append(repr((textkey, plugin_options, label)))

            flat_data.sort()
            self._hashed_metadata = sha1(repr(flat_data).encode()).hexdigest()

        return self._hashed_metadata

    def is_metadata_stale(self):
        self.log.info('comparing metadata hashes %r with %r',
                      self.hashed_metadata(), self.db['last_metadata'])
        return self.db['last_metadata'] != self.hashed_metadata()


def format_metadata(metadata):
    """
    Go over the metadata entry and make sure the option resources
    are matching to the new style of dictionaries if they
    are a string.
    """
    for resource, entry in metadata.items():
        options = entry['options']
        new_options = []
        if not options:
            continue
        for option in options:
            if sys.version_info[0] == 3:
                if type(option) == str:  # TODO Verify that unicode is present on old python installs.
                    new_options.append({'resource': option})
            else:
                if type(option) in (str, unicode):  # TODO Verify that unicode is present on old python installs.
                    new_options.append({'resource': option})

        if new_options:
            entry['options'] = new_options
        if not entry.get('options_schema'):
            entry['options_schema'] = {'resource': 'string'}
    return metadata

Anon7 - 2022
AnonSec Team