def _parameter_elements(self): elements = _vs_add_common_mail_elements([ ("elements", ListChoice( title=_("Information to be displayed in the email body"), choices=[ ("omdsite", _("OMD Site")), ("hosttags", _("Tags of the Host")), ("address", _("IP Address of Host")), ("abstime", _("Absolute Time of Alert")), ("reltime", _("Relative Time of Alert")), ("longoutput", _("Additional Plugin Output")), ("ack_author", _("Acknowledgement Author")), ("ack_comment", _("Acknowledgement Comment")), ("perfdata", _("Performance Data")), ("graph", _("Performance Graphs")), ("notesurl", _("Custom Host/Service Notes URL")), ("context", _("Complete variable list (for testing)")), ], default_value=[ "perfdata", "graph", "abstime", "address", "longoutput" ], )), ("insert_html_section", TextAreaUnicode( title=_("Insert HTML section between body and table"), default_value="<HTMLTAG>CONTENT</HTMLTAG>", cols=40, rows="auto", )), ("url_prefix", _get_url_prefix_specs( "http://" + socket.gethostname() + "/" + (config.omd_site() and config.omd_site() + "/" or "") + "check_mk/", html.request.is_ssl_request and "automatic_https" or "automatic_http")), ("no_floating_graphs", FixedValue( True, title=_("Display graphs among each other"), totext=_("Graphs are shown among each other"), help= _("By default all multiple graphs in emails are displayed floating " "nearby. You can enable this option to show the graphs among each " "other."), )), ]) if not cmk_version.is_raw_edition(): import cmk.gui.cee.plugins.wato.syncsmtp # pylint: disable=no-name-in-module elements += cmk.gui.cee.plugins.wato.syncsmtp.cee_html_mail_smtp_sync_option return elements
def _verify_slave_site_config(self, site_id): # type: (str) -> None if not site_id: raise MKGeneralException(_("Missing variable siteid")) our_id = config.omd_site() if not config.is_single_local_site(): raise MKGeneralException( _("Configuration error. You treat us as " "a <b>remote</b>, but we have an own distributed WATO configuration!" )) if our_id is not None and our_id != site_id: raise MKGeneralException( _("Site ID mismatch. Our ID is '%s', but you are saying we are '%s'." ) % (our_id, site_id)) # Make sure there are no local changes we would lose! changes = ActivateChanges() changes.load() pending = list(reversed(changes.grouped_changes())) if pending: message = _( "There are %d pending changes that would get lost. The most recent are: " ) % len(pending) message += ", ".join(change["text"] for _change_id, change in pending[:10]) raise MKGeneralException(message)
def activate(self): if getattr(config, "mkeventd_enabled", False): mkeventd.execute_command("RELOAD", site=config.omd_site()) log_audit(None, "mkeventd-activate", _("Activated changes of event console configuration")) if hooks.registered('mkeventd-activate-changes'): hooks.call("mkeventd-activate-changes")
def delete_site(cls, site_id): # TODO: Clean this up from cmk.gui.watolib.hosts_and_folders import Folder all_sites = cls.load_sites() if site_id not in all_sites: raise MKUserError( None, _("Unable to delete unknown site id: %s") % site_id) # Make sure that site is not being used by hosts and folders if site_id in Folder.root_folder().all_site_ids(): search_url = html.makeactionuri([ ("host_search_change_site", "on"), ("host_search_site", site_id), ("host_search", "1"), ("folder", ""), ("mode", "search"), ("filled_in", "edit_host"), ]) raise MKUserError( None, _("You cannot delete this connection. It has folders/hosts " "assigned to it. You can use the <a href=\"%s\">host " "search</a> to get a list of the hosts.") % search_url) domains = cls._affected_config_domains() del all_sites[site_id] cls.save_sites(all_sites) cmk.gui.watolib.activate_changes.clear_site_replication_status(site_id) cmk.gui.watolib.changes.add_change("edit-sites", _("Deleted site %s") % site_id, domains=domains, sites=[config.omd_site()])
def generate_response_data(cls, properties, context, settings): if config.is_single_local_site(): site_id: Optional[SiteId] = config.omd_site() else: site_filter = context.get("site", {}).get("site") site_id = SiteId(site_filter) if site_filter else None render_mode = "hosts" if site_id else "sites" if render_mode == "hosts": assert site_id is not None elements = cls._collect_hosts_data(site_id) default_title = _("Host overview") elif render_mode == "sites": elements = cls._collect_sites_data() default_title = _("Site overview") else: raise NotImplementedError() return { # TODO: This should all be done inside the dashlet class once it is instantiated by the # ajax call "title": render_title_with_macros_string( context, settings["single_infos"], settings.get("title", default_title), default_title, ), "render_mode": render_mode, "plot_definitions": [], "data": [e.serialize() for e in elements], }
def _create_nagvis_backends(sites_config): cfg = [ '; MANAGED BY CHECK_MK WATO - Last Update: %s' % time.strftime('%Y-%m-%d %H:%M:%S'), ] for site_id, site in sites_config.items(): if site == config.omd_site(): continue # skip local site, backend already added by omd socket = _encode_socket_for_nagvis(site_id, site) cfg += [ '', '[backend_%s]' % site_id, 'backendtype="mklivestatus"', 'socket="%s"' % socket, ] if site.get("status_host"): cfg.append('statushost="%s"' % ':'.join(site['status_host'])) if site["proxy"] is None and is_livestatus_encrypted(site): address_spec = site["socket"][1] tls_settings = address_spec["tls"][1] cfg.append('verify_tls_peer=%d' % tls_settings["verify"]) cfg.append('verify_tls_ca_path=%s' % ConfigDomainCACertificates.trusted_cas_file) store.save_file('%s/etc/nagvis/conf.d/cmk_backends.ini.php' % cmk.utils.paths.omd_root, '\n'.join(cfg))
def execute(self): if self._tmpfs_mounted(config.omd_site()): yield ACResultOK(_("The temporary filesystem is mounted")) else: yield ACResultWARN( _("The temporary filesystem is not mounted. Your installation " "may work with degraded performance."))
def generate_response_data(cls, properties, context, settings): if config.is_single_local_site(): site_id: Optional[SiteId] = config.omd_site() else: site_filter = context.get("site", {}).get("site") site_id = SiteId(site_filter) if site_filter else None render_mode = "hosts" if site_id else "sites" if render_mode == "hosts": assert site_id is not None elements = cls._collect_hosts_data(site_id) elif render_mode == "sites": elements = cls._collect_sites_data() else: raise NotImplementedError() return { # TODO: Get the correct dashlet title. This needs to use the general dashlet title # calculation. We somehow have to get the title from # cmk.gui.dashboard._render_dashlet_title. "title": _("Site overview"), "render_mode": render_mode, "plot_definitions": [], "data": [e.serialize() for e in elements], }
def _automation_push_profile(self): site_id = html.request.var("siteid") if not site_id: raise MKGeneralException(_("Missing variable siteid")) user_id = html.request.var("user_id") if not user_id: raise MKGeneralException(_("Missing variable user_id")) our_id = config.omd_site() if our_id is not None and our_id != site_id: raise MKGeneralException( _("Site ID mismatch. Our ID is '%s', but you are saying we are '%s'." ) % (our_id, site_id)) profile = html.request.var("profile") if not profile: raise MKGeneralException( _('Invalid call: The profile is missing.')) users = userdb.load_users(lock=True) users[UserId(user_id)] = watolib.mk_eval(profile) userdb.save_users(users) return True
def _wsgi_app(self, environ: WSGIEnvironment, start_response): urls = self.url_map.bind_to_environ(environ) try: wsgi_app, path_args = urls.match() # Remove this again (see Submount above), so the validators don't go crazy. del path_args['_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 return wsgi_app(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 crash_url = f"/{config.omd_site()}/check_mk/crash.py?" + urllib.parse.urlencode( [ ("crash_id", crash.ident_to_text()), ("site", config.omd_site()), ], ) return problem( status=500, title=str(exc), detail= "An internal error occured while processing your request.", ext={ 'crash_report': { 'href': crash_url, 'method': 'get', 'rel': 'cmk/crash-report', 'type': 'text/html', }, 'crash_id': crash.ident_to_text(), })(environ, start_response)
def deserialize(cls, serialized: Dict[str, str]) -> 'FetchAgentOutputRequest': host_name = serialized["host_name"] host = watolib.Host.host(host_name) if host is None: raise MKGeneralException( _("Host %s does not exist on remote site %s. This " "may be caused by a failed configuration synchronization. Have a look at " "the <a href=\"wato.py?folder=&mode=changelog\">activate changes page</a> " "for further information.") % (host_name, config.omd_site())) host.need_permission("read") return cls(host, serialized["agent_type"])
def create_self_signed_cert(pkey): cert = crypto.X509() cert.get_subject().O = "Check_MK Site %s" % config.omd_site() cert.get_subject().CN = config.user.id or "### Check_MK ###" cert.set_serial_number(1) cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(30 * 365 * 24 * 60 * 60) # valid for 30 years. cert.set_issuer(cert.get_subject()) cert.set_pubkey(pkey) cert.sign(pkey, 'sha1') return cert
def _get_default_view_hostnames(self, max_nodes: int) -> Set[HostName]: """ Returns all hosts without any parents """ query = "GET hosts\nColumns: name\nFilter: parents =" with sites.prepend_site(), sites.only_sites(html.request.var("site")): hosts = [(x[0], x[1]) for x in sites.live().query(query)] # If no explicit site is set and the number of initially displayed hosts # exceeds the auto growth range, only the hosts of the master site are shown if len(hosts) > max_nodes: hostnames = {x[1] for x in hosts if x[0] == config.omd_site()} else: hostnames = {x[1] for x in hosts} return hostnames
def transform_topology_dashlet(dashlet_spec: DashletConfig, filter_group: str = "") -> DashletConfig: site_id = dashlet_spec["context"].get("site", config.omd_site()) dashlet_spec.update({ "type": "url", "title": _("Network topology of site %s") % site_id, "url": "../nagvis/frontend/nagvis-js/index.php?mod=Map&header_template=" "on-demand-filter&header_menu=1&label_show=1&sources=automap&act=view" "&backend_id=%s&render_mode=undirected&url_target=main&filter_group=%s" % (site_id, filter_group), "show_in_iframe": True, }) return dashlet_spec
def _get_effective_global_setting(self, varname: str) -> Any: global_settings = load_configuration_settings() default_values = ABCConfigDomain.get_all_default_globals() if cmk.gui.config.is_wato_slave_site(): current_settings = load_configuration_settings(site_specific=True) else: sites = SiteManagementFactory.factory().load_sites() current_settings = sites[config.omd_site()].get("globals", {}) if varname in current_settings: return current_settings[varname] if varname in global_settings: return global_settings[varname] return default_values[varname]
def page(self) -> None: _invalidate_auth_session() if auth_type == 'cookie': raise HTTPRedirect(config.url_prefix() + 'check_mk/login.py') # Implement HTTP logout with cookie hack if not html.request.has_cookie('logout'): html.response.headers['WWW-Authenticate'] = ( 'Basic realm="OMD Monitoring Site %s"' % config.omd_site()) html.response.set_http_cookie('logout', '1') raise FinalizeRequest(http.client.UNAUTHORIZED) html.response.delete_cookie('logout') raise HTTPRedirect(config.url_prefix() + 'check_mk/')
def _crash_report_rows_from_local_site(self): raw_rows = [] store = cmk.utils.crash_reporting.CrashReportStore() for crash_dir in cmk.utils.paths.crash_dir.glob("*/*"): # pylint: disable=no-member serialized_crash = store.load_serialized_from_directory(crash_dir) raw_row = { "site": config.omd_site(), "crash_id": crash_dir.name, } for key, value in serialized_crash.iteritems(): raw_row[key] = json.dumps(value) raw_rows.append(raw_row) return sorted(raw_rows, key=lambda r: r["crash_id"])
def send_command( connection, command: LivestatusCommand, params: List[Any], ): """Send a command to livestatus. Args: connection: A livestatus connection object. command: The livestatus external command to be sent. For reference on these commands have a look at this page: https://docs.checkmk.com/master/en/livestatus_references.html params: A list of anything. Examples: >>> from cmk.gui.livestatus_utils.testing import simple_expect >>> with simple_expect( ... "COMMAND [...] ADD_HOST_COMMENT", match_type="ellipsis") as live: ... send_command(live, "ADD_HOST_COMMENT", []) >>> with simple_expect( ... "COMMAND [...] ADD_HOST_COMMENT;1;2;3", match_type="ellipsis") as live: ... send_command(live, "ADD_HOST_COMMENT", [1, 2, 3]) >>> with simple_expect( ... "COMMAND [...] ADD_HOST_COMMENT;1;2;3", match_type="ellipsis") as live: ... send_command(live, "ADD_HOST_COMMENT", [object()]) Traceback (most recent call last): ... ValueError: Unknown type of parameter 0: <class 'object'> """ current_time = int(time.time()) cmd: str = command for pos, param in enumerate(params): if not isinstance(param, (int, str)): raise ValueError(f"Unknown type of parameter {pos}: {type(param)}") cmd += f";{param}" connection.command(f"[{current_time}] {cmd}", sitename=config.omd_site())
def _show_crash_dump_message(crash: 'GUICrashReport', plain_text: bool, fail_silently: bool, show_crash_link: Optional[bool]) -> None: """Create a crash dump from a GUI exception and display a message to the user""" if show_crash_link is None: show_crash_link = config.user.may("general.see_crash_reports") title = _("Internal error") message = u"%s: %s<br>\n<br>\n" % (title, crash.crash_info["exc_value"]) # Do not reveal crash context information to unauthenticated users or not permitted # users to prevent disclosure of internal information if not show_crash_link: message += _( "An internal error occurred while processing your request. " "You can report this issue to your Checkmk administrator. " "Detailed information can be found on the crash report page " "or in <tt>var/log/web.log</tt>.") else: crash_url = makeuri( request, [ ("site", config.omd_site()), ("crash_id", crash.ident_to_text()), ], filename="crash.py", ) message += _( "An internal error occured while processing your request. " "You can report this issue to the Checkmk team to help " "fixing this issue. Please open the <a href=\"%s\">crash report page</a> " "and use the form for reporting the problem.") % crash_url if plain_text: html.set_output_format("text") html.write("%s\n" % escaping.strip_tags(message)) return if fail_silently: return html.header(title, Breadcrumb()) html.show_error(message) html.footer()
def _get_default_view_hostnames(self, growth_auto_max_nodes): """ Returns all hosts without any parents """ query = "GET hosts\nColumns: name\nFilter: parents =" sites.live().set_prepend_site(True) only_site = html.request.var("site") if only_site: sites.live().set_only_sites([only_site]) hosts = [(x[0], x[1]) for x in sites.live().query(query)] sites.live().set_only_sites(None) sites.live().set_prepend_site(False) # If no explicit site is set and the number of initially displayed hosts # exceeds the auto growth range, only the hosts of the master site are shown if len(hosts) > growth_auto_max_nodes: hostnames = [x[1] for x in hosts if x[0] == config.omd_site()] else: hostnames = [x[1] for x in hosts] return hostnames
def page(self) -> None: assert config.user.id is not None _invalidate_auth_session() session_id = _get_session_id_from_cookie(config.user.id, revalidate_cookie=True) userdb.on_logout(config.user.id, session_id) if auth_type == 'cookie': raise HTTPRedirect(config.url_prefix() + 'check_mk/login.py') # Implement HTTP logout with cookie hack if not request.has_cookie('logout'): response.headers['WWW-Authenticate'] = ( 'Basic realm="OMD Monitoring Site %s"' % config.omd_site()) response.set_http_cookie('logout', '1', secure=request.is_secure) raise FinalizeRequest(http.client.UNAUTHORIZED) response.delete_cookie('logout') raise HTTPRedirect(config.url_prefix() + 'check_mk/')
def _create_nagvis_backends(sites_config): cfg = [ '; MANAGED BY CHECK_MK WATO - Last Update: %s' % time.strftime('%Y-%m-%d %H:%M:%S'), ] for site_id, site in sites_config.items(): if site == config.omd_site(): continue # skip local site, backend already added by omd socket = cmk.gui.sites.encode_socket_for_livestatus(site_id, site) cfg += [ '', '[backend_%s]' % site_id, 'backendtype="mklivestatus"', 'socket="%s"' % socket, ] if site.get("status_host"): cfg.append('statushost="%s"' % ':'.join(site['status_host'])) store.save_file( '%s/etc/nagvis/conf.d/cmk_backends.ini.php' % cmk.utils.paths.omd_root, '\n'.join(cfg))
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, stack=app_stack()), 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(), stack=request_stack(), url_filter=PrependURLFilter(), ), 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)
def confirm_all_local_changes(): ActivateChanges().confirm_site_changes(config.omd_site())
def __init__(self, text): super(ACResult, self).__init__() self.text = text self.site_id = config.omd_site()
def validate_configuration(cls, site_id, site_configuration, all_sites): if not re.match("^[-a-z0-9A-Z_]+$", site_id): raise MKUserError( "id", _("The site id must consist only of letters, digit and the underscore.")) if not site_configuration.get("alias"): raise MKUserError( "alias", _("Please enter an alias name or description for the site %s.") % site_id) if site_configuration.get("url_prefix") and site_configuration.get("url_prefix")[-1] != "/": raise MKUserError("url_prefix", _("The URL prefix must end with a slash.")) # Connection if site_configuration["socket"][0] == "local" and site_id != config.omd_site(): raise MKUserError( "method_sel", _("You can only configure a local site connection for " "the local site. The site IDs ('%s' and '%s') are " "not equal.") % (site_id, config.omd_site())) # Timeout if "timeout" in site_configuration: timeout = site_configuration["timeout"] try: int(timeout) except ValueError: raise MKUserError("timeout", _("The timeout %s is not a valid integer number.") % timeout) # Status host status_host = site_configuration.get("status_host") if status_host: status_host_site, status_host_name = status_host if status_host_site not in all_sites: raise MKUserError("sh_site", _("The site of the status host does not exist.")) if status_host_site == site_id: raise MKUserError("sh_site", _("You cannot use the site itself as site of the status host.")) if not status_host_name: raise MKUserError("sh_host", _("Please specify the name of the status host.")) if site_configuration.get("replication"): multisiteurl = site_configuration.get("multisiteurl") if not site_configuration.get("multisiteurl"): raise MKUserError("multisiteurl", _("Please enter the Multisite URL of the slave site.")) if not multisiteurl.endswith("/check_mk/"): raise MKUserError("multisiteurl", _("The Multisite URL must end with /check_mk/")) if not multisiteurl.startswith("http://") and \ not multisiteurl.startswith("https://"): raise MKUserError( "multisiteurl", _("The Multisites URL must begin with <tt>http://</tt> or <tt>https://</tt>.")) if site_configuration["socket"][0] == "local": raise MKUserError("replication", _("You cannot do replication with the local site.")) # User synchronization user_sync_valuespec = cls.user_sync_valuespec() user_sync_valuespec.validate_value(site_configuration.get("user_sync"), "user_sync")
def local_site_url(): return "http://" + socket.gethostname() + "/" + config.omd_site( ) + "check_mk/"
def _save(self): watolib.SiteManagementFactory().factory().save_sites(self._configured_sites, activate=False) if self._site_id == config.omd_site(): watolib.save_site_global_settings(self._current_settings)
def __init__(self, text): # type: (str) -> None super(ACResult, self).__init__() self.text = text self.site_id = config.omd_site()
def _file_name(self, key_id, key): return "Check_MK-%s-%s-backup_key-%s.pem" % (backup.hostname(), config.omd_site(), key_id)