Beispiel #1
0
    def __call__(self, environ, start_response):
        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()

        with AppContext(self), RequestContext(
                req=req,
                resp=resp,
                funnel=funnel,
                html_obj=htmllib.html(req, resp, funnel, output_format),
                timeout_manager=timeout_manager,
                display_options=DisplayOptions(),
                theme=theme,
        ), patch_json(json):
            config.initialize()
            theme.from_config(config.ui_theme, config.theme_choices())
            return self.wsgi_app(environ, start_response)
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
Beispiel #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)
Beispiel #4
0
 def __call__(self, environ, start_response) -> Response:
     req = http.Request(environ)
     with AppContext(self), RequestContext(req=req,
                                           display_options=DisplayOptions(),
                                           html_obj=htmllib.html(req)):
         config.initialize()
         return _process_request(environ, start_response)
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 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 #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 __call__(self, environ, start_response):
     req = http.Request(environ)
     with AppContext(self), RequestContext(req=req,
                                           html_obj=htmllib.html(req)):
         config.initialize()
         html.init_modes()
         return self.wsgi_app(environ, start_response)
Beispiel #9
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 #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 _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 #12
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, stack=app_stack())
        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,
            stack=request_stack(),
            url_filter=PrependURLFilter(),
        )
    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()
Beispiel #13
0
def fixture_pre_20_cookie():
    environ = dict(
        create_environ(),
        HTTP_COOKIE=
        u"xyz=123; auth_stable=lärs:1534272374.61:1f59cac3fcd5bcc389e4f8397bed315b; abc=123".encode(
            "utf-8"))

    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(http.Request(environ))):
        yield "auth_stable"
Beispiel #14
0
def fixture_current_cookie(with_user, session_id):
    user_id = with_user[0]
    cookie_name = login.auth_cookie_name()
    cookie_value = login._auth_cookie_value(user_id, session_id)

    environ = dict(create_environ(), HTTP_COOKIE=f"{cookie_name}={cookie_value}".encode("utf-8"))

    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(http.Request(environ))):
        yield cookie_name
Beispiel #15
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 #16
0
def test_web_server_auth_session(user_id):
    environ = dict(create_environ(), REMOTE_USER=str(user_id))

    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(http.Request(environ))):

        assert user.id is None
        with login.authenticate(request) as authenticated:
            assert authenticated is True
            assert user.id == user_id
            assert session.user_id == user.id
        assert user.id is None
Beispiel #17
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 #18
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 #19
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 #20
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),
            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.set_prepend_site",
                    new=live.set_prepend_site), \
         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.
        version.omd_site.cache_clear()
        yield live
        # We don't want to pollute other tests.
        version.omd_site.cache_clear()
Beispiel #21
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
Beispiel #22
0
def test_flash(user_id):
    environ = create_environ()
    # Execute the first request flash some message
    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(http.Request(environ))) as request, \
            login.UserContext(user_id):
        session_id = on_succeeded_login(user_id)  # Create and activate session
        assert request.session is not None

        flash("abc")
        assert session.session_info.flashes == ["abc"]

    # Now create the second request to get the previously flashed message
    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(http.Request(environ))), \
            login.UserContext(user_id):
        on_access(user_id, session_id)
        assert request.session is not None
        assert session.session_info.flashes == ["abc"]

        # Get the flashed messages removes the messages from the session
        # and subsequent calls to get_flashed_messages return the messages
        # over and over.
        assert get_flashed_messages() == [HTML("abc")]
        assert get_flashed_messages() == [HTML("abc")]
        assert session.session_info.flashes == []

    # Now create the third request that should not have access to the flashed messages since the
    # second one consumed them.
    with AppContext(DummyApplication(environ, None)), \
            RequestContext(htmllib.html(http.Request(environ))), \
            login.UserContext(user_id):
        on_access(user_id, session_id)
        assert request.session is not None
        assert session.session_info.flashes == []
        assert get_flashed_messages() == []
Beispiel #23
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 #24
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 #25
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 #26
0
def test_generate_snapshot(edition_short, snapshot_manager_class, monkeypatch, tmp_path, with_user):
    user_id = with_user[0]
    monkeypatch.setattr(cmk_version, "edition_short", lambda: edition_short)

    environ = dict(create_environ(), REQUEST_URI='')
    with AppContext(DummyApplication(environ, None)), \
         RequestContext(htmllib.html(Request(environ))):
        login.login(user_id)
        _create_test_sync_config(monkeypatch)
        snapshot_settings = _create_sync_snapshot(snapshot_manager_class, monkeypatch, tmp_path)

    # And now check the resulting snapshot contents
    unpack_dir = tmp_path / "snapshot_unpack"
    with tarfile.open(snapshot_settings.snapshot_path, "r") as t:
        t.extractall(str(unpack_dir))

    expected_subtars = [
        "auth.secret.tar",
        "auth.serials.tar",
        "check_mk.tar",
        "diskspace.tar",
        "htpasswd.tar",
        "mkeventd_mkp.tar",
        "mkeventd.tar",
        "multisite.tar",
        "sitespecific.tar",
        "usersettings.tar",
    ]

    if is_enterprise_repo():
        expected_subtars += [
            "dcd.tar",
            "mknotify.tar",
        ]

    if not cmk_version.is_raw_edition():
        expected_subtars.append("liveproxyd.tar")

    assert sorted(f.name for f in unpack_dir.iterdir()) == sorted(expected_subtars)

    expected_files = {
        'mkeventd_mkp.tar': [],
        'multisite.tar': ["global.mk", "users.mk"],
        'usersettings.tar': [user_id],
        'mkeventd.tar': [],
        'check_mk.tar': ["hosts.mk", "contacts.mk"],
        'htpasswd.tar': ["htpasswd"],
        'liveproxyd.tar': [],
        'sitespecific.tar': ['sitespecific.mk'],
        'auth.secret.tar': [],
        'dcd.tar': [],
        'auth.serials.tar': ["auth.serials"],
        'mknotify.tar': [],
        'diskspace.tar': [],
    }

    # TODO: Shouldn't we clean up these subtle differences?
    if cmk_version.is_managed_edition():
        expected_files.update({
            "mkeventd.tar": ["rules.mk"],
            'check_mk.tar': ["groups.mk", "contacts.mk"],
            'multisite.tar': [
                "bi.mk",
                "customers.mk",
                "global.mk",
                "groups.mk",
                "user_connections.mk",
                "users.mk",
            ],
        })

    if not cmk_version.is_raw_edition():
        expected_files['liveproxyd.tar'] = []

    # And now check the subtar contents
    for subtar in unpack_dir.iterdir():
        subtar_unpack_dir = unpack_dir / subtar.stem
        subtar_unpack_dir.mkdir(parents=True, exist_ok=True)

        with tarfile.open(str(subtar), "r") as s:
            s.extractall(str(subtar_unpack_dir))

        files = sorted(str(f.relative_to(subtar_unpack_dir)) for f in subtar_unpack_dir.iterdir())

        assert sorted(expected_files[subtar.name]) == files, \
            "Subtar %s has wrong files" % subtar.name
Beispiel #27
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 #28
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",
            }
        }
Beispiel #29
0
def register_builtin_html():
    """This fixture registers a global htmllib.html() instance just like the regular GUI"""
    environ = dict(create_environ(), REQUEST_URI='')
    with AppContext(DummyApplication(environ, None)), \
         RequestContext(htmllib.html(Request(environ), Response(is_secure=False))):
        yield
Beispiel #30
0
def test_apply_sync_snapshot(edition_short, snapshot_manager_class, monkeypatch, tmp_path,
                             with_user):
    user_id = with_user[0]
    monkeypatch.setattr(cmk_version, "edition_short", lambda: edition_short)

    environ = dict(create_environ(), REQUEST_URI='')
    with AppContext(DummyApplication(environ, None)), \
         RequestContext(htmllib.html(Request(environ))):
        login.login(user_id)

        _create_test_sync_config(monkeypatch)
        snapshot_settings = _create_sync_snapshot(snapshot_manager_class, monkeypatch, tmp_path)

        # Change unpack target directory from "unit test site" paths to a test specific path
        unpack_dir = tmp_path / "snapshot_unpack"
        components = [
            activate_changes._replace_omd_root(str(unpack_dir), p)
            for p in activate_changes.get_replication_paths()
        ]

        with open(snapshot_settings.snapshot_path, "rb") as f:
            activate_changes.apply_sync_snapshot("unit_remote_1", f.read(), components)

    expected_paths = [
        'etc',
        'var',
        'etc/check_mk',
        'etc/check_mk/conf.d',
        'etc/check_mk/mkeventd.d',
        'etc/check_mk/multisite.d',
        'etc/check_mk/conf.d/wato',
        'etc/check_mk/conf.d/wato/hosts.mk',
        'etc/check_mk/conf.d/wato/contacts.mk',
        'etc/check_mk/mkeventd.d/mkp',
        'etc/check_mk/mkeventd.d/wato',
        'etc/check_mk/mkeventd.d/mkp/rule_packs',
        'etc/check_mk/multisite.d/wato',
        'etc/check_mk/multisite.d/wato/global.mk',
        'var/check_mk',
        'var/check_mk/web',
        "etc/htpasswd",
        "etc/auth.serials",
        "etc/check_mk/multisite.d/wato/users.mk",
        six.ensure_str('var/check_mk/web/%s' % user_id),
        six.ensure_str('var/check_mk/web/%s/cached_profile.mk' % user_id),
        six.ensure_str('var/check_mk/web/%s/enforce_pw_change.mk' % user_id),
        six.ensure_str('var/check_mk/web/%s/last_pw_change.mk' % user_id),
        six.ensure_str('var/check_mk/web/%s/num_failed_logins.mk' % user_id),
        six.ensure_str('var/check_mk/web/%s/serial.mk' % user_id),
    ]

    # The paths are registered once the enterprise plugins are available, independent of the
    # cmk_version.edition_short() value.
    if is_enterprise_repo():
        expected_paths += [
            'etc/check_mk/dcd.d',
            'etc/check_mk/mknotifyd.d',
            'etc/check_mk/mknotifyd.d/wato',
            'etc/check_mk/dcd.d/wato',
        ]

    # TODO: Shouldn't we clean up these subtle differences?
    if cmk_version.is_managed_edition():
        expected_paths += [
            "etc/check_mk/conf.d/wato/groups.mk",
            "etc/check_mk/mkeventd.d/wato/rules.mk",
            "etc/check_mk/multisite.d/wato/bi.mk",
            "etc/check_mk/multisite.d/wato/customers.mk",
            "etc/check_mk/multisite.d/wato/groups.mk",
            "etc/check_mk/multisite.d/wato/user_connections.mk",
            #"etc/check_mk/conf.d/wato/sitespecific.mk",
            #"etc/check_mk/dcd.d/wato/distributed.mk",
            #"etc/check_mk/dcd.d/wato/sitespecific.mk",
            #"etc/check_mk/mkeventd.d/wato/sitespecific.mk",
            #"etc/check_mk/mknotifyd.d/wato/sitespecific.mk",
            #"etc/check_mk/multisite.d/wato/sitespecific.mk",
        ]

        expected_paths.remove("etc/check_mk/conf.d/wato/hosts.mk")

    if not cmk_version.is_raw_edition():
        expected_paths += [
            'etc/check_mk/liveproxyd.d',
            'etc/check_mk/liveproxyd.d/wato',
            #'etc/check_mk/multisite.d/wato/ca-certificates_sitespecific.mk',
        ]

    paths = [str(p.relative_to(unpack_dir)) for p in unpack_dir.glob("**/*")]
    assert sorted(paths) == sorted(expected_paths)