Пример #1
0
 def lockable_input(name, dflt):
     if not self._is_locked(name):
         html.text_input(name, self._user.get(name, dflt), size=50)
     else:
         html.write_text(self._user.get(name, dflt))
         html.hidden_field(name, self._user.get(name, dflt))
Пример #2
0
def normal_login_page(called_directly=True):
    html.set_render_headfoot(False)
    html.add_body_css_class("login")
    html.header(config.get_page_heading(), javascripts=[])

    default_origtarget = "index.py" if html.myfile in ["login", "logout"
                                                       ] else html.makeuri([])
    origtarget = html.get_url_input("_origtarget", default_origtarget)

    # Never allow the login page to be opened in a frameset. Redirect top page to login page.
    # This will result in a full screen login page.
    html.javascript('''if(top != self) {
    window.top.location.href = location;
}''')

    # When someone calls the login page directly and is already authed redirect to main page
    if html.myfile == 'login' and check_auth(html.request):
        raise HTTPRedirect(origtarget)

    html.open_div(id_="login")

    html.open_div(id_="login_window")

    html.div("" if "hide_version" in config.login_screen else cmk.__version__,
             id_="version")

    html.begin_form("login",
                    method='POST',
                    add_transid=False,
                    action='login.py')
    html.hidden_field('_login', '1')
    html.hidden_field('_origtarget', origtarget)
    html.label("%s:" % _('Username'),
               id_="label_user",
               class_=["legend"],
               for_="_username")
    html.br()
    html.text_input("_username", id_="input_user")
    html.label("%s:" % _('Password'),
               id_="label_pass",
               class_=["legend"],
               for_="_password")
    html.br()
    html.password_input("_password", id_="input_pass", size=None)

    if html.has_user_errors():
        html.open_div(id_="login_error")
        html.show_user_errors()
        html.close_div()

    html.open_div(id_="button_text")
    html.button("_login", _('Login'))
    html.close_div()
    html.close_div()

    html.open_div(id_="foot")

    if config.login_screen.get("login_message"):
        html.open_div(id_="login_message")
        html.show_info(config.login_screen["login_message"])
        html.close_div()

    footer = []
    for title, url, target in config.login_screen.get("footer_links", []):
        footer.append(html.render_a(title, href=url, target=target))

    if "hide_version" not in config.login_screen:
        footer.append("Version: %s" % cmk.__version__)

    footer.append("© %s" % html.render_a(
        "tribe29 GmbH", href="https://checkmk.com", target="_blank"))

    html.write(HTML(" - ").join(footer))

    if cmk.is_raw_edition():
        html.br()
        html.br()
        html.write(
            _('You can use, modify and distribute Check_MK under the terms of the <a href="%s" target="_blank">'
              'GNU GPL Version 2</a>.') % "https://checkmk.com/gpl.html")

    html.close_div()

    html.set_focus('_username')
    html.hidden_fields()
    html.end_form()
    html.close_div()

    html.footer()
Пример #3
0
    def page(self):
        # Let exceptions from loading notification scripts happen now
        watolib.load_notification_scripts()

        html.begin_form("user", method="POST")
        html.prevent_password_auto_completion()

        forms.header(_("Identity"))

        # ID
        forms.section(_("Username"), simple=not self._is_new_user, is_required=True)
        if self._is_new_user:
            vs_user_id = UserID(allow_empty=False)

        else:
            vs_user_id = FixedValue(self._user_id)
        vs_user_id.render_input("user_id", self._user_id)

        def lockable_input(name, dflt):
            if not self._is_locked(name):
                html.text_input(name, self._user.get(name, dflt), size=50)
            else:
                html.write_text(self._user.get(name, dflt))
                html.hidden_field(name, self._user.get(name, dflt))

        # Full name
        forms.section(_("Full name"), is_required=True)
        lockable_input('alias', self._user_id)
        html.help(_("Full name or alias of the user"))

        # Email address
        forms.section(_("Email address"))
        email = self._user.get("email", "")
        if not self._is_locked("email"):
            EmailAddress().render_input("email", email)
        else:
            html.write_text(email)
            html.hidden_field("email", email)

        html.help(
            _("The email address is optional and is needed "
              "if the user is a monitoring contact and receives notifications "
              "via Email."))

        forms.section(_("Pager address"))
        lockable_input('pager', '')
        html.help(_("The pager address is optional "))

        if cmk_version.is_managed_edition():
            forms.section(self._vs_customer.title())
            self._vs_customer.render_input("customer", managed.get_customer_id(self._user))

            html.help(self._vs_customer.help())

        vs_sites = self._vs_sites()
        forms.section(vs_sites.title())
        authorized_sites = self._user.get("authorized_sites", vs_sites.default_value())
        if not self._is_locked("authorized_sites"):
            vs_sites.render_input("authorized_sites", authorized_sites)
        else:
            html.write_html(vs_sites.value_to_text(authorized_sites))
        html.help(vs_sites.help())

        custom_user_attr_topics = userdb_utils.get_user_attributes_by_topic()

        self._show_custom_user_attributes(custom_user_attr_topics.get('ident', []))

        # ntopng
        if config.is_ntop_available():
            ntop_connection = config.ntop_connection  # type: ignore[attr-defined]
            if ntop_connection.get("use_custom_attribute_as_ntop_username"):
                forms.section(_("ntopng Username"))
                lockable_input('ntop_alias', '')
                html.help(
                    _("The corresponding username in ntopng of the current checkmk user. "
                      "It is used, in case the user mapping to ntopng is configured to use this "
                      "custom attribute"))

        forms.header(_("Security"))
        forms.section(_("Authentication"))

        is_automation = self._user.get("automation_secret", None) is not None
        html.radiobutton("authmethod", "password", not is_automation,
                         _("Normal user login with password"))
        html.open_ul()
        html.open_table()
        html.open_tr()
        html.td(_("password:"******"_password_" + self._pw_suffix(), autocomplete="new-password")
            html.close_td()
            html.close_tr()

            html.open_tr()
            html.td(_("repeat:"))
            html.open_td()
            html.password_input("_password2_" + self._pw_suffix(), autocomplete="new-password")
            html.write_text(" (%s)" % _("optional"))
            html.close_td()
            html.close_tr()

            html.open_tr()
            html.td("%s:" % _("Enforce change"))
            html.open_td()
            # Only make password enforcement selection possible when user is allowed to change the PW
            uid = None if self._user_id is None else UserId(self._user_id)
            if (self._is_new_user or (config.user_may(uid, 'general.edit_profile') and
                                      config.user_may(uid, 'general.change_password'))):
                html.checkbox("enforce_pw_change",
                              self._user.get("enforce_pw_change", False),
                              label=_("Change password at next login or access"))
            else:
                html.write_text(
                    _("Not permitted to change the password. Change can not be enforced."))
        else:
            html.i(_('The password can not be changed (It is locked by the user connector).'))
            html.hidden_field('_password', '')
            html.hidden_field('_password2', '')

        html.close_td()
        html.close_tr()
        html.close_table()
        html.close_ul()

        html.radiobutton("authmethod", "secret", is_automation,
                         _("Automation secret for machine accounts"))

        html.open_ul()
        html.text_input("_auth_secret",
                        self._user.get("automation_secret", ""),
                        size=30,
                        id_="automation_secret")
        html.write_text(" ")
        html.open_b(style=["position: relative", "top: 4px;"])
        html.write(" &nbsp;")
        html.icon_button("javascript:cmk.wato.randomize_secret('automation_secret', 20);",
                         _("Create random secret"), "random")
        html.close_b()
        html.close_ul()

        html.help(
            _("If you want the user to be able to login "
              "then specify a password here. Users without a login make sense "
              "if they are monitoring contacts that are just used for "
              "notifications. The repetition of the password is optional. "
              "<br>For accounts used by automation processes (such as fetching "
              "data from views for further procession), set the method to "
              "<u>secret</u>. The secret will be stored in a local file. Processes "
              "with read access to that file will be able to use Multisite as "
              "a webservice without any further configuration."))

        # Locking
        forms.section(_("Disable password"), simple=True)
        if not self._is_locked('locked'):
            html.checkbox("locked",
                          self._user.get("locked", False),
                          label=_("disable the login to this account"))
        else:
            html.write_text(
                _('Login disabled') if self._user.get("locked", False) else _('Login possible'))
            html.hidden_field('locked', '1' if self._user.get("locked", False) else '')
        html.help(
            _("Disabling the password will prevent a user from logging in while "
              "retaining the original password. Notifications are not affected "
              "by this setting."))

        forms.section(_("Idle timeout"))
        idle_timeout = self._user.get("idle_timeout")
        if not self._is_locked("idle_timeout"):
            watolib.get_vs_user_idle_timeout().render_input("idle_timeout", idle_timeout)
        else:
            html.write_text(idle_timeout)
            html.hidden_field("idle_timeout", idle_timeout)

        # Roles
        forms.section(_("Roles"))
        is_member_of_at_least_one = False
        for role_id, role in sorted(self._roles.items(), key=lambda x: (x[1]["alias"], x[0])):
            if not self._is_locked("roles"):
                html.checkbox("role_" + role_id, role_id in self._user.get("roles", []))
                url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)])
                html.a(role["alias"], href=url)
                html.br()
            else:
                is_member = role_id in self._user.get("roles", [])
                if is_member:
                    is_member_of_at_least_one = True
                    url = watolib.folder_preserving_link([("mode", "edit_role"), ("edit", role_id)])
                    html.a(role["alias"], href=url)
                    html.br()

                html.hidden_field("role_" + role_id, '1' if is_member else '')
        if self._is_locked('roles') and not is_member_of_at_least_one:
            html.i(_('No roles assigned.'))
        self._show_custom_user_attributes(custom_user_attr_topics.get('security', []))

        # Contact groups
        forms.header(_("Contact Groups"), isopen=False)
        forms.section()
        groups_page_url = watolib.folder_preserving_link([("mode", "contact_groups")])
        group_assign_url = watolib.folder_preserving_link([("mode", "rulesets"),
                                                           ("group", "grouping")])
        if not self._contact_groups:
            html.write(
                _("Please first create some <a href='%s'>contact groups</a>") % groups_page_url)
        else:
            entries = sorted([(group['alias'] or c, c) for c, group in self._contact_groups.items()
                             ])
            is_member_of_at_least_one = False
            for alias, gid in entries:
                is_member = gid in self._user.get("contactgroups", [])

                if not self._is_locked('contactgroups'):
                    html.checkbox("cg_" + gid, gid in self._user.get("contactgroups", []))
                else:
                    if is_member:
                        is_member_of_at_least_one = True
                    html.hidden_field("cg_" + gid, '1' if is_member else '')

                if not self._is_locked('contactgroups') or is_member:
                    url = watolib.folder_preserving_link([("mode", "edit_contact_group"),
                                                          ("edit", gid)])
                    html.a(alias, href=url)
                    html.br()

            if self._is_locked('contactgroups') and not is_member_of_at_least_one:
                html.i(_('No contact groups assigned.'))

        html.help(
            _("Contact groups are used to assign monitoring "
              "objects to users. If you haven't defined any contact groups yet, "
              "then first <a href='%s'>do so</a>. Hosts and services can be "
              "assigned to contact groups using <a href='%s'>rules</a>.<br><br>"
              "If you do not put the user into any contact group "
              "then no monitoring contact will be created for the user.") %
            (groups_page_url, group_assign_url))

        forms.header(_("Notifications"), isopen=False)
        if not self._rbn_enabled():
            forms.section(_("Enabling"), simple=True)
            html.checkbox("notifications_enabled",
                          self._user.get("notifications_enabled", False),
                          label=_("enable notifications"))
            html.help(
                _("Notifications are sent out "
                  "when the status of a host or service changes."))

            # Notification period
            forms.section(_("Notification time period"))
            user_np = self._user.get("notification_period")
            if not isinstance(user_np, str):
                raise Exception("invalid notification period %r" % (user_np,))
            choices: Choices = [
                (id_, "%s" % (tp["alias"])) for (id_, tp) in self._timeperiods.items()
            ]
            html.dropdown("notification_period", choices, deflt=user_np, ordered=True)
            html.help(
                _("Only during this time period the "
                  "user will get notifications about host or service alerts."))

            # Notification options
            notification_option_names = {  # defined here: _() must be executed always!
                "host": {
                    "d": _("Host goes down"),
                    "u": _("Host gets unreachble"),
                    "r": _("Host goes up again"),
                },
                "service": {
                    "w": _("Service goes into warning state"),
                    "u": _("Service goes into unknown state"),
                    "c": _("Service goes into critical state"),
                    "r": _("Service recovers to OK"),
                },
                "both": {
                    "f": _("Start or end of flapping state"),
                    "s": _("Start or end of a scheduled downtime"),
                }
            }

            forms.section(_("Notification Options"))
            for title, what, opts in [(_("Host events"), "host", "durfs"),
                                      (_("Service events"), "service", "wucrfs")]:
                html.write_text("%s:" % title)
                html.open_ul()

                user_opts = self._user.get(what + "_notification_options", opts)
                for opt in opts:
                    opt_name = notification_option_names[what].get(
                        opt, notification_option_names["both"].get(opt))
                    html.checkbox(what + "_" + opt, opt in user_opts, label=opt_name)
                    html.br()
                html.close_ul()

            html.help(
                _("Here you specify which types of alerts "
                  "will be notified to this contact. Note: these settings will only be saved "
                  "and used if the user is member of a contact group."))

            forms.section(_("Notification Method"))
            watolib.get_vs_flexible_notifications().render_input(
                "notification_method", self._user.get("notification_method"))

        else:
            forms.section(_("Fallback notifications"), simple=True)

            html.checkbox("fallback_contact",
                          self._user.get("fallback_contact", False),
                          label=_("Receive fallback notifications"))

            html.help(
                _("In case none of your notification rules handles a certain event a notification "
                  "will be sent to this contact. This makes sure that in that case at least <i>someone</i> "
                  "gets notified. Furthermore this contact will be used for notifications to any host or service "
                  "that is not known to the monitoring. This can happen when you forward notifications "
                  "from the Event Console.<br><br>Notification fallback can also configured in the global "
                  "setting <a href=\"wato.py?mode=edit_configvar&varname=notification_fallback_email\">"
                  "Fallback email address for notifications</a>."))

        self._show_custom_user_attributes(custom_user_attr_topics.get('notify', []))

        forms.header(_("Personal settings"), isopen=False)
        select_language(self._user)
        self._show_custom_user_attributes(custom_user_attr_topics.get('personal', []))
        forms.header(_("Interface settings"), isopen=False)
        self._show_custom_user_attributes(custom_user_attr_topics.get('interface', []))

        # Later we could add custom macros here, which then could be used
        # for notifications. On the other hand, if we implement some check_mk
        # --notify, we could directly access the data in the account with the need
        # to store values in the monitoring core. We'll see what future brings.
        forms.end()
        if self._is_new_user:
            html.set_focus("user_id")
        else:
            html.set_focus("alias")
        html.hidden_fields()
        html.end_form()
Пример #4
0
    def page(self):
        search = get_search_expression()

        html.begin_form("role", method="POST")

        # ID
        forms.header(_("Basic Properties"))
        forms.section(_("Internal ID"), simple="builtin" in self._role)
        if self._role.get("builtin"):
            html.write_text("%s (%s)" % (self._role_id, _("builtin role")))
            html.hidden_field("id", self._role_id)
        else:
            html.text_input("id", self._role_id)
            html.set_focus("id")

        # Alias
        forms.section(_("Alias"))
        html.help(_("An alias or description of the role"))
        html.text_input("alias", self._role.get("alias", ""), size=50)

        # Based on
        if not self._role.get("builtin"):
            forms.section(_("Based on role"))
            html.help(
                _("Each user defined role is based on one of the builtin roles. "
                  "When created it will start with all permissions of that role. When due to a software "
                  "update or installation of an addons new permissions appear, the user role will get or "
                  "not get those new permissions based on the default settings of the builtin role it's "
                  "based on."))
            role_choices: Choices = [
                (i, r["alias"]) for i, r in self._roles.items() if r.get("builtin")
            ]
            html.dropdown("basedon",
                          role_choices,
                          deflt=self._role.get("basedon", "user"),
                          ordered=True)

        forms.end()

        html.h2(_("Permissions"))

        # Permissions
        base_role_id = self._role.get("basedon", self._role_id)

        html.help(
            _("When you leave the permissions at &quot;default&quot; then they get their "
              "settings from the factory defaults (for builtin roles) or from the "
              "factory default of their base role (for user define roles). Factory defaults "
              "may change due to software updates. When choosing another base role, all "
              "permissions that are on default will reflect the new base role."))

        for section in permission_section_registry.get_sorted_sections():
            # Now filter by the optional search term
            filtered_perms = []
            for perm in permission_registry.get_sorted_permissions(section):
                if search and (search not in perm.title.lower() and
                               search not in perm.name.lower()):
                    continue

                filtered_perms.append(perm)

            if not filtered_perms:
                continue

            forms.header(section.title, isopen=search is not None)
            for perm in filtered_perms:
                forms.section(perm.title)

                pvalue = self._role["permissions"].get(perm.name)
                def_value = base_role_id in perm.defaults

                choices: Choices = [
                    ("yes", _("yes")),
                    ("no", _("no")),
                    ("default", _("default (%s)") % (def_value and _("yes") or _("no"))),
                ]
                deflt = {True: "yes", False: "no"}.get(pvalue, "default")

                html.dropdown("perm_" + perm.name, choices, deflt=deflt, style="width: 130px;")
                html.help(perm.description)

        forms.end()
        html.hidden_fields()
        html.end_form()
Пример #5
0
 def render_input(self, varprefix, value):
     if value is not None:
         html.hidden_field(varprefix + "attr_" + self.name(), value)
         html.write(value)
Пример #6
0
 def render_input(self, varprefix: str, value: Optional[str]) -> None:
     if value is not None:
         html.hidden_field(varprefix + "attr_" + self.name(), value)
         html.write_text(value)
Пример #7
0
    def _show_hosts(self):
        if not self._folder.has_hosts():
            return

        hostnames = sorted(self._folder.hosts().keys(),
                           key=utils.key_num_split)
        search_text = html.request.var("search")

        # Show table of hosts in this folder
        html.begin_form("hosts", method="POST")
        with table_element("hosts",
                           title=_("Hosts"),
                           searchable=False,
                           omit_empty_columns=True) as table:

            # Compute colspan for bulk actions
            colspan = 6
            for attr in host_attribute_registry.attributes():
                if attr.show_in_table():
                    colspan += 1
            if not self._folder.locked_hosts() and config.user.may(
                    "wato.edit_hosts") and config.user.may("wato.move_hosts"):
                colspan += 1
            if self._folder.is_search_folder():
                colspan += 1

            contact_group_names = load_contact_group_information()

            host_errors = self._folder.host_validation_errors()
            rendered_hosts: List[HostName] = []

            # Now loop again over all hosts and display them
            max_hosts = len(hostnames)
            for hostname in hostnames:
                if table.limit_reached:
                    table.limit_hint = max_hosts
                    continue
                self._show_host_row(rendered_hosts, table, hostname,
                                    search_text, colspan, host_errors,
                                    contact_group_names)

        html.hidden_field("selection_id", weblib.selection_id())
        html.hidden_fields()
        html.end_form()

        selected = config.user.get_rowselection(
            weblib.selection_id(), 'wato-folder-/' + self._folder.path())

        row_count = len(hostnames)
        headinfo = "%d %s" % (row_count,
                              _("host") if row_count == 1 else _("hosts"))
        html.javascript("cmk.utils.update_header_info(%s);" %
                        json.dumps(headinfo))

        selection_properties = {
            "page_id": "wato-folder-%s" % ('/' + self._folder.path()),
            "selection_id": weblib.selection_id(),
            "selected_rows": selected,
        }
        html.javascript('cmk.selection.init_rowselect(%s);' %
                        (json.dumps(selection_properties)))
Пример #8
0
    def _show_login_page(self) -> None:
        html.set_render_headfoot(False)
        html.add_body_css_class("login")
        html.header(get_page_heading(), Breadcrumb(), javascripts=[])

        default_origtarget = ("index.py" if requested_file_name(request)
                              in ["login", "logout"] else makeuri(request, []))
        origtarget = request.get_url_input("_origtarget", default_origtarget)

        # Never allow the login page to be opened in the iframe. Redirect top page to login page.
        # This will result in a full screen login page.
        html.javascript("""if(top != self) {
    window.top.location.href = location;
}""")

        # When someone calls the login page directly and is already authed redirect to main page
        if requested_file_name(request) == "login" and _check_auth(request):
            raise HTTPRedirect(origtarget)

        html.open_div(id_="login")

        html.open_div(id_="login_window")

        html.open_a(href="https://checkmk.com")
        html.img(
            src=theme.detect_icon_path(icon_name="logo", prefix="mk-"),
            id_="logo",
            class_="custom" if theme.has_custom_logo() else None,
        )
        html.close_a()

        html.begin_form("login",
                        method="POST",
                        add_transid=False,
                        action="login.py")
        html.hidden_field("_login", "1")
        html.hidden_field("_origtarget", origtarget)
        html.label("%s:" % _("Username"),
                   id_="label_user",
                   class_=["legend"],
                   for_="_username")
        html.br()
        html.text_input("_username", id_="input_user")
        html.label("%s:" % _("Password"),
                   id_="label_pass",
                   class_=["legend"],
                   for_="_password")
        html.br()
        html.password_input("_password", id_="input_pass", size=None)

        if user_errors:
            html.open_div(id_="login_error")
            html.show_user_errors()
            html.close_div()

        html.open_div(id_="button_text")
        html.button("_login", _("Login"), cssclass="hot")
        html.close_div()
        html.close_div()

        html.open_div(id_="foot")

        if active_config.login_screen.get("login_message"):
            html.open_div(id_="login_message")
            html.show_message(active_config.login_screen["login_message"])
            html.close_div()

        footer: List[HTML] = []
        for title, url, target in active_config.login_screen.get(
                "footer_links", []):
            footer.append(html.render_a(title, href=url, target=target))

        if "hide_version" not in active_config.login_screen:
            footer.append(
                escape_to_html("Version: %s" % cmk_version.__version__))

        footer.append(
            HTML("&copy; %s" % html.render_a(
                "tribe29 GmbH", href="https://tribe29.com", target="_blank")))

        html.write_html(HTML(" - ").join(footer))

        if cmk_version.is_raw_edition():
            html.br()
            html.br()
            html.write_text(
                _('You can use, modify and distribute Check_MK under the terms of the <a href="%s" target="_blank">'
                  "GNU GPL Version 2</a>.") % "https://checkmk.com/gpl.html")

        html.close_div()

        html.set_focus("_username")
        html.hidden_fields()
        html.end_form()
        html.close_div()

        html.footer()