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,
-}
-
# .----------------------------------------------------------------------.
# | _ ____ _ ____ |
# | | | | _ \ / \ | _ \ |
Module: check_mk
Branch: master
Commit: 277c6f6750f84b1205072764b6bde7f95a30c2eb
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=277c6f6750f84b…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Tue Nov 13 15:44:24 2012 +0100
userdb/ldap: Implemented page hook
---
web/htdocs/index.py | 4 +++
web/htdocs/userdb.py | 51 ++++++++++++++++++++++++++++++++-----------
web/htdocs/wato.py | 5 ++++
web/plugins/userdb/ldap.py | 16 ++++++++++++-
4 files changed, 61 insertions(+), 15 deletions(-)
diff --git a/web/htdocs/index.py b/web/htdocs/index.py
index e2fd68f..fc90b52 100644
--- a/web/htdocs/index.py
+++ b/web/htdocs/index.py
@@ -286,6 +286,10 @@ def handler(req, profiling = True):
else:
return result
+ # Call userdb page hooks which are executed on a regular base to e.g. syncronize
+ # information withough explicit user triggered actions
+ userdb.hook_page()
+
# Set all permissions, read site config, and similar stuff
config.login(html.req.user)
diff --git a/web/htdocs/userdb.py b/web/htdocs/userdb.py
index 164fb44..960bfe7 100644
--- a/web/htdocs/userdb.py
+++ b/web/htdocs/userdb.py
@@ -100,6 +100,11 @@ def create_non_existing_user(connector_id, username):
# Call the sync function for this new user
hook_sync(connector_id = connector_id, only_username = username)
+def user_locked(username):
+ import wato
+ users = wato.load_users()
+ return users[username].get('locked', False)
+
# .----------------------------------------------------------------------.
# | _ _ _ |
# | | | | | ___ ___ | | _____ |
@@ -113,19 +118,31 @@ def create_non_existing_user(connector_id, username):
def hook_login(username, password):
for connector in multisite_user_connectors:
handler = connector.get('login', None)
- if handler:
- result = handler(username, password)
- # None -> User unknown, means continue with other connectors
- # True -> success
- # False -> failed
- if result == True:
- # Check wether or not the user exists (and maybe create it)
- create_non_existing_user(connector['id'], username)
-
- return result
-
- elif result == False:
- return result
+ if not handler:
+ continue
+
+ result = handler(username, password)
+ # None -> User unknown, means continue with other connectors
+ # True -> success
+ # False -> failed
+ if result == True:
+ # Check wether or not the user exists (and maybe create it)
+ create_non_existing_user(connector['id'], username)
+
+ # Now, after successfull login (and optional user account
+ # creation), check wether or not the user is locked.
+ # In e.g. htpasswd connector this is checked by validating the
+ # password against the hash in the htpasswd file prefixed with
+ # a "!". But when using other conectors it might be neccessary
+ # to validate the user "locked" attribute.
+ lock_handler = connector.get('locked', None)
+ if lock_handler:
+ result = not lock_handler(username) # returns True if locked
+
+ return result
+
+ elif result == False:
+ return result
# Hook function can be registered here to be executed to synchronize all users.
# Is called on:
@@ -150,3 +167,11 @@ def hook_sync(connector_id = None, add_to_changelog = False, only_username = Non
)
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:
+ handler = connector.get('page', None)
+ if handler:
+ handler()
diff --git a/web/htdocs/wato.py b/web/htdocs/wato.py
index 7c96457..83f443c 100644
--- a/web/htdocs/wato.py
+++ b/web/htdocs/wato.py
@@ -8449,9 +8449,14 @@ def save_users(profiles):
# 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 = '!'
diff --git a/web/plugins/userdb/ldap.py b/web/plugins/userdb/ldap.py
index d0b9b9e..8713402 100644
--- a/web/plugins/userdb/ldap.py
+++ b/web/plugins/userdb/ldap.py
@@ -261,6 +261,7 @@ ldap_attribute_plugins['alias'] = {
# Connector hook functions
#
+# This function only validates credentials, no locked checking or similar
def ldap_login(username, password):
ldap_connect()
# Returns None when the user is not found or not uniq, else returns the
@@ -328,17 +329,28 @@ def ldap_sync(add_to_changelog, only_username):
# Calculates the attributes of the users which are locked for users managed
# by this connector
-def ldap_locked():
+def ldap_locked_attributes():
locked = set([ 'password' ]) # This attributes are locked in all cases!
for key in config.ldap_active_plugins:
locked.update(ldap_attribute_plugins[key]['set_attributes'])
return list(locked)
+# Is called on every multisite http request
+def ldap_page():
+ # FIXME: Implement
+ pass
+
multisite_user_connectors.append({
'id': 'ldap',
'title': _('LDAP (AD, OpenLDAP)'),
'login': ldap_login,
'sync': ldap_sync,
- 'locked_attributes': ldap_locked,
+ 'page': ldap_page,
+ 'locked': user_locked, # no ldap check, just check the WATO attribute.
+ # This handles setups where the locked attribute is not
+ # synchronized and the user is enabled in LDAP and disabled
+ # in Check_MK. When the user is locked in LDAP a login is
+ # not possible.
+ 'locked_attributes': ldap_locked_attributes,
})