def _validate_ldap_connection(self, value, varprefix): for role_id, group_specs in value["active_plugins"].get( "groups_to_roles", {}).items(): if role_id == "nested": continue # This is the option to enabled/disable nested group handling, not a role to DN entry for index, group_spec in enumerate(group_specs): dn, connection_id = group_spec if connection_id is None: group_dn = value["group_dn"] else: connection = get_connection(connection_id) if not connection: continue assert isinstance(connection, LDAPUserConnector) group_dn = connection.get_group_dn() if not group_dn: raise MKUserError( varprefix, _("You need to configure the group base DN to be able to " "use the roles synchronization plugin."), ) if not dn.lower().endswith(group_dn.lower()): varname = "connection_p_active_plugins_p_groups_to_roles_p_%s_1_%d" % ( role_id, index, ) raise MKUserError( varname, _("The configured DN does not match the group base DN." ))
def create_non_existing_user(connection_id: str, username: UserId) -> None: if user_exists(username): return # User exists. Nothing to do... users = load_users(lock=True) users[username] = new_user_template(connection_id) save_users(users) # Call the sync function for this new user connection = get_connection(connection_id) try: if connection is None: raise MKUserError(None, _("Invalid user connection: %s") % connection_id) connection.do_sync(add_to_changelog=False, only_username=username, load_users_func=load_users, save_users_func=save_users) except MKLDAPException as e: show_exception(connection_id, _("Error during sync"), e, debug=config.debug) except Exception as e: show_exception(connection_id, _("Error during sync"), e)
def create_non_existing_user(connection_id: str, username: UserId) -> None: # Since user_exists also looks into the htpasswd and treats all users that can be found there as # "existing users", we don't care about partially known users here and don't create them ad-hoc. # The load_users() method will handle this kind of users (TODO: Consolidate this!). # Which makes this function basically relevant for users that authenticate using an LDAP # connection and do not exist yet. if user_exists(username): return # User exists. Nothing to do... users = load_users(lock=True) users[username] = new_user_template(connection_id) save_users(users) # Call the sync function for this new user connection = get_connection(connection_id) try: if connection is None: raise MKUserError(None, _("Invalid user connection: %s") % connection_id) connection.do_sync(add_to_changelog=False, only_username=username, load_users_func=load_users, save_users_func=save_users) except MKLDAPException as e: show_exception(connection_id, _("Error during sync"), e, debug=config.debug) except Exception as e: show_exception(connection_id, _("Error during sync"), e)
def __init__(self, new, connection_id): self._new = new self._connection_id = connection_id self._connection = get_connection(self._connection_id) general_elements = self._general_elements() connection_elements = self._connection_elements() user_elements = self._user_elements() group_elements = self._group_elements() other_elements = self._other_elements() valuespec = Dictionary( title=_("LDAP Connection"), elements=general_elements + connection_elements + user_elements + group_elements + other_elements, headers=[ (_("General Properties"), [key for key, _vs in general_elements]), (_("LDAP Connection"), [key for key, _vs in connection_elements]), (_("Users"), [key for key, _vs in user_elements]), (_("Groups"), [key for key, _vs in group_elements]), (_("Attribute Sync Plugins"), ["active_plugins"]), (_("Other"), ["cache_livetime"]), ], render="form", form_narrow=True, optional_keys=[ "port", "use_ssl", "bind", "page_size", "response_timeout", "failover_servers", "user_filter", "user_filter_group", "user_id", "lower_user_ids", "connect_timeout", "version", "group_filter", "group_member", "suffix", "create_only_on_login", ], validate=self._validate_ldap_connection, ) super().__init__(valuespec, forth=LDAPUserConnector.transform_config)
def _get_attributes( connection_id: Optional[str], selector: Callable[[UserConnector], List[str]]) -> List[str]: connection = get_connection(connection_id) return selector(connection) if connection else []
def _show_user_list(self): visible_custom_attrs = [(name, attr) for name, attr in userdb.get_user_attributes() if attr.show_in_table()] users = userdb.load_users() entries = users.items() html.begin_form("bulk_delete_form", method="POST") roles = userdb.load_roles() timeperiods = watolib.timeperiods.load_timeperiods() contact_groups = load_contact_group_information() with table_element("users", None, empty_text=_("No users are defined yet.")) as table: online_threshold = time.time() - config.user_online_maxage for uid, user in sorted( entries, key=lambda x: x[1].get("alias", x[0]).lower()): table.row() # Checkboxes table.cell(html.render_input( "_toggle_group", type_="button", class_="checkgroup", onclick="cmk.selection.toggle_all_rows();", value='X'), sortable=False, css="checkbox") if uid != config.user.id: html.checkbox( "_c_user_%s" % six.ensure_str(base64.b64encode(uid.encode("utf-8")))) user_connection_id = cleanup_connection_id( user.get('connector')) connection = get_connection(user_connection_id) # Buttons table.cell(_("Actions"), css="buttons") if connection: # only show edit buttons when the connector is available and enabled edit_url = watolib.folder_preserving_link([("mode", "edit_user"), ("edit", uid)]) html.icon_button(edit_url, _("Properties"), "edit") clone_url = watolib.folder_preserving_link([ ("mode", "edit_user"), ("clone", uid) ]) html.icon_button(clone_url, _("Create a copy of this user"), "clone") delete_url = make_action_link([("mode", "users"), ("_delete", uid)]) html.icon_button(delete_url, _("Delete"), "delete") notifications_url = watolib.folder_preserving_link([ ("mode", "user_notifications"), ("user", uid) ]) if watolib.load_configuration_settings().get( "enable_rulebased_notifications"): html.icon_button( notifications_url, _("Custom notification table of this user"), "notifications") # ID table.cell(_("ID"), uid) # Online/Offline if config.save_user_access_times: last_seen = user.get('last_seen', 0) if last_seen >= online_threshold: title = _('Online') img_txt = 'online' elif last_seen != 0: title = _('Offline') img_txt = 'offline' elif last_seen == 0: title = _('Never logged in') img_txt = 'inactive' title += ' (%s %s)' % (render.date(last_seen), render.time_of_day(last_seen)) table.cell(_("Act.")) html.icon(title, img_txt) table.cell(_("Last seen")) if last_seen != 0: html.write_text("%s %s" % (render.date(last_seen), render.time_of_day(last_seen))) else: html.write_text(_("Never logged in")) if cmk_version.is_managed_edition(): table.cell(_("Customer"), managed.get_customer_name(user)) # Connection if connection: table.cell( _("Connection"), '%s (%s)' % (connection.short_title(), user_connection_id)) locked_attributes = userdb.locked_attributes( user_connection_id) else: table.cell( _("Connection"), "%s (%s) (%s)" % (_("UNKNOWN"), user_connection_id, _("disabled")), css="error") locked_attributes = [] # Authentication if "automation_secret" in user: auth_method = _("Automation") elif user.get("password") or 'password' in locked_attributes: auth_method = _("Password") else: auth_method = "<i>%s</i>" % _("none") table.cell(_("Authentication"), auth_method) table.cell(_("State")) if user.get("locked", False): html.icon(_('The login is currently locked'), 'user_locked') if "disable_notifications" in user and isinstance( user["disable_notifications"], bool): disable_notifications_opts = { "disable": user["disable_notifications"] } else: disable_notifications_opts = user.get( "disable_notifications", {}) if disable_notifications_opts.get("disable", False): html.icon(_('Notifications are disabled'), 'notif_disabled') # Full name / Alias table.text_cell(_("Alias"), user.get("alias", "")) # Email table.text_cell(_("Email"), user.get("email", "")) # Roles table.cell(_("Roles")) if user.get("roles", []): role_links = [(watolib.folder_preserving_link([ ("mode", "edit_role"), ("edit", role) ]), roles[role].get("alias")) for role in user["roles"]] html.write_html( HTML(", ").join( html.render_a(alias, href=link) for (link, alias) in role_links)) # contact groups table.cell(_("Contact groups")) cgs = user.get("contactgroups", []) if cgs: cg_aliases = [ contact_groups[c]['alias'] if c in contact_groups else c for c in cgs ] cg_urls = [ watolib.folder_preserving_link([("mode", "edit_contact_group"), ("edit", c)]) for c in cgs ] html.write_html( HTML(", ").join( html.render_a(content, href=url) for (content, url) in zip(cg_aliases, cg_urls))) else: html.i(_("none")) #table.cell(_("Sites")) #html.write(vs_authorized_sites().value_to_text(user.get("authorized_sites", # vs_authorized_sites().default_value()))) # notifications if not watolib.load_configuration_settings().get( "enable_rulebased_notifications"): table.cell(_("Notifications")) if not cgs: html.i(_("not a contact")) elif not user.get("notifications_enabled", True): html.write_text(_("disabled")) elif user.get("host_notification_options", "") == "" and \ user.get("service_notification_options", "") == "": html.write_text(_("all events disabled")) else: tp = user.get("notification_period", "24X7") if tp not in timeperiods: tp = tp + _(" (invalid)") elif tp not in watolib.timeperiods.builtin_timeperiods( ): url = watolib.folder_preserving_link([ ("mode", "edit_timeperiod"), ("edit", tp) ]) tp = html.render_a(timeperiod_spec_alias( timeperiods[tp], tp), href=url) else: tp = timeperiod_spec_alias(timeperiods[tp], tp) html.write(tp) # the visible custom attributes for name, attr in visible_custom_attrs: vs = attr.valuespec() table.cell(escaping.escape_attribute(_u(vs.title()))) html.write( vs.value_to_text(user.get(name, vs.default_value()))) html.button("_bulk_delete_users", _("Bulk Delete"), "submit", style="margin-top:10px") html.hidden_fields() html.end_form() if not load_contact_group_information(): url = "wato.py?mode=contact_groups" html.open_div(class_="info") html.write( _("Note: you haven't defined any contact groups yet. If you <a href='%s'>" "create some contact groups</a> you can assign users to them und thus " "make them monitoring contacts. Only monitoring contacts can receive " "notifications.") % url) html.write( " you can assign users to them und thus " "make them monitoring contacts. Only monitoring contacts can receive " "notifications.") html.close_div()
def _get_attributes(connection_id, selector): # type: (Optional[str], Callable[[UserConnector], List[str]]) -> List[str] connection = get_connection(connection_id) return selector(connection) if connection else []