예제 #1
0
def _render_tag_group(tg_id, tag, object_type, with_link, label_type,
                      label_source):
    # type: (Union[TagID, Text], Union[TagValue, Text], str, bool, str, str) -> HTML
    span = html.render_tag(html.render_div(
        html.render_span("%s:%s" % (tg_id, tag), class_=["tagify__tag-text"])),
                           class_=["tagify--noAnim", label_source])
    if not with_link:
        return span

    if label_type == "tag_group":
        type_filter_vars = [
            ("%s_tag_0_grp" % object_type, tg_id),
            ("%s_tag_0_op" % object_type, "is"),
            ("%s_tag_0_val" % object_type, tag),
        ]  # type: HTTPVariables
    elif label_type == "label":
        type_filter_vars = [
            ("%s_label" % object_type,
             ensure_unicode(json.dumps([{
                 "value": "%s:%s" % (tg_id, tag)
             }]))),
        ]

    else:
        raise NotImplementedError()

    url_vars = [
        ("filled_in", "filter"),
        ("search", "Search"),
        ("view_name", "searchhost" if object_type == "host" else "searchsvc"),
    ]  # type: HTTPVariables

    url = html.makeuri_contextless(url_vars + type_filter_vars,
                                   filename="view.py")
    return html.render_a(span, href=url)
예제 #2
0
def unescape_attributes(value):
    # type: (str) -> Text
    # In python3 use html.unescape
    return ensure_unicode(value.replace("&", "&")\
                .replace(""", "\"")\
                .replace("&lt;", "<")\
                .replace("&gt;", ">"))
예제 #3
0
 def _ensure_unicode(self, value):
     # type: (HTMLInput) -> str
     # value can of of any type: HTML, int, float, None, str, ...
     # TODO cleanup call sites
     if not isinstance(value, six.string_types):
         value = six.text_type(value)
     return ensure_unicode(value)
예제 #4
0
    def load(cls):
        cls.clear_instances()

        # First load builtin pages. Set username to ''
        for name, page_dict in cls.builtin_pages().items():
            page_dict["owner"] = UserId(u'')  # might have been forgotten on copy action
            page_dict["public"] = True
            page_dict["name"] = name
            new_page = cls(page_dict)
            cls.add_instance(("", name), new_page)

        # Now scan users subdirs for files "user_$type_name.mk"
        for user_dir in os.listdir(config.config_dir):
            user = UserId(ensure_unicode(user_dir))
            try:
                path = "%s/%s/user_%ss.mk" % (config.config_dir, six.ensure_str(user),
                                              cls.type_name())
                if not os.path.exists(path):
                    continue

                if not userdb.user_exists(user):
                    continue

                user_pages = store.load_object_from_file(path, default={})
                for name, page_dict in user_pages.items():
                    page_dict["owner"] = user
                    page_dict["name"] = name
                    cls.add_instance((user, name), cls(page_dict))

            except SyntaxError as e:
                raise MKGeneralException(
                    _("Cannot load %s from %s: %s") % (cls.type_name(), path, e))

        cls._load()
        cls._declare_instance_permissions()
예제 #5
0
def escape_attribute(value):
    # type: (Union[None, int, HTML, str, Text]) -> Text
    """Escape HTML attributes.

    For example: replace '"' with '&quot;', '<' with '&lt;'.
    This code is slow. Works on str and unicode without changing
    the type. Also works on things that can be converted with '%s'.

    Args:
        value:

    Examples:

        >>> escape_attribute("Hello this is <b>dog</b>!")
        'Hello this is &lt;b&gt;dog&lt;/b&gt;!'

        >>> escape_attribute("Hello this is <foo>dog</foo>!")
        'Hello this is &lt;foo&gt;dog&lt;/foo&gt;!'


    Returns:

    """
    attr_type = type(value)
    if value is None:
        return u''
    elif attr_type == int:
        return six.text_type(value)
    elif isinstance(value, HTML):
        return value.__html__()  # This is HTML code which must not be escaped
    elif not isinstance(attr_type, six.string_types):  # also possible: type Exception!
        value = u"%s" % value
    return ensure_unicode(html_escape(value, quote=True))
예제 #6
0
def _load_user_scripts_from(adir):
    scripts = {}
    if os.path.exists(adir):
        for entry in os.listdir(adir):
            entry = ensure_unicode(entry)
            if entry == ".f12":
                continue
            path = adir + "/" + entry
            if os.path.isfile(path) and os.access(path, os.X_OK):
                info = {"title": entry, "bulk": False}
                try:
                    with Path(path).open(encoding="utf-8") as lines:
                        next(lines)
                        line = next(lines).strip()
                        if line.startswith("#") and re.search(
                                r'coding[=:]\s*([-\w.]+)', line):
                            line = next(lines).strip()
                        if line.startswith("#"):
                            info["title"] = line.lstrip("#").strip().split(
                                "#", 1)[0]
                        while True:
                            line = next(lines).strip()
                            if not line.startswith("#") or ":" not in line:
                                break
                            key, value = line[1:].strip().split(":", 1)
                            value = value.strip()
                            if key.lower() == "bulk":
                                info["bulk"] = (value == "yes")

                except Exception:
                    pass
                scripts[entry] = info
    return scripts
예제 #7
0
def omd_site():
    # type: () -> Text
    try:
        return ensure_unicode(os.environ["OMD_SITE"])
    except KeyError:
        raise MKGeneralException(
            _("OMD_SITE environment variable not set. You can "
              "only execute this in an OMD site."))
예제 #8
0
파일: login.py 프로젝트: catchdave/checkmk
def _parse_auth_cookie(cookie_name):
    # type: (str) -> Tuple[UserId, float, str]
    raw_cookie = html.request.cookie(cookie_name, "::")
    assert raw_cookie is not None

    raw_value = ensure_unicode(raw_cookie)
    username, issue_time, cookie_hash = raw_value.split(':', 2)
    return UserId(username), float(issue_time) if issue_time else 0.0, six.ensure_str(cookie_hash)
예제 #9
0
    def _get_agent_info_program(self, commandline, command_stdin):
        exepath = commandline.split()[0]  # for error message, hide options!

        self._logger.debug("Calling external program %r" % (commandline))
        p = None
        try:
            if config.monitoring_core == "cmc":
                p = subprocess.Popen(  # nosec
                    commandline,
                    shell=True,
                    stdin=subprocess.PIPE if command_stdin else open(os.devnull),
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    preexec_fn=os.setsid,
                    close_fds=True,
                    encoding="utf-8",
                )
            else:
                # We can not create a separate process group when running Nagios
                # Upon reaching the service_check_timeout Nagios only kills the process
                # group of the active check.
                p = subprocess.Popen(  # nosec
                    commandline,
                    shell=True,
                    stdin=subprocess.PIPE if command_stdin else open(os.devnull),
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    close_fds=True,
                    encoding="utf-8",
                )

            if command_stdin:
                stdout, stderr = p.communicate(input=ensure_unicode(command_stdin))
            else:
                stdout, stderr = p.communicate()
            exitstatus = p.returncode

        except MKTimeout:
            # On timeout exception try to stop the process to prevent child process "leakage"
            if p:
                os.killpg(os.getpgid(p.pid), signal.SIGTERM)
                p.wait()
            raise
        finally:
            # The stdout and stderr pipe are not closed correctly on a MKTimeout
            # Normally these pipes getting closed after p.communicate finishes
            # Closing them a second time in a OK scenario won't hurt neither..
            if p:
                p.stdout.close()
                p.stderr.close()

        if exitstatus:
            if exitstatus == 127:
                raise MKAgentError("Program '%s' not found (exit code 127)" % exepath)
            else:
                raise MKAgentError("Agent exited with code %d: %s" % (exitstatus, stderr))

        return stdout
예제 #10
0
def get_optional_package_infos():
    # type: () -> Dict[Text, Dict]
    optional = {}
    for pkg_path in _get_optional_package_paths():
        with pkg_path.open("rb") as pkg:
            package_info = _get_package_info_from_package(cast(BinaryIO, pkg))
            optional[ensure_unicode(pkg_path.name)] = package_info

    return optional
예제 #11
0
파일: login.py 프로젝트: surajrb/checkmk
def check_auth_web_server(request):
    # type: (Request) -> UserId
    """Try to get the authenticated user from the HTTP request

    The user may have configured (basic) authentication by the web server. In
    case a user is provided, we trust that user.
    """
    user = request.remote_user
    if user is not None:
        set_auth_type("web_server")
        return UserId(ensure_unicode(user))
예제 #12
0
 def get_unicode_input(self, varname, deflt=None):
     # type: (str, Optional[Text]) -> Optional[Text]
     try:
         val = self.var(varname, six.ensure_str(deflt) if deflt is not None else None)
         if val is None:
             return None
         return ensure_unicode(val)
     except UnicodeDecodeError:
         raise MKUserError(
             varname,
             _("The given text is wrong encoded. "
               "You need to provide a UTF-8 encoded text."))
예제 #13
0
파일: login.py 프로젝트: catchdave/checkmk
def _get_session_id_from_cookie(username):
    # type: (UserId) -> str
    raw_value = html.request.cookie(_session_cookie_name(), "::")
    assert raw_value is not None
    cookie_username, session_id, cookie_hash = raw_value.split(':', 2)

    if ensure_unicode(cookie_username) != username \
       or cookie_hash != _generate_hash(username, cookie_username + ":" + session_id):
        auth_logger.error("Invalid session: %s, Cookie: %r" % (username, raw_value))
        return ""

    return session_id
예제 #14
0
파일: login.py 프로젝트: surajrb/checkmk
def _check_auth_http_header():
    # type: () -> Optional[UserId]
    """When http header auth is enabled, try to read the user_id from the var
    and when there is some available, set the auth cookie (for other addons) and proceed."""
    assert isinstance(config.auth_by_http_header, str)
    user_id = html.request.get_request_header(config.auth_by_http_header)
    if not user_id:
        return None

    user_id = UserId(ensure_unicode(user_id))
    set_auth_type("http_header")
    _renew_cookie(auth_cookie_name(), user_id)
    return user_id
예제 #15
0
 def _validate_tree_path(self, tree_path):
     # type: (AnyStr) -> None
     if not tree_path:
         raise MKGeneralException("Empty tree path or zero.")
     # TODO: Check if six.binary_type/ensure_unicode is necessary.
     if not isinstance(tree_path, (six.binary_type, six.text_type)):
         raise MKGeneralException(
             "Wrong tree path format. Must be of type string.")
     tp = ensure_unicode(tree_path)
     if not tp.endswith((":", ".")):
         raise MKGeneralException("No valid tree path.")
     if bool(re.compile('[^a-zA-Z0-9_.:-]').search(tp)):
         raise MKGeneralException(
             "Specified tree path contains unexpected characters.")
예제 #16
0
파일: prediction.py 프로젝트: n00rm/checkmk
def lq_logic(filter_condition, values, join):
    # type: (str, Union[AnyStr, List[AnyStr]], str) -> Text
    """JOIN with (Or, And) FILTER_CONDITION the VALUES for a livestatus query"""
    if isinstance(values, six.string_types):
        values = [values]
    conds = [
        u"%s %s" % (filter_condition, livestatus.lqencode(x)) for x in values
    ]
    if len(conds) > 1:
        return ensure_unicode("\n".join(conds) + "\n%s: %d\n" %
                              (join, len(conds)))
    if conds:
        return conds[0] + u'\n'
    return u""
예제 #17
0
def format_plugin_output(output, row=None, shall_escape=True):
    # type: (CellContent, Optional[Row], bool) -> Text
    assert not isinstance(output, dict)
    ok_marker = '<b class="stmark state0">OK</b>'
    warn_marker = '<b class="stmark state1">WARN</b>'
    crit_marker = '<b class="stmark state2">CRIT</b>'
    unknown_marker = '<b class="stmark state3">UNKN</b>'

    # In case we have a host or service row use the optional custom attribute
    # ESCAPE_PLUGIN_OUTPUT (set by host / service ruleset) to override the global
    # setting.
    if row:
        custom_vars = row.get("service_custom_variables",
                              row.get("host_custom_variables", {}))
        if "ESCAPE_PLUGIN_OUTPUT" in custom_vars:
            shall_escape = custom_vars["ESCAPE_PLUGIN_OUTPUT"] == "1"

    if shall_escape:
        output = escaping.escape_attribute(output)
    else:
        output = ensure_unicode("%s" % output)

    output = output.replace("(!)", warn_marker) \
              .replace("(!!)", crit_marker) \
              .replace("(?)", unknown_marker) \
              .replace("(.)", ok_marker)

    if row and "[running on" in output:
        a = output.index("[running on")
        e = output.index("]", a)
        hosts = output[a + 12:e].replace(" ", "").split(",")
        h = get_host_list_links(row["site"], hosts)
        output = output[:a] + "running on " + ", ".join(h) + output[e + 1:]

    if shall_escape:
        http_url = r"(http[s]?://[A-Za-z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+)"
        # (?:&lt;A HREF=&quot;), (?: target=&quot;_blank&quot;&gt;)? and endswith(" </A>") is a special
        # handling for the HTML code produced by check_http when "clickable URL" option is active.
        output = re.sub(
            "(?:&lt;A HREF=&quot;)?" + http_url +
            "(?: target=&quot;_blank&quot;&gt;)?", lambda p: str(
                html.render_icon_button(
                    p.group(1).replace('&quot;', ''),
                    p.group(1).replace('&quot;', ''), "link")), output)

        if output.endswith(" &lt;/A&gt;"):
            output = output[:-11]

    return output
예제 #18
0
def _cleanup_old_user_profiles(updated_profiles):
    # type: (Users) -> None
    profile_files_to_delete = [
        "automation.secret",
        "transids.mk",
        "serial.mk",
    ]
    directory = cmk.utils.paths.var_dir + "/web"
    for user_dir in os.listdir(cmk.utils.paths.var_dir + "/web"):
        if user_dir not in ['.', '..'] and ensure_unicode(user_dir) not in updated_profiles:
            entry = directory + "/" + user_dir
            if not os.path.isdir(entry):
                continue

            for to_delete in profile_files_to_delete:
                if os.path.exists(entry + '/' + to_delete):
                    os.unlink(entry + '/' + to_delete)
예제 #19
0
def _get_local_vars_of_last_exception():
    # type: () -> Text
    local_vars = {}
    try:
        for key, val in inspect.trace()[-1][0].f_locals.items():
            local_vars[key] = _format_var_for_export(val)
    except IndexError:
        # please don't crash in the attempt to report a crash.
        # Don't know why inspect.trace() causes an IndexError but it does happen
        pass

    # This needs to be encoded as the local vars might contain binary data which can not be
    # transported using JSON.
    return ensure_unicode(
        base64.b64encode(
            _format_var_for_export(pprint.pformat(local_vars).encode("utf-8"),
                                   maxsize=5 * 1024 * 1024)))
예제 #20
0
    def _upload_csv_file(self):
        store.makedirs(self._upload_tmp_path)

        self._cleanup_old_files()

        upload_info = self._vs_upload().from_html_vars("_upload")
        self._vs_upload().validate_value(upload_info, "_upload")
        _file_name, _mime_type, content = upload_info["file"]

        file_id = "%s-%d" % (config.user.id, int(time.time()))

        store.save_text_to_file(self._file_path(), ensure_unicode(content))

        # make selections available to next page
        html.request.set_var("file_id", file_id)

        if upload_info["do_service_detection"]:
            html.request.set_var("do_service_detection", "1")
예제 #21
0
파일: console.py 프로젝트: n00rm/checkmk
def output(text, *args, **kwargs):
    # type: (AnyStr, *Any, **IO[Any]) -> None
    if args:
        text = text % args

    if six.PY3:
        ensured_text = ensure_unicode(text)  # type: Text
    else:
        ensured_text = ensure_bytestr(text)  # type: bytes

    stream = kwargs.get("stream", sys.stdout)

    try:
        stream.write(ensured_text)
        stream.flush()
    except Exception:
        # TODO: Way to generic!
        pass  # avoid exception on broken pipe (e.g. due to | head)
예제 #22
0
def bearer_auth(token):
    # type: (str) ->  Optional[RFC7662]
    try:
        user_id, secret = token.split(' ', 1)
    except ValueError:
        return None

    if not secret:
        return None

    if not user_id:
        return None

    if "/" in user_id:
        return None

    if verify_automation_secret(UserId(ensure_unicode(user_id)), secret):
        # Auth with automation secret succeeded - mark transid as unneeded in this case
        return _subject(user_id)

    return None
예제 #23
0
def strip_tags(ht):
    # type: (Union[HTML, str, Text]) -> Text
    """Strip all HTML tags from a text.

    Args:
        ht: A text with possible HTML tags in it.

    Examples:
        >>> strip_tags("<b>foobar</b> blah")
        'foobar blah'

        Edge cases.

        >>> strip_tags("<p<b<>re>foobar</</b>b> blah")
        're>foobarb> blah'

    Returns:
        A string without working HTML tags.

    """
    if isinstance(ht, HTML):
        ht = ht.__html__()

    if not isinstance(ht, six.string_types):
        return u"%s" % ht

    ht = ensure_unicode(ht)

    while True:
        x = ht.find('<')
        if x == -1:
            break
        y = ht.find('>', x)
        if y == -1:
            break
        ht = ht[0:x] + ht[y + 1:]
    return ht.replace("&nbsp;", " ")
예제 #24
0
def log_entry(linkinfo, action, message, user_id=None):
    # TODO: Create a more generic referencing
    # linkinfo identifies the object operated on. It can be a Host or a Folder
    # or a text.
    # linkinfo is either a Folder, or a Host or a hostname or None
    if hasattr(linkinfo, "linkinfo"):
        link = linkinfo.linkinfo()
    else:
        link = linkinfo

    write_tokens = (
        time.strftime("%s"),
        link or "-",
        user_id or config.user.id or "-",
        action,
        message.replace("\n", "\\n"),
    )

    write_tokens = (ensure_unicode(t) for t in write_tokens)

    store.makedirs(audit_log_path.parent)
    with audit_log_path.open(mode="a", encoding='utf-8') as f:
        audit_log_path.chmod(0o660)
        f.write(u" ".join(write_tokens) + u"\n")
예제 #25
0
def omd_version():
    # type: () -> Text
    version_link = Path(cmk.utils.paths.omd_root).joinpath("version")
    return ensure_unicode(version_link.resolve().name)  # pylint: disable=no-member
예제 #26
0
def test_ensure_unicode(source, utf8str):
    assert ensure_unicode(source) == utf8str
예제 #27
0
파일: login.py 프로젝트: surajrb/checkmk
def _generate_secret():
    # type: () -> Text
    return ensure_unicode(utils.get_random_string(256))
예제 #28
0
def _(string):
    # type: (AnyStr) -> str
    return ensure_unicode(string)
예제 #29
0
def write_package_info(package):
    # type: (PackageInfo) -> None
    pkg_info_path = package_dir() / package["name"]
    with pkg_info_path.open("w", encoding="utf-8") as f:
        f.write(ensure_unicode(pprint.pformat(package) + "\n"))
예제 #30
0
def load_users(lock=False):
    # type: (bool) -> Users
    filename = _root_dir() + "contacts.mk"

    if lock:
        # Note: the lock will be released on next save_users() call or at
        #       end of page request automatically.
        store.aquire_lock(filename)

    if 'users' in g:
        return g.users

    # First load monitoring contacts from Check_MK's world. If this is
    # the first time, then the file will be empty, which is no problem.
    # Execfile will the simply leave contacts = {} unchanged.
    contacts = store.load_from_mk_file(filename, "contacts", {})

    # Now load information about users from the GUI config world
    filename = _multisite_dir() + "users.mk"
    users = store.load_from_mk_file(_multisite_dir() + "users.mk",
                                    "multisite_users", {})

    # Merge them together. Monitoring users not known to Multisite
    # will be added later as normal users.
    result = {}
    for uid, user in users.items():
        # Transform user IDs which were stored with a wrong type
        uid = ensure_unicode(uid)

        profile = contacts.get(uid, {})
        profile.update(user)
        result[uid] = profile

        # Convert non unicode mail addresses
        if "email" in profile:
            profile["email"] = ensure_unicode(profile["email"])

    # This loop is only neccessary if someone has edited
    # contacts.mk manually. But we want to support that as
    # far as possible.
    for uid, contact in contacts.items():
        # Transform user IDs which were stored with a wrong type
        uid = ensure_unicode(uid)

        if uid not in result:
            result[uid] = contact
            result[uid]["roles"] = ["user"]
            result[uid]["locked"] = True
            result[uid]["password"] = ""

    # Passwords are read directly from the apache htpasswd-file.
    # That way heroes of the command line will still be able to
    # change passwords with htpasswd. Users *only* appearing
    # in htpasswd will also be loaded and assigned to the role
    # they are getting according to the multisite old-style
    # configuration variables.

    def readlines(f):
        try:
            return Path(f).open(encoding="utf-8")
        except IOError:
            return []

    # FIXME TODO: Consolidate with htpasswd user connector
    filename = cmk.utils.paths.htpasswd_file
    for line in readlines(filename):
        line = line.strip()
        if ':' in line:
            uid, password = line.strip().split(":")[:2]
            uid = ensure_unicode(uid)
            if password.startswith("!"):
                locked = True
                password = password[1:]
            else:
                locked = False
            if uid in result:
                result[uid]["password"] = password
                result[uid]["locked"] = locked
            else:
                # Create entry if this is an admin user
                new_user = {
                    "roles": config.roles_of_user(uid),
                    "password": password,
                    "locked": False,
                }
                result[uid] = new_user
            # Make sure that the user has an alias
            result[uid].setdefault("alias", uid)
        # Other unknown entries will silently be dropped. Sorry...

    # Now read the serials, only process for existing users
    serials_file = '%s/auth.serials' % os.path.dirname(
        cmk.utils.paths.htpasswd_file)
    for line in readlines(serials_file):
        line = line.strip()
        if ':' in line:
            user_id, serial = line.split(':')[:2]
            user_id = ensure_unicode(user_id)
            if user_id in result:
                result[user_id]['serial'] = utils.saveint(serial)

    # Now read the user specific files
    directory = cmk.utils.paths.var_dir + "/web/"
    for d in os.listdir(directory):
        if d[0] != '.':
            uid = ensure_unicode(d)

            # read special values from own files
            if uid in result:
                for attr, conv_func in [
                    ('num_failed_logins', utils.saveint),
                    ('last_pw_change', utils.saveint),
                    ('last_seen', utils.savefloat),
                    ('enforce_pw_change', lambda x: bool(utils.saveint(x))),
                    ('idle_timeout', _convert_idle_timeout),
                    ('session_id', _convert_session_info),
                ]:
                    val = load_custom_attr(uid, attr, conv_func)
                    if val is not None:
                        result[uid][attr] = val

            # read automation secrets and add them to existing
            # users or create new users automatically
            try:
                user_secret_path = Path(directory) / d / "automation.secret"
                with user_secret_path.open(encoding="utf-8") as f:
                    secret = six.ensure_str(
                        f.read().strip())  # type: Optional[str]
            except IOError:
                secret = None

            if secret:
                if uid in result:
                    result[uid]["automation_secret"] = secret
                else:
                    result[uid] = {
                        "roles": ["guest"],
                        "automation_secret": secret,
                    }

    # populate the users cache
    g.users = result

    return result