예제 #1
0
    def action(self):
        if not html.check_transaction():
            return "users"

        if self._is_new_user:
            self._user_id = UserID(allow_empty=False).from_html_vars("user_id")
            user_attrs = {}
        else:
            self._user_id = html.get_unicode_input("edit").strip()
            user_attrs = self._users[self._user_id]

        # Full name
        user_attrs["alias"] = html.get_unicode_input("alias").strip()

        # Locking
        user_attrs["locked"] = html.get_checkbox("locked")
        increase_serial = False

        if self._user_id in self._users and self._users[
                self._user_id]["locked"] != user_attrs["locked"] and user_attrs["locked"]:
            increase_serial = True  # when user is being locked now, increase the auth serial

        # Authentication: Password or Secret
        auth_method = html.request.var("authmethod")
        if auth_method == "secret":
            secret = html.request.var("_auth_secret", "").strip()
            user_attrs["automation_secret"] = secret
            user_attrs["password"] = hash_password(secret)
            increase_serial = True  # password changed, reflect in auth serial

        else:
            password = html.request.var("_password_" + self._pw_suffix(), '').strip()
            password2 = html.request.var("_password2_" + self._pw_suffix(), '').strip()

            # We compare both passwords only, if the user has supplied
            # the repeation! We are so nice to our power users...
            # Note: this validation is done before the main-validiation later on
            # It doesn't make any sense to put this block into the main validation function
            if password2 and password != password2:
                raise MKUserError("_password2", _("The both passwords do not match."))

            # Detect switch back from automation to password
            if "automation_secret" in user_attrs:
                del user_attrs["automation_secret"]
                if "password" in user_attrs:
                    del user_attrs["password"]  # which was the encrypted automation password!

            if password:
                user_attrs["password"] = hash_password(password)
                user_attrs["last_pw_change"] = int(time.time())
                increase_serial = True  # password changed, reflect in auth serial

            # PW change enforcement
            user_attrs["enforce_pw_change"] = html.get_checkbox("enforce_pw_change")
            if user_attrs["enforce_pw_change"]:
                increase_serial = True  # invalidate all existing user sessions, enforce relogon

        # Increase serial (if needed)
        if increase_serial:
            user_attrs["serial"] = user_attrs.get("serial", 0) + 1

        # Email address
        user_attrs["email"] = EmailAddressUnicode().from_html_vars("email")

        idle_timeout = watolib.get_vs_user_idle_timeout().from_html_vars("idle_timeout")
        user_attrs["idle_timeout"] = idle_timeout
        if idle_timeout is not None:
            user_attrs["idle_timeout"] = idle_timeout
        elif idle_timeout is None and "idle_timeout" in user_attrs:
            del user_attrs["idle_timeout"]

        # Pager
        user_attrs["pager"] = html.request.var("pager", '').strip()

        if cmk.is_managed_edition():
            customer = self._vs_customer.from_html_vars("customer")
            self._vs_customer.validate_value(customer, "customer")

            if customer != managed.default_customer_id():
                user_attrs["customer"] = customer
            elif "customer" in user_attrs:
                del user_attrs["customer"]

        vs_sites = self._vs_sites()
        authorized_sites = vs_sites.from_html_vars("authorized_sites")
        vs_sites.validate_value(authorized_sites, "authorized_sites")

        if authorized_sites is not None:
            user_attrs["authorized_sites"] = authorized_sites
        elif "authorized_sites" in user_attrs:
            del user_attrs["authorized_sites"]

        # Roles
        user_attrs["roles"] = [
            role for role in self._roles.keys() if html.get_checkbox("role_" + role)
        ]

        # Language configuration
        set_lang = html.get_checkbox("_set_lang")
        language = html.request.var("language")
        if set_lang:
            if language == "":
                language = None
            user_attrs["language"] = language
        elif not set_lang and "language" in user_attrs:
            del user_attrs["language"]

        # Contact groups
        cgs = []
        for c in self._contact_groups:
            if html.get_checkbox("cg_" + c):
                cgs.append(c)
        user_attrs["contactgroups"] = cgs

        # Notification settings are only active if we do *not* have
        # rule based notifications!
        if not self._rbn_enabled():
            # Notifications
            user_attrs["notifications_enabled"] = html.get_checkbox("notifications_enabled")

            ntp = html.request.var("notification_period")
            if ntp not in self._timeperiods:
                ntp = "24X7"
            user_attrs["notification_period"] = ntp

            for what, opts in [("host", "durfs"), ("service", "wucrfs")]:
                user_attrs[what + "_notification_options"] = "".join(
                    [opt for opt in opts if html.get_checkbox(what + "_" + opt)])

            value = watolib.get_vs_flexible_notifications().from_html_vars("notification_method")
            user_attrs["notification_method"] = value
        else:
            user_attrs["fallback_contact"] = html.get_checkbox("fallback_contact")

        # Custom user attributes
        for name, attr in userdb.get_user_attributes():
            value = attr.valuespec().from_html_vars('ua_' + name)
            user_attrs[name] = value

        # Generate user "object" to update
        user_object = {self._user_id: {"attributes": user_attrs, "is_new_user": self._is_new_user}}
        # The following call validates and updated the users
        edit_users(user_object)
        return "users"
예제 #2
0
    def _set(self, request):
        # NOTE: This encoding here should be kept
        # Otherwise and unicode encoded text will be written into the
        # configuration file with unknown side effects
        ruleset_name = request["ruleset_name"].encode("utf-8")

        # Future validation, currently the rule API actions are admin only, so the check is pointless
        # may_edit_ruleset(ruleset_name)

        # Check if configuration hash has changed in the meantime
        ruleset_dict = self._get_ruleset_configuration(ruleset_name)
        if "configuration_hash" in request:
            validate_config_hash(request["configuration_hash"], ruleset_dict)

        # Check permissions of new rules and rules we are going to delete
        new_ruleset = request["ruleset"]
        folders_set_ruleset = set(new_ruleset.keys())
        folders_obsolete_ruleset = set(
            ruleset_dict.keys()) - folders_set_ruleset

        for check_folders in [folders_set_ruleset, folders_obsolete_ruleset]:
            for folder_path in check_folders:
                if not watolib.Folder.folder_exists(folder_path):
                    raise MKUserError(
                        None,
                        _("Folder %s does not exist") % folder_path)
                rule_folder = watolib.Folder.folder(folder_path)
                rule_folder.need_permission("write")

        tag_to_group_map = ruleset_matcher.get_tag_to_group_map(config.tags)

        # Verify all rules
        rule_vs = watolib.Ruleset(ruleset_name,
                                  tag_to_group_map).rulespec.valuespec

        for folder_path, rules in new_ruleset.items():
            for rule in rules:
                value = rule["value"]

                try:
                    rule_vs.validate_datatype(value, "test_value")
                    rule_vs.validate_value(value, "test_value")
                except MKException as e:
                    # TODO: The abstract MKException should never be instanciated directly
                    # Change this call site and make MKException an abstract base class
                    raise MKException("ERROR: %s. Affected Rule %r" %
                                      (str(e), rule))

        # Add new rulesets
        for folder_path, rules in new_ruleset.items():
            folder = watolib.Folder.folder(folder_path)

            new_ruleset = watolib.Ruleset(ruleset_name, tag_to_group_map)
            new_ruleset.from_config(folder, rules)

            folder_rulesets = watolib.FolderRulesets(folder)
            folder_rulesets.load()
            # TODO: This add_change() call should be made by the data classes
            watolib.add_change("edit-ruleset",
                               _("Set ruleset '%s' for '%s' with %d rules") % (
                                   new_ruleset.title(),
                                   folder.title(),
                                   len(rules),
                               ),
                               sites=folder.all_site_ids())
            folder_rulesets.set(ruleset_name, new_ruleset)
            folder_rulesets.save()

        # Remove obsolete rulesets
        for folder_path in folders_obsolete_ruleset:
            folder = watolib.Folder.folder(folder_path)

            folder_rulesets = watolib.FolderRulesets(folder)
            folder_rulesets.load()
            # TODO: This add_change() call should be made by the data classes
            watolib.add_change(
                "edit-ruleset",
                _("Deleted ruleset '%s' for '%s'") % (
                    watolib.Ruleset(ruleset_name, tag_to_group_map).title(),
                    folder.title(),
                ),
                sites=folder.all_site_ids())

            new_ruleset = watolib.Ruleset(ruleset_name, tag_to_group_map)
            new_ruleset.from_config(folder, [])
            folder_rulesets.set(ruleset_name, new_ruleset)
            folder_rulesets.save()
예제 #3
0
 def _require_metric(value, varprefix):
     if value is None:
         raise MKUserError(varprefix, _("You need to select a metric"))
예제 #4
0
    def action(self):
        # TODO: remove subclass specific things specifict things (everything with _type == 'user')
        if not html.check_transaction():
            return

        title = html.request.get_unicode_input_mandatory("title").strip()
        if not title:
            raise MKUserError("title", _("Please specify a title."))

        for this_attr in self._attrs:
            if title == this_attr['title'] and self._name != this_attr['name']:
                raise MKUserError(
                    "alias",
                    _("This alias is already used by the attribute %s.") %
                    this_attr['name'])

        topic = html.request.get_unicode_input_mandatory('topic', '').strip()
        help_txt = html.request.get_unicode_input_mandatory('help', '').strip()
        show_in_table = html.get_checkbox('show_in_table')
        add_custom_macro = html.get_checkbox('add_custom_macro')

        if self._new:
            self._name = html.request.get_ascii_input_mandatory("name",
                                                                '').strip()
            if not self._name:
                raise MKUserError(
                    "name", _("Please specify a name for the new attribute."))
            if ' ' in self._name:
                raise MKUserError(
                    "name",
                    _("Sorry, spaces are not allowed in attribute names."))
            if not re.match("^[-a-z0-9A-Z_]*$", self._name):
                raise MKUserError(
                    "name",
                    _("Invalid attribute name. Only the characters a-z, A-Z, 0-9, _ and - are allowed."
                      ))
            if [a for a in self._attrs if a['name'] == self._name]:
                raise MKUserError(
                    "name",
                    _("Sorry, there is already an attribute with that name."))

            ty = html.request.get_ascii_input_mandatory('type', '').strip()
            if ty not in [t[0] for t in custom_attr_types()]:
                raise MKUserError('type',
                                  _('The choosen attribute type is invalid.'))

            self._attr = {
                'name': self._name,
                'type': ty,
            }
            self._attrs.append(self._attr)

            add_change(
                "edit-%sattr" % self._type,
                _("Create new %s attribute %s") % (self._type, self._name))
        else:
            add_change(
                "edit-%sattr" % self._type,
                _("Modified %s attribute %s") % (self._type, self._name))
        self._attr.update({
            'title': title,
            'topic': topic,
            'help': help_txt,
            'show_in_table': show_in_table,
            'add_custom_macro': add_custom_macro,
        })

        self._add_extra_attrs_from_html_vars()

        save_custom_attrs_to_mk_file(self._all_attrs)
        self._update_config()

        return self._type + "_attrs"
예제 #5
0
def _show_page_user_profile(change_pw):
    start_async_replication = False

    if not config.user.id:
        raise MKUserError(None, _('Not logged in.'))

    if not config.user.may('general.edit_profile') and not config.user.may(
            'general.change_password'):
        raise MKAuthException(
            _("You are not allowed to edit your user profile."))

    if not config.wato_enabled:
        raise MKAuthException(
            _('User profiles can not be edited (WATO is disabled).'))

    success = None
    if html.request.has_var('_save') and html.check_transaction():
        users = userdb.load_users(lock=True)

        try:
            # Profile edit (user options like language etc.)
            if config.user.may('general.edit_profile'):
                if not change_pw:
                    set_lang = html.get_checkbox('_set_lang')
                    language = html.request.var('language')
                    # Set the users language if requested
                    if set_lang:
                        if language == '':
                            language = None
                        # Set custom language
                        users[config.user.id]['language'] = language
                        config.user.language = language
                        html.set_language_cookie(language)

                    else:
                        # Remove the customized language
                        if 'language' in users[config.user.id]:
                            del users[config.user.id]['language']
                        config.user.reset_language()

                    # load the new language
                    cmk.gui.i18n.localize(config.user.language)

                    user = users.get(config.user.id)
                    if config.user.may('general.edit_notifications'
                                       ) and user.get("notifications_enabled"):
                        value = forms.get_input(
                            watolib.get_vs_flexible_notifications(),
                            "notification_method")
                        users[config.user.id]["notification_method"] = value

                    # Custom attributes
                    if config.user.may('general.edit_user_attributes'):
                        for name, attr in userdb.get_user_attributes():
                            if attr.user_editable():
                                if not attr.permission() or config.user.may(
                                        attr.permission()):
                                    vs = attr.valuespec()
                                    value = vs.from_html_vars('ua_' + name)
                                    vs.validate_value(value, "ua_" + name)
                                    users[config.user.id][name] = value

            # Change the password if requested
            password_changed = False
            if config.user.may('general.change_password'):
                cur_password = html.request.var('cur_password')
                password = html.request.var('password')
                password2 = html.request.var('password2', '')

                if change_pw:
                    # Force change pw mode
                    if not cur_password:
                        raise MKUserError(
                            "cur_password",
                            _("You need to provide your current password."))
                    if not password:
                        raise MKUserError(
                            "password", _("You need to change your password."))
                    if cur_password == password:
                        raise MKUserError(
                            "password",
                            _("The new password must differ from your current one."
                              ))

                if cur_password and password:
                    if userdb.hook_login(config.user.id,
                                         cur_password) is False:
                        raise MKUserError("cur_password",
                                          _("Your old password is wrong."))
                    if password2 and password != password2:
                        raise MKUserError(
                            "password2",
                            _("The both new passwords do not match."))

                    watolib.verify_password_policy(password)
                    users[config.user.id]['password'] = hash_password(password)
                    users[config.user.id]['last_pw_change'] = int(time.time())

                    if change_pw:
                        # Has been changed, remove enforcement flag
                        del users[config.user.id]['enforce_pw_change']

                    # Increase serial to invalidate old cookies
                    if 'serial' not in users[config.user.id]:
                        users[config.user.id]['serial'] = 1
                    else:
                        users[config.user.id]['serial'] += 1

                    password_changed = True

            # Now, if in distributed environment where users can login to remote sites,
            # set the trigger for pushing the new auth information to the slave sites
            # asynchronous
            if config.user.authorized_login_sites():
                start_async_replication = True

            userdb.save_users(users)

            if password_changed:
                # Set the new cookie to prevent logout for the current user
                login.set_auth_cookie(config.user.id)

            success = True
        except MKUserError as e:
            html.add_user_error(e.varname, e)
    else:
        users = userdb.load_users()

    watolib.init_wato_datastructures(with_wato_lock=True)

    # When in distributed setup, display the replication dialog instead of the normal
    # profile edit dialog after changing the password.
    if start_async_replication:
        user_profile_async_replication_page()
        return

    if change_pw:
        title = _("Change Password")
    else:
        title = _("Edit User Profile")

    html.header(title)

    # Rule based notifications: The user currently cannot simply call the according
    # WATO module due to WATO permission issues. So we cannot show this button
    # right now.
    if not change_pw:
        rulebased_notifications = watolib.load_configuration_settings().get(
            "enable_rulebased_notifications")
        if rulebased_notifications and config.user.may(
                'general.edit_notifications'):
            html.begin_context_buttons()
            url = "wato.py?mode=user_notifications_p"
            html.context_button(_("Notifications"), url, "notifications")
            html.end_context_buttons()
    else:
        reason = html.request.var('reason')
        if reason == 'expired':
            html.p(
                _('Your password is too old, you need to choose a new password.'
                  ))
        else:
            html.p(
                _('You are required to change your password before proceeding.'
                  ))

    if success:
        html.reload_sidebar()
        if change_pw:
            html.show_message(_("Your password has been changed."))
            raise HTTPRedirect(html.request.var('_origtarget', 'index.py'))
        else:
            html.show_message(_("Successfully updated user profile."))
            # Ensure theme changes are applied without additional user interaction
            html.immediate_browser_redirect(0.5, html.makeuri([]))

    if html.has_user_errors():
        html.show_user_errors()

    user = users.get(config.user.id)
    if user is None:
        html.show_warning(_("Sorry, your user account does not exist."))
        html.footer()
        return

    # Returns true if an attribute is locked and should be read only. Is only
    # checked when modifying an existing user
    locked_attributes = userdb.locked_attributes(user.get('connector'))

    def is_locked(attr):
        return attr in locked_attributes

    html.begin_form("profile", method="POST")
    html.prevent_password_auto_completion()
    html.open_div(class_="wato")
    forms.header(_("Personal Settings"))

    if not change_pw:
        forms.section(_("Name"), simple=True)
        html.write_text(user.get("alias", config.user.id))

    if config.user.may(
            'general.change_password') and not is_locked('password'):
        forms.section(_("Current Password"))
        html.password_input('cur_password', autocomplete="new-password")

        forms.section(_("New Password"))
        html.password_input('password', autocomplete="new-password")

        forms.section(_("New Password Confirmation"))
        html.password_input('password2', autocomplete="new-password")

    if not change_pw and config.user.may('general.edit_profile'):
        select_language(user)

        # Let the user configure how he wants to be notified
        if not rulebased_notifications \
            and config.user.may('general.edit_notifications') \
            and user.get("notifications_enabled"):
            forms.section(_("Notifications"))
            html.help(
                _("Here you can configure how you want to be notified about host and service problems and "
                  "other monitoring events."))
            watolib.get_vs_flexible_notifications().render_input(
                "notification_method", user.get("notification_method"))

        if config.user.may('general.edit_user_attributes'):
            for name, attr in userdb.get_user_attributes():
                if attr.user_editable():
                    vs = attr.valuespec()
                    forms.section(_u(vs.title()))
                    value = user.get(name, vs.default_value())
                    if not attr.permission() or config.user.may(
                            attr.permission()):
                        vs.render_input("ua_" + name, value)
                        html.help(_u(vs.help()))
                    else:
                        html.write(vs.value_to_text(value))

    # Save button
    forms.end()
    html.button("_save", _("Save"))
    html.close_div()
    html.hidden_fields()
    html.end_form()
    html.footer()
예제 #6
0
파일: utils.py 프로젝트: gradecke/checkmk
 def _validate_value(self, value: DropdownChoiceValue,
                     varprefix: str) -> None:
     if value is not None and not self._regex.match(ensure_str(value)):
         raise MKUserError(varprefix, self._regex_error)
예제 #7
0
 def validate_url(cls, value: str, varprefix: str) -> None:
     if is_allowed_url(value, cross_domain=True, schemes=["http", "https"]):
         return
     raise MKUserError(varprefix,
                       _("This URL ist not allowed to be used as bookmark"))
예제 #8
0
파일: utils.py 프로젝트: tklecker/checkmk
 def validate_dynamic_levels(value, varprefix):
     if [v for v in value if v[0] < 0]:
         raise MKUserError(
             varprefix,
             _("You need to specify levels of at least 0 bytes."))
예제 #9
0
    def action(self) -> ActionResult:
        if not transactions.check_transaction():
            return redirect(self.mode_url())

        if request.var("_delete"):
            delid = request.get_ascii_input_mandatory("_delete")

            if delid not in self._roles:
                raise MKUserError(None, _("This role does not exist."))

            if transactions.transaction_valid() and self._roles[delid].get(
                    'builtin'):
                raise MKUserError(None,
                                  _("You cannot delete the builtin roles!"))

            users = userdb.load_users()
            for user in users.values():
                if delid in user["roles"]:
                    raise MKUserError(
                        None,
                        _("You cannot delete roles, that are still in use (%s)!"
                          % delid))

            self._rename_user_role(delid, None)  # Remove from existing users
            del self._roles[delid]
            self._save_roles()
            watolib.add_change("edit-roles",
                               _("Deleted role '%s'") % delid,
                               sites=config.get_login_sites())

        elif request.var("_clone"):
            cloneid = request.get_ascii_input_mandatory("_clone")

            try:
                cloned_role = self._roles[cloneid]
            except KeyError:
                raise MKUserError(None, _("This role does not exist."))

            newid = cloneid
            while newid in self._roles:
                newid += "x"

            new_role = {}
            new_role.update(cloned_role)

            new_alias = new_role["alias"]
            while not watolib.is_alias_used("roles", newid, new_alias)[0]:
                new_alias += _(" (copy)")
            new_role["alias"] = new_alias

            if cloned_role.get("builtin"):
                new_role["builtin"] = False
                new_role["basedon"] = cloneid

            self._roles[newid] = new_role
            self._save_roles()
            watolib.add_change("edit-roles",
                               _("Created new role '%s'") % newid,
                               sites=config.get_login_sites())

        return redirect(self.mode_url())
예제 #10
0
 def _validate_alias(self, value, varprefix):
     unique, message = watolib.is_alias_used("timeperiods", self._name,
                                             value)
     if not unique:
         raise MKUserError("alias", message)
예제 #11
0
def do_log_ack(site, host_name, file_name):
    logs_to_ack = []
    if not host_name and not file_name:  # all logs on all hosts
        for this_site, this_host, logs in all_logs():
            for int_filename in logs:
                file_display = form_file_to_ext(int_filename)
                logs_to_ack.append((this_site, this_host, int_filename, file_display))
        ack_msg = _('all logfiles on all hosts')

    elif host_name and not file_name:  # all logs on one host
        for int_filename in logfiles_of_host(site, host_name):
            file_display = form_file_to_ext(int_filename)
            logs_to_ack.append((site, host_name, int_filename, file_display))
        ack_msg = _('all logfiles of host %s') % host_name

    elif host_name and file_name:  # one log on one host
        int_filename = form_file_to_int(file_name)
        logs_to_ack = [(site, host_name, int_filename, form_file_to_ext(int_filename))]
        ack_msg = _('the log file %s on host %s') % (file_name, host_name)

    else:
        for this_site, this_host, logs in all_logs():
            file_display = form_file_to_ext(file_name)
            if file_name in logs:
                logs_to_ack.append((this_site, this_host, file_name, file_display))
        ack_msg = _('log file %s on all hosts') % file_name

    html.header(_("Acknowledge %s") % html.render_text(ack_msg))

    html.begin_context_buttons()
    button_all_logfiles()
    if host_name:
        html.context_button(_("All Logfiles of Host"), html.makeuri([('file', '')]))
    if host_name and file_name:
        html.context_button(_("Back to Logfile"), html.makeuri([]))
    html.end_context_buttons()

    ack = html.request.var('_ack')
    if not html.confirm(
            _("Do you really want to acknowledge %s by <b>deleting</b> all stored messages?") %
            ack_msg):
        html.footer()
        return

    if not config.user.may("general.act"):
        html.h1(_('Permission denied'), class_=["error"])
        html.div(_('You are not allowed to acknowledge %s') % ack_msg, class_=["error"])
        html.footer()
        return

    # filter invalid values
    if ack != '1':
        raise MKUserError('_ack', _('Invalid value for ack parameter.'))

    for this_site, this_host, int_filename, display_name in logs_to_ack:
        try:
            acknowledge_logfile(this_site, this_host, int_filename, display_name)
        except Exception as e:
            html.show_error(
                _('The log file <tt>%s</tt> of host <tt>%s</tt> could not be deleted: %s.') %
                (display_name, this_host, e))
            html.footer()
            return

    html.show_message(
        '<b>%s</b><p>%s</p>' %
        (_('Acknowledged %s') % ack_msg, _('Acknowledged all messages in %s.') % ack_msg))
    html.footer()
예제 #12
0
 def _validate_id(self, value, varprefix):
     if value in self._timeperiods:
         raise MKUserError(
             varprefix,
             _("This name is already being used by another timeperiod."))
예제 #13
0
 def _get_timeperiod(self, name):
     try:
         return self._timeperiods[name]
     except KeyError:
         raise MKUserError(None, _("This timeperiod does not exist."))
예제 #14
0
def edit_dictionaries(
        dictionaries: 'Sequence[Tuple[str, Union[Transform, Dictionary]]]',
        value: Dict[str, Any],
        focus: Optional[str] = None,
        hover_help: bool = True,
        validate: Optional[Callable[[Any], None]] = None,
        title: Optional[str] = None,
        method: str = "GET",
        preview: bool = False,
        varprefix: str = "",
        formname: str = "form",
        consume_transid: bool = True):

    if request.get_ascii_input(
            "filled_in") == formname and transactions.transaction_valid():
        if not preview and consume_transid:
            transactions.check_transaction()

        messages: List[str] = []
        new_value: Dict[str, Dict[str, Any]] = {}
        for keyname, vs_dict in dictionaries:
            dict_varprefix = varprefix + keyname
            new_value[keyname] = {}
            try:
                edited_value = vs_dict.from_html_vars(dict_varprefix)
                vs_dict.validate_value(edited_value, dict_varprefix)
                new_value[keyname].update(edited_value)
            except MKUserError as e:
                messages.append("%s: %s" %
                                (vs_dict.title() or _("Properties"), e))
                user_errors.add(e)
            except Exception as e:
                messages.append("%s: %s" %
                                (vs_dict.title() or _("Properties"), e))
                user_errors.add(MKUserError(None, str(e)))

            if validate and not user_errors:
                try:
                    validate(new_value[keyname])
                except MKUserError as e:
                    messages.append(str(e))
                    user_errors.add(e)

        if messages:
            messages_joined = "".join(["%s<br>\n" % m for m in messages])
            if not preview:
                html.show_error(messages_joined)
            else:
                raise MKUserError(None, messages_joined)
        else:
            return new_value

    html.begin_form(formname, method=method)
    for keyname, vs_dict in dictionaries:
        dict_varprefix = varprefix + keyname
        subvalue = value.get(keyname, {})
        vs_dict.render_input_as_form(dict_varprefix, subvalue)

    end()
    # Should be ignored be hidden_fields, but I do not dare to change it there
    request.del_var("filled_in")
    html.hidden_fields()
    html.end_form()
예제 #15
0
    def action(self) -> ActionResult:
        # TODO: remove subclass specific things specifict things (everything with _type == 'user')
        if not transactions.check_transaction():
            return None

        title = request.get_unicode_input_mandatory("title").strip()
        if not title:
            raise MKUserError("title", _("Please specify a title."))

        for this_attr in self._attrs:
            if title == this_attr["title"] and self._name != this_attr["name"]:
                raise MKUserError(
                    "alias",
                    _("This alias is already used by the attribute %s.") %
                    this_attr["name"],
                )

        topic = request.get_unicode_input_mandatory("topic", "").strip()
        help_txt = request.get_unicode_input_mandatory("help", "").strip()
        show_in_table = html.get_checkbox("show_in_table")
        add_custom_macro = html.get_checkbox("add_custom_macro")

        if self._new:
            self._name = request.get_ascii_input_mandatory("name", "").strip()
            if not self._name:
                raise MKUserError(
                    "name", _("Please specify a name for the new attribute."))
            if " " in self._name:
                raise MKUserError(
                    "name",
                    _("Sorry, spaces are not allowed in attribute names."))
            if not re.match("^[-a-z0-9A-Z_]*$", self._name):
                raise MKUserError(
                    "name",
                    _("Invalid attribute name. Only the characters a-z, A-Z, 0-9, _ and - are allowed."
                      ),
                )
            if [a for a in self._attrs if a["name"] == self._name]:
                raise MKUserError(
                    "name",
                    _("Sorry, there is already an attribute with that name."))

            ty = request.get_ascii_input_mandatory("type", "").strip()
            if ty not in [t[0] for t in custom_attr_types()]:
                raise MKUserError("type",
                                  _("The choosen attribute type is invalid."))

            self._attr = {
                "name": self._name,
                "type": ty,
            }
            self._attrs.append(self._attr)

            add_change(
                "edit-%sattr" % self._type,
                _("Create new %s attribute %s") % (self._type, self._name),
            )
        else:
            add_change(
                "edit-%sattr" % self._type,
                _("Modified %s attribute %s") % (self._type, self._name))
        self._attr.update({
            "title": title,
            "topic": topic,
            "help": help_txt,
            "show_in_table": show_in_table,
            "add_custom_macro": add_custom_macro,
        })

        self._add_extra_attrs_from_html_vars()

        save_custom_attrs_to_mk_file(self._all_attrs)
        self._update_config()

        return redirect(mode_url(self._type + "_attrs"))
예제 #16
0
    def action(self) -> ActionResult:
        if html.form_submitted("search"):
            return None

        alias = request.get_unicode_input("alias")

        unique, info = watolib.is_alias_used("roles", self._role_id, alias)
        if not unique:
            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 config.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=config.get_login_sites())
        return redirect(mode_url("roles"))
예제 #17
0
    def _reload_js(self):
        # Be compatible to pre 1.5.0i2 format
        # TODO: Do this conversion during __init__() or during config loading
        if "graph_render_options" not in self._dashlet_spec:
            if self._dashlet_spec.pop("show_service", True):
                title_format = ("add_title_infos",
                                ["add_host_name", "add_service_description"])
            else:
                title_format = ("plain", [])

            self._dashlet_spec["graph_render_options"] = {
                "show_legend": self._dashlet_spec.pop("show_legend", False),
                "title_format": title_format,
            }

        host = self._dashlet_spec['context'].get('host',
                                                 html.request.var("host"))
        if not host:
            raise MKUserError('host', _('Missing needed host parameter.'))

        service = self._dashlet_spec['context'].get('service')
        if not service:
            service = "_HOST_"

        # When the site is available via URL context, use it. Otherwise it is needed
        # to check all sites for the requested host
        if html.request.has_var('site'):
            site = html.request.var('site')
        else:
            query = "GET hosts\nFilter: name = %s\nColumns: name" % livestatus.lqencode(
                host)
            try:
                sites.live().set_prepend_site(True)
                site = sites.live().query_column(query)[0]
            except IndexError:
                raise MKUserError(
                    "host",
                    _("The host could not be found on any active site."))
            finally:
                sites.live().set_prepend_site(False)

        # New graphs which have been added via "add to visual" option don't have a timerange
        # configured. So we assume the default timerange here by default.
        timerange = self._dashlet_spec.get('timerange', '1')

        graph_identification = ("template", {
            "site":
            site,
            "host_name":
            host,
            "service_description":
            service,
            "graph_index":
            self._dashlet_spec["source"] - 1,
        })

        graph_render_options = self._dashlet_spec["graph_render_options"]

        return "dashboard_render_graph(%d, %s, %s, '%s')" % \
                (self._dashlet_id, json.dumps(graph_identification),
                 json.dumps(graph_render_options), timerange)
예제 #18
0
def edit_dictionaries(
        dictionaries,  # type: List[Tuple[str, Union[Transform, Dictionary]]]
        value,  # type: Dict[str, Any]
        focus=None,  # type: Optional[str]
        hover_help=True,  # type: bool
        validate=None,  # type: Optional[Callable[[Any], None]]
        buttontext=None,  # type: Optional[str]
        title=None,  # type: Optional[str]
        buttons=None,  # type: List[Tuple[str, str, str]]
        method="GET",  # type: str
        preview=False,  # type: bool
        varprefix="",  # type: str
        formname="form",  # type: str
        consume_transid=True  # type: bool
):

    if html.request.get_ascii_input(
            "filled_in") == formname and html.transaction_valid():
        if not preview and consume_transid:
            html.check_transaction()

        messages = []  # type: List[str]
        new_value = {}  # type: Dict[str, Dict[str, Any]]
        for keyname, vs_dict in dictionaries:
            dict_varprefix = varprefix + keyname
            new_value[keyname] = {}
            try:
                edited_value = vs_dict.from_html_vars(dict_varprefix)
                vs_dict.validate_value(edited_value, dict_varprefix)
                new_value[keyname].update(edited_value)
            except MKUserError as e:
                messages.append("%s: %s" %
                                (vs_dict.title() or _("Properties"), e))
                html.add_user_error(e.varname, e)
            except Exception as e:
                messages.append("%s: %s" %
                                (vs_dict.title() or _("Properties"), e))
                html.add_user_error(None, e)

            if validate and not html.has_user_errors():
                try:
                    validate(new_value[keyname])
                except MKUserError as e:
                    messages.append("%s" % e)
                    html.add_user_error(e.varname, e)

        if messages:
            messages_joined = "".join(["%s<br>\n" % m for m in messages])
            if not preview:
                html.show_error(messages_joined)
            else:
                raise MKUserError(None, messages_joined)
        else:
            return new_value

    html.begin_form(formname, method=method)
    for keyname, vs_dict in dictionaries:
        dict_varprefix = varprefix + keyname
        subvalue = value.get(keyname, {})
        vs_dict.render_input_as_form(dict_varprefix, subvalue)

    end()
    if buttons:
        for name, button_title, _icon in buttons:
            html.button(name, button_title)
    else:
        if buttontext is None:
            buttontext = _("Save")
        html.button("save", buttontext)
    # Should be ignored be hidden_fields, but I do not dare to change it there
    html.request.del_var("filled_in")
    html.hidden_fields()
    html.end_form()
예제 #19
0
def decrypt_private_key(encrypted_private_key, passphrase):
    try:
        return crypto.load_privatekey(crypto.FILETYPE_PEM, encrypted_private_key,
                                      passphrase.encode("utf-8"))
    except crypto.Error:
        raise MKUserError("key_p_passphrase", _("Invalid pass phrase"))
예제 #20
0
    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")
예제 #21
0
    def action(self):
        if html.request.var("_search"):  # just commit to search form
            return

        ### Operations on SUBFOLDERS

        if html.request.var("_delete_folder"):
            if html.transaction_valid():
                return self._delete_subfolder_after_confirm(
                    html.request.var("_delete_folder"))
            return

        elif html.request.has_var("_move_folder_to"):
            if html.check_transaction():
                what_folder = watolib.Folder.folder(html.request.var("_ident"))
                target_folder = watolib.Folder.folder(
                    html.request.var("_move_folder_to"))
                watolib.Folder.current().move_subfolder_to(
                    what_folder, target_folder)
            return

        ### Operations on HOSTS

        # Deletion of single hosts
        delname = html.request.var("_delete_host")
        if delname and watolib.Folder.current().has_host(delname):
            return delete_host_after_confirm(delname)

        # Move single hosts to other folders
        if html.request.has_var("_move_host_to"):
            hostname = html.request.var("_ident")
            if hostname:
                target_folder = watolib.Folder.folder(
                    html.request.var("_move_host_to"))
                watolib.Folder.current().move_hosts([hostname], target_folder)
                return

        # bulk operation on hosts
        if not html.transaction_valid():
            return

        # Host table: No error message on search filter reset
        if html.request.var("_hosts_reset_sorting") or html.request.var(
                "_hosts_sort"):
            return

        selected_host_names = get_hostnames_from_checkboxes()
        if len(selected_host_names) == 0:
            raise MKUserError(
                None,
                _("Please select some hosts before doing bulk operations on hosts."
                  ))

        if html.request.var("_bulk_inventory"):
            return "bulkinventory"

        elif html.request.var("_parentscan"):
            return "parentscan"

        # Deletion
        if html.request.var("_bulk_delete"):
            return self._delete_hosts_after_confirm(selected_host_names)

        # Move
        elif html.request.var("_bulk_move"):
            target_folder_path = html.request.var(
                "bulk_moveto", html.request.var("_top_bulk_moveto"))
            if target_folder_path == "@":
                raise MKUserError("bulk_moveto",
                                  _("Please select the destination folder"))
            target_folder = watolib.Folder.folder(target_folder_path)
            watolib.Folder.current().move_hosts(selected_host_names,
                                                target_folder)
            return None, _("Moved %d hosts to %s") % (len(selected_host_names),
                                                      target_folder.title())

        # Move to target folder (from import)
        elif html.request.var("_bulk_movetotarget"):
            return self._move_to_imported_folders(selected_host_names)

        elif html.request.var("_bulk_edit"):
            return "bulkedit"

        elif html.request.var("_bulk_cleanup"):
            return "bulkcleanup"
예제 #22
0
 def validate_input(self, value, varprefix):
     if not isinstance(value, dict):
         raise MKUserError(self.name(), "Unknown format.")
     self.load_data()
     self._vs_contactgroups().validate_value(value.get("groups", []),
                                             varprefix)
예제 #23
0
def validate_process_discovery_descr_option(description, varprefix):
    if '%s' in description and re.search(r'%(\d+)', description):
        raise MKUserError(
            varprefix,
            _('Combining "%s" and "%1" style replacements in the sevice description is not allowed.'
              ))
예제 #24
0
    def _action(self) -> None:
        assert config.user.id is not None

        users = userdb.load_users(lock=True)
        user = users[config.user.id]

        cur_password = html.request.get_str_input_mandatory('cur_password')
        password = html.request.get_str_input_mandatory('password')
        password2 = html.request.get_str_input_mandatory('password2', '')

        # Force change pw mode
        if not cur_password:
            raise MKUserError("cur_password",
                              _("You need to provide your current password."))

        if not password:
            raise MKUserError("password",
                              _("You need to change your password."))

        if cur_password == password:
            raise MKUserError(
                "password",
                _("The new password must differ from your current one."))

        if userdb.check_credentials(config.user.id, cur_password) is False:
            raise MKUserError("cur_password", _("Your old password is wrong."))

        if password2 and password != password2:
            raise MKUserError("password2",
                              _("The both new passwords do not match."))

        watolib.verify_password_policy(password)
        user['password'] = hash_password(password)
        user['last_pw_change'] = int(time.time())

        # In case the user was enforced to change it's password, remove the flag
        try:
            del user['enforce_pw_change']
        except KeyError:
            pass

        # Increase serial to invalidate old authentication cookies
        if 'serial' not in user:
            user['serial'] = 1
        else:
            user['serial'] += 1

        userdb.save_users(users)

        # Set the new cookie to prevent logout for the current user
        login.update_auth_cookie(config.user.id)

        # 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 = html.request.get_str_input_mandatory(
            '_origtarget', 'user_change_pw.py')
        if config.user.authorized_login_sites():
            raise HTTPRedirect(
                makeuri_contextless(request, [("back", origtarget)],
                                    filename="user_profile_replicate.py"))
        raise HTTPRedirect(origtarget)
예제 #25
0
    def _discover_services(self, request):
        mode = request.get("mode", "new")
        hostname = request.get("hostname")

        check_hostname(hostname, should_exist=True)

        host = watolib.Host.host(hostname)

        host_attributes = host.effective_attributes()

        if host.is_cluster():
            # This is currently the only way to get some actual discovery statitics.
            # Start a dry-run -> Get statistics
            # Do an actual discovery on the nodes -> data is written
            result = watolib.check_mk_automation(host_attributes.get("site"),
                                                 "try-inventory",
                                                 ["@scan"] + [hostname])
            counts = {"new": 0, "old": 0}
            for entry in result["check_table"]:
                if entry[0] in counts:
                    counts[entry[0]] += 1

            counts = {
                hostname: (
                    counts["new"],
                    0,  # this info is not available for clusters
                    counts["old"],
                    counts["new"] + counts["old"])
            }

            # A cluster cannot fail, just the nodes. This information is currently discarded
            failed_hosts = None
            watolib.check_mk_automation(host_attributes.get("site"),
                                        "inventory",
                                        ["@scan", mode] + host.cluster_nodes())
        else:
            counts, failed_hosts = watolib.check_mk_automation(
                host_attributes.get("site"), "inventory",
                ["@scan", mode] + [hostname])

        if failed_hosts:
            if not host.discovery_failed():
                host.set_discovery_failed()
            raise MKUserError(
                None,
                _("Failed to inventorize %s: %s") %
                (hostname, failed_hosts[hostname]))

        if host.discovery_failed():
            host.clear_discovery_failed()

        if mode == "refresh":
            message = _(
                "Refreshed check configuration of host [%s] with %d services"
            ) % (hostname, counts[hostname][3])
            watolib.add_service_change(host, "refresh-autochecks", message)
        else:
            message = _(
                "Saved check configuration of host [%s] with %d services") % (
                    hostname, counts[hostname][3])
            watolib.add_service_change(host, "set-autochecks", message)

        msg = _(
            "Service discovery successful. Added %d, removed %d, kept %d, total %d services "
            "and %d new, %d total host labels") % tuple(counts[hostname])
        return msg
예제 #26
0
    def action(self):
        if not html.check_transaction():
            return "tags"

        vs = self._valuespec()
        tag_group_spec = vs.from_html_vars("tag_group")
        vs.validate_value(tag_group_spec, "tag_group")

        # Create new object with existing host tags
        changed_hosttags_config = cmk.utils.tags.TagConfig()
        changed_hosttags_config.parse_config(
            self._tag_config_file.load_for_modification())

        changed_tag_group = cmk.utils.tags.TagGroup(tag_group_spec)
        self._tag_group = changed_tag_group

        if self._new:
            # Inserts and verifies changed tag group
            changed_hosttags_config.insert_tag_group(changed_tag_group)
            try:
                changed_hosttags_config.validate_config()
            except MKGeneralException as e:
                raise MKUserError(None, "%s" % e)
            self._save_tags_and_update_hosts(
                changed_hosttags_config.get_dict_format())
            add_change(
                "edit-hosttags",
                _("Created new host tag group '%s'") % changed_tag_group.id)
            return "tags", _(
                "Created new host tag group '%s'") % changed_tag_group.title

        # Updates and verifies changed tag group
        changed_hosttags_config.update_tag_group(changed_tag_group)
        try:
            changed_hosttags_config.validate_config()
        except MKGeneralException as e:
            raise MKUserError(None, "%s" % e)

        remove_tag_ids, replace_tag_ids = [], {}
        new_by_title = {tag.title: tag.id for tag in changed_tag_group.tags}

        for former_tag in self._untainted_tag_group.tags:
            # Detect renaming
            if former_tag.title in new_by_title:
                new_id = new_by_title[former_tag.title]
                if new_id != former_tag.id:
                    # new_id may be None
                    replace_tag_ids[former_tag.id] = new_id
                    continue

            # Detect removal
            if former_tag.id is not None \
                    and former_tag.id not in [ tmp_tag.id for tmp_tag in changed_tag_group.tags ]:
                # remove explicit tag (hosts/folders) or remove it from tag specs (rules)
                remove_tag_ids.append(former_tag.id)

        tg_id = self._tag_group.id
        if tg_id is None:
            raise Exception("tag group ID not set")
        operation = OperationReplaceGroupedTags(tg_id, remove_tag_ids,
                                                replace_tag_ids)

        # Now check, if any folders, hosts or rules are affected
        message = _rename_tags_after_confirmation(operation)
        if message:
            self._save_tags_and_update_hosts(
                changed_hosttags_config.get_dict_format())
            add_change(
                "edit-hosttags",
                _("Edited host tag group %s (%s)") % (message, self._id))
            return "tags", message is not True and message or None

        return "tags"
예제 #27
0
 def _get_group(self, group_name):
     try:
         return self._groups[self._name]
     except KeyError:
         raise MKUserError(None, _("This group does not exist."))
예제 #28
0
def _rename_tags_after_confirmation(operation):
    # type: (ABCOperation) -> Union[bool, str]
    """Handle renaming and deletion of tags

    Find affected hosts, folders and rules. Remove or fix those rules according
    the users' wishes.
    """
    repair_mode = html.request.var("_repair")
    if repair_mode is not None:
        try:
            mode = TagCleanupMode(repair_mode)
        except ValueError:
            raise MKUserError("_repair", "Invalid mode")

        if mode == TagCleanupMode.ABORT:
            raise MKUserError("id_0", _("Aborting change."))

        # make attribute unknown to system, important for save() operations
        if isinstance(operation, OperationRemoveTagGroup):
            watolib.host_attributes.undeclare_host_tag_attribute(
                operation.tag_group_id)

        affected_folders, affected_hosts, affected_rulesets = \
        _change_host_tags_in_folders(operation, mode, watolib.Folder.root_folder())

        return _("Modified folders: %d, modified hosts: %d, modified rulesets: %d") % \
            (len(affected_folders), len(affected_hosts), len(affected_rulesets))

    message = u""
    affected_folders, affected_hosts, affected_rulesets = \
        _change_host_tags_in_folders(operation, TagCleanupMode.CHECK, watolib.Folder.root_folder())

    if affected_folders:
        message += _("Affected folders with an explicit reference to this tag "
                     "group and that are affected by the change") + ":"
        with html.plugged():
            _show_affected_folders(affected_folders)
            message += html.drain()

    if affected_hosts:
        message += _("Hosts where this tag group is explicitely set "
                     "and that are effected by the change") + ":"
        with html.plugged():
            _show_affected_hosts(affected_hosts)
            message += html.drain()

    if affected_rulesets:
        message += _(
            "Rulesets that contain rules with references to the changed tags"
        ) + ":"
        with html.plugged():
            _show_affected_rulesets(affected_rulesets)
            message += html.drain()

    if message:
        wato_html_head(operation.confirm_title())
        html.open_div(class_="really")
        html.h3(_("Your modifications affect some objects"))
        html.write_text(message)
        html.br()
        html.write_text(
            _("WATO can repair things for you. It can rename tags in folders, host and rules. "
              "Removed tag groups will be removed from hosts and folders, removed tags will be "
              "replaced with the default value for the tag group (for hosts and folders). What "
              "rules concern, you have to decide how to proceed."))
        html.begin_form("confirm", method="POST")

        if affected_rulesets and _is_removing_tags(operation):
            html.br()
            html.b(
                _("Some tags that are used in rules have been removed by you. What "
                  "shall we do with that rules?"))
            html.open_ul()
            html.radiobutton(
                "_repair", "remove", True,
                _("Just remove the affected tags from the rules."))
            html.br()
            html.radiobutton(
                "_repair", "delete", False,
                _("Delete rules containing tags that have been removed, if tag is used in a positive sense. Just remove that tag if it's used negated."
                  ))
        else:
            html.open_ul()
            html.radiobutton("_repair", "repair", True,
                             _("Fix affected folders, hosts and rules."))

        html.br()
        html.radiobutton("_repair", "abort", False,
                         _("Abort your modifications."))
        html.close_ul()

        html.button("_do_confirm", _("Proceed"), "")
        html.hidden_fields(add_action_vars=True)
        html.end_form()
        html.close_div()
        return False

    return True
예제 #29
0
 def _validate_value(self, value: DropdownChoiceModel,
                     varprefix: str) -> None:
     if not value or value == self._MARKER_DEPRECATED_CHOICE:
         raise MKUserError(varprefix, _("Please select a graph."))
예제 #30
0
    def _show_service_info(self, all_rulesets):
        assert self._service is not None

        serviceinfo = watolib.check_mk_automation(
            self._host.site_id(), "analyse-service",
            [self._hostname, self._service])
        if not serviceinfo:
            return

        forms.header(_("Check origin and parameters"),
                     isopen=True,
                     narrow=True,
                     css="rulesettings")
        origin = serviceinfo["origin"]
        origin_txt = {
            "active": _("Active check"),
            "static": _("Manual check"),
            "auto": _("Inventorized check"),
            "classic": _("Classical check"),
        }[origin]
        self._render_rule_reason(_("Type of check"), None, "", "", False,
                                 origin_txt)

        # First case: discovered checks. They come from var/check_mk/autochecks/HOST.
        if origin == "auto":
            checkgroup = serviceinfo["checkgroup"]
            checktype = serviceinfo["checktype"]
            if not checkgroup:
                self._render_rule_reason(
                    _("Parameters"), None, "", "", True,
                    _("This check is not configurable via WATO"))

            # Logwatch needs a special handling, since it is not configured
            # via checkgroup_parameters but via "logwatch_rules" in a special
            # WATO module.
            elif checkgroup == "logwatch":
                rulespec = rulespec_registry["logwatch_rules"]
                self._output_analysed_ruleset(
                    all_rulesets,
                    rulespec,
                    svc_desc_or_item=serviceinfo["item"],
                    svc_desc=self._service,
                    known_settings=serviceinfo["parameters"])

            else:
                # Note: some discovered checks have a check group but
                # *no* ruleset for discovered checks. One example is "ps".
                # That can be configured as a manual check or created by
                # inventory. But in the later case all parameters are set
                # by the inventory. This will be changed in a later version,
                # but we need to address it anyway.
                grouprule = "checkgroup_parameters:" + checkgroup
                if grouprule not in rulespec_registry:
                    try:
                        rulespec = rulespec_registry["static_checks:" +
                                                     checkgroup]
                    except KeyError:
                        self._render_rule_reason(
                            _("Parameters"), None, "", "", True,
                            _("This check is not configurable via WATO"))
                        return

                    url = watolib.folder_preserving_link([
                        ('mode', 'edit_ruleset'),
                        ('varname', "static_checks:" + checkgroup),
                        ('host', self._hostname)
                    ])
                    assert isinstance(rulespec.valuespec, Tuple)
                    self._render_rule_reason(
                        _("Parameters"), url, _("Determined by discovery"),
                        None, False,
                        rulespec.valuespec._elements[2].value_to_text(
                            serviceinfo["parameters"]))

                else:
                    rulespec = rulespec_registry[grouprule]
                    self._output_analysed_ruleset(
                        all_rulesets,
                        rulespec,
                        svc_desc_or_item=serviceinfo["item"],
                        svc_desc=self._service,
                        known_settings=serviceinfo["parameters"])

        elif origin == "static":
            checkgroup = serviceinfo["checkgroup"]
            checktype = serviceinfo["checktype"]
            if not checkgroup:
                html.write_text(_("This check is not configurable via WATO"))
            else:
                rulespec = rulespec_registry["static_checks:" + checkgroup]
                itemspec = rulespec.item_spec
                if itemspec:
                    item_text = itemspec.value_to_text(serviceinfo["item"])
                    assert rulespec.item_spec is not None
                    title = rulespec.item_spec.title()
                else:
                    item_text = serviceinfo["item"]
                    title = _("Item")
                self._render_rule_reason(title, None, "", "", False, item_text)
                self._output_analysed_ruleset(
                    all_rulesets,
                    rulespec,
                    svc_desc_or_item=serviceinfo["item"],
                    svc_desc=self._service,
                    known_settings=self._PARAMETERS_OMIT)
                assert isinstance(rulespec.valuespec, Tuple)
                html.write(rulespec.valuespec._elements[2].value_to_text(
                    serviceinfo["parameters"]))
                html.close_td()
                html.close_tr()
                html.close_table()

        elif origin == "active":
            checktype = serviceinfo["checktype"]
            rulespec = rulespec_registry["active_checks:" + checktype]
            self._output_analysed_ruleset(
                all_rulesets,
                rulespec,
                svc_desc_or_item=None,
                svc_desc=None,
                known_settings=serviceinfo["parameters"])

        elif origin == "classic":
            ruleset = all_rulesets.get("custom_checks")
            origin_rule_result = self._get_custom_check_origin_rule(
                ruleset, self._hostname, self._service)
            if origin_rule_result is None:
                raise MKUserError(
                    None,
                    _("Failed to determine origin rule of %s / %s") %
                    (self._hostname, self._service))
            rule_folder, rule_index, rule = origin_rule_result

            url = watolib.folder_preserving_link([('mode', 'edit_ruleset'),
                                                  ('varname', "custom_checks"),
                                                  ('host', self._hostname)])
            forms.section(html.render_a(_("Command Line"), href=url))
            url = watolib.folder_preserving_link([('mode', 'edit_rule'),
                                                  ('varname', "custom_checks"),
                                                  ('rule_folder',
                                                   rule_folder.path()),
                                                  ('rule_id', rule.id),
                                                  ('host', self._hostname)])

            html.open_table(class_="setting")
            html.open_tr()

            html.open_td(class_="reason")
            html.a("%s %d %s %s" %
                   (_("Rule"), rule_index + 1, _("in"), rule_folder.title()),
                   href=url)
            html.close_td()
            html.open_td(class_=["settingvalue", "used"])
            if "command_line" in serviceinfo:
                html.tt(serviceinfo["command_line"])
            else:
                html.write_text(_("(no command line, passive check)"))
            html.close_td()

            html.close_tr()
            html.close_table()

        self._show_labels(serviceinfo.get("labels", {}), "service",
                          serviceinfo.get("label_sources", {}))