Example #1
0
def _handle_not_authenticated() -> Response:
    if fail_silently():
        # While api call don't show the login dialog
        raise MKUnauthenticatedException(_("You are not authenticated."))

    # Redirect to the login-dialog with the current url as original target
    # Never render the login form directly when accessing urls like "index.py"
    # or "dashboard.py". This results in strange problems.
    requested_file = requested_file_name(request)
    if requested_file != "login":
        post_login_url = makeuri(request, [])
        if requested_file != "index":
            # Ensure that users start with a navigation after they have logged in
            post_login_url = makeuri_contextless(
                request, [("start_url", post_login_url)], filename="index.py"
            )
        raise HTTPRedirect(
            "%scheck_mk/login.py?_origtarget=%s" % (url_prefix(), urlencode(post_login_url))
        )

    # This either displays the login page or validates the information submitted
    # to the login form. After successful login a http redirect to the originally
    # requested page is performed.
    login_page = login.LoginPage()
    login_page.set_no_html_output(plain_error())
    login_page.handle_page()

    return response
Example #2
0
def page_login() -> None:
    title = _("Checkmk Mobile")
    mobile_html_head(title)
    jqm_page_header(title, id_="login")
    html.div(_("Welcome to Checkmk Mobile."), id_="loginhead")

    html.begin_form("login", method='POST', add_transid=False)
    # Keep information about original target URL
    default_origtarget = "index.py" if requested_file_name(request) in ["login", "logout"
                                                                       ] else makeuri(request, [])
    origtarget = request.get_url_input("_origtarget", default_origtarget)
    html.hidden_field('_origtarget', escaping.escape_attribute(origtarget))

    html.text_input("_username", label=_("Username:"******"username", id_="input_user")
    html.password_input(
        "_password",
        size=None,
        label=_("Password:"******"current-password",
        id_="input_pass",
    )
    html.br()
    html.button("_login", _('Login'))
    html.set_focus("_username")
    html.end_form()
    html.open_div(id_="loginfoot")
    html.img("themes/facelift/images/logo_cmk_small.png", class_="logomk")
    html.div(HTML(_("&copy; <a target=\"_blank\" href=\"https://checkmk.com\">tribe29 GmbH</a>")),
             class_="copyright")
    html.close_div()  # close content-div
    html.close_div()
    html.close_div()  # close page-div
    mobile_html_foot()
Example #3
0
    def begin_form(
        self,
        name: str,
        action: Optional[str] = None,
        method: str = "GET",
        onsubmit: Optional[str] = None,
        add_transid: bool = True,
    ) -> None:
        self.form_name = name
        self.form_vars = []
        self.form_has_submit_button = False

        if action is None:
            action = requested_file_name(self.request) + ".py"
        self.open_form(
            id_="form_%s" % name,
            name=name,
            class_=name,
            action=action,
            method=method,
            onsubmit=onsubmit,
            enctype="multipart/form-data" if method.lower() == "post" else None,
        )

        session = request_local_attr("session")
        if hasattr(session, "session_info"):
            self.hidden_field("csrf_token", session.session_info.csrf_token)

        self.hidden_field("filled_in", name, add_var=True)
        if add_transid:
            self.hidden_field(
                "_transid",
                str(transactions.get()),
                add_var=True,
            )
Example #4
0
    def __init__(
        self,
        table_id: Optional[str] = None,
        title: Optional["HTMLContent"] = None,
        searchable: bool = True,
        sortable: bool = True,
        foldable: Foldable = Foldable.NOT_FOLDABLE,
        limit: Union[None, int, Literal[False]] = None,
        output_format: str = "html",
        omit_if_empty: bool = False,
        omit_empty_columns: bool = False,
        omit_headers: bool = False,
        omit_update_header: bool = False,
        empty_text: Optional[str] = None,
        help: Optional[str] = None,  # pylint: disable=redefined-builtin
        css: Optional[str] = None,
        isopen: bool = True,
    ):
        super().__init__()
        self.next_func = lambda: None
        self.next_header: Optional[str] = None

        # Use our pagename as table id if none is specified
        table_id = table_id if table_id is not None else requested_file_name(
            request)
        assert table_id is not None

        # determine row limit
        if limit is None:
            limit = config.table_row_limit
        if request.get_ascii_input(
                "limit") == "none" or output_format != "html":
            limit = None

        self.id = table_id
        self.title = title
        self.rows: TableRows = []
        self.limit = limit
        self.limit_reached = False
        self.limit_hint: Optional[int] = None
        self.headers: List[TableHeader] = []
        self.options = {
            "collect_headers": False,  # also: True, "finished"
            "omit_if_empty": omit_if_empty,
            "omit_empty_columns": omit_empty_columns,
            "omit_headers": omit_headers,
            "omit_update_header": omit_update_header,
            "searchable": searchable,
            "sortable": sortable,
            "foldable": foldable,
            "output_format": output_format,  # possible: html, csv, fetch
        }

        self.empty_text = empty_text if empty_text is not None else _(
            "No entries.")
        self.help = help
        self.css = css
        self.mode = "row"
        self.isopen: Final = isopen
Example #5
0
 def _page_menu(self, breadcrumb) -> PageMenu:
     menu = make_simple_form_page_menu(_("Profile"),
                                       breadcrumb,
                                       form_name="profile",
                                       button_name="_save")
     menu.dropdowns.insert(
         1, page_menu_dropdown_user_related(requested_file_name(request)))
     return menu
Example #6
0
def load_all_plugins() -> None:
    # Optimization: in case of the graph ajax call only check the metrics module. This
    # improves the performance for these requests.
    # TODO: CLEANUP: Move this to the pagehandlers if this concept works out.
    # werkzeug.wrappers.Request.script_root would be helpful here, but we don't have that yet.
    only_modules = ["metrics"
                    ] if requested_file_name(request) == "ajax_graph" else None
    modules.load_all_plugins(only_modules=only_modules)
Example #7
0
    def infos(self):
        # Hack for create mode of dashlet editor. The user first selects a datasource and then the
        # single contexts, the dashlet editor needs to use these information.
        if requested_file_name(request) == "edit_dashlet" and request.has_var(
                "datasource"):
            ds_name = request.get_str_input_mandatory("datasource")
            return views.data_source_registry[ds_name]().infos

        return self._get_infos_from_view_spec(self._dashlet_spec)
Example #8
0
def _process_request(
    environ: WSGIEnvironment,
    start_response: StartResponse,
    debug: bool = False,
) -> WSGIResponse:  # pylint: disable=too-many-branches
    resp: Response
    try:
        page_handler = get_and_wrap_page(requested_file_name(request))
        resp = page_handler()
    except HTTPRedirect as e:
        # This can't be a new Response as it can have already cookies set/deleted by the pages.
        # We can't return the response because the Exception has been raised instead.
        # TODO: Remove all HTTPRedirect exceptions from all pages. Making the Exception a subclass
        #       of Response may also work as it can then be directly returned from here.
        resp = response
        resp.status_code = e.status
        resp.headers["Location"] = e.url

    except FinalizeRequest as e:
        # TODO: Remove all FinalizeRequest exceptions from all pages and replace it with a `return`.
        #       It may be necessary to rewire the control-flow a bit as this exception could have
        #       been used to short-circuit some code and jump directly to the response. This
        #       needs to be changed as well.
        resp = response
        resp.status_code = e.status

    except livestatus.MKLivestatusNotFoundError as e:
        resp = _render_exception(e, title=_("Data not found"))

    except MKUserError as e:
        resp = _render_exception(e, title=_("Invalid user input"))

    except MKAuthException as e:
        resp = _render_exception(e, title=_("Permission denied"))

    except livestatus.MKLivestatusException as e:
        resp = _render_exception(e, title=_("Livestatus problem"))
        resp.status_code = http_client.BAD_GATEWAY

    except MKUnauthenticatedException as e:
        resp = _render_exception(e, title=_("Not authenticated"))
        resp.status_code = http_client.UNAUTHORIZED

    except MKConfigError as e:
        resp = _render_exception(e, title=_("Configuration error"))
        logger.error("MKConfigError: %s", e)

    except (MKGeneralException, cmk.utils.store.MKConfigLockTimeout) as e:
        resp = _render_exception(e, title=_("General error"))
        logger.error("%s: %s", e.__class__.__name__, e)

    except Exception:
        resp = handle_unhandled_exception()
        if debug:
            raise

    return resp(environ, start_response)
Example #9
0
def _renew_cookie(cookie_name: str, username: UserId, session_id: str) -> None:
    # Do not renew if:
    # a) The _ajaxid var is set
    # b) A logout is requested
    requested_file = requested_file_name(request)
    if (requested_file != "logout" and not request.has_var("_ajaxid")
        ) and cookie_name == auth_cookie_name():
        auth_logger.debug("Renewing auth cookie (%s.py, vars: %r)" %
                          (requested_file, dict(request.itervars())))
        _renew_auth_session(username, session_id)
Example #10
0
def _redirect_for_two_factor_authentication(user_id: UserId) -> None:
    if requested_file_name(request) in (
            "user_login_two_factor",
            "user_webauthn_login_begin",
            "user_webauthn_login_complete",
    ):
        return

    if userdb.is_two_factor_login_enabled(
            user_id) and not userdb.is_two_factor_completed():
        raise HTTPRedirect("user_login_two_factor.py?_origtarget=%s" %
                           urlencode(makeuri(request, [])))
Example #11
0
def default_response_headers(req: http.Request) -> Dict[str, str]:
    headers = {
        # Disable caching for all our pages as they are mostly dynamically generated,
        # user related and are required to be up-to-date on every refresh
        "Cache-Control": "no-cache",
    }

    # Would be better to put this to page individual code, but we currently have
    # no mechanism for a page to set do this before the authentication is made.
    if requested_file_name(req) == "webapi":
        headers["Access-Control-Allow-Origin"] = "*"

    return headers
Example #12
0
 def from_exception(cls, details=None, type_specific_attributes=None):
     return super().from_exception(
         details={
             "page": requested_file_name(request) + ".py",
             "vars": {
                 key: "***" if value in ["password", "_password"] else value
                 for key, value in request.itervars()
             },
             "username": user.id,
             "user_agent": request.user_agent.string,
             "referer": request.referer,
             "is_mobile": is_mobile(request, response),
             "is_ssl_request": request.is_ssl_request,
             "language": cmk.gui.i18n.get_current_language(),
             "request_method": request.request_method,
         },
     )
Example #13
0
def _check_auth_cookie(cookie_name: str) -> Optional[UserId]:
    username, session_id, cookie_hash = user_from_cookie(
        _fetch_cookie(cookie_name))
    check_parsed_auth_cookie(username, session_id, cookie_hash)

    try:
        userdb.on_access(username, session_id)
    except MKAuthException:
        del_auth_cookie()
        raise

    # Once reached this the cookie is a good one. Renew it!
    _renew_cookie(cookie_name, username, session_id)

    if requested_file_name(request) != "user_change_pw":
        result = userdb.need_to_change_pw(username)
        if result:
            raise HTTPRedirect("user_change_pw.py?_origtarget=%s&reason=%s" %
                               (urlencode(makeuri(request, [])), result))

    # Return the authenticated username
    return username
Example #14
0
def plain_error() -> bool:
    """Webservice functions may decide to get a normal result code
    but a text with an error message in case of an error"""
    return request.has_var("_plain_error") or requested_file_name(request) == "webapi"
Example #15
0
    def _show_login_page(self) -> None:
        html.set_render_headfoot(False)
        html.add_body_css_class("login")
        html.header(get_page_heading(), Breadcrumb(), javascripts=[])

        default_origtarget = ("index.py" if requested_file_name(request)
                              in ["login", "logout"] else makeuri(request, []))
        origtarget = request.get_url_input("_origtarget", default_origtarget)

        # Never allow the login page to be opened in the iframe. Redirect top page to login page.
        # This will result in a full screen login page.
        html.javascript("""if(top != self) {
    window.top.location.href = location;
}""")

        # When someone calls the login page directly and is already authed redirect to main page
        if requested_file_name(request) == "login" and _check_auth(request):
            raise HTTPRedirect(origtarget)

        html.open_div(id_="login")

        html.open_div(id_="login_window")

        html.open_a(href="https://checkmk.com")
        html.img(
            src=theme.detect_icon_path(icon_name="logo", prefix="mk-"),
            id_="logo",
            class_="custom" if theme.has_custom_logo() else None,
        )
        html.close_a()

        html.begin_form("login",
                        method="POST",
                        add_transid=False,
                        action="login.py")
        html.hidden_field("_login", "1")
        html.hidden_field("_origtarget", origtarget)
        html.label("%s:" % _("Username"),
                   id_="label_user",
                   class_=["legend"],
                   for_="_username")
        html.br()
        html.text_input("_username", id_="input_user")
        html.label("%s:" % _("Password"),
                   id_="label_pass",
                   class_=["legend"],
                   for_="_password")
        html.br()
        html.password_input("_password", id_="input_pass", size=None)

        if user_errors:
            html.open_div(id_="login_error")
            html.show_user_errors()
            html.close_div()

        html.open_div(id_="button_text")
        html.button("_login", _("Login"), cssclass="hot")
        html.close_div()
        html.close_div()

        html.open_div(id_="foot")

        if config.login_screen.get("login_message"):
            html.open_div(id_="login_message")
            html.show_message(config.login_screen["login_message"])
            html.close_div()

        footer: List[HTML] = []
        for title, url, target in config.login_screen.get("footer_links", []):
            footer.append(html.render_a(title, href=url, target=target))

        if "hide_version" not in config.login_screen:
            footer.append(escape_html("Version: %s" % cmk_version.__version__))

        footer.append(
            HTML("&copy; %s" % html.render_a(
                "tribe29 GmbH", href="https://tribe29.com", target="_blank")))

        html.write_html(HTML(" - ").join(footer))

        if cmk_version.is_raw_edition():
            html.br()
            html.br()
            html.write_text(
                _('You can use, modify and distribute Check_MK under the terms of the <a href="%s" target="_blank">'
                  "GNU GPL Version 2</a>.") % "https://checkmk.com/gpl.html")

        html.close_div()

        html.set_focus("_username")
        html.hidden_fields()
        html.end_form()
        html.close_div()

        html.footer()
Example #16
0
def _redirect_for_password_change(user_id: UserId) -> None:
    if requested_file_name(request) != "user_change_pw":
        result = userdb.need_to_change_pw(user_id)
        if result:
            raise HTTPRedirect("user_change_pw.py?_origtarget=%s&reason=%s" %
                               (urlencode(makeuri(request, [])), result))