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
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
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"]))
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
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
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]
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
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)
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
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
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
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)