def get_request(self): site_id = request.get_ascii_input_mandatory("site_id") cmk.gui.watolib.activate_changes.verify_remote_site_config(site_id) try: domains = ast.literal_eval(request.get_ascii_input_mandatory("domains")) except SyntaxError: raise watolib.MKAutomationException( _("Invalid request: %r") % request.get_ascii_input_mandatory("domains")) return ActivateChangesRequest(site_id=site_id, domains=domains)
def page(self): if not user.may("wato.automation"): raise MKAuthException(_("This account has no permission for automation.")) response.set_content_type("text/plain") _set_version_headers() # Parameter was added with 1.5.0p10 if not request.has_var("_version"): raise MKGeneralException(_("Your central site is incompatible with this remote site")) # - _version and _edition_short were added with 1.5.0p10 to the login call only # - x-checkmk-version and x-checkmk-edition were added with 2.0.0p1 # Prefer the headers and fall back to the request variables for now. central_version = ( request.headers["x-checkmk-version"] if "x-checkmk-version" in request.headers else request.get_ascii_input_mandatory("_version") ) central_edition_short = ( request.headers["x-checkmk-edition"] if "x-checkmk-edition" in request.headers else request.get_ascii_input_mandatory("_edition_short") ) if not compatible_with_central_site( central_version, central_edition_short, cmk_version.__version__, cmk_version.edition_short(), ): raise MKGeneralException( _( "Your central site (Version: %s, Edition: %s) is incompatible with this " "remote site (Version: %s, Edition: %s)" ) % ( central_version, central_edition_short, cmk_version.__version__, cmk_version.edition_short(), ) ) response.set_data( repr( { "version": cmk_version.__version__, "edition_short": cmk_version.edition_short(), "login_secret": _get_login_secret(create_on_demand=True), } ) )
def page(self) -> None: if not user.may("wato.diagnostics"): raise MKAuthException( _("Sorry, you lack the permission for downloading diagnostics dumps.") ) site = request.get_ascii_input_mandatory("site") tarfile_name = request.get_ascii_input_mandatory("tarfile_name") file_content = self._get_diagnostics_dump_file(site, tarfile_name) response.set_content_type("application/x-tgz") response.headers["Content-Disposition"] = "Attachment; filename=%s" % tarfile_name response.set_data(file_content)
def _show_form(self) -> None: assert user.id is not None credentials = load_two_factor_credentials(user.id) credential_id = request.get_ascii_input_mandatory("_edit") credential = credentials["webauthn_credentials"].get(credential_id) if credential is None: raise MKUserError("_edit", _("The credential does not exist")) html.begin_form("profile", method="POST") html.prevent_password_auto_completion() html.open_div(class_="wato") self._valuespec(credential).render_input( "profile", { "registered_at": credential["registered_at"], "alias": credential["alias"], }, ) forms.end() html.close_div() html.hidden_field("_edit", credential_id) html.hidden_fields() html.end_form() html.footer()
def _get_search_vars(self) -> HTTPVariables: search_vars = {} if request.has_var("host_search_host"): search_vars["host_search_host"] = request.get_ascii_input_mandatory("host_search_host") for varname, value in request.itervars(prefix="host_search_change_"): if html.get_checkbox(varname) is False: continue search_vars[varname] = value attr_ident = varname.split("host_search_change_", 1)[1] # The URL variable naming scheme is not clear. Try to match with "attr_" prefix # and without. We should investigate and clean this up. attr_prefix = "host_search_attr_%s" % attr_ident search_vars.update(request.itervars(prefix=attr_prefix)) attr_prefix = "host_search_%s" % attr_ident search_vars.update(request.itervars(prefix=attr_prefix)) for varname, value in request.itervars(): if varname.startswith(("_", "host_search_")) or varname == "mode": continue search_vars[varname] = value search_vars["mode"] = "folder" return list(search_vars.items())
def _action(self) -> None: assert user.id is not None users = userdb.load_users(lock=True) user_spec = users[user.id] language = request.get_ascii_input_mandatory("language", "") # Set the users language if requested to set it explicitly if language != "_default_": user_spec["language"] = language user.language = language set_language_cookie(request, response, language) else: if "language" in user_spec: del user_spec["language"] user.reset_language() # load the new language localize(user.language) if user.may("general.edit_notifications") and user_spec.get( "notifications_enabled"): value = forms.get_input(get_vs_flexible_notifications(), "notification_method") user_spec["notification_method"] = value # Custom attributes if user.may("general.edit_user_attributes"): for name, attr in userdb.get_user_attributes(): if not attr.user_editable(): continue perm_name = attr.permission() if perm_name and not user.may(perm_name): continue vs = attr.valuespec() value = vs.from_html_vars("ua_" + name) vs.validate_value(value, "ua_" + name) # TODO: Dynamically fiddling around with a TypedDict is a bit questionable user_spec[name] = value # type: ignore[literal-required] userdb.save_users(users) flash(_("Successfully updated user profile.")) # In distributed setups with remote sites where the user can login, start the # user profile replication now which will redirect the user to the destination # page after completion. Otherwise directly open up the destination page. if user.authorized_login_sites(): back_url = "user_profile_replicate.py?back=user_profile.py" else: back_url = "user_profile.py" # Ensure theme changes are applied without additional user interaction html.reload_whole_page(back_url) html.footer() raise FinalizeRequest(code=200)
def inpage_search_form(mode: Optional[str] = None, default_value: str = "") -> None: form_name = "inpage_search_form" reset_button_id = "%s_reset" % form_name was_submitted = request.get_ascii_input("filled_in") == form_name html.begin_form(form_name, add_transid=False) html.text_input( "search", size=32, default_value=default_value, placeholder=_("Filter"), required=True, title="", ) html.hidden_fields() if mode: html.hidden_field("mode", mode, add_var=True) reset_url = request.get_ascii_input_mandatory( "reset_url", requested_file_with_query(request)) html.hidden_field("reset_url", reset_url, add_var=True) html.button("submit", "", cssclass="submit", help_=_("Apply")) html.buttonlink(reset_url, "", obj_id=reset_button_id, title=_("Reset")) html.end_form() html.javascript("cmk.page_menu.inpage_search_init(%s, %s)" % (json.dumps(reset_button_id), json.dumps(was_submitted)))
def _from_vars(self): self._role_id = request.get_ascii_input_mandatory("edit") try: self._role = self._roles[self._role_id] except KeyError: raise MKUserError("edit", _("This role does not exist."))
def page(self): html.div(html.render_message(_("Loading...")), id_="async_progress_msg") html.div("", id_="status_container") html.javascript( "cmk.background_job.start('ajax_background_job_details.py', %s)" % json.dumps(request.get_ascii_input_mandatory("job_id")) )
def _action(self) -> None: assert user.id is not None credentials = load_two_factor_credentials(user.id, lock=True) credential_id = request.get_ascii_input_mandatory("_edit") credential = credentials["webauthn_credentials"].get(credential_id) if credential is None: raise MKUserError("_edit", _("The credential does not exist")) vs = self._valuespec(credential) settings = vs.from_html_vars("profile") vs.validate_value(settings, "profile") credential["alias"] = settings["alias"] save_two_factor_credentials(user.id, credentials) flash(_("Successfully changed the credential.")) # In distributed setups with remote sites where the user can login, start the # user profile replication now which will redirect the user to the destination # page after completion. Otherwise directly open up the destination page. origtarget = "user_two_factor_overview.py" if user.authorized_login_sites(): raise redirect( makeuri_contextless(request, [("back", origtarget)], filename="user_profile_replicate.py")) raise redirect(origtarget)
def _from_vars(self): self._hostname = request.get_ascii_input_mandatory("host") self._host = watolib.Folder.current().host(self._hostname) self._host.need_permission("read") if self._host.is_cluster(): raise MKGeneralException(_("This page does not support cluster hosts."))
def _action(self) -> None: assert config.user.id is not None users = userdb.load_users(lock=True) user = users[config.user.id] language = request.get_ascii_input_mandatory('language', "") # Set the users language if requested to set it explicitly if language != "_default_": user['language'] = language config.user.language = language set_language_cookie(request, response, language) else: if 'language' in user: del user['language'] config.user.reset_language() # load the new language cmk.gui.i18n.localize(config.user.language) if config.user.may('general.edit_notifications') and user.get( "notifications_enabled"): value = forms.get_input(watolib.get_vs_flexible_notifications(), "notification_method") user["notification_method"] = value # Custom attributes if config.user.may('general.edit_user_attributes'): for name, attr in userdb.get_user_attributes(): if not attr.user_editable(): continue if attr.permission() and not config.user.may( attr.permission()): continue vs = attr.valuespec() value = vs.from_html_vars('ua_' + name) vs.validate_value(value, "ua_" + name) user[name] = value userdb.save_users(users) flash(_("Successfully updated user profile.")) # In distributed setups with remote sites where the user can login, start the # user profile replication now which will redirect the user to the destination # page after completion. Otherwise directly open up the destination page. if config.user.authorized_login_sites(): back_url = "user_profile_replicate.py?back=user_profile.py" else: back_url = "user_profile.py" # Ensure theme changes are applied without additional user interaction html.reload_whole_page(back_url) html.footer() raise FinalizeRequest(code=200)
def _init_host(self) -> watolib.CREHost: hostname = request.get_ascii_input_mandatory("host") folder = watolib.Folder.current() if not folder.has_host(hostname): raise MKUserError("host", _("You called this page with an invalid host name.")) host = folder.load_host(hostname) host.need_permission("read") return host
def page_api() -> None: try: if not request.has_var("output_format"): response.set_content_type("application/json") output_format = "json" else: output_format = request.get_ascii_input_mandatory( "output_format", "json").lower() if output_format not in _FORMATTERS: response.set_content_type("text/plain") raise MKUserError( None, "Only %s are supported as output formats" % " and ".join('"%s"' % f for f in _FORMATTERS), ) # TODO: Add some kind of helper for boolean-valued variables? pretty_print = False pretty_print_var = request.get_str_input_mandatory( "pretty_print", "no").lower() if pretty_print_var not in ("yes", "no"): raise MKUserError(None, 'pretty_print must be "yes" or "no"') pretty_print = pretty_print_var == "yes" api_call = _get_api_call() _check_permissions(api_call) request_object = _get_request(api_call) _check_formats(output_format, api_call, request_object) _check_request_keys(api_call, request_object) resp = _execute_action(api_call, request_object) except MKAuthException as e: resp = { "result_code": 1, "result": _("Authorization Error. Insufficent permissions for '%s'") % e, } except MKException as e: resp = { "result_code": 1, "result": _("Checkmk exception: %s\n%s") % (e, "".join(traceback.format_exc())), } except Exception: if active_config.debug: raise logger.exception("error handling web API call") resp = { "result_code": 1, "result": _("Unhandled exception: %s") % traceback.format_exc(), } response.set_data( _FORMATTERS[output_format][1 if pretty_print else 0](resp))
def _from_vars(self): self._hostname = request.get_ascii_input_mandatory("host") self._host = watolib.Folder.current().host(self._hostname) if self._host is None: raise MKUserError("host", _("The given host does not exist.")) self._host.need_permission("read") # TODO: Validate? self._service = request.get_unicode_input("service")
def get_request(self): site_id = SiteId(request.get_ascii_input_mandatory("site_id")) activate_changes.verify_remote_site_config(site_id) try: serialized_domain_requests = ast.literal_eval( request.get_ascii_input_mandatory("domains") ) if serialized_domain_requests and isinstance(serialized_domain_requests[0], str): serialized_domain_requests = [ asdict(DomainRequest(x)) for x in serialized_domain_requests ] except SyntaxError: raise watolib.MKAutomationException( _("Invalid request: %r") % request.get_ascii_input_mandatory("domains") ) return ActivateChangesRequest(site_id=site_id, domains=serialized_domain_requests)
def get_request(self) -> PushSnapshotRequest: site_id = request.get_ascii_input_mandatory("siteid") cmk.gui.watolib.activate_changes.verify_remote_site_config(site_id) snapshot = request.uploaded_file("snapshot") if not snapshot: raise MKGeneralException(_('Invalid call: The snapshot is missing.')) return PushSnapshotRequest(site_id=site_id, tar_content=ensure_binary(snapshot[2]))
def _from_vars(self): host_name = request.get_ascii_input_mandatory("host") if not watolib.Folder.current().has_host(host_name): raise MKUserError("host", _("You called this page with an invalid host name.")) if not config.user.may("wato.rename_hosts"): raise MKAuthException(_("You don't have the right to rename hosts")) self._host = watolib.Folder.current().host(host_name) self._host.need_permission("write")
def _from_vars(self): self._start = bool(request.var("_start")) # 'all' not set -> only scan checked hosts in current folder, no recursion # otherwise: all host in this folder, maybe recursively self._all = bool(request.var("all")) self._complete_folder = self._all # Ignored during initial form display self._settings = ParentScanSettings( where=request.get_ascii_input_mandatory("where", "subfolder"), alias=request.get_unicode_input_mandatory("alias", "").strip(), recurse=html.get_checkbox("recurse") or False, select=request.get_ascii_input_mandatory("select", "noexplicit"), timeout=request.get_integer_input_mandatory("timeout", 8), probes=request.get_integer_input_mandatory("probes", 2), max_ttl=request.get_integer_input_mandatory("max_ttl", 10), force_explicit=html.get_checkbox("force_explicit") or False, ping_probes=request.get_integer_input_mandatory("ping_probes", 5), ) self._job = ParentScanBackgroundJob()
def _ajax_switch_masterstate(self) -> None: response.set_content_type("text/plain") if not user.may("sidesnap.master_control"): return if not transactions.check_transaction(): return site = request.get_ascii_input_mandatory("site") column = request.get_ascii_input_mandatory("switch") state = request.get_integer_input_mandatory("state") commands = { ("enable_notifications", 1): "ENABLE_NOTIFICATIONS", ("enable_notifications", 0): "DISABLE_NOTIFICATIONS", ("execute_service_checks", 1): "START_EXECUTING_SVC_CHECKS", ("execute_service_checks", 0): "STOP_EXECUTING_SVC_CHECKS", ("execute_host_checks", 1): "START_EXECUTING_HOST_CHECKS", ("execute_host_checks", 0): "STOP_EXECUTING_HOST_CHECKS", ("enable_flap_detection", 1): "ENABLE_FLAP_DETECTION", ("enable_flap_detection", 0): "DISABLE_FLAP_DETECTION", ("process_performance_data", 1): "ENABLE_PERFORMANCE_DATA", ("process_performance_data", 0): "DISABLE_PERFORMANCE_DATA", ("enable_event_handlers", 1): "ENABLE_EVENT_HANDLERS", ("enable_event_handlers", 0): "DISABLE_EVENT_HANDLERS", } command = commands.get((column, state)) if not command: html.write_text(_("Command %s/%d not found") % (column, state)) return sites.live().command("[%d] %s" % (int(time.time()), command), site) sites.live().set_only_sites([site]) sites.live().query( "GET status\nWaitTrigger: program\nWaitTimeout: 10000\nWaitCondition: %s = %d\nColumns: %s\n" % (column, state, column) ) sites.live().set_only_sites() self.show()
def action(self) -> ActionResult: if not transactions.transaction_valid(): return redirect(mode_url("folder")) attributes = watolib.collect_attributes(self._host_type_name(), new=True) cluster_nodes = self._get_cluster_nodes() hostname = request.get_ascii_input_mandatory("host") Hostname().validate_value(hostname, "host") folder = watolib.Folder.current() if transactions.check_transaction(): folder.create_hosts([(hostname, attributes, cluster_nodes)]) self._host = folder.load_host(hostname) inventory_url = watolib.folder_preserving_link( [ ("mode", "inventory"), ("host", self._host.name()), ("_scan", "1"), ] ) create_msg = ( None if self._host.is_ping_host() else ( _( "Successfully created the host. Now you should do a " '<a href="%s">service discovery</a> in order to auto-configure ' "all services to be checked on this host." ) % inventory_url ) ) if request.var("_save"): return redirect(inventory_url) if create_msg: flash(create_msg) if request.var("diag_host"): return redirect( mode_url("diag_host", folder=folder.path(), host=self._host.name(), _try="1") ) return redirect(mode_url("folder", folder=folder.path()))
def _from_vars(self): self._varname = request.get_ascii_input_mandatory("varname") try: self._config_variable = config_variable_registry[self._varname]() self._valuespec = self._config_variable.valuespec() except KeyError: raise MKUserError("varname", _("The global setting \"%s\" does not exist.") % self._varname) if not self._may_edit_configvar(self._varname): raise MKAuthException(_("You are not permitted to edit this global setting.")) self._current_settings = watolib.load_configuration_settings() self._global_settings = {}
def action(self) -> ActionResult: if not transactions.check_transaction(): return redirect(mode_url("%s_groups" % self.type_name)) alias = request.get_unicode_input_mandatory("alias").strip() self.group = {"alias": alias} self._determine_additional_group_data() if self._new: self._name = request.get_ascii_input_mandatory("name").strip() watolib.add_group(self._name, self.type_name, self.group) else: watolib.edit_group(self._name, self.type_name, self.group) return redirect(mode_url("%s_groups" % self.type_name))
def action(self) -> ActionResult: if not transactions.check_transaction(): return redirect(mode_url("%s_groups" % self.type_name)) if request.var('_delete'): delname = request.get_ascii_input_mandatory("_delete") usages = watolib.find_usages_of_group(delname, self.type_name) if usages: message = "<b>%s</b><br>%s:<ul>" % \ (_("You cannot delete this %s group.") % self.type_name, _("It is still in use by")) for title, link in usages: message += '<li><a href="%s">%s</a></li>\n' % (link, title) message += "</ul>" raise MKUserError(None, message) watolib.delete_group(delname, self.type_name) self._groups = self._load_groups() return redirect(mode_url("%s_groups" % self.type_name))
def _from_vars(self): self._check_type = request.get_ascii_input_mandatory("check_type", "") builtin_check_types = ["check-mk", "check-mk-inventory"] if (not re.match("^[a-zA-Z0-9_.]+$", self._check_type) and self._check_type not in builtin_check_types): raise MKUserError("check_type", _("Invalid check type")) manpage = man_pages.load_man_page(self._check_type) if manpage is None: raise MKUserError(None, _("There is no manpage for this check.")) self._manpage = manpage checks = get_check_information().plugin_infos if self._check_type in checks: self._manpage = { "type": "check_mk", **checks[self._check_type], **self._manpage, } elif self._check_type.startswith("check_"): # Assume active check self._manpage = { "type": "active", **self._manpage, } elif self._check_type in builtin_check_types: self._manpage = { "type": "check_mk", "service_description": "Check_MK%s" % ("" if self._check_type == "check-mk" else " Discovery"), **self._manpage, } else: raise MKUserError( None, _("Could not detect type of manpage: %s. Maybe the check is missing " ) % self._check_type, )
def _from_vars(self): self._topic = request.get_ascii_input_mandatory("topic", "") if not re.match("^[a-zA-Z0-9_./]+$", self._topic): raise MKUserError("topic", _("Invalid topic")) self._path: Tuple[str, ...] = tuple(self._topic.split("/")) # e.g. [ "hw", "network" ] for comp in self._path: ID().validate_value(comp, None) # Beware against code injection! self._manpages = _get_check_catalog(self._path) self._titles = man_pages.man_page_catalog_titles() self._has_second_level = None for t, has_second_level, title, _helptext in _man_page_catalog_topics(): if t == self._path[0]: self._has_second_level = has_second_level self._topic_title = title break if len(self._path) == 2: self._topic_title = self._titles.get(self._path[1], self._path[1])
def get_request(self) -> str: return request.get_ascii_input_mandatory("tarfile_name")
def get_request(self) -> str: return ast.literal_eval(request.get_ascii_input_mandatory("request"))
def get_request(self) -> CheckmkAutomationRequest: return CheckmkAutomationRequest( *ast.literal_eval(request.get_ascii_input_mandatory("request")))
def action(self) -> ActionResult: if html.form_submitted("search"): return None alias = request.get_unicode_input_mandatory("alias") unique, info = watolib.is_alias_used("roles", self._role_id, alias) if not unique: assert info is not None raise MKUserError("alias", info) new_id = request.get_ascii_input_mandatory("id") if not new_id: raise MKUserError("id", "You have to provide a ID.") if not re.match("^[-a-z0-9A-Z_]*$", new_id): raise MKUserError( "id", _("Invalid role ID. Only the characters a-z, A-Z, 0-9, _ and - are allowed." )) if new_id != self._role_id: if new_id in self._roles: raise MKUserError("id", _("The ID is already used by another role")) self._role["alias"] = alias # based on if not self._role.get("builtin"): basedon = request.get_ascii_input_mandatory("basedon") if basedon not in builtin_role_ids: raise MKUserError( "basedon", _("Invalid valid for based on. Must be id of builtin rule." )) self._role["basedon"] = basedon # Permissions permissions = self._role["permissions"] for var_name, value in request.itervars(prefix="perm_"): try: perm = permission_registry[var_name[5:]] except KeyError: continue if value == "yes": permissions[perm.name] = True elif value == "no": permissions[perm.name] = False elif value == "default": try: del permissions[perm.name] except KeyError: pass # Already at defaults if self._role_id != new_id: self._roles[new_id] = self._role del self._roles[self._role_id] self._rename_user_role(self._role_id, new_id) self._save_roles() watolib.add_change("edit-roles", _("Modified user role '%s'") % new_id, sites=get_login_sites()) return redirect(mode_url("roles"))