Ejemplo n.º 1
0
def _check_auth(request: Request) -> Optional[UserId]:
    user_id = _check_auth_web_server(request)

    if html.request.var("_secret"):
        user_id = _check_auth_automation()

    elif config.auth_by_http_header:
        if not config.user_login:
            return None
        user_id = _check_auth_http_header()

    if user_id is None:
        if not config.user_login:
            return None
        user_id = _check_auth_by_cookie()

    if (user_id is not None
            and not isinstance(user_id, str)) or user_id == u'':
        raise MKInternalError(_("Invalid user authentication"))

    if user_id and not userdb.is_customer_user_allowed_to_login(user_id):
        # A CME not assigned with the current sites customer
        # is not allowed to login
        auth_logger.debug(
            "User '%s' is not allowed to authenticate: Invalid customer" %
            user_id)
        return None

    return user_id
Ejemplo n.º 2
0
def pdf2png(pdf_source):
    # Older version of pdftoppm cannot read pipes. The need to seek around
    # in the file. Therefore we need to save the PDF source into a temporary file.
    temp_file = tempfile.NamedTemporaryFile(dir=cmk.utils.paths.tmp_dir)
    temp_file.write(pdf_source)
    temp_file.flush()

    command = [
        "pdftoppm", "-png", "-f", "1", "-l", "1", "-scale-to", "1000",
        temp_file.name
    ]
    p = subprocess.Popen(
        command,
        close_fds=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    stdout, stderr = p.communicate()
    exitcode = p.returncode
    if exitcode != 0:
        raise MKInternalError(
            _('Cannot create PNG from PDF: %s, Exit code is %d, '
              'command was "%s", PDF source code was "%s..."') %
            (stderr, exitcode, " ".join(command), pdf_source[:500]))

    return stdout
Ejemplo n.º 3
0
    def __init__(self, perfometer, translated_metrics):
        super(MetricometerRendererDual, self).__init__(perfometer, translated_metrics)

        if len(perfometer["perfometers"]) != 2:
            raise MKInternalError(
                _("Perf-O-Meter of type 'dual' must contain exactly "
                  "two definitions, not %d") % len(perfometer["perfometers"]))
Ejemplo n.º 4
0
def hook_login(username, password):
    # type: (UserId, str) -> Union[UserId, bool]
    for connection_id, connection in active_connections():
        result = connection.check_credentials(username, password)
        # None        -> User unknown, means continue with other connectors
        # '<user_id>' -> success
        # False       -> failed
        if result not in [False, None]:
            username = result
            if not isinstance(username, six.string_types):
                raise MKInternalError(
                    _("The username returned by the %s "
                      "connector is not of type string (%r).") % (connection_id, username))
            # Check whether or not the user exists (and maybe create it)
            create_non_existing_user(connection_id, username)

            if not is_customer_user_allowed_to_login(username):
                # A CME not assigned with the current sites customer
                # is not allowed to login
                auth_logger.debug("User '%s' is not allowed to login: Invalid customer" % username)
                return False

            # Now, after successfull login (and optional user account creation), check whether or
            # not the user is locked.
            if _user_locked(username):
                auth_logger.debug("User '%s' is not allowed to login: Account locked" % username)
                return False  # The account is locked

            return result

        if result is False:
            return False

    return False
Ejemplo n.º 5
0
def check_credentials(username: UserId,
                      password: str) -> Union[UserId, Literal[False]]:
    """Verify the credentials given by a user using all auth connections"""
    for connection_id, connection in active_connections():
        # None        -> User unknown, means continue with other connectors
        # '<user_id>' -> success
        # False       -> failed
        result = connection.check_credentials(username, password)

        if result is False:
            return False

        if result is None:
            continue

        user_id: UserId = result
        if not isinstance(user_id, str):
            raise MKInternalError(
                _("The username returned by the %s "
                  "connector is not of type string (%r).") %
                (connection_id, user_id))

        # Check whether or not the user exists (and maybe create it)
        #
        # We have the cases where users exist "partially"
        # a) The htpasswd file of the site may have a username:pwhash data set
        #    and Checkmk does not have a user entry yet
        # b) LDAP authenticates a user and Checkmk does not have a user entry yet
        #
        # In these situations a user account with the "default profile" should be created
        create_non_existing_user(connection_id, user_id)

        if not is_customer_user_allowed_to_login(user_id):
            # A CME not assigned with the current sites customer
            # is not allowed to login
            auth_logger.debug(
                "User '%s' is not allowed to login: Invalid customer" %
                user_id)
            return False

        # Now, after successfull login (and optional user account creation), check whether or
        # not the user is locked.
        if user_locked(user_id):
            auth_logger.debug(
                "User '%s' is not allowed to login: Account locked" % user_id)
            return False  # The account is locked

        return user_id

    return False
Ejemplo n.º 6
0
    def get_stack(self) -> MetricRendererStack:
        content: List[Tuple[Union[int, float], str]] = []
        for nr, sub_perfometer in enumerate(self._perfometer["perfometers"]):
            renderer = renderer_registry.get_renderer(sub_perfometer, self._translated_metrics)

            sub_stack = renderer.get_stack()
            if len(sub_stack) != 1:
                raise MKInternalError(
                    _("Perf-O-Meter of type 'dual' must only contain plain Perf-O-Meters"))

            half_stack = [(int(value / 2.0), color) for (value, color) in sub_stack[0]]
            if nr == 0:
                half_stack.reverse()
            content += half_stack

        return [content]
Ejemplo n.º 7
0
def notify_mail(user_id, msg):
    users = userdb.load_users(lock=False)
    user = users.get(user_id)

    if not user:
        raise MKInternalError(_('This user does not exist.'))

    if not user.get('email'):
        raise MKInternalError(_('This user has no mail address configured.'))

    recipient_name = user.get('alias')
    if not recipient_name:
        recipient_name = user_id

    sender_name = users[config.user.id].get('alias')
    if not sender_name:
        sender_name = user_id

    # Code mostly taken from notify_via_email() from notify.py module
    subject = _('Check_MK: Notification')
    body = _('''Greetings %s,

%s sent you a notification:

---
%s
---

''') % (recipient_name, sender_name, msg['text'])

    if msg['valid_till']:
        body += _(
            'This notification has been created at %s and is valid till %s.'
        ) % (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(msg['time'])),
             time.strftime('%Y-%m-%d %H:%M:%S',
                           time.localtime(msg['valid_till'])))

    # FIXME: Maybe use the configured mail command for Check_MK-Notify one day
    # TODO: mail does not accept umlauts: "contains invalid character '\303'" in mail
    #       addresses. handle this correctly.
    command = [
        "mail", "-s",
        six.ensure_str(subject),
        six.ensure_str(user['email'])
    ]

    # Make sure that mail(x) is using UTF-8. Otherwise we cannot send notifications
    # with non-ASCII characters. Unfortunately we do not know whether C.UTF-8 is
    # available. If e.g. nail detects a non-Ascii character in the mail body and
    # the specified encoding is not available, it will silently not send the mail!
    # Our resultion in future: use /usr/sbin/sendmail directly.
    # Our resultion in the present: look with locale -a for an existing UTF encoding
    # and use that.
    for encoding in os.popen("locale -a 2>/dev/null"):
        l = encoding.lower()
        if "utf8" in l or "utf-8" in l or "utf.8" in l:
            encoding = encoding.strip()
            os.putenv("LANG", encoding)
            break
    else:
        raise MKInternalError(
            _('No UTF-8 encoding found in your locale -a! Please provide C.UTF-8 encoding.'
              ))

    try:
        p = subprocess.Popen(
            command,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            stdin=subprocess.PIPE,
            close_fds=True,
            encoding="utf-8",
        )
    except OSError as e:
        raise MKInternalError(
            _('Mail could not be delivered. '
              'Failed to execute command "%s": %s') % (" ".join(command), e))

    stdout, _stderr = p.communicate(input=body)
    exitcode = p.returncode
    if exitcode != 0:
        raise MKInternalError(
            _('Mail could not be delivered. Exit code of command is %r. '
              'Output is: %s') % (exitcode, stdout))
    else:
        return True
Ejemplo n.º 8
0
def login(user_id):
    if not isinstance(user_id, unicode):
        raise MKInternalError("Invalid user id type")
    config.set_user_by_id(user_id)
    html.set_user_id(user_id)
Ejemplo n.º 9
0
def notify_mail(user_id, msg):
    users = userdb.load_users(lock=False)
    user_spec = users.get(user_id)

    if not user_spec:
        raise MKInternalError(_("This user does not exist."))

    if not user_spec.get("email"):
        raise MKInternalError(_("This user has no mail address configured."))

    recipient_name = user_spec.get("alias")
    if not recipient_name:
        recipient_name = user_id

    if user.id is None:
        raise Exception("no user ID")
    sender_name = users[user.id].get("alias")
    if not sender_name:
        sender_name = user_id

    # Code mostly taken from notify_via_email() from notify.py module
    subject = _("Checkmk: Notification")
    body = (
        _(
            """Greetings %s,

%s sent you a notification:

---
%s
---

"""
        )
        % (recipient_name, sender_name, msg["text"])
    )

    if msg["valid_till"]:
        body += _("This notification has been created at %s and is valid till %s.") % (
            time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(msg["time"])),
            time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(msg["valid_till"])),
        )

    # FIXME: Maybe use the configured mail command for Check_MK-Notify one day
    # TODO: mail does not accept umlauts: "contains invalid character '\303'" in mail
    #       addresses. handle this correctly.
    # ? type of user_spec seems to be Dict[str,Any]
    command = [
        "mail",
        "-s",
        subject,
        ensure_str(user_spec["email"]),  # pylint: disable= six-ensure-str-bin-call
    ]

    # Make sure that mail(x) is using UTF-8. Otherwise we cannot send notifications
    # with non-ASCII characters. Unfortunately we do not know whether C.UTF-8 is
    # available. If e.g. nail detects a non-Ascii character in the mail body and
    # the specified encoding is not available, it will silently not send the mail!
    # Our resultion in future: use /usr/sbin/sendmail directly.
    # Our resultion in the present: look with locale -a for an existing UTF encoding
    # and use that.
    for encoding in os.popen("locale -a 2>/dev/null"):
        l = encoding.lower()
        if "utf8" in l or "utf-8" in l or "utf.8" in l:
            encoding = encoding.strip()
            os.putenv("LANG", encoding)
            break
    else:
        raise MKInternalError(
            _("No UTF-8 encoding found in your locale -a! Please provide C.UTF-8 encoding.")
        )

    try:
        p = subprocess.Popen(
            command,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            stdin=subprocess.PIPE,
            close_fds=True,
            encoding="utf-8",
        )
    except OSError as e:
        raise MKInternalError(
            _("Mail could not be delivered. " 'Failed to execute command "%s": %s')
            % (" ".join(command), e)
        )

    stdout, _stderr = p.communicate(input=body)
    exitcode = p.returncode
    if exitcode != 0:
        raise MKInternalError(
            _("Mail could not be delivered. Exit code of command is %r. " "Output is: %s")
            % (exitcode, stdout)
        )
    return True
Ejemplo n.º 10
0
    if req.var("_secret"):
        user_id = _check_auth_automation()

    elif auth_by_http_header := config.auth_by_http_header:
        if not config.user_login:
            return None
        user_id = _check_auth_http_header(auth_by_http_header)

    if user_id is None:
        if not config.user_login:
            return None
        user_id = _check_auth_by_cookie()

    if (user_id is not None and not isinstance(user_id, str)) or user_id == "":
        raise MKInternalError(_("Invalid user authentication"))

    if user_id and not userdb.is_customer_user_allowed_to_login(user_id):
        # A CME not assigned with the current sites customer
        # is not allowed to login
        auth_logger.debug(
            "User '%s' is not allowed to authenticate: Invalid customer" %
            user_id)
        return None

    if user_id and auth_type in ("http_header", "web_server"):
        _check_auth_cookie_for_web_server_auth(user_id)

    return user_id

Ejemplo n.º 11
0
def message_mail(user_id, msg):
    users = userdb.load_users(lock=False)
    user_spec = users.get(user_id)

    if not user_spec:
        raise MKInternalError(_("This user does not exist."))

    if not user_spec.get("email"):
        raise MKInternalError(_("This user has no mail address configured."))

    recipient_name = user_spec.get("alias")
    if not recipient_name:
        recipient_name = user_id

    if user.id is None:
        raise Exception("no user ID")
    sender_name = users[user.id].get("alias")
    if not sender_name:
        sender_name = user_id

    # Code mostly taken from message_via_email() from message.py module
    subject = _("Checkmk: Message")
    body = (
        _(
            """Greetings %s,

%s sent you a message:

---
%s
---

"""
        )
        % (recipient_name, sender_name, msg["text"])
    )

    if msg["valid_till"]:
        body += _("This message has been created at %s and is valid till %s.") % (
            time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(msg["time"])),
            time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(msg["valid_till"])),
        )

    # FIXME: Maybe use the configured mail command for Check_MK-Message one day
    # TODO: mail does not accept umlauts: "contains invalid character '\303'" in mail
    #       addresses. handle this correctly.
    # ? type of user_spec seems to be Dict[str,Any]
    command = [
        "mail",
        "-s",
        subject,
        ensure_str(user_spec["email"]),  # pylint: disable= six-ensure-str-bin-call
    ]

    ensure_utf8()

    try:
        completed_process = subprocess.run(
            command,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            close_fds=True,
            encoding="utf-8",
            check=False,
            input=body,
        )
    except OSError as e:
        raise MKInternalError(
            _("Mail could not be delivered. " 'Failed to execute command "%s": %s')
            % (" ".join(command), e)
        )

    if completed_process.returncode:
        raise MKInternalError(
            _("Mail could not be delivered. Exit code of command is %r. " "Output is: %s")
            % (completed_process.returncode, completed_process.stdout)
        )
    return True
Ejemplo n.º 12
0
def login(user_id):
    if not isinstance(user_id, six.text_type):
        raise MKInternalError("Invalid user id type")
    config.set_user_by_id(user_id)