Example #1
0
def test_logged_in_nobody_permissions(mocker):
    user = LoggedInNobody()

    mocker.patch.object(config, "roles", {})
    mocker.patch.object(permissions, "permission_registry")

    assert user.may("any_permission") is False
    with pytest.raises(MKAuthException):
        user.need_permission("any_permission")
Example #2
0
    def test_dcd_not_found_if_not_super_user(
        self,
        monkeypatch: MonkeyPatch,
        mock_livestatus: MockLiveStatusConnection,
    ):
        """
        This test ensures that test_index_is_built_as_super_user makes sense, ie. that if we do not
        build as a super user, the entry "Custom host attributes" is not found.
        """

        @contextmanager
        def SuperUserContext() -> Iterator[None]:
            yield

        monkeypatch.setattr(
            search,
            "SuperUserContext",
            SuperUserContext,
        )

        with _UserContext(LoggedInNobody()):
            builder = IndexBuilder(real_match_item_generator_registry)
            with self._livestatus_mock(mock_livestatus):
                builder.build_full_index()

        searcher = IndexSearcher()
        searcher._redis_client = builder._redis_client
        assert not list(searcher.search("custom host attributes"))
Example #3
0
    def __call__(self, environ: WSGIEnvironment,
                 start_response: StartResponse) -> WSGIResponse:
        req = http.Request(environ)

        output_format = get_output_format(
            req.get_ascii_input_mandatory("output_format", "html").lower())
        mime_type = get_mime_type_from_output_format(output_format)

        resp = Response(headers=default_response_headers(req),
                        mimetype=mime_type)
        funnel = OutputFunnel(resp)

        timeout_manager = TimeoutManager()
        timeout_manager.enable_timeout(req.request_timeout)

        theme = Theme()
        config_obj = config_module.make_config_object(
            config_module.get_default_config())

        with AppContext(self), RequestContext(
                req=req,
                resp=resp,
                funnel=funnel,
                config_obj=config_obj,
                user=LoggedInNobody(),
                html_obj=htmllib.html(req, resp, funnel, output_format),
                timeout_manager=timeout_manager,
                display_options=DisplayOptions(),
                theme=theme,
        ), patch_json(json):
            config_module.initialize()
            theme.from_config(config.ui_theme)
            return self.wsgi_app(environ, start_response)
Example #4
0
    def __init__(
        self,
        req: http.Request,
        resp: http.Response,
        funnel: OutputFunnel,
        config_obj: Config,
        html_obj: Optional[htmllib.html] = None,
        timeout_manager: Optional[TimeoutManager] = None,  # pylint: disable=redefined-outer-name
        theme: Optional[Theme] = None,  # pylint: disable=redefined-outer-name
        display_options: Optional[DisplayOptions] = None,  # pylint: disable=redefined-outer-name
        prefix_logs_with_url: bool = True,
    ):
        self.html = html_obj
        self.auth_type: Optional[str] = None
        self.timeout_manager = timeout_manager
        self.theme = theme
        self.display_options = display_options
        self.session: Optional[userdb.Session] = None
        self.flashes: Optional[List[str]] = None
        self._prefix_logs_with_url = prefix_logs_with_url

        self.request = req
        self.response = resp
        self.output_funnel = funnel
        self.config = config_obj

        # TODO: cyclical import with config -> globals -> config -> ...
        from cmk.gui.utils.logged_in import LoggedInNobody
        self._user: LoggedInUser = LoggedInNobody()
        # TODO: This needs to be a helper of LoggedInUser
        self.transactions = TransactionManager(req, self._user)
        self.user_errors = UserErrors()

        self._prepend_url_filter = _PrependURLFilter()
        self._web_log_handler: Optional[logging.Handler] = None
Example #5
0
def mock_livestatus(
    with_context: bool = False,
    with_html: bool = False
) -> Generator[MockLiveStatusConnection, None, None]:
    live = MockLiveStatusConnection()

    env = EnvironBuilder().get_environ()
    req = http.Request(env)
    resp = http.Response()

    app_context: ContextManager
    req_context: ContextManager
    if with_html:
        html_obj = None
    else:
        html_obj = html(
            request=req,
            response=resp,
            output_funnel=OutputFunnel(resp),
            output_format="html",
        )
    if with_context:
        app_context = AppContext(None)
        req_context = RequestContext(
            html_obj=html_obj,
            req=req,
            resp=resp,
            funnel=OutputFunnel(resp),
            config_obj=make_config_object(get_default_config()),
            user=LoggedInNobody(),
            display_options=DisplayOptions(),
            prefix_logs_with_url=False,
        )
    else:
        app_context = contextlib.nullcontext()
        req_context = contextlib.nullcontext()

    with app_context, req_context, mock.patch(
            "cmk.gui.sites._get_enabled_and_disabled_sites",
            new=live.enabled_and_disabled_sites), mock.patch(
                "livestatus.MultiSiteConnection.expect_query",
                new=live.expect_query,
                create=True), mock.patch(
                    "livestatus.SingleSiteConnection._create_socket",
                    new=live.create_socket), mock.patch.dict(
                        os.environ, {
                            "OMD_ROOT": "/",
                            "OMD_SITE": "NO_SITE"
                        }):

        # We don't want to be polluted by other tests.
        omd_site.cache_clear()
        yield live
        # We don't want to pollute other tests.
        omd_site.cache_clear()
Example #6
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()),
            user=LoggedInNobody(),
            display_options=DisplayOptions(),
    ):
        yield
Example #7
0
 def with_context(environ, start_response):
     req = http.Request(environ)
     resp = http.Response()
     with AppContext(app), RequestContext(
             req=req,
             resp=resp,
             funnel=OutputFunnel(resp),
             config_obj=config.make_config_object(
                 config.get_default_config()),
             user=LoggedInNobody(),
             display_options=DisplayOptions(),
     ), cmk.utils.store.cleanup_locks(), sites.cleanup_connections():
         config.initialize()
         return app(environ, start_response)
Example #8
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,
    )
Example #9
0
    def test_index_is_built_as_super_user(
        self,
        mock_livestatus: MockLiveStatusConnection,
    ):
        """
        We test that the index is always built as a super user.
        """

        with _UserContext(LoggedInNobody()):
            builder = IndexBuilder(real_match_item_generator_registry)
            with self._livestatus_mock(mock_livestatus):
                builder.build_full_index()

        searcher = IndexSearcher()
        searcher._redis_client = builder._redis_client

        # if the search index did not internally use the super user while building, this item would
        # be missing, because the match item generator for the setup menu only yields entries which
        # the current user is allowed to see
        assert list(searcher.search("custom host attributes"))
Example #10
0
    with UserContext(first_user_id):
        assert global_user.id == first_user_id

        with UserContext(second_user_id):
            assert global_user.id == second_user_id

        assert global_user.id == first_user_id

    assert global_user.id is None


@pytest.mark.parametrize(
    "user, alias, email, role_ids, baserole_id",
    [
        (
            LoggedInNobody(),
            "Unauthenticated user",
            "nobody",
            [],
            "guest",  # TODO: Why is this guest "guest"?
        ),
        (
            LoggedInSuperUser(),
            "Superuser for unauthenticated pages",
            "admin",
            ["admin"],
            "admin",
        ),
    ],
)
def test_unauthenticated_users(user, alias, email, role_ids, baserole_id):
Example #11
0
    def _wsgi_app(self, environ: WSGIEnvironment, start_response: StartResponse) -> WSGIResponse:
        urls = self.url_map.bind_to_environ(environ)
        endpoint: Optional[Endpoint] = None
        try:
            result: Tuple[str, Mapping[str, Any]] = urls.match(return_rule=False)
            endpoint_ident, matched_path_args = result  # pylint: disable=unpacking-non-sequence
            wsgi_app = self.endpoints[endpoint_ident]
            if isinstance(wsgi_app, Authenticate):
                endpoint = wsgi_app.endpoint

            # Remove _path again (see Submount above), so the validators don't go crazy.
            path_args = {key: value for key, value in matched_path_args.items() if key != "_path"}

            # This is an implicit dependency, as we only know the args at runtime, but the
            # function at setup-time.
            environ[ARGS_KEY] = path_args

            req = Request(environ)
            resp = Response()
            with AppContext(self), RequestContext(
                req=req,
                resp=resp,
                funnel=OutputFunnel(resp),
                config_obj=config.make_config_object(config.get_default_config()),
                endpoint=endpoint,
                user=LoggedInNobody(),
                display_options=DisplayOptions(),
            ), cmk.utils.store.cleanup_locks(), sites.cleanup_connections():
                config.initialize()
                load_dynamic_permissions()
                return wsgi_app(environ, start_response)
        except ProblemException as exc:
            return exc(environ, start_response)
        except HTTPException as exc:
            # We don't want to log explicit HTTPExceptions as these are intentional.
            assert isinstance(exc.code, int)
            return problem(
                status=exc.code,
                title=http.client.responses[exc.code],
                detail=str(exc),
            )(environ, start_response)
        except MKException as exc:
            if self.debug:
                raise

            return problem(
                status=EXCEPTION_STATUS.get(type(exc), 500),
                title="An exception occurred.",
                detail=str(exc),
            )(environ, start_response)
        except Exception as exc:
            crash = APICrashReport.from_exception()
            crash_reporting.CrashReportStore().save(crash)
            logger.exception("Unhandled exception (Crash-ID: %s)", crash.ident_to_text())
            if self.debug:
                raise

            request = Request(environ)
            site = config.omd_site()
            query_string = urllib.parse.urlencode(
                [
                    ("crash_id", (crash.ident_to_text())),
                    ("site", site),
                ]
            )
            crash_url = f"{request.host_url}{site}/check_mk/crash.py?{query_string}"
            crash_details = {
                "crash_id": (crash.ident_to_text()),
                "crash_report": {
                    "href": crash_url,
                    "method": "get",
                    "rel": "cmk/crash-report",
                    "type": "text/html",
                },
            }
            if user.may("general.see_crash_reports"):
                crash_details["stack_trace"] = traceback.format_exc().split("\n")

            return problem(
                status=500,
                title=http.client.responses[500],
                detail=str(exc),
                ext=crash_details,
            )(environ, start_response)