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, ))
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)
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"
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()
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() == {}
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")
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
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
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()
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
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)
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)
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
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}).")
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")
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")
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
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
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
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
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()
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, )
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
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")
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
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
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 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", } }