Module: check_mk
Branch: master
Commit: f9169bfb7fd177c5276e00eef34b5a06d7e43453
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=f9169bfb7fd177…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Fri Nov 16 15:54:45 2012 +0100
ldap: Moved user_id to userspec config option
---
web/plugins/userdb/ldap.py | 13 ++++++++-----
web/plugins/wato/check_mk_configuration.py | 16 ++++++++--------
2 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/web/plugins/userdb/ldap.py b/web/plugins/userdb/ldap.py
index 00cb989..7379205 100644
--- a/web/plugins/userdb/ldap.py
+++ b/web/plugins/userdb/ldap.py
@@ -218,14 +218,17 @@ def ldap_replace_macros(tmpl):
return dn
+def ldap_user_id_attr():
+ return config.ldap_userspec.get('user_id', ldap_attr('user_id', False))
+
def ldap_get_user_dn(username):
# Check wether or not the user exists in the directory
# It's only ok when exactly one entry is found.
# Returns the DN in this case.
result = ldap_search(
ldap_replace_macros(config.ldap_userspec['dn']),
- '(%s=%s)' % (ldap_attr('user_id'), ldap.filter.escape_filter_chars(username)),
- [ldap_attr('user_id')],
+ '(%s=%s)' % (ldap_user_id_attr(), ldap.filter.escape_filter_chars(username)),
+ [ldap_user_id_attr()],
)
if result:
@@ -233,7 +236,7 @@ def ldap_get_user_dn(username):
def ldap_get_users(add_filter = None):
columns = [
- ldap_attr('user_id'), # needed in all cases as uniq id
+ ldap_user_id_attr(), # needed in all cases as uniq id
] + ldap_needed_attributes()
filt = ldap_filter('users')
@@ -243,7 +246,7 @@ def ldap_get_users(add_filter = None):
result = {}
for dn, ldap_user in ldap_search(ldap_replace_macros(config.ldap_userspec['dn']),
filt, columns = columns):
- user_id = ldap_user[ldap_attr('user_id')][0]
+ user_id = ldap_user[ldap_user_id_attr()][0]
result[user_id] = ldap_user
return result
@@ -433,7 +436,7 @@ def ldap_sync(add_to_changelog, only_username):
filt = None
if only_username:
- filt = '(%s=%s)' % (ldap_attr('user_id'), only_username)
+ filt = '(%s=%s)' % (ldap_user_id_attr(), only_username)
import wato
users = wato.load_users()
diff --git a/web/plugins/wato/check_mk_configuration.py b/web/plugins/wato/check_mk_configuration.py
index 7d68aa9..f53f97f 100644
--- a/web/plugins/wato/check_mk_configuration.py
+++ b/web/plugins/wato/check_mk_configuration.py
@@ -397,8 +397,15 @@ register_configvar(group,
size = 80,
default_value = lambda: userdb.ldap_filter('users', False),
)),
+ ("user_id", TextAscii(
+ title = _("User-ID"),
+ help = _("The attribute used to identify the individual users. It must have "
+ "unique values to make an user identifyable by the value of this "
+ "attribute."),
+ default_value = lambda: userdb.ldap_attr('user_id', False),
+ )),
],
- optional_keys = ['scope', 'filter'],
+ optional_keys = ['scope', 'filter', 'user_id'],
),
domain = "multisite",
)
@@ -478,13 +485,6 @@ register_configvar(group,
"communication with the LDAP server. It controls which attributes are "
"e.g. used for the unique username or similar."),
elements = [
- ("user_id", TextAscii(
- title = _("User-ID"),
- help = _("The attribute used to identify the individual users. It must have "
- "unique values to make an user identifyable by the value of this "
- "attribute."),
- default_value = lambda: userdb.ldap_attr('user_id', False),
- )),
("pw_changed", TextAscii(
title = _("Relogon Indicator"),
help = _("When the value of this attribute changes for a user account, all "
Module: check_mk
Branch: master
Commit: 000f06ac00149dceddae9c01555c205071003580
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=000f06ac00149d…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Thu Nov 15 12:26:02 2012 +0100
Updated changelog
---
ChangeLog | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1361666..70ee673 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,6 +22,11 @@
* New button for generating test events directly via WATO
Multisite:
+ * Implemented LDAP integration of Multisite. You can now authenticate your
+ users using the form based authentication with LDAP. It is also possible
+ to synchronize some attributes like mail addresses, names and roles from
+ LDAP into multisite.
+ * Modularized the authentication and user management code in WATO
* Restructured cookie auth cookies (all auth cookies will be invalid
after update -> all users have to login again)
* Modularized login and cookie validation
Module: check_mk
Branch: master
Commit: 529371c3e1fcdd684f568293708132b1f604aee5
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=529371c3e1fcdd…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Thu Nov 15 11:25:33 2012 +0100
login: storing the users serial in a dedicated now (to make it easily readable by external auth checkers like in pnp/nagvis)
---
web/htdocs/wato.py | 30 ++++++++++++++++++++----------
1 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/web/htdocs/wato.py b/web/htdocs/wato.py
index 2de411c..51851bc 100644
--- a/web/htdocs/wato.py
+++ b/web/htdocs/wato.py
@@ -8382,12 +8382,14 @@ def load_users():
result[id] = new_user
# Other unknown entries will silently be dropped. Sorry...
- # Now read the automation secrets and add them to existing
- # users or create new users automatically
+ # Now read the user specific files
dir = defaults.var_dir + "/web/"
for d in os.listdir(dir):
if d[0] != '.':
id = d
+
+ # read automation secrets and add them to existing
+ # users or create new users automatically
secret_file = dir + d + "/automation.secret"
if os.path.exists(secret_file):
secret = file(secret_file).read().strip()
@@ -8399,15 +8401,18 @@ def load_users():
"automation_secret" : secret,
}
+ # read the users serials, only process for existing users
+ if id in result:
+ serial_file = dir + d + '/serial.mk'
+ if os.path.exists(serial_file):
+ result[id]['serial'] = saveint(file(serial_file).read().strip())
+
return result
def split_dict(d, keylist, positive):
return dict([(k,v) for (k,v) in d.items() if (k in keylist) == positive])
def save_users(profiles):
- # TODO: delete var/check_mk/web/$USER of non-existing users. Do we
- # need to remove other references as well?
-
custom_values = [ name for (name, vs) in user_attributes ]
# Keys not to put into contact definitions for Check_MK
@@ -8428,7 +8433,6 @@ def save_users(profiles):
"automation_secret",
"alias",
"language",
- "serial",
"connector",
] + custom_values
@@ -8460,16 +8464,22 @@ def save_users(profiles):
# Execute user connector save hooks
userdb.hook_save(profiles)
- # Write authentication secret for local processes
+ # Write user specific files
for id, user in profiles.items():
- auth_dir = defaults.var_dir + "/web/" + id
- auth_file = auth_dir + "/automation.secret"
- make_nagios_directory(auth_dir)
+ user_dir = defaults.var_dir + "/web/" + id
+ make_nagios_directory(user_dir)
+
+ # authentication secret for local processes
+ auth_file = user_dir + "/automation.secret"
if "automation_secret" in user:
create_user_file(auth_file, "w").write("%s\n" % user["automation_secret"])
elif os.path.exists(auth_file):
os.remove(auth_file)
+ # Write out the users serial
+ serial_file = user_dir + '/serial.mk'
+ create_user_file(serial_file, 'w').write('%d\n' % user.get('serial', 0))
+
# Remove settings directories of non-existant users
dir = defaults.var_dir + "/web"
for e in os.listdir(dir):
Module: check_mk
Branch: master
Commit: 8b0843ebde7a58c8a2a470dfdaabe9a8a5ff87b6
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=8b0843ebde7a58…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Thu Nov 15 12:23:55 2012 +0100
Better error handling in PNP-Graph hover menus in case of invalid responses
---
ChangeLog | 1 +
web/htdocs/js/checkmk.js | 17 +++++++++++++++++
web/plugins/icons/builtin.py | 2 +-
3 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index c813bed..1361666 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -41,6 +41,7 @@
* Dashboard "iframe" attribute can now be rendered dynamically using the
"iframefunc" attribute in the dashlet declaration
* Dashboard header can now be hidden by setting "title" to None
+ * Better error handling in PNP-Graph hover menus in case of invalid responses
Livestatus:
* Added new table statehist, used for SLA queries
diff --git a/web/htdocs/js/checkmk.js b/web/htdocs/js/checkmk.js
index 9e83337..29b5434 100644
--- a/web/htdocs/js/checkmk.js
+++ b/web/htdocs/js/checkmk.js
@@ -436,6 +436,23 @@ function render_pnp_graphs(container, site, host, service, pnpview, base_url, pn
pnp_response_handler, data, pnp_error_response_handler);
}
+// Renders contents for the PNP hover menus
+function pnp_hover_contents(url) {
+ var c = get_url_sync(url);
+ // It is possible that, if using multisite based authentication, pnp sends a 302 redirect
+ // to the login page which is transparently followed by XmlHttpRequest. There is no chance
+ // to catch the redirect. So we try to check the response content. If it does not contain
+ // the expected code, simply display an error message.
+ if(c.indexOf('/image?') === -1) {
+ // Error! unexpected response
+ c = '<div style="background-color:#BA2C2C;width:350px;padding:5px"> '
+ + 'ERROR: Received an unexpected response '
+ + 'while trying to display the PNP-Graphs. Maybe there is a problem with the '
+ + 'authentication.</div>';
+ }
+ return c;
+}
+
// ----------------------------------------------------------------------------
// Synchronous action handling
// ----------------------------------------------------------------------------
diff --git a/web/plugins/icons/builtin.py b/web/plugins/icons/builtin.py
index 4715e2c..5eace4a 100644
--- a/web/plugins/icons/builtin.py
+++ b/web/plugins/icons/builtin.py
@@ -193,7 +193,7 @@ def pnp_icon(row, what):
url = pnp_url(row, what)
else:
url = ""
- return '<a href="%s" onmouseover="displayHoverMenu(event, get_url_sync(\'%s\'))" ' \
+ return '<a href="%s" onmouseover="displayHoverMenu(event, pnp_hover_contents(\'%s\'))" ' \
'onmouseout="hoverHide()"><img class=icon src="images/icon_pnp.png"></a>' % \
(url, pnp_popup_url(row, what))
Module: check_mk
Branch: master
Commit: 42c9412dc337bfa6d07d565788f14f9bf323a4cd
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=42c9412dc337bf…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Tue Oct 30 13:33:23 2012 +0100
Added log method to html class for debug logging to apache error log
---
web/htdocs/htmllib.py | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/web/htdocs/htmllib.py b/web/htdocs/htmllib.py
index 9bbc669..2a303ce 100644
--- a/web/htdocs/htmllib.py
+++ b/web/htdocs/htmllib.py
@@ -24,7 +24,7 @@
# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA.
-from mod_python import Cookie
+from mod_python import Cookie, apache
import time, cgi, config, os, defaults, pwd, urllib, weblib, random
from lib import *
# Python 2.3 does not have 'set' in normal namespace.
@@ -1186,6 +1186,16 @@ class html:
for element in x:
self.write("<pre>%s</pre>\n" % pprint.pformat(element))
+ # Debug logging directly to apache error_log
+ # Even if this is for debugging purpose, set the log-level to WARN in all cases
+ # since the apache in OMD sites has LogLevel set to "warn" by default which would
+ # suppress messages generated here. Again, this is only for debugging during
+ # development, so this should be no problem for regular users.
+ def log(self, msg):
+ if type(msg) != str:
+ msg = repr(msg)
+ self.req.log_error(msg, apache.APLOG_WARNING)
+
def debug_vars(self):
self.write('<table onmouseover="this.style.display=\'none\';" class=debug_vars>')
self.write("<tr><th colspan=2>POST / GET Variables</th></tr>")
Module: check_mk
Branch: master
Commit: 1ae0f6b3a5c7d03915fe15e42f1079bc19841949
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=1ae0f6b3a5c7d0…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Wed Nov 14 12:07:09 2012 +0100
userdb: moved htpasswd saving to htpasswd userdb module; Modularized user saving
---
web/htdocs/userdb.py | 44 ++++++++++++++++++++++++++++++---------
web/htdocs/wato.py | 39 +++++++++--------------------------
web/plugins/userdb/htpasswd.py | 23 ++++++++++++++++++++-
web/plugins/userdb/ldap.py | 15 -------------
4 files changed, 66 insertions(+), 55 deletions(-)
diff --git a/web/htdocs/userdb.py b/web/htdocs/userdb.py
index 960bfe7..643c048 100644
--- a/web/htdocs/userdb.py
+++ b/web/htdocs/userdb.py
@@ -54,21 +54,25 @@ def list_user_connectors():
def connector_enabled(connector_id):
return connector_id in config.user_connectors
+def enabled_connectors():
+ connectors = []
+ for connector in multisite_user_connectors:
+ if connector['id'] in config.user_connectors:
+ connectors.append(connector)
+ return connectors
+
# Returns the connector dictionary of the given id
def get_connector(connector_id):
if connector_id is None:
connector_id = 'htpasswd'
- for connector in multisite_user_connectors:
+ for connector in enabled_connectors():
if connector['id'] == connector_id:
return connector
-# Returns a list of locked attributes. If connector is None the htpasswd
-# connector is assumed.
+# Returns a list of locked attributes
def locked_attributes(connector_id):
- for connector in multisite_user_connectors:
- if connector['id'] == connector_id:
- return connector.get('locked_attributes', lambda: [])()
- return []
+ connector = get_connector(connector_id)
+ return connector.get('locked_attributes', lambda: [])()
# This is a function needed in WATO and the htpasswd module. This should
# really be modularized one day. Till this day this is a good place ...
@@ -116,7 +120,7 @@ def user_locked(username):
# This hook is called to validate the login credentials provided by a user
def hook_login(username, password):
- for connector in multisite_user_connectors:
+ for connector in enabled_connectors():
handler = connector.get('login', None)
if not handler:
continue
@@ -147,11 +151,12 @@ def hook_login(username, password):
# Hook function can be registered here to be executed to synchronize all users.
# Is called on:
# a) before rendering the user management page in WATO
+# b) a user is created during login (only for this user)
def hook_sync(connector_id = None, add_to_changelog = False, only_username = None):
if connector_id:
connectors = [ get_connector(connector_id) ]
else:
- connectors = multisite_user_connectors
+ connectors = enabled_connectors()
for connector in connectors:
handler = connector.get('sync', None)
@@ -168,10 +173,29 @@ def hook_sync(connector_id = None, add_to_changelog = False, only_username = Non
else:
raise
+# Hook function can be registered here to be executed during saving of the
+# new user construct
+def hook_save(users):
+ for connector in enabled_connectors():
+ handler = connector.get('save', None)
+ if not handler:
+ continue
+ try:
+ handler(users)
+ except:
+ if config.debug:
+ import traceback
+ html.show_error(
+ "<h3>" + _("Error executing sync hook") + "</h3>"
+ "<pre>%s</pre>" % (traceback.format_exc())
+ )
+ else:
+ raise
+
# Hook function can be registered here to execute actions on a "regular" base without
# user triggered action. This hook is called on each page load.
def hook_page():
- for connector in multisite_user_connectors:
+ for connector in enabled_connectors():
handler = connector.get('page', None)
if handler:
handler()
diff --git a/web/htdocs/wato.py b/web/htdocs/wato.py
index 83f443c..5b5ecf4 100644
--- a/web/htdocs/wato.py
+++ b/web/htdocs/wato.py
@@ -7895,15 +7895,14 @@ def mode_edit_user(phase):
if new:
if cloneid:
- user = users.get(cloneid, {})
+ user = users.get(cloneid, userdb.new_user_template('htpasswd'))
else:
- user = {}
+ user = userdb.new_user_template('htpasswd')
else:
- user = users.get(userid, {})
+ user = users.get(userid, userdb.new_user_template('htpasswd'))
# Returns true if an attribute is locked and should be read only. Is only
# checked when modifying an existing user
- # FIXME: Also lock those attributes on form processing
locked_attributes = userdb.locked_attributes(user.get('connector'))
def is_locked(attr):
return not new and attr in locked_attributes
@@ -7975,11 +7974,9 @@ def mode_edit_user(phase):
new_user["password"] = userdb.encrypt_password(password)
increase_serial = True # password changed, reflect in auth serial
- # Set initial password serial or increase existing
- if new:
- new_user["serial"] = 0
- elif increase_serial:
- new_user["serial"] += 1
+ # Increase serial (if needed)
+ if increase_serial:
+ new_user['serial'] = new_user.get('serial', 0) + 1
# Email address
email = html.var("email").strip()
@@ -8444,27 +8441,11 @@ def save_users(profiles):
out.write("# Written by WATO\n# encoding: utf-8\n\n")
out.write("multisite_users = \\\n%s\n" % pprint.pformat(users))
- # Apache htpasswd. We only store passwords here. During
- # loading we created entries for all admin users we know. Other
- # users from htpasswd are lost. If you start managing users with
- # WATO, you should continue to do so or stop doing to for ever...
- # Locked accounts get a '!' before their password. This disable it.
- # FIXME: implement as 'save'-hook in htpasswd connector
- filename = defaults.htpasswd_file
- out = create_user_file(filename, "w")
- for id, user in profiles.items():
- # only process users which are handled by htpasswd connector
- if user.get('connector', 'htpasswd') != 'htpasswd':
- continue
-
- if user.get("password"):
- if user.get("locked", False):
- locksym = '!'
- else:
- locksym = ""
- out.write("%s:%s%s\n" % (id, locksym, user["password"]))
+ # Execute user connector save hooks
+ userdb.hook_save(profiles)
- # Authentication secret for local processes
+ # Write authentication secret for local processes
+ for id, user in profiles.items():
auth_dir = defaults.var_dir + "/web/" + id
auth_file = auth_dir + "/automation.secret"
make_nagios_directory(auth_dir)
diff --git a/web/plugins/userdb/htpasswd.py b/web/plugins/userdb/htpasswd.py
index bdcb089..5fc9f56 100644
--- a/web/plugins/userdb/htpasswd.py
+++ b/web/plugins/userdb/htpasswd.py
@@ -90,11 +90,32 @@ def htpasswd_login(username, password):
return None # not existing user, skip over
return password_valid(users[username], password)
+# Saves htpasswd connector managed users
+def htpasswd_save(users):
+ # Apache htpasswd. We only store passwords here. During
+ # loading we created entries for all admin users we know. Other
+ # users from htpasswd are lost. If you start managing users with
+ # WATO, you should continue to do so or stop doing to for ever...
+ # Locked accounts get a '!' before their password. This disable it.
+ out = create_user_file(defaults.htpasswd_file, "w")
+ for id, user in users.items():
+ # only process users which are handled by htpasswd connector
+ if user.get('connector', 'htpasswd') != 'htpasswd':
+ continue
+
+ if user.get("password"):
+ if user.get("locked", False):
+ locksym = '!'
+ else:
+ locksym = ""
+ out.write("%s:%s%s\n" % (id, locksym, user["password"]))
+
multisite_user_connectors.append({
'id': 'htpasswd',
'title': _('htpasswd file'),
# Register hook functions
'login': htpasswd_login,
- # Not registering: sync, save, locked_attributes, page
+ 'save': htpasswd_save,
+ # Not registering: sync, locked_attributes, page
})
diff --git a/web/plugins/userdb/ldap.py b/web/plugins/userdb/ldap.py
index 7efb909..fec04e0 100644
--- a/web/plugins/userdb/ldap.py
+++ b/web/plugins/userdb/ldap.py
@@ -59,21 +59,6 @@ user_filter = {
'openldap': '(objectcategory=user)',
}
-def ldap_ad_auth_expired():
- # FIXME
- pass
-
-def ldap_openldap_auth_expired():
- # FIXME
- pass
-
-# Directory type specific function to check wether or not a user
-# session is expired (e.g. because the password has been)
-ldap_pw_expire_check = {
- 'ad': ldap_ad_auth_expired,
- 'openldap': ldap_openldap_auth_expired,
-}
-
# .----------------------------------------------------------------------.
# | _ ____ _ ____ |
# | | | | _ \ / \ | _ \ |