Example #1
0
    def load(cls):
        cls.clear_instances()

        # First load builtin pages. Set username to ''
        for name, page_dict in cls.builtin_pages().items():
            page_dict["owner"] = UserId(u'')  # might have been forgotten on copy action
            page_dict["public"] = True
            page_dict["name"] = name
            new_page = cls(page_dict)
            cls.add_instance(("", name), new_page)

        # Now scan users subdirs for files "user_$type_name.mk"
        for user_dir in os.listdir(config.config_dir):
            user = UserId(ensure_unicode(user_dir))
            try:
                path = "%s/%s/user_%ss.mk" % (config.config_dir, six.ensure_str(user),
                                              cls.type_name())
                if not os.path.exists(path):
                    continue

                if not userdb.user_exists(user):
                    continue

                user_pages = store.load_object_from_file(path, default={})
                for name, page_dict in user_pages.items():
                    page_dict["owner"] = user
                    page_dict["name"] = name
                    cls.add_instance((user, name), cls(page_dict))

            except SyntaxError as e:
                raise MKGeneralException(
                    _("Cannot load %s from %s: %s") % (cls.type_name(), path, e))

        cls._load()
        cls._declare_instance_permissions()
Example #2
0
def _check_parsed_auth_cookie(username: UserId, session_id: str,
                              cookie_hash: str) -> None:
    if not userdb.user_exists(username):
        raise MKAuthException(_('Username is unknown'))

    if cookie_hash != _generate_auth_hash(username, session_id):
        raise MKAuthException(_('Invalid credentials'))
Example #3
0
def _check_parsed_auth_cookie(username, issue_time, cookie_hash):
    # type: (UserId, float, str) -> None
    if not userdb.user_exists(username):
        raise MKAuthException(_('Username is unknown'))

    if cookie_hash != _generate_auth_hash(username, issue_time):
        raise MKAuthException(_('Invalid credentials'))
Example #4
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}).")
Example #5
0
def test_check_credentials_local_user_create_htpasswd_user_ad_hoc() -> None:
    user_id = UserId("someuser")
    assert userdb.user_exists(user_id) is False
    assert userdb._user_exists_according_to_profile(user_id) is False
    assert user_id not in _load_users_uncached(lock=False)

    htpasswd.Htpasswd(Path(cmk.utils.paths.htpasswd_file)).save(
        {user_id: htpasswd.hash_password("cmk")})
    # Once a user exists in the htpasswd, the GUI treats the user as existing user and will
    # automatically initialize the missing data structures
    assert userdb.user_exists(user_id) is True
    assert userdb._user_exists_according_to_profile(user_id) is False
    assert str(user_id) in _load_users_uncached(lock=False)

    assert userdb.check_credentials(user_id, "cmk") == user_id

    # Nothing changes during regular access
    assert userdb.user_exists(user_id) is True
    assert userdb._user_exists_according_to_profile(user_id) is False
    assert str(user_id) in _load_users_uncached(lock=False)
Example #6
0
def _verify_user(environ) -> 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)

            gui_user = gui_user_auth(user_id, secret)
            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), 'webserver'))

    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 oder in the code.
    final_candidate = verified[0]
    if not userdb.is_customer_user_allowed_to_login(final_candidate['sub']):
        raise MKAuthException(f"{final_candidate['sub']} may not log in here.")

    if userdb.user_locked(final_candidate['sub']):
        raise MKAuthException(f"{final_candidate['sub']} not authorized.")

    return final_candidate
Example #7
0
def _verify_user(environ) -> RFC7662:
    verified: List[RFC7662] = []

    auth_header = environ.get('HTTP_AUTHORIZATION', '')
    if auth_header:
        user_id, secret = user_from_bearer_header(auth_header)
        automation_user = automation_auth(user_id, secret)
        gui_user = gui_user_auth(user_id, secret)

        if not (automation_user or gui_user):
            raise MKAuthException(f"{user_id} not authorized.")

        if automation_user:
            verified.append(automation_user)

        if gui_user:
            verified.append(gui_user)

    remote_user = environ.get('REMOTE_USER', '')
    if remote_user and userdb.user_exists(UserId(remote_user)):
        verified.append(rfc7662_subject(UserId(remote_user), 'webserver'))

    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 oder in the code.
    final_candidate = verified[0]
    if not userdb.is_customer_user_allowed_to_login(final_candidate['sub']):
        raise MKAuthException(f"{final_candidate['sub']} may not log in here.")

    if userdb.user_locked(final_candidate['sub']):
        raise MKAuthException(f"{final_candidate['sub']} not authorized.")

    return final_candidate
Example #8
0
 def is_relevant(self):
     return userdb.user_exists("omdadmin")
Example #9
0
 def is_relevant(self) -> bool:
     return userdb.user_exists(UserId("omdadmin"))
Example #10
0
def check_parsed_auth_cookie(username, issue_time, cookie_hash):
    if not userdb.user_exists(username):
        raise MKAuthException(_('Username is unknown'))

    if cookie_hash != generate_auth_hash(username, issue_time):
        raise MKAuthException(_('Invalid credentials'))
Example #11
0
 def is_relevant(self):
     # type: () -> bool
     return userdb.user_exists(UserId("omdadmin"))
Example #12
0
def execute_network_scan_job() -> None:
    init_wato_datastructures(with_wato_lock=True)

    if watolib.is_wato_slave_site():
        return  # Don't execute this job on slaves.

    folder = find_folder_to_scan()
    if not folder:
        return  # Nothing to do.

    # We need to have the context of the user. The jobs are executed when
    # config.set_user_by_id() has not been executed yet. So there is no user context
    # available. Use the run_as attribute from the job config and revert
    # the previous state after completion.
    old_user = config.user.id
    run_as = folder.attribute("network_scan")["run_as"]
    if not userdb.user_exists(run_as):
        raise MKGeneralException(
            _("The user %s used by the network "
              "scan of the folder %s does not exist.") % (run_as, folder.title()))
    config.set_user_by_id(folder.attribute("network_scan")["run_as"])

    result: NetworkScanResult = {
        "start": time.time(),
        "end": True,  # means currently running
        "state": None,
        "output": "The scan is currently running.",
    }

    # Mark the scan in progress: Is important in case the request takes longer than
    # the interval of the cron job (1 minute). Otherwise the scan might be started
    # a second time before the first one finished.
    save_network_scan_result(folder, result)

    try:
        if config.site_is_local(folder.site_id()):
            found = cmk.gui.watolib.network_scan.do_network_scan(folder)
        else:
            found = watolib.do_remote_automation(config.site(folder.site_id()), "network-scan",
                                                 [("folder", folder.path())])

        if not isinstance(found, list):
            raise MKGeneralException(_("Received an invalid network scan result: %r") % found)

        add_scanned_hosts_to_folder(folder, found)

        result.update({
            "state": True,
            "output": _("The network scan found %d new hosts.") % len(found),
        })
    except Exception as e:
        result.update({
            "state": False,
            "output": _("An exception occured: %s") % e,
        })
        logger.error("Exception in network scan:\n%s", traceback.format_exc())

    result["end"] = time.time()

    save_network_scan_result(folder, result)

    if old_user:
        config.set_user_by_id(old_user)
Example #13
0
def execute_network_scan_job() -> None:
    """Executed by the multisite cron job once a minute. Is only executed in the
    central site. Finds the next folder to scan and starts it via WATO
    automation. The result is written to the folder in the master site."""
    init_wato_datastructures(with_wato_lock=True)

    if is_wato_slave_site():
        return  # Don't execute this job on slaves.

    folder = _find_folder_to_scan()
    if not folder:
        return  # Nothing to do.

    run_as = folder.attribute("network_scan")["run_as"]
    if not userdb.user_exists(run_as):
        raise MKGeneralException(
            _("The user %s used by the network "
              "scan of the folder %s does not exist.") %
            (run_as, folder.title()))

    with UserContext(run_as):
        result: NetworkScanResult = {
            "start": time.time(),
            "end": True,  # means currently running
            "state": None,
            "output": "The scan is currently running.",
        }

        # Mark the scan in progress: Is important in case the request takes longer than
        # the interval of the cron job (1 minute). Otherwise the scan might be started
        # a second time before the first one finished.
        _save_network_scan_result(folder, result)

        try:
            if site_is_local(folder.site_id()):
                found = _do_network_scan(folder)
            else:
                found = do_remote_automation(get_site_config(folder.site_id()),
                                             "network-scan",
                                             [("folder", folder.path())])

            if not isinstance(found, list):
                raise MKGeneralException(
                    _("Received an invalid network scan result: %r") % found)

            _add_scanned_hosts_to_folder(folder, found)

            result.update({
                "state":
                True,
                "output":
                _("The network scan found %d new hosts.") % len(found),
            })
        except Exception as e:
            result.update({
                "state": False,
                "output": _("An exception occured: %s") % e,
            })
            logger.error("Exception in network scan:\n%s",
                         traceback.format_exc())

        result["end"] = time.time()

        _save_network_scan_result(folder, result)