Beispiel #1
0
 def test_get_request(
     self,
     monkeypatch: pytest.MonkeyPatch,
 ) -> None:
     request = Request({})
     request.set_var("site_id", "NO_SITE")
     request.set_var("to_delete", "['x/y/z.txt', 'abc.ending', '/ä/☃/☕']")
     request.set_var("config_generation", "123")
     request.files = werkzeug_datastructures.ImmutableMultiDict({
         "sync_archive":
         werkzeug_datastructures.FileStorage(
             stream=io.BytesIO(b"some data"),
             filename="sync_archive",
             name="sync_archive",
         )
     })
     monkeypatch.setattr(
         activate_changes,
         "_request",
         request,
     )
     assert (activate_changes.AutomationReceiveConfigSync().get_request() ==
             activate_changes.ReceiveConfigSyncRequest(
                 site_id=SiteId("NO_SITE"),
                 sync_archive=b"some data",
                 to_delete=["x/y/z.txt", "abc.ending", "/ä/☃/☕"],
                 config_generation=123,
             ))
Beispiel #2
0
def is_mobile(request: Request, response: Response) -> bool:
    if request.has_var("mobile"):
        mobile = bool(request.var("mobile"))
        # Persist the explicitly set state in a cookie to have it maintained through further requests
        response.set_http_cookie("mobile", str(int(mobile)), secure=request.is_secure)
        return mobile

    if request.has_cookie("mobile"):
        return request.cookie("mobile", "0") == "1"

    return _is_mobile_client(request.user_agent.string)
Beispiel #3
0
def _check_auth(req: Request) -> Optional[UserId]:
    user_id = _check_auth_web_server(req)

    if req.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 == "":
        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 test_write_and_read_host_attributes(tmp_path, attributes, monkeypatch):
    folder_path = str(tmp_path)
    # Write/Read operations always require a valid user
    monkeypatch.setattr(config, "user", config.LoggedInSuperUser())

    # Used to write the data
    write_data_folder = watolib.Folder("testfolder",
                                       folder_path=folder_path,
                                       parent_folder=None)

    # Used to read the previously written data
    read_data_folder = watolib.Folder("testfolder",
                                      folder_path=folder_path,
                                      parent_folder=None)

    environ = dict(create_environ(), REQUEST_URI='')
    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(Request(environ))):
        # Write data
        # Note: The create_hosts function modifies the attributes dict, adding a meta_data key inplace
        write_data_folder.create_hosts([("testhost", attributes, [])])
        write_folder_hosts = write_data_folder.hosts()
        assert len(write_folder_hosts) == 1

        # Read data back
        read_folder_hosts = read_data_folder.hosts()
        assert len(read_folder_hosts) == 1
        for _, host in read_folder_hosts.items():
            assert host.attributes() == attributes
def test_del_vars():
    environ = dict(create_environ(),
                   REQUEST_URI='',
                   QUERY_STRING='foo=foo&_username=foo&_password=bar&bar=bar')
    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(Request(environ))):
        # First we hit the cached property so we can see that the underlying Request object
        # actually got replaced later.
        _ = request.args
        _ = html.request.args

        html.request.set_var("foo", "123")

        html.del_var_from_env("_username")
        html.del_var_from_env("_password")

        # Make test independent of dict sorting
        assert html.request.query_string in [
            'foo=foo&bar=bar', 'bar=bar&foo=foo'
        ]

        assert '_password' not in html.request.args
        assert '_username' not in html.request.args

        # Check the request local proxied version too.
        # Make test independent of dict sorting
        assert request.query_string in ['foo=foo&bar=bar', 'bar=bar&foo=foo']
        assert '_password' not in request.args
        assert '_username' not in request.args

        assert html.request.var("foo") == "123"
Beispiel #6
0
def debug_vars(
    writer: HTMLWriter,
    request: Request,
    prefix: Optional[str] = None,
    hide_with_mouse: bool = True,
    vars_: Optional[Mapping[str, str]] = None,
) -> None:
    it = request.itervars() if vars_ is None else vars_.items()
    hover = "this.style.display='none';"
    writer.open_table(class_=["debug_vars"],
                      onmouseover=hover if hide_with_mouse else None)
    oddeven = "even"
    writer.tr(writer.render_th(_("POST / GET Variables"), colspan="2"),
              class_=oddeven)
    for name, value in sorted(it):
        oddeven = "even" if oddeven == "odd" else "odd"
        if name in ["_password", "password"]:
            value = "***"
        if not prefix or name.startswith(prefix):
            writer.tr(
                writer.render_td(name, class_="left") +
                writer.render_td(value, class_="right"),
                class_=oddeven,
            )
    writer.close_table()
Beispiel #7
0
def test_load_group_information_empty(tmp_path):
    environ = dict(create_environ(), REQUEST_URI='')
    with AppContext(DummyApplication(environ, None)), \
         RequestContext(htmllib.html(Request(environ))):
        assert groups.load_contact_group_information() == {}
        assert gui_groups.load_host_group_information() == {}
        assert gui_groups.load_service_group_information() == {}
Beispiel #8
0
    def run(self):
        self._logger.log(VERBOSE, "Initializing application...")
        environ = dict(create_environ(), REQUEST_URI='')

        this_html = htmllib.html(Request(environ))
        # Currently the htmllib.html constructor enables the timeout by default. This side effect
        # should really be cleaned up.
        this_html.disable_request_timeout()

        with AppContext(DummyApplication(environ, None)), \
                RequestContext(this_html):
            self._initialize_gui_environment()

            self._logger.log(VERBOSE, "Updating Checkmk configuration...")
            for step_func, title in self._steps():
                self._logger.log(VERBOSE, " + %s..." % title)
                try:
                    step_func()
                except Exception:
                    self._logger.log(VERBOSE,
                                     " + \"%s\" failed" % title,
                                     exc_info=True)
                    if self._arguments.debug:
                        raise

        self._logger.log(VERBOSE, "Done")
Beispiel #9
0
 def _SearchContext(self) -> Iterator[None]:
     _request = Request(create_environ())
     with RequestContext(
             html_obj=html(_request),
             req=_request,
             display_options=DisplayOptions(),
     ), UserContext(self._user_id):
         yield
Beispiel #10
0
def module_wide_request_context():
    # This one is kind of an hack because some other test-fixtures touch the user object AFTER the
    # request context has already ended. If we increase our scope this won't matter, but it is of
    # course wrong. These other fixtures have to be fixed.
    environ = create_environ()
    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(Request(environ))):
        yield
Beispiel #11
0
    def _initialize_gui_environment(self):
        environ = dict(create_environ(), REQUEST_URI='')
        current_app.set_current(DummyApplication(environ, None))
        html.set_current(htmllib.html(Request(environ), Response(is_secure=False)))

        cmk.gui.modules.load_all_plugins()
        cmk.gui.config.load_config()
        cmk.gui.config.set_super_user()
Beispiel #12
0
def with_request_context():
    environ = create_environ()
    resp = Response()
    with AppContext(DummyApplication(environ, None)), \
            RequestContext(req=Request(environ),
                           resp=resp,
                           funnel=OutputFunnel(resp),
                           display_options=DisplayOptions()):
        yield
Beispiel #13
0
def _check_auth(req: Request) -> Optional[UserId]:
    user_id = _check_auth_web_server(req)

    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)
Beispiel #14
0
def set_language_cookie(request: Request, response: Response,
                        lang: Optional[str]) -> None:
    cookie_lang = request.cookie("language")
    if cookie_lang == lang:
        return

    if lang is None:
        del_language_cookie(response)
    else:
        response.set_http_cookie("language", lang, secure=request.is_secure)
Beispiel #15
0
def with_request_context():
    environ = create_environ()
    resp = Response()
    with AppContext(session_wsgi_app(debug=False)), RequestContext(
            req=Request(environ),
            resp=resp,
            funnel=OutputFunnel(resp),
            config_obj=make_config_object(get_default_config()),
            display_options=DisplayOptions(),
    ):
        yield
Beispiel #16
0
def _verify_user(environ: WSGIEnvironment, now: datetime) -> RFC7662:
    verified: List[RFC7662] = []

    auth_header = environ.get("HTTP_AUTHORIZATION", "")
    basic_user = None
    if auth_header:
        auth_type, _ = auth_header.split(None, 1)
        if auth_type == "Bearer":
            user_id, secret = user_from_bearer_header(auth_header)
            automation_user = automation_auth(user_id, secret)
            if automation_user:
                verified.append(automation_user)
            else:
                # GUI user and Automation users are mutually exclusive. Checking only once is less
                # work for the system.
                gui_user = gui_user_auth(user_id, secret, now)
                if gui_user:
                    verified.append(gui_user)
        elif auth_type == "Basic":
            # We store this for sanity checking below, once we get a REMOTE_USER key.
            # If we don't get a REMOTE_USER key, this value will be ignored.
            basic_user = user_from_basic_header(auth_header)
        else:
            raise MKAuthException(f"Unsupported Auth Type: {auth_type}")

    remote_user = environ.get("REMOTE_USER", "")
    if remote_user and userdb.user_exists(UserId(remote_user)):
        if basic_user and basic_user[0] != remote_user:
            raise MKAuthException("Mismatch in authentication headers.")
        verified.append(rfc7662_subject(UserId(remote_user), "web_server"))

    cookie = Request(environ).cookies.get(f"auth_{omd_site()}")
    if cookie:
        user_id, session_id, cookie_hash = user_from_cookie(cookie)
        check_parsed_auth_cookie(user_id, session_id, cookie_hash)
        verified.append(rfc7662_subject(user_id, "cookie"))

    if not verified:
        raise MKAuthException(
            "You need to be authenticated to use the REST API.")

    # We pick the first successful authentication method, which means the precedence is the same
    # as the order in the code.
    final_candidate = verified[0]
    user_id = final_candidate["sub"]
    if not userdb.is_customer_user_allowed_to_login(user_id):
        raise MKAuthException(f"{user_id} may not log in here.")

    if userdb.user_locked(user_id):
        raise MKAuthException(f"{user_id} not authorized.")

    if change_reason := userdb.need_to_change_pw(user_id, now):
        raise MKAuthException(
            f"{user_id} needs to change the password ({change_reason}).")
Beispiel #17
0
    def run(self):
        self._logger.log(VERBOSE, "Updating Checkmk configuration...")

        environ = dict(create_environ(), REQUEST_URI='')
        with AppContext(DummyApplication(environ, None)), \
             RequestContext(htmllib.html(Request(environ), Response(is_secure=False))):
            self._initialize_gui_environment()
            for step_func, title in self._steps():
                self._logger.log(VERBOSE, " + %s..." % title)
                step_func()

        self._logger.log(VERBOSE, "Done")
Beispiel #18
0
    def load_from_html(self, request: Request, html: htmllib.html) -> None:
        # Parse display options and
        if html.output_format == "html":
            options = request.get_ascii_input_mandatory("display_options", "")
        else:
            options = self.all_off()

        # Remember the display options in the object for later linking etc.
        self.options = self._merge_with_defaults(options)

        # This is needed for letting only the data table reload. The problem is that
        # the data table is re-fetched via javascript call using special display_options
        # but these special display_options must not be used in links etc. So we use
        # a special var _display_options for defining the display_options for rendering
        # the data table to be reloaded. The contents of "display_options" are used for
        # linking to other views.
        if request.has_var('_display_options'):
            self.options = self._merge_with_defaults(
                request.get_ascii_input_mandatory("_display_options", ""))

        # But there is one special case: Links to other views (sorter header links, painter column
        # links). These links need to know about the provided display_option parameter. The links
        # could use "display_options.options" but this contains the implicit options which should
        # not be added to the URLs. So the real parameters need to be preserved for this case.
        self.title_options = request.get_ascii_input("display_options")

        # If display option 'M' is set, then all links are targetet to the 'main'
        # frame. Also the display options are removed since the view in the main
        # frame should be displayed in standard mode.
        if self.disabled(self.M):
            html.set_link_target("main")
            request.del_var("display_options")
Beispiel #19
0
def request_context(environ: Mapping[str, Any]) -> Iterator[None]:
    this_html = html(Request(environ))

    # Currently the htmllib.html constructor enables the timeout by default. This side effect
    # should really be cleaned up.
    this_html.disable_request_timeout()

    with RequestContext(
            this_html,
            display_options=DisplayOptions(),
            prefix_logs_with_url=False,
    ):
        yield
Beispiel #20
0
class URLChecker:
    def __init__(self):
        self._user_id = user.ident
        self._request = Request(create_environ())

    def _set_query_vars(self, query_vars: QueryVars) -> None:
        for name, vals in query_vars.items():
            self._request.set_var(name, vals[0])

    def is_permitted(self, url: str) -> bool:
        file_name, query_vars = file_name_and_query_vars_from_url(url)
        self._set_query_vars(query_vars)
        try:
            with RequestContext(html_obj=html(self._request),
                                req=self._request):
                with UserContext(self._user_id):
                    page_handler = get_page_handler(file_name)
                    if page_handler:
                        page_handler()
            return True
        except MKAuthException:
            return False
Beispiel #21
0
def request_context(environ: Mapping[str, Any]) -> Iterator[None]:
    req = Request(environ)
    resp = Response(mimetype="text/html")
    funnel = OutputFunnel(resp)
    with RequestContext(
            req=req,
            resp=resp,
            funnel=funnel,
            html_obj=html(req, resp, funnel, output_format="html"),
            display_options=DisplayOptions(),
            theme=Theme(),
            prefix_logs_with_url=False,
    ):
        yield
Beispiel #22
0
def with_request_context():
    environ = create_environ()
    resp = Response()
    with AppContext(session_wsgi_app(debug=False), stack=app_stack()), RequestContext(
        req=Request(environ),
        resp=resp,
        funnel=OutputFunnel(resp),
        config_obj=make_config_object(get_default_config()),
        user=LoggedInNobody(),
        display_options=DisplayOptions(),
        stack=request_stack(),
        url_filter=PrependURLFilter(),
    ):
        yield
Beispiel #23
0
class URLChecker:
    def __init__(self):
        self._user_id = user.ident
        self._request = Request(create_environ())
        from cmk.gui.wato.pages.hosts import ModeEditHost
        self._mode_edit_host = ModeEditHost

    def _set_query_vars(self, query_vars: QueryVars) -> None:
        for name, vals in query_vars.items():
            self._request.set_var(name, vals[0])

    def is_permitted(self, url: str) -> bool:
        is_host_url = "mode=edit_host" in url
        file_name, query_vars = file_name_and_query_vars_from_url(url)
        self._set_query_vars(query_vars)
        try:
            with AppContext(current_app), \
                 RequestContext(html_obj=html(self._request), req=self._request), \
                 UserContext(self._user_id):
                if is_host_url:
                    self._try_host()
                else:
                    self._try_page(file_name)
            return True
        except MKAuthException:
            return False

    @staticmethod
    def _try_page(file_name: str) -> None:
        page_handler = get_page_handler(file_name)
        if page_handler:
            page_handler()

    # TODO: Find a better solution here. We treat hosts separately because calling the page takes
    #  very long in this case and is not necessary (the initializer already throws an exception).
    def _try_host(self) -> None:
        self._mode_edit_host()
Beispiel #24
0
def make_request_context(
        environ: Optional[Mapping[str, Any]] = None) -> RequestContext:
    req = Request(
        dict(create_environ(), REQUEST_URI="") if environ is None else environ)
    resp = Response(mimetype="text/html")
    funnel = OutputFunnel(resp)
    return RequestContext(
        req=req,
        resp=resp,
        funnel=funnel,
        config_obj=make_config_object(get_default_config()),
        user=LoggedInNobody(),
        html_obj=html(req, resp, funnel, output_format="html"),
        display_options=DisplayOptions(),
        timeout_manager=TimeoutManager(),
        theme=Theme(),
        prefix_logs_with_url=False,
    )
Beispiel #25
0
 def _SearchContext(self) -> Iterator[None]:
     _request = Request(create_environ())
     _response = Response()
     _funnel = OutputFunnel(_response)
     _theme = Theme()
     _theme.from_config(config.ui_theme, config.theme_choices())
     with RequestContext(
             req=_request,
             resp=_response,
             funnel=_funnel,
             html_obj=html(_request,
                           _response,
                           _funnel,
                           output_format="html"),
             display_options=DisplayOptions(),
             theme=_theme,
     ), UserContext(self._user_id):
         yield
Beispiel #26
0
    def run(self):
        self._logger.log(VERBOSE, "Initializing application...")
        environ = dict(create_environ(), REQUEST_URI='')

        this_html = htmllib.html(Request(environ), Response(is_secure=False))
        # Currently the htmllib.html constructor enables the timeout by default. This side effect
        # should really be cleaned up.
        this_html.disable_request_timeout()

        with AppContext(DummyApplication(environ, None)), \
                RequestContext(this_html):
            self._initialize_gui_environment()

            self._logger.log(VERBOSE, "Updating Checkmk configuration...")
            for step_func, title in self._steps():
                self._logger.log(VERBOSE, " + %s..." % title)
                step_func()

        self._logger.log(VERBOSE, "Done")
Beispiel #27
0
def makeuri(
    request: Request,
    addvars: HTTPVariables,
    filename: Optional[str] = None,
    remove_prefix: Optional[str] = None,
    delvars: Optional[Sequence[str]] = None,
) -> str:
    new_vars = [nv[0] for nv in addvars]
    vars_: HTTPVariables = [(v, val) for v, val in request.itervars()
                            if v[0] != "_" and v not in new_vars and (
                                not delvars or v not in delvars)]
    if remove_prefix is not None:
        vars_ = [i for i in vars_ if not i[0].startswith(remove_prefix)]
    vars_ = vars_ + addvars
    if filename is None:
        filename = URLEncoder.urlencode(requested_file_name(request)) + ".py"
    if vars_:
        return filename + "?" + URLEncoder.urlencode_vars(vars_)
    return filename
Beispiel #28
0
def register_builtin_html():
    """This fixture registers a global htmllib.html() instance just like the regular GUI"""
    environ = create_environ()
    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(Request(environ))):
        yield
Beispiel #29
0
 def __init__(self):
     self._user_id = user.ident
     self._request = Request(create_environ())
     from cmk.gui.wato.pages.hosts import ModeEditHost
     self._mode_edit_host = ModeEditHost
Beispiel #30
0
def test_load_group_information(tmp_path):
    with open(cmk.utils.paths.check_mk_config_dir + "/wato/groups.mk", "w") as f:
        f.write("""# encoding: utf-8

if type(define_contactgroups) != dict:
    define_contactgroups = {}
define_contactgroups.update({'all': u'Everything'})

if type(define_hostgroups) != dict:
    define_hostgroups = {}
define_hostgroups.update({'all_hosts': u'All hosts :-)'})

if type(define_servicegroups) != dict:
    define_servicegroups = {}
define_servicegroups.update({'all_services': u'All särvices'})
""")

    with open(cmk.utils.paths.default_config_dir + "/multisite.d/wato/groups.mk", "w") as f:
        f.write("""# encoding: utf-8

multisite_hostgroups = {
    "all_hosts": {
        "ding": "dong",
    },
}

multisite_servicegroups = {
    "all_services": {
        "d1ng": "dong",
    },
}

multisite_contactgroups = {
    "all": {
        "d!ng": "dong",
    },
}
""")

    environ = dict(create_environ(), REQUEST_URI='')
    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(Request(environ))):
        assert groups.load_group_information() == {
            'contact': {
                'all': {
                    'alias': u'Everything',
                    "d!ng": "dong",
                }
            },
            'host': {
                'all_hosts': {
                    'alias': u'All hosts :-)',
                    "ding": "dong",
                }
            },
            'service': {
                'all_services': {
                    'alias': u'All s\xe4rvices',
                    "d1ng": "dong",
                }
            },
        }

        assert groups.load_contact_group_information() == {
            'all': {
                'alias': u'Everything',
                "d!ng": "dong",
            }
        }

        assert gui_groups.load_host_group_information() == {
            'all_hosts': {
                'alias': u'All hosts :-)',
                "ding": "dong",
            }
        }

        assert gui_groups.load_service_group_information() == {
            'all_services': {
                'alias': u'All s\xe4rvices',
                "d1ng": "dong",
            }
        }